diff --git a/BUILD.gn b/BUILD.gn
index e9d1908..2dc631c9 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -42,29 +42,19 @@
   assert(!is_component_build)
 }
 
-# This file defines the following three main targets:
+# This file defines the following two main targets:
 #
-# "gn_all" should (transitively) cause everything to be built; if you run
-# 'ninja gn_all' and then 'ninja all', the second build should do no work.
+# "gn_all" is used to create explicit dependencies from the root BUILD.gn to
+# each top-level component that we wish to include when building everything via
+# "all". This is required since the set of targets built by "all" is determined
+# automatically based on reachability from the root BUILD.gn (for details, see
+# crbug.com/503241). Builders should typically use "all", or list targets
+# explicitly, rather than relying on "gn_all".
 #
 # "gn_visibility": targets that are normally not visible to top-level targets,
 # but are built anyway by "all". Since we don't want any such targets, we have
 # this placeholder to make sure hidden targets that aren't otherwise depended
 # on yet are accounted for.
-#
-# "All" is an alias for "gn_all". It exists for bot compatibility w/ GYP for
-# the iOS bots and the official builders, but should not be generally used
-# during the GYP->GN migration.  We cannot guarantee that GN's "All" builds the
-# same set of targets as GYP's "All" does, because GYP's "All" supports
-# wildcards.
-#
-# Lastly, none of these targets are guaranteed to be the same as what ninja
-# will build with "all". For more on how "all" works and how GN determines
-# "all", see crbug.com/503241.
-#
-# TODO(GYP_GONE): crbug.com/481694. Make sure that the above is true and there
-# are scripts run on the bots that enforce this. Once the GYP migration is
-# over, we can collapse all of these targets as desired.
 
 group("gn_all") {
   testonly = true
@@ -747,16 +737,6 @@
   }
 }
 
-# TODO(GYP_GONE): This target exists for compatibility with GYP, specifically
-# for the iOS bots and the official builders.
-group("All") {
-  testonly = true
-
-  deps = [
-    ":gn_all",
-  ]
-}
-
 if (is_fuchsia) {
   # TODO(https://crbug.com/731217): This can't practically be in //v8 without
   # duplicating all the Fuchsia running infrastructure there.
diff --git a/DEPS b/DEPS
index 09e2b72b..b7fc797 100644
--- a/DEPS
+++ b/DEPS
@@ -78,7 +78,7 @@
   # 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': '0dec3af001ac443447f1f90c522f74feb0be850a',
+  'skia_revision': '5c68dce7750a5525a5cfae29943716ce5c0d51b3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -90,7 +90,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '62fcf62aecc7dc23b73e1cfefb751191eafc39d3',
+  'angle_revision': '2b7bbc2822805fc29d19ba93a365d8e02e84d045',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -102,7 +102,7 @@
   # 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': 'ab384ed5a2c6c05a5d55645b7a50c6c42b613165',
+  'pdfium_revision': '891aaf63b3490989a189bcc51b18647073f988d4',
   # 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.
@@ -134,7 +134,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': '436908b7d264b36cf00478756f59f109e93e31a5',
+  'catapult_revision': 'cd1fd5940f684f7f327cdf301e5a554a31b31861',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -197,7 +197,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '624dd86aef86bc5892fbc8717b1e2c3e5f3843f0',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '7e090434dde5009a693101a63864ab47b895e87f',
       'condition': 'checkout_ios',
   },
 
@@ -232,7 +232,7 @@
   },
 
   'src/ios/third_party/motion_animator_objc/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-motion/motion-animator-objc.git' + '@' + 'f31562c64954525d21b74bc638bd5b7625a32d20',
+      'url': Var('chromium_git') + '/external/github.com/material-motion/motion-animator-objc.git' + '@' + 'ff39ecc69fdee46d388cc9f882201d54c3d5039c',
       'condition': 'checkout_ios',
   },
 
@@ -292,7 +292,7 @@
     Var('boringssl_git') + '/boringssl.git' + '@' +  Var('boringssl_revision'),
 
   'src/third_party/breakpad/breakpad':
-    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'c283630201acedb25190d3b73ad0416fb55e4639',
+    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '4af3e83b10b17bbd31099d55c2e272d56fb0ef13',
 
   'src/third_party/catapult':
     Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
@@ -484,7 +484,7 @@
     Var('chromium_git') + '/webm/libwebm.git' + '@' + '4956b2dec65352af32dc71bab553acb631c64177',
 
   'src/third_party/libyuv':
-    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '56480051e074f8d75f62fcabde9164fc51817467',  # from r1688
+    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'c67db6053495a2744511a43ba7b6ba3fa49b26a5',  # from r1685
 
   'src/third_party/lighttpd': {
       'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
@@ -643,7 +643,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd458ada06171a85af00367251a4ed55db7fe2018',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'f8409521d96bfa7af127815cafe3e09ba720ebe8', # commit position 20628
+    Var('webrtc_git') + '/src.git' + '@' + 'c0ed4db0ba6390262a254b235aac6d89fc8e440b', # commit position 20628
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -666,7 +666,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@fb72216115d65e9fc6ed93f141bceb334c3f1c05',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a9073a99865e1df9ae31aa59e9a2710ea44bbe40',
     'condition': 'checkout_src_internal',
   },
 }
@@ -1074,14 +1074,6 @@
                 "-s", "src/v8/test/fuzzer/wasm_corpus.tar.gz.sha1",
     ],
   },
-  {
-    'name': 'devtools_install_node',
-    'action': [ 'vpython',
-                'src/third_party/WebKit/Source/devtools/scripts/local_node/node.py',
-                '--running-as-hook',
-                '--version',
-    ],
-  },
 
   # Pull down Node binaries for WebUI toolchain.
   {
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 3dec54d..d5f392a 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -425,7 +425,7 @@
       r'std::regex',
       (
         'Using std::regex adds unnecessary binary size to Chrome. Please use',
-        're2::RE2 instead (crbug/755321)',
+        're2::RE2 instead (crbug.com/755321)',
       ),
       True,
       (),
@@ -443,7 +443,7 @@
       r'/\bbase::Bind\(',
       (
           'Please consider using base::Bind{Once,Repeating} instead '
-          'of base::Bind. (crbug/714018)',
+          'of base::Bind. (crbug.com/714018)',
       ),
       False,
       (),
@@ -452,7 +452,7 @@
       r'/\bbase::Callback<',
       (
           'Please consider using base::{Once,Repeating}Callback instead '
-          'of base::Callback. (crbug/714018)',
+          'of base::Callback. (crbug.com/714018)',
       ),
       False,
       (),
@@ -461,7 +461,7 @@
       r'/\bbase::Closure\b',
       (
           'Please consider using base::{Once,Repeating}Closure instead '
-          'of base::Closure. (crbug/714018)',
+          'of base::Closure. (crbug.com/714018)',
       ),
       False,
       (),
@@ -2086,7 +2086,8 @@
   # Mac, so skip it on other platforms.
   if input_api.platform != 'linux2':
     return []
-  # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
+  # TODO(agrieve): Update when there's a better way to detect
+  # this: crbug.com/570091
   is_android = input_api.os_path.exists('third_party/android_tools')
   pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
   results = []
diff --git a/WATCHLISTS b/WATCHLISTS
index 8a24f8d..167a742 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1406,19 +1406,22 @@
         '|media/audio/audio_(output_controller|power_monitor)',
     },
     'tab_capture': {
-      'filepath': 'cc/output/copy_output_'\
-        '|chrome/browser/extensions/api/tab_capture/'\
+      'filepath': 'chrome/browser/extensions/api/tab_capture/'\
         '|chrome/renderer/resources/extensions/tab_capture_custom_bindings.js'\
         '|chrome/test/data/extensions/api_test/tab_capture/'\
+        '|components/viz/common/(frame_sinks/copy_output_|gl_helper|yuv_)'\
+        '|components/viz/service/display/'\
+        '|components/viz/service/frame_sinks/(frame_sink_manager'\
+            '|video_capture/)'\
         '|content/browser/media/capture/'\
-        '|content/browser/renderer_host/delegated_frame_host'\
         '|content/browser/renderer_host/media/(audio_'\
             '|media_stream_manager|video_)'\
         '|content/public/renderer/media_stream_'\
         '|content/renderer/media/(media_stream|(.+audio_source))'\
         '|media/audio/(audio_output_controller|fake_audio_|virtual_audio_)'\
         '|media/base/video_frame\.h'\
-        '|media/capture/',
+        '|media/capture/'\
+        '|services/viz/privileged/interfaces/compositing/frame_sink',
     },
     'tab_contents': {
       'filepath': 'chrome/browser/tab_contents/|'\
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index e7da6e2..8e7adbd3 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -723,7 +723,6 @@
     "//gin",
     "//gpu/command_buffer/client:gles2_c_lib",
     "//gpu/command_buffer/client:gles2_implementation",
-    "//gpu/command_buffer/common:gles2_utils",
     "//gpu/command_buffer/service",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings",
diff --git a/android_webview/browser/aw_render_thread_context_provider.cc b/android_webview/browser/aw_render_thread_context_provider.cc
index 36ab732..4e9079a 100644
--- a/android_webview/browser/aw_render_thread_context_provider.cc
+++ b/android_webview/browser/aw_render_thread_context_provider.cc
@@ -40,7 +40,7 @@
   // the Android OS. The widget we pass here will be ignored since we're
   // providing the GLSurface to the context already.
   DCHECK(!surface->IsOffscreen());
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   // The context is wrapping an already allocated surface, so we can't control
   // what buffers it has from these attributes. We do expect an alpha and
   // stencil buffer to exist for webview, as the display compositor requires
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc
index 877526a..0f9c367 100644
--- a/android_webview/browser/cookie_manager.cc
+++ b/android_webview/browser/cookie_manager.cc
@@ -118,29 +118,6 @@
 // Are cookies allowed for file:// URLs by default?
 const bool kDefaultFileSchemeAllowed = false;
 
-void ImportLegacyCookieStore(const FilePath& cookie_store_path) {
-  // We use the old cookie store to create the new cookie store only if the
-  // new cookie store does not exist.
-  if (base::PathExists(cookie_store_path))
-    return;
-
-  // WebViewClassic gets the database path from Context and appends a
-  // hardcoded name. See:
-  // https://android.googlesource.com/platform/frameworks/base/+/bf6f6f9d/core/java/android/webkit/JniUtil.java
-  // https://android.googlesource.com/platform/external/webkit/+/7151e/
-  //     Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp
-  FilePath old_cookie_store_path;
-  base::android::GetDatabaseDirectory(&old_cookie_store_path);
-  old_cookie_store_path = old_cookie_store_path.Append(
-      FILE_PATH_LITERAL("webviewCookiesChromium.db"));
-  if (base::PathExists(old_cookie_store_path) &&
-      !base::Move(old_cookie_store_path, cookie_store_path)) {
-    LOG(WARNING) << "Failed to move old cookie store path from "
-                 << old_cookie_store_path.AsUTF8Unsafe() << " to "
-                 << cookie_store_path.AsUTF8Unsafe();
-  }
-}
-
 void GetUserDataDir(FilePath* user_data_dir) {
   if (!PathService::Get(base::DIR_ANDROID_APP_DATA, user_data_dir)) {
     NOTREACHED() << "Failed to get app data directory for Android WebView";
@@ -315,9 +292,6 @@
     FilePath cookie_store_path =
         user_data_dir.Append(FILE_PATH_LITERAL("Cookies"));
 
-    cookie_store_backend_thread_.task_runner()->PostTask(
-        FROM_HERE, base::Bind(ImportLegacyCookieStore, cookie_store_path));
-
     content::CookieStoreConfig cookie_config(cookie_store_path, true, true,
                                              nullptr);
     cookie_config.client_task_runner = cookie_store_task_runner_;
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
index b37efc4..acd89132e 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -211,7 +211,7 @@
 
         ThreadUtils.setWillOverrideUiThread();
         // Load chromium library.
-        AwBrowserProcess.loadLibrary();
+        AwBrowserProcess.loadLibrary(mWebViewDelegate.getDataDirectorySuffix());
 
         final PackageInfo packageInfo = WebViewFactory.getLoadedPackageInfo();
 
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewDelegateFactory.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewDelegateFactory.java
index cb75912..085c646 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewDelegateFactory.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewDelegateFactory.java
@@ -85,6 +85,9 @@
 
         /** @see android.webkit.WebViewDelegate#isMultiProcessEnabled */
         boolean isMultiProcessEnabled();
+
+        /** @see android.webkit.WebViewDelegate#getDataDirectorySuffix */
+        String getDataDirectorySuffix();
     }
 
     /**
@@ -206,6 +209,11 @@
         public boolean isMultiProcessEnabled() {
             return mDelegate.isMultiProcessEnabled();
         }
+
+        @Override
+        public String getDataDirectorySuffix() {
+            return null;
+        }
     }
 
     /**
@@ -396,5 +404,10 @@
         public boolean isMultiProcessEnabled() {
             throw new UnsupportedOperationException();
         }
+
+        @Override
+        public String getDataDirectorySuffix() {
+            return null;
+        }
     }
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
index 9b0f8036..faba1b4 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
@@ -19,6 +19,7 @@
 import org.chromium.android_webview.crash.CrashReceiverService;
 import org.chromium.android_webview.crash.ICrashReceiverService;
 import org.chromium.android_webview.policy.AwPolicyProvider;
+import org.chromium.base.BuildInfo;
 import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
@@ -46,7 +47,7 @@
  */
 @JNINamespace("android_webview")
 public final class AwBrowserProcess {
-    public static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "webview";
+    public static final String WEBVIEW_DIR_BASENAME = "webview";
 
     private static final String TAG = "AwBrowserProcess";
     private static final String EXCLUSIVE_LOCK_FILE = "webview_data.lock";
@@ -58,9 +59,17 @@
      * Loads the native library, and performs basic static construction of objects needed
      * to run webview in this process. Does not create threads; safe to call from zygote.
      * Note: it is up to the caller to ensure this is only called once.
+     *
+     * @param processDataDirSuffix The suffix to use when setting the data directory for this
+     *                             process; null to use no suffix.
      */
-    public static void loadLibrary() {
-        PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
+    public static void loadLibrary(String processDataDirSuffix) {
+        if (processDataDirSuffix == null) {
+            PathUtils.setPrivateDataDirectorySuffix(WEBVIEW_DIR_BASENAME, null);
+        } else {
+            String processDataDirName = WEBVIEW_DIR_BASENAME + "_" + processDataDirSuffix;
+            PathUtils.setPrivateDataDirectorySuffix(processDataDirName, processDataDirName);
+        }
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
         try {
             LibraryLoader libraryLoader = LibraryLoader.get(LibraryProcessType.PROCESS_WEBVIEW);
@@ -96,7 +105,7 @@
      */
     public static void start() {
         final Context appContext = ContextUtils.getApplicationContext();
-        tryObtainingDataDirLock(appContext);
+        tryObtainingDataDirLock();
         // We must post to the UI thread to cover the case that the user
         // has invoked Chromium startup by using the (thread-safe)
         // CookieManager rather than creating a WebView.
@@ -138,10 +147,10 @@
         }
     }
 
-    private static void tryObtainingDataDirLock(Context context) {
-        // Too many apps rely on this at present to make this fatal,
-        // even though it's known to be unsafe.
-        boolean dieOnFailure = false;
+    private static void tryObtainingDataDirLock() {
+        // Many existing apps rely on this even though it's known to be unsafe.
+        // Make it fatal for apps that target P or higher.
+        boolean dieOnFailure = BuildInfo.targetsAtLeastP();
 
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
         try {
@@ -157,8 +166,8 @@
                 Log.w(TAG, "Failed to create lock file " + lockFile, e);
             }
             if (!success) {
-                final String error = "Using WebView from more than one process at once in a single "
-                        + "app is not supported. https://crbug.com/558377";
+                final String error = "Using WebView from more than one process at once with the "
+                        + "same data directory is not supported. https://crbug.com/558377";
                 if (dieOnFailure) {
                     throw new RuntimeException(error);
                 } else {
diff --git a/android_webview/java/src/org/chromium/android_webview/variations/AwVariationsConfigurationService.java b/android_webview/java/src/org/chromium/android_webview/variations/AwVariationsConfigurationService.java
index 1f1e39f..e48f6fc 100644
--- a/android_webview/java/src/org/chromium/android_webview/variations/AwVariationsConfigurationService.java
+++ b/android_webview/java/src/org/chromium/android_webview/variations/AwVariationsConfigurationService.java
@@ -66,7 +66,7 @@
         ContextUtils.initApplicationContext(this.getApplicationContext());
         // Ensure that PathUtils.getDataDirectory() will return the app_webview directory in the
         // following code.
-        PathUtils.setPrivateDataDirectorySuffix(AwBrowserProcess.PRIVATE_DATA_DIRECTORY_SUFFIX);
+        PathUtils.setPrivateDataDirectorySuffix(AwBrowserProcess.WEBVIEW_DIR_BASENAME);
     }
 
     @Override
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java
index d05ed48..49e363c4 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java
@@ -60,7 +60,7 @@
                                      .getTargetContext()
                                      .getApplicationContext();
         ContextUtils.initApplicationContext(appContext);
-        AwBrowserProcess.loadLibrary();
+        AwBrowserProcess.loadLibrary(null);
     }
 
     private void startChromium() throws Exception {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/variations/AwVariationsConfigurationServiceTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/variations/AwVariationsConfigurationServiceTest.java
index d18c4f7..7c4fb9b9 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/variations/AwVariationsConfigurationServiceTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/variations/AwVariationsConfigurationServiceTest.java
@@ -50,7 +50,7 @@
         ContextUtils.initApplicationContextForTests(InstrumentationRegistry.getInstrumentation()
                                                             .getTargetContext()
                                                             .getApplicationContext());
-        PathUtils.setPrivateDataDirectorySuffix(AwBrowserProcess.PRIVATE_DATA_DIRECTORY_SUFFIX);
+        PathUtils.setPrivateDataDirectorySuffix(AwBrowserProcess.WEBVIEW_DIR_BASENAME);
 
         mSeedInfo = new SeedInfo();
         mSeedInfo.seedData = "SeedData".getBytes();
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java
index ee55e7f7..1a192fd1 100644
--- a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java
+++ b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java
@@ -69,7 +69,7 @@
         ContentApplication.initCommandLine(this);
 
         ContextUtils.initApplicationContext(getApplicationContext());
-        AwBrowserProcess.loadLibrary();
+        AwBrowserProcess.loadLibrary(null);
 
         if (CommandLine.getInstance().hasSwitch(AwShellSwitches.ENABLE_ATRACE)) {
             Log.e(TAG, "Enabling Android trace.");
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestRunnerActivity.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestRunnerActivity.java
index 9e9de75..2fc2ac8d 100644
--- a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestRunnerActivity.java
+++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestRunnerActivity.java
@@ -32,7 +32,7 @@
         AwShellResourceProvider.registerResources(this);
         ContextUtils.initApplicationContext(getApplicationContext());
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-        AwBrowserProcess.loadLibrary();
+        AwBrowserProcess.loadLibrary(null);
         StrictMode.setThreadPolicy(oldPolicy);
 
         mLinearLayout = new LinearLayout(this);
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/SecondBrowserProcess.java b/android_webview/test/shell/src/org/chromium/android_webview/test/SecondBrowserProcess.java
index b10fe83..8427b41 100644
--- a/android_webview/test/shell/src/org/chromium/android_webview/test/SecondBrowserProcess.java
+++ b/android_webview/test/shell/src/org/chromium/android_webview/test/SecondBrowserProcess.java
@@ -56,7 +56,7 @@
         AwResource.setResources(this.getResources());
         AwResource.setConfigKeySystemUuidMapping(R.array.config_key_system_uuid_mapping);
         ContextUtils.initApplicationContext(getApplicationContext());
-        AwBrowserProcess.loadLibrary();
+        AwBrowserProcess.loadLibrary(null);
         AwBrowserProcess.start();
     }
 }
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index 52912e89..d414dc5 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -26,6 +26,7 @@
 #include "ash/system/tray/system_tray_notifier.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
+#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/display/display.h"
 #include "ui/display/manager/display_manager.h"
@@ -34,6 +35,7 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/vector2d.h"
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/scroll_view.h"
@@ -331,6 +333,17 @@
   FocusNextWidget(reverse);
 }
 
+void LockContentsView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+  Shelf* shelf = Shelf::ForWindow(GetWidget()->GetNativeWindow());
+  ShelfWidget* shelf_widget = shelf->shelf_widget();
+  int next_id = views::AXAuraObjCache::GetInstance()->GetID(shelf_widget);
+  node_data->AddIntAttribute(ui::AX_ATTR_NEXT_FOCUS_ID, next_id);
+
+  int previous_id =
+      views::AXAuraObjCache::GetInstance()->GetID(shelf->GetStatusAreaWidget());
+  node_data->AddIntAttribute(ui::AX_ATTR_PREVIOUS_FOCUS_ID, previous_id);
+}
+
 void LockContentsView::OnUsersChanged(
     const std::vector<mojom::LoginUserInfoPtr>& users) {
   // The debug view will potentially call this method many times. Make sure to
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index ec6de9db..dfd687d 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -78,6 +78,7 @@
   void AddedToWidget() override;
   void OnFocus() override;
   void AboutToRequestFocusFromTabTraversal(bool reverse) override;
+  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
   // LockScreenAppsFocusObserver:
   void OnFocusLeavingLockScreenApps(bool reverse) override;
diff --git a/ash/login/ui/lock_screen.h b/ash/login/ui/lock_screen.h
index c2ab08e..e0bb5a6e 100644
--- a/ash/login/ui/lock_screen.h
+++ b/ash/login/ui/lock_screen.h
@@ -40,6 +40,8 @@
   // Check if the lock screen is currently shown.
   static bool IsShown();
 
+  LockWindow* window() { return window_; }
+
   // Destroys an existing lock screen instance.
   void Destroy();
 
diff --git a/ash/login/ui/login_password_view.cc b/ash/login/ui/login_password_view.cc
index 7fa324c..e31391d 100644
--- a/ash/login/ui/login_password_view.cc
+++ b/ash/login/ui/login_password_view.cc
@@ -85,6 +85,22 @@
   DISALLOW_COPY_AND_ASSIGN(NonAccessibleSeparator);
 };
 
+// A textfield that selects all text on focus.
+class LoginTextfield : public views::Textfield {
+ public:
+  LoginTextfield() {}
+  ~LoginTextfield() override {}
+
+  // views::Textfield:
+  void OnFocus() override {
+    views::Textfield::OnFocus();
+    SelectAll(false /*reverse*/);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LoginTextfield);
+};
+
 // Set of resources for an easy unlock icon.
 struct IconBundle {
   // Creates an IconBundle for a static image.
@@ -379,7 +395,7 @@
 
   // Password textfield. We control the textfield size by sizing the parent
   // view, as the textfield will expand to fill it.
-  textfield_ = new views::Textfield();
+  textfield_ = new LoginTextfield();
   textfield_->set_controller(this);
   textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
   textfield_->SetTextColor(kTextColor);
diff --git a/ash/public/cpp/ash_switches.cc b/ash/public/cpp/ash_switches.cc
index 1c1db2dc..629eb3d6 100644
--- a/ash/public/cpp/ash_switches.cc
+++ b/ash/public/cpp/ash_switches.cc
@@ -37,6 +37,9 @@
 const char kAshDisableTabletAutohideTitlebars[] =
     "ash-disable-tablet-autohide-titlebars";
 
+// Disables the split view on tablet mode.
+const char kAshDisableTabletSplitView[] = "disable-tablet-splitview";
+
 // Disable the Touch Exploration Mode. Touch Exploration Mode will no longer be
 // turned on automatically when spoken feedback is enabled when this flag is
 // set.
@@ -72,9 +75,6 @@
 const char kAshSidebarEnabled[] = "enable-ash-sidebar";
 const char kAshSidebarDisabled[] = "disable-ash-sidebar";
 
-// Enables the split view on tablet mode.
-const char kAshEnableTabletSplitView[] = "enable-tablet-splitview";
-
 // Enables the observation of accelerometer events to enter tablet
 // mode.  The flag is "enable-touchview" not "enable-tabletmode" as this
 // is used to enable tablet mode on convertible devices.
diff --git a/ash/public/cpp/ash_switches.h b/ash/public/cpp/ash_switches.h
index cc441c5..f448c338 100644
--- a/ash/public/cpp/ash_switches.h
+++ b/ash/public/cpp/ash_switches.h
@@ -23,6 +23,7 @@
 ASH_PUBLIC_EXPORT extern const char kAshDisableShelfModelSynchronization[];
 ASH_PUBLIC_EXPORT extern const char kAshDisableSmoothScreenRotation[];
 ASH_PUBLIC_EXPORT extern const char kAshDisableTabletAutohideTitlebars[];
+ASH_PUBLIC_EXPORT extern const char kAshDisableTabletSplitView[];
 ASH_PUBLIC_EXPORT extern const char kAshDisableTouchExplorationMode[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableV1AppBackButton[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableDisplayMoveWindowAccels[];
@@ -31,7 +32,6 @@
 ASH_PUBLIC_EXPORT extern const char kAshEnableNightLight[];
 ASH_PUBLIC_EXPORT extern const char kAshEnablePaletteOnAllDisplays[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableScaleSettingsTray[];
-ASH_PUBLIC_EXPORT extern const char kAshEnableTabletSplitView[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableTabletMode[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableWaylandServer[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableMirroredScreen[];
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index 0ad840a..3aeb431 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -12,6 +12,8 @@
 #include "ash/lock_screen_action/lock_screen_action_background_controller.h"
 #include "ash/lock_screen_action/lock_screen_action_background_state.h"
 #include "ash/login/login_screen_controller.h"
+#include "ash/login/ui/lock_screen.h"
+#include "ash/login/ui/lock_window.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/root_window_controller.h"
 #include "ash/session/session_controller.h"
@@ -28,8 +30,10 @@
 #include "ash/tray_action/tray_action.h"
 #include "ash/wm/lock_state_controller.h"
 #include "base/metrics/user_metrics.h"
+#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
 #include "ui/views/animation/ink_drop_impl.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/focus/focus_search.h"
@@ -180,6 +184,19 @@
   }
 }
 
+void LoginShelfView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+  if (LockScreen::IsShown()) {
+    int previous_id = views::AXAuraObjCache::GetInstance()->GetID(
+        static_cast<views::Widget*>(LockScreen::Get()->window()));
+    node_data->AddIntAttribute(ui::AX_ATTR_PREVIOUS_FOCUS_ID, previous_id);
+  }
+
+  Shelf* shelf = Shelf::ForWindow(GetWidget()->GetNativeWindow());
+  int next_id =
+      views::AXAuraObjCache::GetInstance()->GetID(shelf->GetStatusAreaWidget());
+  node_data->AddIntAttribute(ui::AX_ATTR_NEXT_FOCUS_ID, next_id);
+}
+
 void LoginShelfView::ButtonPressed(views::Button* sender,
                                    const ui::Event& event) {
   UserMetricsRecorder::RecordUserClick(GetUserClickTarget(sender->id()));
diff --git a/ash/shelf/login_shelf_view.h b/ash/shelf/login_shelf_view.h
index 1fa6268..203150cd 100644
--- a/ash/shelf/login_shelf_view.h
+++ b/ash/shelf/login_shelf_view.h
@@ -55,6 +55,7 @@
   const char* GetClassName() const override;
   void OnFocus() override;
   void AboutToRequestFocusFromTabTraversal(bool reverse) override;
+  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
 
   // views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index 9019a482..5ef28f1 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -1950,16 +1950,18 @@
   shelf_->NotifyShelfIconPositionsChanged();
   PreferredSizeChanged();
 
-  float opacity = 0.f;
-  const gfx::SlideAnimation* animation =
-      bounds_animator_->GetAnimationForView(GetBackButton());
-  if (animation)
-    opacity = static_cast<float>(animation->GetCurrentValue());
-  if (!IsTabletModeEnabled())
-    opacity = 1.f - opacity;
+  if (shelf_->is_tablet_mode_animation_running()) {
+    float opacity = 0.f;
+    const gfx::SlideAnimation* animation =
+        bounds_animator_->GetAnimationForView(GetBackButton());
+    if (animation)
+      opacity = static_cast<float>(animation->GetCurrentValue());
+    if (!IsTabletModeEnabled())
+      opacity = 1.f - opacity;
 
-  GetBackButton()->layer()->SetOpacity(opacity);
-  GetBackButton()->SetFocusBehavior(FocusBehavior::ALWAYS);
+    GetBackButton()->layer()->SetOpacity(opacity);
+    GetBackButton()->SetFocusBehavior(FocusBehavior::ALWAYS);
+  }
 }
 
 void ShelfView::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
diff --git a/ash/system/palette/palette_welcome_bubble.cc b/ash/system/palette/palette_welcome_bubble.cc
index 9fa03a3..b143f2e5 100644
--- a/ash/system/palette/palette_welcome_bubble.cc
+++ b/ash/system/palette/palette_welcome_bubble.cc
@@ -6,7 +6,6 @@
 
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/cpp/shell_window_ids.h"
-#include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/session/session_controller.h"
 #include "ash/shell.h"
 #include "ash/shell_port.h"
@@ -16,12 +15,9 @@
 #include "components/prefs/pref_service.h"
 #include "ui/aura/window.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/font.h"
-#include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/bubble/bubble_dialog_delegate.h"
-#include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
 
 namespace ash {
 
@@ -32,11 +28,9 @@
 
 }  // namespace
 
-// View which contains two text (one title) and a close button for closing the
-// bubble. Controlled by PaletteWelcomeBubble and anchored to a PaletteTray.
+// Controlled by PaletteWelcomeBubble and anchored to a PaletteTray.
 class PaletteWelcomeBubble::WelcomeBubbleView
-    : public views::BubbleDialogDelegateView,
-      public views::ButtonListener {
+    : public views::BubbleDialogDelegateView {
  public:
   WelcomeBubbleView(views::View* anchor, views::BubbleBorder::Arrow arrow)
       : views::BubbleDialogDelegateView(anchor, arrow) {
@@ -46,63 +40,33 @@
     set_parent_window(
         anchor_widget()->GetNativeWindow()->GetRootWindow()->GetChildById(
             kShellWindowId_SettingBubbleContainer));
-    SetLayoutManager(
-        std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
-
-    // Add the header which contains the title and close button.
-    auto* header = new views::View();
-    auto box_layout =
-        std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal);
-    auto* layout_ptr = header->SetLayoutManager(std::move(box_layout));
-    AddChildView(header);
-
-    // Add the title, which is bolded.
-    auto* title = new views::Label(
-        l10n_util::GetStringUTF16(IDS_ASH_STYLUS_WARM_WELCOME_BUBBLE_TITLE));
-    title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    title->SetFontList(views::Label::GetDefaultFontList().Derive(
-        0, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::BOLD));
-    header->AddChildView(title);
-    layout_ptr->SetFlexForView(title, 1);
-
-    // Add a button to close the bubble.
-    close_button_ = new views::ImageButton(this);
-    close_button_->SetImage(
-        views::Button::STATE_NORMAL,
-        gfx::CreateVectorIcon(kWindowControlCloseIcon, SK_ColorBLACK));
-    header->AddChildView(close_button_);
-
-    auto* content = new views::Label(l10n_util::GetStringUTF16(
-        IDS_ASH_STYLUS_WARM_WELCOME_BUBBLE_DESCRIPTION));
-    content->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    content->SetMultiLine(true);
-    content->SizeToFit(kBubbleContentLabelPreferredWidthDp);
-    AddChildView(content);
-
     views::BubbleDialogDelegateView::CreateBubble(this);
   }
 
   ~WelcomeBubbleView() override = default;
 
-  views::ImageButton* close_button() { return close_button_; }
-
   // ui::BubbleDialogDelegateView:
+  base::string16 GetWindowTitle() const override {
+    return l10n_util::GetStringUTF16(IDS_ASH_STYLUS_WARM_WELCOME_BUBBLE_TITLE);
+  }
+
+  bool ShouldShowWindowTitle() const override { return true; }
+
+  bool ShouldShowCloseButton() const override { return true; }
+
+  void Init() override {
+    SetLayoutManager(std::make_unique<views::FillLayout>());
+    auto* label = new views::Label(l10n_util::GetStringUTF16(
+        IDS_ASH_STYLUS_WARM_WELCOME_BUBBLE_DESCRIPTION));
+    label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+    label->SetMultiLine(true);
+    label->SizeToFit(kBubbleContentLabelPreferredWidthDp);
+    AddChildView(label);
+  }
+
   int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; }
 
-  // views::ButtonListener:
-  void ButtonPressed(views::Button* sender, const ui::Event& event) override {
-    if (sender == close_button_)
-      GetWidget()->Close();
-  }
-
-  // views::View:
-  gfx::Size CalculatePreferredSize() const override {
-    return BubbleDialogDelegateView::CalculatePreferredSize();
-  }
-
  private:
-  views::ImageButton* close_button_ = nullptr;
-
   DISALLOW_COPY_AND_ASSIGN(WelcomeBubbleView);
 };
 
@@ -161,13 +125,6 @@
                                         true);
 }
 
-views::ImageButton* PaletteWelcomeBubble::GetCloseButtonForTest() {
-  if (bubble_view_)
-    return bubble_view_->close_button();
-
-  return nullptr;
-}
-
 base::Optional<gfx::Rect> PaletteWelcomeBubble::GetBubbleBoundsForTest() {
   if (bubble_view_)
     return base::make_optional(bubble_view_->GetBoundsInScreen());
diff --git a/ash/system/palette/palette_welcome_bubble.h b/ash/system/palette/palette_welcome_bubble.h
index 27ea46f..d34024e5 100644
--- a/ash/system/palette/palette_welcome_bubble.h
+++ b/ash/system/palette/palette_welcome_bubble.h
@@ -16,7 +16,6 @@
 class PrefService;
 
 namespace views {
-class ImageButton;
 class Widget;
 }  // namespace views
 
@@ -52,9 +51,6 @@
   // views::WidgetObserver:
   void OnWidgetClosing(views::Widget* widget) override;
 
-  // Returns the close button on the bubble if it exists.
-  views::ImageButton* GetCloseButtonForTest();
-
   // Returns the bounds of the bubble view if it exists.
   base::Optional<gfx::Rect> GetBubbleBoundsForTest();
 
diff --git a/ash/system/palette/palette_welcome_bubble_unittest.cc b/ash/system/palette/palette_welcome_bubble_unittest.cc
index d37ef995..c37c871 100644
--- a/ash/system/palette/palette_welcome_bubble_unittest.cc
+++ b/ash/system/palette/palette_welcome_bubble_unittest.cc
@@ -96,20 +96,6 @@
   EXPECT_FALSE(welcome_bubble_->bubble_shown());
 }
 
-// Verify that tapping the close button on the welcome bubble closes the bubble.
-TEST_F(PaletteWelcomeBubbleTest, CloseButton) {
-  ShowBubble();
-  ASSERT_TRUE(welcome_bubble_->bubble_shown());
-  ASSERT_TRUE(welcome_bubble_->GetCloseButtonForTest());
-
-  GetEventGenerator().set_current_location(
-      welcome_bubble_->GetCloseButtonForTest()
-          ->GetBoundsInScreen()
-          .CenterPoint());
-  GetEventGenerator().ClickLeftButton();
-  EXPECT_FALSE(welcome_bubble_->bubble_shown());
-}
-
 // Verify that tapping on the screen outside of the welcome bubble closes the
 // bubble.
 TEST_F(PaletteWelcomeBubbleTest, TapOutsideOfBubble) {
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc
index db9c6ea..f0eddd99 100644
--- a/ash/system/tray/tray_background_view.cc
+++ b/ash/system/tray/tray_background_view.cc
@@ -9,6 +9,8 @@
 
 #include "ash/ash_constants.h"
 #include "ash/focus_cycler.h"
+#include "ash/login/ui/lock_screen.h"
+#include "ash/login/ui/lock_window.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_constants.h"
@@ -31,6 +33,7 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/gfx/transform.h"
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
 #include "ui/views/animation/flood_fill_ink_drop_ripple.h"
 #include "ui/views/animation/ink_drop_highlight.h"
 #include "ui/views/animation/ink_drop_mask.h"
@@ -291,6 +294,17 @@
 void TrayBackgroundView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   ActionableView::GetAccessibleNodeData(node_data);
   node_data->SetName(GetAccessibleNameForTray());
+
+  if (LockScreen::IsShown()) {
+    int next_id = views::AXAuraObjCache::GetInstance()->GetID(
+        static_cast<views::Widget*>(LockScreen::Get()->window()));
+    node_data->AddIntAttribute(ui::AX_ATTR_NEXT_FOCUS_ID, next_id);
+  }
+
+  Shelf* shelf = Shelf::ForWindow(GetWidget()->GetNativeWindow());
+  ShelfWidget* shelf_widget = shelf->shelf_widget();
+  int previous_id = views::AXAuraObjCache::GetInstance()->GetID(shelf_widget);
+  node_data->AddIntAttribute(ui::AX_ATTR_PREVIOUS_FOCUS_ID, previous_id);
 }
 
 void TrayBackgroundView::ChildPreferredSizeChanged(views::View* child) {
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc
index 67788ca..d658447 100644
--- a/ash/wallpaper/wallpaper_controller.cc
+++ b/ash/wallpaper/wallpaper_controller.cc
@@ -5,6 +5,7 @@
 #include "ash/wallpaper/wallpaper_controller.h"
 
 #include <memory>
+#include <numeric>
 #include <string>
 #include <utility>
 
@@ -295,6 +296,9 @@
 const char WallpaperController::kOriginalWallpaperSubDir[] = "original";
 const char WallpaperController::kThumbnailWallpaperSubDir[] = "thumb";
 
+const char WallpaperController::kSmallWallpaperSuffix[] = "_small";
+const char WallpaperController::kLargeWallpaperSuffix[] = "_large";
+
 const int WallpaperController::kSmallWallpaperMaxWidth = 1366;
 const int WallpaperController::kSmallWallpaperMaxHeight = 800;
 const int WallpaperController::kLargeWallpaperMaxWidth = 2560;
@@ -305,15 +309,6 @@
 
 const SkColor WallpaperController::kDefaultWallpaperColor = SK_ColorGRAY;
 
-WallpaperController::MovableOnDestroyCallback::MovableOnDestroyCallback(
-    const base::Closure& callback)
-    : callback_(callback) {}
-
-WallpaperController::MovableOnDestroyCallback::~MovableOnDestroyCallback() {
-  if (!callback_.is_null())
-    callback_.Run();
-}
-
 WallpaperController::WallpaperController()
     : locked_(false),
       wallpaper_mode_(WALLPAPER_NONE),
@@ -387,6 +382,14 @@
 }
 
 // static
+std::string
+WallpaperController::GetCustomWallpaperSubdirForCurrentResolution() {
+  WallpaperResolution resolution = GetAppropriateResolution();
+  return resolution == WALLPAPER_RESOLUTION_SMALL ? kSmallWallpaperSubDir
+                                                  : kLargeWallpaperSubDir;
+}
+
+// static
 base::FilePath WallpaperController::GetCustomWallpaperPath(
     const std::string& sub_dir,
     const std::string& wallpaper_files_id,
@@ -403,6 +406,17 @@
 }
 
 // static
+base::FilePath WallpaperController::GetDeviceWallpaperDir() {
+  DCHECK(!dir_chrome_os_wallpapers_path_.empty());
+  return dir_chrome_os_wallpapers_path_.Append(kDeviceWallpaperDir);
+}
+
+// static
+base::FilePath WallpaperController::GetDeviceWallpaperFilePath() {
+  return GetDeviceWallpaperDir().Append(kDeviceWallpaperFile);
+}
+
+// static
 bool WallpaperController::ResizeImage(
     const gfx::ImageSkia& image,
     wallpaper::WallpaperLayout layout,
@@ -479,6 +493,38 @@
 }
 
 // static
+void WallpaperController::SetWallpaperFromPath(
+    const AccountId& account_id,
+    const user_manager::UserType& user_type,
+    const wallpaper::WallpaperInfo& info,
+    const base::FilePath& wallpaper_path,
+    bool show_wallpaper,
+    const scoped_refptr<base::SingleThreadTaskRunner>& reply_task_runner,
+    base::WeakPtr<WallpaperController> weak_ptr) {
+  base::FilePath valid_path = wallpaper_path;
+  if (!base::PathExists(valid_path)) {
+    // Falls back to the original file if the file with correct resolution does
+    // not exist. This may happen when the original custom wallpaper is small or
+    // browser shutdown before resized wallpaper saved.
+    valid_path =
+        GetCustomWallpaperDir(kOriginalWallpaperSubDir).Append(info.location);
+  }
+
+  if (!base::PathExists(valid_path)) {
+    LOG(ERROR) << "The path " << valid_path.value()
+               << " doesn't exist. Falls back to default wallpaper.";
+    reply_task_runner->PostTask(
+        FROM_HERE, base::Bind(&WallpaperController::SetDefaultWallpaperImpl,
+                              weak_ptr, account_id, user_type, show_wallpaper));
+  } else {
+    reply_task_runner->PostTask(
+        FROM_HERE,
+        base::Bind(&WallpaperController::StartDecodeFromPath, weak_ptr,
+                   account_id, user_type, valid_path, info, show_wallpaper));
+  }
+}
+
+// static
 void WallpaperController::DecodeWallpaperIfApplicable(
     LoadedCallback callback,
     std::unique_ptr<std::string> data,
@@ -496,19 +542,6 @@
 }
 
 // static
-void WallpaperController::ReadAndDecodeWallpaper(
-    LoadedCallback callback,
-    scoped_refptr<base::SequencedTaskRunner> task_runner,
-    const base::FilePath& file_path) {
-  std::string* data = new std::string;
-  base::PostTaskAndReplyWithResult(
-      task_runner.get(), FROM_HERE,
-      base::Bind(&base::ReadFileToString, file_path, data),
-      base::Bind(&DecodeWallpaperIfApplicable, std::move(callback),
-                 base::Passed(base::WrapUnique(data))));
-}
-
-// static
 gfx::ImageSkia WallpaperController::CreateSolidColorWallpaper() {
   SkBitmap bitmap;
   bitmap.allocN32Pixels(1, 1);
@@ -602,8 +635,7 @@
 void WallpaperController::SetDefaultWallpaperImpl(
     const AccountId& account_id,
     const user_manager::UserType& user_type,
-    bool show_wallpaper,
-    MovableOnDestroyCallbackHolder on_finish) {
+    bool show_wallpaper) {
   // There is no visible wallpaper in kiosk mode.
   if (IsInKioskMode())
     return;
@@ -649,19 +681,17 @@
   // We need to decode the image if the cached default wallpaper doesn't exist,
   // or if the two file paths don't match; otherwise, directly run the callback
   // with the cached decoded image.
-  if (!default_wallpaper_image_.get() ||
-      default_wallpaper_image_->file_path() != file_path) {
+  if (default_wallpaper_image_.get() &&
+      default_wallpaper_image_->file_path() == file_path) {
+    OnDefaultWallpaperDecoded(file_path, layout, show_wallpaper,
+                              std::move(default_wallpaper_image_));
+  } else {
     default_wallpaper_image_.reset();
     ReadAndDecodeWallpaper(
         base::Bind(&WallpaperController::OnDefaultWallpaperDecoded,
                    weak_factory_.GetWeakPtr(), file_path, layout,
-                   show_wallpaper, base::Passed(std::move(on_finish))),
+                   show_wallpaper),
         sequenced_task_runner_, file_path);
-    num_decode_request_for_testing_++;
-  } else {
-    OnDefaultWallpaperDecoded(file_path, layout, show_wallpaper,
-                              std::move(on_finish),
-                              std::move(default_wallpaper_image_));
   }
 }
 
@@ -704,7 +734,7 @@
   // TODO(crbug.com/776464): Find a way to directly set wallpaper from here, or
   // combine this with |SetDefaultWallpaperImpl| since there's duplicate code.
   SetDefaultWallpaperImpl(EmptyAccountId(), user_manager::USER_TYPE_REGULAR,
-                          show_wallpaper, MovableOnDestroyCallbackHolder());
+                          show_wallpaper);
 }
 
 void WallpaperController::SetWallpaperImage(const gfx::ImageSkia& image,
@@ -859,6 +889,19 @@
          current_wallpaper_->original_image_id();
 }
 
+void WallpaperController::ReadAndDecodeWallpaper(
+    LoadedCallback callback,
+    scoped_refptr<base::SequencedTaskRunner> task_runner,
+    const base::FilePath& file_path) {
+  decode_requests_for_testing_.push_back(file_path);
+  std::string* data = new std::string;
+  base::PostTaskAndReplyWithResult(
+      task_runner.get(), FROM_HERE,
+      base::Bind(&base::ReadFileToString, file_path, data),
+      base::Bind(&DecodeWallpaperIfApplicable, std::move(callback),
+                 base::Passed(base::WrapUnique(data))));
+}
+
 void WallpaperController::OpenSetWallpaperPage() {
   if (wallpaper_controller_client_ &&
       Shell::Get()->wallpaper_delegate()->CanOpenSetWallpaperPage()) {
@@ -1020,6 +1063,12 @@
   return &wallpaper_cache_map_;
 }
 
+AccountId WallpaperController::GetCurrentUserAccountId() {
+  if (current_user_)
+    return current_user_->account_id;
+  return EmptyAccountId();
+}
+
 void WallpaperController::SetClientAndPaths(
     mojom::WallpaperControllerClientPtr client,
     const base::FilePath& user_data_path,
@@ -1045,8 +1094,9 @@
   // removed, and only a single |CanSetUserWallpaper| check is needed here.
   if ((type != wallpaper::POLICY &&
        IsPolicyControlled(user_info->account_id, !user_info->is_ephemeral)) ||
-      IsInKioskMode())
+      IsInKioskMode()) {
     return;
+  }
 
   SaveAndSetWallpaper(std::move(user_info), wallpaper_files_id, file_name,
                       gfx::ImageSkia::CreateFrom1xBitmap(image), type, layout,
@@ -1064,20 +1114,24 @@
   if (!CanSetUserWallpaper(user_info->account_id, !user_info->is_ephemeral))
     return;
 
+  gfx::ImageSkia online_wallpaper = gfx::ImageSkia::CreateFrom1xBitmap(image);
+  if (online_wallpaper.isNull()) {
+    SetDefaultWallpaperImpl(user_info->account_id, user_info->type,
+                            show_wallpaper);
+    return;
+  }
+
   WallpaperInfo info = {url, layout, wallpaper::ONLINE,
                         base::Time::Now().LocalMidnight()};
   SetUserWallpaperInfo(user_info->account_id, info, !user_info->is_ephemeral);
-
-  if (show_wallpaper) {
-    // TODO(crbug.com/776464): This should ideally go through PendingWallpaper.
-    SetWallpaper(image, info);
-  }
+  if (show_wallpaper)
+    SetWallpaperImage(online_wallpaper, info);
 
   // Leave the file path empty, because in most cases the file path is not used
   // when fetching cache, but in case it needs to be checked, we should avoid
   // confusing the URL with a real file path.
-  wallpaper_cache_map_[user_info->account_id] = CustomWallpaperElement(
-      base::FilePath(), gfx::ImageSkia::CreateFrom1xBitmap(image));
+  wallpaper_cache_map_[user_info->account_id] =
+      CustomWallpaperElement(base::FilePath(), online_wallpaper);
 }
 
 void WallpaperController::SetDefaultWallpaper(
@@ -1094,10 +1148,7 @@
   RemoveUserWallpaper(std::move(user_info), wallpaper_files_id);
   InitializeUserWallpaperInfo(account_id, is_persistent);
   if (show_wallpaper) {
-    // TODO(crbug.com/776464): This should ideally go through PendingWallpaper.
-    // The callback is specific to PendingWallpaper and is left empty for now.
-    SetDefaultWallpaperImpl(account_id, type, true /*show_wallpaper=*/,
-                            MovableOnDestroyCallbackHolder());
+    SetDefaultWallpaperImpl(account_id, type, true /*show_wallpaper=*/);
   }
 }
 
@@ -1126,14 +1177,89 @@
 
 void WallpaperController::ShowUserWallpaper(
     mojom::WallpaperUserInfoPtr user_info) {
-  NOTIMPLEMENTED();
+  // Guest user or regular user in ephemeral mode.
+  // TODO(wzang/xdai): Check if the wallpaper info for ephemeral users should
+  // be saved to local state.
+  if ((user_info->is_ephemeral && user_info->has_gaia_account) ||
+      user_info->type == user_manager::USER_TYPE_GUEST) {
+    InitializeUserWallpaperInfo(user_info->account_id,
+                                !user_info->is_ephemeral);
+    SetDefaultWallpaperImpl(user_info->account_id, user_info->type,
+                            true /*show_wallpaper=*/);
+    LOG(ERROR) << "User is ephemeral or guest! Fallback to default wallpaper.";
+    return;
+  }
+
+  current_user_ = std::move(user_info);
+  const AccountId account_id = current_user_->account_id;
+  const bool is_persistent = !current_user_->is_ephemeral;
+  WallpaperInfo info;
+  if (!GetUserWallpaperInfo(account_id, &info, is_persistent)) {
+    InitializeUserWallpaperInfo(account_id, is_persistent);
+    GetUserWallpaperInfo(account_id, &info, is_persistent);
+  }
+  current_user_wallpaper_info_ = info;
+
+  gfx::ImageSkia user_wallpaper;
+  if (GetWallpaperFromCache(account_id, &user_wallpaper)) {
+    SetWallpaperImage(user_wallpaper, info);
+    return;
+  }
+
+  if (info.location.empty()) {
+    // Uses default built-in wallpaper when file is empty. Eventually, we
+    // will only ship one built-in wallpaper in ChromeOS image.
+    SetDefaultWallpaperImpl(account_id, current_user_->type,
+                            true /*show_wallpaper=*/);
+    return;
+  }
+
+  if (info.type != wallpaper::CUSTOMIZED && info.type != wallpaper::POLICY &&
+      info.type != wallpaper::DEVICE) {
+    // Load wallpaper according to WallpaperInfo.
+    SetWallpaperFromInfo(account_id, current_user_->type, info,
+                         true /*show_wallpaper=*/);
+    return;
+  }
+
+  base::FilePath wallpaper_path;
+  if (info.type == wallpaper::DEVICE) {
+    wallpaper_path = GetDeviceWallpaperFilePath();
+  } else {
+    std::string sub_dir = GetCustomWallpaperSubdirForCurrentResolution();
+    // Wallpaper is not resized when layout is
+    // wallpaper::WALLPAPER_LAYOUT_CENTER.
+    // Original wallpaper should be used in this case.
+    // TODO(bshe): Generates cropped custom wallpaper for CENTER layout.
+    if (info.layout == wallpaper::WALLPAPER_LAYOUT_CENTER)
+      sub_dir = kOriginalWallpaperSubDir;
+    wallpaper_path = GetCustomWallpaperDir(sub_dir);
+    wallpaper_path = wallpaper_path.Append(info.location);
+  }
+
+  CustomWallpaperMap::iterator it = wallpaper_cache_map_.find(account_id);
+  // Do not try to load the wallpaper if the path is the same, since loading
+  // could still be in progress. We ignore the existence of the image.
+  if (it != wallpaper_cache_map_.end() && it->second.first == wallpaper_path)
+    return;
+
+  // Set the new path and reset the existing image - the image will be
+  // added once it becomes available.
+  wallpaper_cache_map_[account_id] =
+      CustomWallpaperElement(wallpaper_path, gfx::ImageSkia());
+
+  sequenced_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&WallpaperController::SetWallpaperFromPath,
+                                account_id, current_user_->type, info,
+                                wallpaper_path, true /*show_wallpaper=*/,
+                                base::ThreadTaskRunnerHandle::Get(),
+                                weak_factory_.GetWeakPtr()));
 }
 
 void WallpaperController::ShowSigninWallpaper() {
   // TODO(crbug.com/791654): Call |SetDeviceWallpaperIfApplicable| from here.
   SetDefaultWallpaperImpl(EmptyAccountId(), user_manager::USER_TYPE_REGULAR,
-                          true /*show_wallpaper=*/,
-                          MovableOnDestroyCallbackHolder());
+                          true /*show_wallpaper=*/);
 }
 
 void WallpaperController::RemoveUserWallpaper(
@@ -1342,13 +1468,80 @@
                            base::Bind(&DeleteWallpaperInList, file_to_remove));
 }
 
+void WallpaperController::SetWallpaperFromInfo(
+    const AccountId& account_id,
+    const user_manager::UserType& user_type,
+    const WallpaperInfo& info,
+    bool show_wallpaper) {
+  if (info.type != wallpaper::ONLINE && info.type != wallpaper::DEFAULT) {
+    // This method is meant to be used for ONLINE and DEFAULT types. In
+    // unexpected cases, revert to default wallpaper to fail safely. See
+    // crosbug.com/38429.
+    LOG(ERROR) << "Wallpaper reverts to default unexpected.";
+    SetDefaultWallpaperImpl(account_id, user_type, show_wallpaper);
+    return;
+  }
+
+  // Do a sanity check that the file path is not empty.
+  if (info.location.empty()) {
+    // File name might be empty on debug configurations when stub users
+    // were created directly in local state (for testing). Ignore such
+    // errors i.e. allow such type of debug configurations on the desktop.
+    LOG(WARNING) << "User wallpaper info is empty: " << account_id.Serialize();
+    SetDefaultWallpaperImpl(account_id, user_type, show_wallpaper);
+    return;
+  }
+
+  base::FilePath wallpaper_path;
+  if (info.type == wallpaper::ONLINE) {
+    std::string file_name = GURL(info.location).ExtractFileName();
+    WallpaperResolution resolution = GetAppropriateResolution();
+    // Only solid color wallpapers have stretch layout and they have only
+    // one resolution.
+    if (info.layout != wallpaper::WALLPAPER_LAYOUT_STRETCH &&
+        resolution == WALLPAPER_RESOLUTION_SMALL) {
+      file_name = base::FilePath(file_name)
+                      .InsertBeforeExtension(kSmallWallpaperSuffix)
+                      .value();
+    }
+    DCHECK(!dir_chrome_os_wallpapers_path_.empty());
+    wallpaper_path = dir_chrome_os_wallpapers_path_.Append(file_name);
+
+    // If the wallpaper exists and it already contains the correct image we
+    // can return immediately.
+    CustomWallpaperMap::iterator it = wallpaper_cache_map_.find(account_id);
+    if (it != wallpaper_cache_map_.end() &&
+        it->second.first == wallpaper_path && !it->second.second.isNull())
+      return;
+
+    ReadAndDecodeWallpaper(
+        base::Bind(&WallpaperController::OnWallpaperDecoded,
+                   weak_factory_.GetWeakPtr(), account_id, user_type,
+                   wallpaper_path, info, show_wallpaper),
+        sequenced_task_runner_, wallpaper_path);
+  } else {
+    // TODO(crbug.com/776464): Remove this branch after refactoring.
+    // Default wallpapers are migrated from M21 user profiles. A code
+    // refactor overlooked that case and caused these wallpapers not being
+    // loaded at all. On some slow devices, it caused login webui not
+    // visible after upgrade to M26 from M21. See crosbug.com/38429 for
+    // details.
+    DCHECK(!dir_user_data_path_.empty());
+    wallpaper_path = dir_user_data_path_.Append(info.location);
+
+    ReadAndDecodeWallpaper(
+        base::Bind(&WallpaperController::OnWallpaperDecoded,
+                   weak_factory_.GetWeakPtr(), account_id, user_type,
+                   wallpaper_path, info, show_wallpaper),
+        sequenced_task_runner_, wallpaper_path);
+  }
+}
+
 void WallpaperController::OnDefaultWallpaperDecoded(
     const base::FilePath& path,
     wallpaper::WallpaperLayout layout,
     bool show_wallpaper,
-    MovableOnDestroyCallbackHolder on_finish,
     std::unique_ptr<user_manager::UserImage> user_image) {
-  wallpaper_file_path_for_testing_ = path;
   if (user_image->image().isNull()) {
     // Create a solid color wallpaper if the default wallpaper decoding fails.
     default_wallpaper_image_.reset(
@@ -1384,7 +1577,7 @@
   // Empty image indicates decode failure. Use default wallpaper in this case.
   if (image.isNull()) {
     SetDefaultWallpaperImpl(user_info->account_id, user_info->type,
-                            show_wallpaper, MovableOnDestroyCallbackHolder());
+                            show_wallpaper);
     return;
   }
 
@@ -1416,7 +1609,7 @@
   const std::string relative_path =
       base::FilePath(wallpaper_files_id).Append(file_name).value();
   // User's custom wallpaper path is determined by relative path and the
-  // appropriate wallpaper resolution in GetCustomWallpaperInternal.
+  // appropriate wallpaper resolution.
   WallpaperInfo info = {relative_path, layout, type,
                         base::Time::Now().LocalMidnight()};
   SetUserWallpaperInfo(user_info->account_id, info, !user_info->is_ephemeral);
@@ -1427,6 +1620,40 @@
       CustomWallpaperElement(wallpaper_path, image);
 }
 
+void WallpaperController::StartDecodeFromPath(
+    const AccountId& account_id,
+    const user_manager::UserType& user_type,
+    const base::FilePath& wallpaper_path,
+    const wallpaper::WallpaperInfo& info,
+    bool show_wallpaper) {
+  ReadAndDecodeWallpaper(
+      base::Bind(&WallpaperController::OnWallpaperDecoded,
+                 weak_factory_.GetWeakPtr(), account_id, user_type,
+                 wallpaper_path, info, show_wallpaper),
+      sequenced_task_runner_, wallpaper_path);
+}
+
+void WallpaperController::OnWallpaperDecoded(
+    const AccountId& account_id,
+    const user_manager::UserType& user_type,
+    const base::FilePath& path,
+    const wallpaper::WallpaperInfo& info,
+    bool show_wallpaper,
+    std::unique_ptr<user_manager::UserImage> user_image) {
+  // Empty image indicates decode failure. Use default wallpaper in this case.
+  if (user_image->image().isNull()) {
+    LOG(ERROR) << "Failed to decode user wallpaper at " << path.value()
+               << "Falls back to default wallpaper. ";
+    SetDefaultWallpaperImpl(account_id, user_type, show_wallpaper);
+    return;
+  }
+
+  wallpaper_cache_map_[account_id] =
+      CustomWallpaperElement(path, user_image->image());
+  if (show_wallpaper)
+    SetWallpaperImage(user_image->image(), info);
+}
+
 void WallpaperController::SetProminentColors(
     const std::vector<SkColor>& colors) {
   if (prominent_colors_ == colors)
@@ -1539,8 +1766,7 @@
     // If device policy wallpaper failed decoding, fall back to the default
     // wallpaper.
     SetDefaultWallpaperImpl(EmptyAccountId(), user_manager::USER_TYPE_REGULAR,
-                            true /*show_wallpaper=*/,
-                            MovableOnDestroyCallbackHolder());
+                            true /*show_wallpaper=*/);
   } else {
     WallpaperInfo info(GetDevicePolicyWallpaperFilePath().value(),
                        wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h
index 0ffc5324..175716b 100644
--- a/ash/wallpaper/wallpaper_controller.h
+++ b/ash/wallpaper/wallpaper_controller.h
@@ -99,6 +99,10 @@
   static const char kOriginalWallpaperSubDir[];
   static const char kThumbnailWallpaperSubDir[];
 
+  // File path suffices of resized small or large wallpaper.
+  static const char kSmallWallpaperSuffix[];
+  static const char kLargeWallpaperSuffix[];
+
   // The width and height of small/large resolution wallpaper. When screen size
   // is smaller than |kSmallWallpaperMaxWidth| and |kSmallWallpaperMaxHeight|,
   // the small resolution wallpaper should be used. Otherwise, use the large
@@ -115,24 +119,6 @@
   // The color of the wallpaper if no other wallpaper images are available.
   static const SkColor kDefaultWallpaperColor;
 
-  // This object is passed between several threads while wallpaper is being
-  // loaded. It will notify callback when last reference to it is removed
-  // (thus indicating that the last load action has finished).
-  class MovableOnDestroyCallback {
-   public:
-    explicit MovableOnDestroyCallback(const base::Closure& callback);
-
-    ~MovableOnDestroyCallback();
-
-   private:
-    base::Closure callback_;
-
-    DISALLOW_COPY_AND_ASSIGN(MovableOnDestroyCallback);
-  };
-
-  using MovableOnDestroyCallbackHolder =
-      std::unique_ptr<MovableOnDestroyCallback>;
-
   WallpaperController();
   ~WallpaperController() override;
 
@@ -147,6 +133,9 @@
   // Returns the appropriate wallpaper resolution for all root windows.
   static WallpaperResolution GetAppropriateResolution();
 
+  // Returns wallpaper subdirectory name for current resolution.
+  static std::string GetCustomWallpaperSubdirForCurrentResolution();
+
   // Returns custom wallpaper path. Appends |sub_dir|, |wallpaper_files_id| and
   // |file_name| to custom wallpaper directory.
   static base::FilePath GetCustomWallpaperPath(
@@ -178,8 +167,26 @@
                                      int preferred_height,
                                      gfx::ImageSkia* output_skia);
 
-  // TODO(crbug.com/776464): Move |DecodeWallpaperIfApplicable| and
-  // |ReadAndDecodeWallpaper| to a separate utility file.
+  // TODO(crbug.com/776464): These utility functions for device policy wallpaper
+  // are temporary during the refactoring.
+  // Returns the file directory where the downloaded device wallpaper is saved.
+  static base::FilePath GetDeviceWallpaperDir();
+
+  // Returns the full path for the downloaded device wallpaper.
+  static base::FilePath GetDeviceWallpaperFilePath();
+
+  // Gets |account_id|'s custom wallpaper at |wallpaper_path|. Falls back to the
+  // original custom wallpaper. When |show_wallpaper| is true, shows the
+  // wallpaper immediately. Must run on wallpaper sequenced worker thread.
+  static void SetWallpaperFromPath(
+      const AccountId& account_id,
+      const user_manager::UserType& user_type,
+      const wallpaper::WallpaperInfo& info,
+      const base::FilePath& wallpaper_path,
+      bool show_wallpaper,
+      const scoped_refptr<base::SingleThreadTaskRunner>& reply_task_runner,
+      base::WeakPtr<WallpaperController> weak_ptr);
+
   // If |data_is_ready| is true, start decoding the image, which will run
   // |callback| upon completion; if it's false, run |callback| immediately with
   // an empty image.
@@ -190,13 +197,6 @@
                                           std::unique_ptr<std::string> data,
                                           bool data_is_ready);
 
-  // Reads image from |file_path| on disk, and calls
-  // |DecodeWallpaperIfApplicable| with the result of |ReadFileToString|.
-  static void ReadAndDecodeWallpaper(
-      LoadedCallback callback,
-      scoped_refptr<base::SequencedTaskRunner> task_runner,
-      const base::FilePath& file_path);
-
   // Creates a 1x1 solid color image to be used as the backup default wallpaper.
   static gfx::ImageSkia CreateSolidColorWallpaper();
 
@@ -247,8 +247,7 @@
   // request; may be different from the active user.
   void SetDefaultWallpaperImpl(const AccountId& account_id,
                                const user_manager::UserType& user_type,
-                               bool show_wallpaper,
-                               MovableOnDestroyCallbackHolder on_finish);
+                               bool show_wallpaper);
 
   // Implementation of |SetCustomizedDefaultWallpaper|. Sets
   // |default_wallpaper_image_| either to |small_wallpaper_image| or
@@ -291,13 +290,19 @@
   // SessionObserver:
   void OnSessionStateChanged(session_manager::SessionState state) override;
 
-  // Returns true if the specified wallpaper is already stored
-  // in |current_wallpaper_|.
-  // If |compare_layouts| is false, layout is ignored.
+  // Returns true if the specified wallpaper is already stored in
+  // |current_wallpaper_|. If |compare_layouts| is false, layout is ignored.
   bool WallpaperIsAlreadyLoaded(const gfx::ImageSkia& image,
                                 bool compare_layouts,
                                 wallpaper::WallpaperLayout layout) const;
 
+  // Reads image from |file_path| on disk, and calls
+  // |DecodeWallpaperIfApplicable| with the result of |ReadFileToString|.
+  void ReadAndDecodeWallpaper(
+      LoadedCallback callback,
+      scoped_refptr<base::SequencedTaskRunner> task_runner,
+      const base::FilePath& file_path);
+
   void set_wallpaper_reload_delay_for_test(int value) {
     wallpaper_reload_delay_ = value;
   }
@@ -364,9 +369,10 @@
   // Returns the pointer of |wallpaper_cache_map_|.
   CustomWallpaperMap* GetWallpaperCacheMap();
 
-  int num_decode_request_for_testing() {
-    return num_decode_request_for_testing_;
-  }
+  // TODO(crbug.com/776464): Remove this after WallpaperManager is removed.
+  // Returns the account id of |current_user_|, or an empty account id if
+  // |current_user_| is null.
+  AccountId GetCurrentUserAccountId();
 
   // mojom::WallpaperController overrides:
   void SetClientAndPaths(
@@ -394,6 +400,10 @@
       const base::FilePath& file_path,
       const base::FilePath& resized_directory) override;
   void SetDeviceWallpaperPolicyEnforced(bool enforced) override;
+  // TODO(crbug.com/776464): |ShowUserWallpaper| is incomplete until device
+  // policy wallpaper is migrated. Callers from chrome should use
+  // |WallpaperManager::ShowUserWallpaper| instead. Callers in ash can't use it
+  // for now.
   void ShowUserWallpaper(mojom::WallpaperUserInfoPtr user_info) override;
   void ShowSigninWallpaper() override;
   void RemoveUserWallpaper(mojom::WallpaperUserInfoPtr user_info,
@@ -453,13 +463,20 @@
   void RemoveUserWallpaperImpl(const AccountId& account_id,
                                const std::string& wallpaper_files_id);
 
-  // Sets default wallpaper to be the decoded image, and shows the wallpaper now
-  // if |show_wallpaper| is true.
+  // Decodes |account_id|'s wallpaper. Shows the decoded wallpaper if
+  // |show_wallpaper| is true.
+  void SetWallpaperFromInfo(const AccountId& account_id,
+                            const user_manager::UserType& user_type,
+                            const wallpaper::WallpaperInfo& info,
+                            bool show_wallpaper);
+
+  // Used as the callback of default wallpaper decoding. Sets default wallpaper
+  // to be the decoded image, and shows the wallpaper now if |show_wallpaper|
+  // is true.
   void OnDefaultWallpaperDecoded(
       const base::FilePath& path,
       wallpaper::WallpaperLayout layout,
       bool show_wallpaper,
-      MovableOnDestroyCallbackHolder on_finish,
       std::unique_ptr<user_manager::UserImage> user_image);
 
   // Saves |image| to disk if |user_info->is_ephemeral| is false, or if it is a
@@ -474,6 +491,24 @@
                            wallpaper::WallpaperLayout layout,
                            bool show_wallpaper);
 
+  // A wrapper of |ReadAndDecodeWallpaper| used in |SetWallpaperFromPath|.
+  void StartDecodeFromPath(const AccountId& account_id,
+                           const user_manager::UserType& user_type,
+                           const base::FilePath& wallpaper_path,
+                           const wallpaper::WallpaperInfo& info,
+                           bool show_wallpaper);
+
+  // Used as the callback of wallpaper decoding. (Wallpapers of type DEFAULT
+  // and DEVICE should use their corresponding |*Decoded|, and all other types
+  // should use this.) Shows the wallpaper now if |show_wallpaper| is true.
+  // Otherwise, only update the cache.
+  void OnWallpaperDecoded(const AccountId& account_id,
+                          const user_manager::UserType& user_type,
+                          const base::FilePath& path,
+                          const wallpaper::WallpaperInfo& info,
+                          bool show_wallpaper,
+                          std::unique_ptr<user_manager::UserImage> user_image);
+
   // Sets |prominent_colors_| and notifies the observers if there is a change.
   void SetProminentColors(const std::vector<SkColor>& prominent_colors);
 
@@ -550,6 +585,9 @@
   // empty string disables color caching.
   wallpaper::WallpaperInfo current_user_wallpaper_info_;
 
+  // Cached user info of the current user.
+  mojom::WallpaperUserInfoPtr current_user_;
+
   // Cached wallpapers of users.
   CustomWallpaperMap wallpaper_cache_map_;
 
@@ -580,11 +618,11 @@
   // Tracks how many wallpapers have been set.
   int wallpaper_count_for_testing_ = 0;
 
-  // Tracks how many wallpaper decoding requests have been initiated.
-  int num_decode_request_for_testing_ = 0;
-
-  // Caches the file path of the current decoded wallpaper.
-  base::FilePath wallpaper_file_path_for_testing_;
+  // The file paths of decoding requests that have been initiated. Must be a
+  // list because more than one decoding requests may happen during a single
+  // 'set wallpaper' request. (e.g. when a custom wallpaper decoding fails, a
+  // default wallpaper decoding is initiated.)
+  std::vector<base::FilePath> decode_requests_for_testing_;
 
   base::WeakPtrFactory<WallpaperController> weak_factory_;
 
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index ad5a9e5d..2863f5b 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -51,12 +51,54 @@
 const int kLockScreenWallpaperId =
     ash::kShellWindowId_LockScreenWallpaperContainer;
 
-const std::string default_small_wallpaper_name = "small.jpg";
-const std::string default_large_wallpaper_name = "large.jpg";
-const std::string guest_small_wallpaper_name = "guest_small.jpg";
-const std::string guest_large_wallpaper_name = "guest_large.jpg";
-const std::string child_small_wallpaper_name = "child_small.jpg";
-const std::string child_large_wallpaper_name = "child_large.jpg";
+constexpr int kLargeWallpaperWidth = 256;
+const int kLargeWallpaperHeight = WallpaperController::kLargeWallpaperMaxHeight;
+constexpr int kSmallWallpaperWidth = 256;
+const int kSmallWallpaperHeight = WallpaperController::kSmallWallpaperMaxHeight;
+
+constexpr char default_small_wallpaper_name[] = "small.jpg";
+constexpr char default_large_wallpaper_name[] = "large.jpg";
+constexpr char guest_small_wallpaper_name[] = "guest_small.jpg";
+constexpr char guest_large_wallpaper_name[] = "guest_large.jpg";
+constexpr char child_small_wallpaper_name[] = "child_small.jpg";
+constexpr char child_large_wallpaper_name[] = "child_large.jpg";
+
+// Colors used to distinguish between wallpapers with large and small
+// resolution.
+const SkColor kLargeCustomWallpaperColor = SK_ColorDKGRAY;
+const SkColor kSmallCustomWallpaperColor = SK_ColorLTGRAY;
+
+// A color that can be passed to |CreateImage|. Specifically chosen to not
+// conflict with any of the custom wallpaper colors.
+const SkColor kWallpaperColor = SK_ColorMAGENTA;
+
+std::string GetDummyFileId(const AccountId& account_id) {
+  return account_id.GetUserEmail() + "-hash";
+}
+
+std::string GetDummyFileName(const AccountId& account_id) {
+  return account_id.GetUserEmail() + "-file";
+}
+
+// Dummy account ids and file ids.
+constexpr char user_1[] = "user1@test.com";
+const AccountId account_id_1 = AccountId::FromUserEmail(user_1);
+const std::string wallpaper_files_id_1 = GetDummyFileId(account_id_1);
+const std::string file_name_1 = GetDummyFileName(account_id_1);
+
+constexpr char user_2[] = "user2@test.com";
+const AccountId account_id_2 = AccountId::FromUserEmail(user_2);
+const std::string wallpaper_files_id_2 = GetDummyFileId(account_id_2);
+const std::string file_name_2 = GetDummyFileName(account_id_2);
+
+// Creates an image of size |size|.
+gfx::ImageSkia CreateImage(int width, int height, SkColor color) {
+  SkBitmap bitmap;
+  bitmap.allocN32Pixels(width, height);
+  bitmap.eraseColor(color);
+  gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
+  return image;
+}
 
 // Returns number of child windows in a shell window container.
 int ChildCountForContainer(int container_id) {
@@ -84,13 +126,53 @@
   }
 }
 
+// Returns custom wallpaper path. Creates the directory if it doesn't exist.
+base::FilePath GetCustomWallpaperPath(const char* sub_dir,
+                                      const std::string& wallpaper_files_id,
+                                      const std::string& file_name) {
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  base::FilePath wallpaper_path = WallpaperController::GetCustomWallpaperPath(
+      sub_dir, wallpaper_files_id, file_name);
+  if (!base::DirectoryExists(wallpaper_path.DirName()))
+    base::CreateDirectory(wallpaper_path.DirName());
+
+  return wallpaper_path;
+}
+
+void WaitUntilCustomWallpapersDeleted(const AccountId& account_id) {
+  const std::string wallpaper_file_id = GetDummyFileId(account_id);
+
+  base::FilePath small_wallpaper_dir =
+      WallpaperController::GetCustomWallpaperDir(
+          WallpaperController::kSmallWallpaperSubDir)
+          .Append(wallpaper_file_id);
+  base::FilePath large_wallpaper_dir =
+      WallpaperController::GetCustomWallpaperDir(
+          WallpaperController::kLargeWallpaperSubDir)
+          .Append(wallpaper_file_id);
+  base::FilePath original_wallpaper_dir =
+      WallpaperController::GetCustomWallpaperDir(
+          WallpaperController::kOriginalWallpaperSubDir)
+          .Append(wallpaper_file_id);
+  base::FilePath thumbnail_wallpaper_dir =
+      WallpaperController::GetCustomWallpaperDir(
+          WallpaperController::kThumbnailWallpaperSubDir)
+          .Append(wallpaper_file_id);
+
+  while (base::PathExists(small_wallpaper_dir) ||
+         base::PathExists(large_wallpaper_dir) ||
+         base::PathExists(original_wallpaper_dir) ||
+         base::PathExists(thumbnail_wallpaper_dir)) {
+  }
+}
+
 // Monitors if any task is processed by the message loop.
 class TaskObserver : public base::MessageLoop::TaskObserver {
  public:
   TaskObserver() : processed_(false) {}
   ~TaskObserver() override = default;
 
-  // MessageLoop::TaskObserver overrides.
+  // MessageLoop::TaskObserver:
   void WillProcessTask(const base::PendingTask& pending_task) override {}
   void DidProcessTask(const base::PendingTask& pending_task) override {
     processed_ = true;
@@ -183,6 +265,15 @@
     controller_->InitializePathsForTesting();
   }
 
+  void TearDown() override {
+    // Remove the custom wallpaper directories that may be created.
+    controller_->RemoveUserWallpaper(InitializeUser(account_id_1),
+                                     wallpaper_files_id_1);
+    controller_->RemoveUserWallpaper(InitializeUser(account_id_2),
+                                     wallpaper_files_id_2);
+    AshTestBase::TearDown();
+  }
+
   WallpaperView* wallpaper_view() {
     WallpaperWidgetController* controller =
         Shell::Get()
@@ -195,19 +286,6 @@
   }
 
  protected:
-  // A color that can be passed to CreateImage(). Specifically chosen to not
-  // conflict with any of the default wallpaper colors.
-  static const SkColor kWallpaperColor = SK_ColorMAGENTA;
-
-  // Creates an image of size |size|.
-  gfx::ImageSkia CreateImage(int width, int height, SkColor color) {
-    SkBitmap bitmap;
-    bitmap.allocN32Pixels(width, height);
-    bitmap.eraseColor(color);
-    gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
-    return image;
-  }
-
   // Helper function that tests the wallpaper is always fitted to the native
   // display resolution when the layout is WALLPAPER_LAYOUT_CENTER.
   void WallpaperFitToNativeResolution(WallpaperView* view,
@@ -271,8 +349,8 @@
   }
 
   // Helper function to create a new |mojom::WallpaperUserInfoPtr| instance with
-  // default values. In addition, clear the wallpaper count. May be called
-  // multiple times for the same |account_id|.
+  // default values. In addition, clear the wallpaper count and the decoding
+  // request list. May be called multiple times for the same |account_id|.
   mojom::WallpaperUserInfoPtr InitializeUser(const AccountId& account_id) {
     mojom::WallpaperUserInfoPtr wallpaper_user_info =
         mojom::WallpaperUserInfo::New();
@@ -281,12 +359,45 @@
     wallpaper_user_info->is_ephemeral = false;
     wallpaper_user_info->has_gaia_account = true;
 
+    controller_->decode_requests_for_testing_.clear();
     controller_->current_user_wallpaper_info_ = wallpaper::WallpaperInfo();
     controller_->wallpaper_count_for_testing_ = 0;
 
     return wallpaper_user_info;
   }
 
+  // Saves images with different resolution to corresponding paths and saves
+  // wallpaper info to local state, so that subsequent calls of |ShowWallpaper|
+  // can retrieve the images and info.
+  void CreateAndSaveWallpapers(const AccountId& account_id) {
+    std::string wallpaper_files_id = GetDummyFileId(account_id);
+    std::string file_name = GetDummyFileName(account_id);
+    base::FilePath small_wallpaper_path =
+        GetCustomWallpaperPath(WallpaperController::kSmallWallpaperSubDir,
+                               wallpaper_files_id, file_name);
+    base::FilePath large_wallpaper_path =
+        GetCustomWallpaperPath(WallpaperController::kLargeWallpaperSubDir,
+                               wallpaper_files_id, file_name);
+
+    // Saves the small/large resolution wallpapers to small/large custom
+    // wallpaper paths.
+    ASSERT_TRUE(WallpaperController::WriteJPEGFileForTesting(
+        small_wallpaper_path, kSmallWallpaperWidth, kSmallWallpaperHeight,
+        kSmallCustomWallpaperColor));
+    ASSERT_TRUE(WallpaperController::WriteJPEGFileForTesting(
+        large_wallpaper_path, kLargeWallpaperWidth, kLargeWallpaperHeight,
+        kLargeCustomWallpaperColor));
+
+    std::string relative_path =
+        base::FilePath(wallpaper_files_id).Append(file_name).value();
+    // Saves wallpaper info to local state for user.
+    wallpaper::WallpaperInfo info = {
+        relative_path, WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::CUSTOMIZED,
+        base::Time::Now().LocalMidnight()};
+    controller_->SetUserWallpaperInfo(account_id, info,
+                                      true /*is_persistent=*/);
+  }
+
   // Simulates setting a custom wallpaper by directly setting the wallpaper
   // info.
   void SimulateSettingCustomWallpaper(const AccountId& account_id) {
@@ -351,13 +462,20 @@
         child_large_file, kWallpaperSize, kWallpaperSize, kWallpaperColor));
   }
 
-  // Wrapper for private ShouldCalculateColors()
+  // Wrapper for private ShouldCalculateColors().
   bool ShouldCalculateColors() { return controller_->ShouldCalculateColors(); }
 
   int GetWallpaperCount() { return controller_->wallpaper_count_for_testing_; }
 
-  base::FilePath GetWallpaperFilePath() {
-    return controller_->wallpaper_file_path_for_testing_;
+  bool CompareDecodeFilePaths(const std::vector<base::FilePath> expected) {
+    if (controller_->decode_requests_for_testing_.size() != expected.size())
+      return false;
+
+    for (size_t i = 0; i < expected.size(); ++i) {
+      if (controller_->decode_requests_for_testing_[i] != expected[i])
+        return false;
+    }
+    return true;
   }
 
   WallpaperController* controller_;  // Not owned.
@@ -706,60 +824,51 @@
 
 TEST_F(WallpaperControllerTest, SetCustomWallpaper) {
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
-  const std::string file_name = "dummy_file_name";
-  const std::string wallpaper_files_id = "dummy_file_id";
-  const std::string user_email = "user@test.com";
-  const AccountId account_id = AccountId::FromUserEmail(user_email);
   WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
   wallpaper::WallpaperType type = wallpaper::CUSTOMIZED;
 
-  SimulateUserLogin(user_email);
+  SimulateUserLogin(user_1);
 
   // Verify the wallpaper is set successfully and wallpaper info is updated.
-  controller_->SetCustomWallpaper(InitializeUser(account_id),
-                                  wallpaper_files_id, file_name, layout, type,
-                                  *image.bitmap(), true /*show_wallpaper=*/);
+  controller_->SetCustomWallpaper(
+      InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1, layout,
+      type, *image.bitmap(), true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   wallpaper::WallpaperInfo wallpaper_info;
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
-                                                true /*is_persistent=*/));
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
+                                                true /* is_persistent */));
   wallpaper::WallpaperInfo expected_wallpaper_info(
-      base::FilePath(wallpaper_files_id).Append(file_name).value(), layout,
+      base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout,
       type, base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
 
   // Verify that the wallpaper is not set when |show_wallpaper| is false, but
   // wallpaper info is updated properly.
-  controller_->SetCustomWallpaper(InitializeUser(account_id),
-                                  wallpaper_files_id, file_name, layout, type,
-                                  *image.bitmap(), true /*show_wallpaper=*/);
+  controller_->SetCustomWallpaper(
+      InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1, layout,
+      type, *image.bitmap(), true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
-                                                true /*is_persistent=*/));
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
+                                                true /* is_persistent */));
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
-  // Remove the custom wallpaper directory that may be created.
-  controller_->RemoveUserWallpaper(InitializeUser(account_id),
-                                   wallpaper_files_id);
 }
 
 TEST_F(WallpaperControllerTest, SetOnlineWallpaper) {
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   const std::string url = "dummy_url";
-  const std::string user_email = "user@test.com";
-  const AccountId account_id = AccountId::FromUserEmail(user_email);
   WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
 
-  SimulateUserLogin(user_email);
+  SimulateUserLogin(user_1);
 
   // Verify the wallpaper is set successfully and wallpaper info is updated.
-  controller_->SetOnlineWallpaper(InitializeUser(account_id), *image.bitmap(),
+  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), *image.bitmap(),
                                   url, layout, true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   wallpaper::WallpaperInfo wallpaper_info;
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 true /*is_persistent=*/));
   wallpaper::WallpaperInfo expected_wallpaper_info(
       url, layout, wallpaper::ONLINE, base::Time::Now().LocalMidnight());
@@ -767,26 +876,23 @@
 
   // Verify that the wallpaper is not set when |show_wallpaper| is false, but
   // wallpaper info is updated properly.
-  controller_->SetOnlineWallpaper(InitializeUser(account_id), *image.bitmap(),
+  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), *image.bitmap(),
                                   url, layout, false /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 true /*is_persistent=*/));
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
 }
 
 TEST_F(WallpaperControllerTest, SetDefaultWallpaperForRegularAccount) {
   CreateDefaultWallpapers();
-
-  const std::string user_email = "user@test.com";
-  const AccountId account_id = AccountId::FromUserEmail(user_email);
-  SimulateUserLogin(user_email);
+  SimulateUserLogin(user_1);
 
   // First, simulate setting a user custom wallpaper.
-  SimulateSettingCustomWallpaper(account_id);
+  SimulateSettingCustomWallpaper(account_id_1);
   wallpaper::WallpaperInfo wallpaper_info;
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 true /*is_persistent=*/));
   wallpaper::WallpaperInfo default_wallpaper_info(
       std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
@@ -797,51 +903,51 @@
   // info, and the large default wallpaper is set successfully with the correct
   // file path.
   UpdateDisplay("1600x1200");
-  controller_->SetDefaultWallpaper(InitializeUser(account_id),
-                                   std::string() /*wallpaper_files_id=*/,
+  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
+                                   wallpaper_files_id_1,
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(wallpaper_dir_->GetPath().Append(default_large_wallpaper_name),
-            GetWallpaperFilePath());
+  EXPECT_TRUE(CompareDecodeFilePaths(
+      {wallpaper_dir_->GetPath().Append(default_large_wallpaper_name)}));
 
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 true /*is_persistent=*/));
   // The user wallpaper info has been reset to the default value.
   EXPECT_EQ(wallpaper_info, default_wallpaper_info);
 
-  SimulateSettingCustomWallpaper(account_id);
+  SimulateSettingCustomWallpaper(account_id_1);
   // Verify |SetDefaultWallpaper| removes the previously set custom wallpaper
   // info, and the small default wallpaper is set successfully with the correct
   // file path.
   UpdateDisplay("800x600");
-  controller_->SetDefaultWallpaper(InitializeUser(account_id),
-                                   std::string() /*wallpaper_files_id=*/,
+  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
+                                   wallpaper_files_id_1,
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(wallpaper_dir_->GetPath().Append(default_small_wallpaper_name),
-            GetWallpaperFilePath());
+  EXPECT_TRUE(CompareDecodeFilePaths(
+      {wallpaper_dir_->GetPath().Append(default_small_wallpaper_name)}));
 
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 true /*is_persistent=*/));
   // The user wallpaper info has been reset to the default value.
   EXPECT_EQ(wallpaper_info, default_wallpaper_info);
 
-  SimulateSettingCustomWallpaper(account_id);
+  SimulateSettingCustomWallpaper(account_id_1);
   // Verify that when screen is rotated, |SetDefaultWallpaper| removes the
   // previously set custom wallpaper info, and the large default wallpaper is
   // set successfully with the correct file path.
   UpdateDisplay("1200x800/r");
-  controller_->SetDefaultWallpaper(InitializeUser(account_id),
-                                   std::string() /*wallpaper_files_id=*/,
+  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
+                                   wallpaper_files_id_1,
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(wallpaper_dir_->GetPath().Append(default_large_wallpaper_name),
-            GetWallpaperFilePath());
+  EXPECT_TRUE(CompareDecodeFilePaths(
+      {wallpaper_dir_->GetPath().Append(default_large_wallpaper_name)}));
 
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 true /*is_persistent=*/));
   // The user wallpaper info has been reset to the default value.
   EXPECT_EQ(wallpaper_info, default_wallpaper_info);
@@ -850,49 +956,48 @@
 TEST_F(WallpaperControllerTest, SetDefaultWallpaperForChildAccount) {
   CreateDefaultWallpapers();
 
-  const std::string user_email = "child@test.com";
-  const AccountId account_id = AccountId::FromUserEmail(user_email);
-  SimulateUserLogin(user_email);
+  const std::string child_email = "child@test.com";
+  const AccountId child_account_id = AccountId::FromUserEmail(child_email);
+  const std::string child_wallpaper_files_id = GetDummyFileId(child_account_id);
+  SimulateUserLogin(child_email);
 
   // Verify the large child wallpaper is set successfully with the correct file
   // path.
   UpdateDisplay("1600x1200");
-  mojom::WallpaperUserInfoPtr wallpaper_user_info = InitializeUser(account_id);
+  mojom::WallpaperUserInfoPtr wallpaper_user_info =
+      InitializeUser(child_account_id);
   wallpaper_user_info->type = user_manager::USER_TYPE_CHILD;
   controller_->SetDefaultWallpaper(std::move(wallpaper_user_info),
-                                   std::string() /*wallpaper_files_id=*/,
+                                   child_wallpaper_files_id,
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(wallpaper_dir_->GetPath().Append(child_large_wallpaper_name),
-            GetWallpaperFilePath());
+  EXPECT_TRUE(CompareDecodeFilePaths(
+      {wallpaper_dir_->GetPath().Append(child_large_wallpaper_name)}));
 
   // Verify the small child wallpaper is set successfully with the correct file
   // path.
   UpdateDisplay("800x600");
-  wallpaper_user_info = InitializeUser(account_id);
+  wallpaper_user_info = InitializeUser(child_account_id);
   wallpaper_user_info->type = user_manager::USER_TYPE_CHILD;
   controller_->SetDefaultWallpaper(std::move(wallpaper_user_info),
-                                   std::string() /*wallpaper_files_id=*/,
+                                   child_wallpaper_files_id,
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(wallpaper_dir_->GetPath().Append(child_small_wallpaper_name),
-            GetWallpaperFilePath());
+  EXPECT_TRUE(CompareDecodeFilePaths(
+      {wallpaper_dir_->GetPath().Append(child_small_wallpaper_name)}));
 }
 
 TEST_F(WallpaperControllerTest, SetDefaultWallpaperForGuestSession) {
   CreateDefaultWallpapers();
 
   // First, simulate setting a custom wallpaper for a regular user.
-  const std::string user_email = "user@test.com";
-  const AccountId regular_user_account_id =
-      AccountId::FromUserEmail("user@test.com");
-  SimulateUserLogin(user_email);
-  SimulateSettingCustomWallpaper(regular_user_account_id);
+  SimulateUserLogin(user_1);
+  SimulateSettingCustomWallpaper(account_id_1);
   wallpaper::WallpaperInfo wallpaper_info;
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(
-      regular_user_account_id, &wallpaper_info, true /*is_persistent=*/));
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
+                                                true /*is_persistent=*/));
   wallpaper::WallpaperInfo default_wallpaper_info(
       std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
       wallpaper::DEFAULT, base::Time::Now().LocalMidnight());
@@ -909,31 +1014,30 @@
   // custom wallpaper info, but a guest specific wallpaper should be set,
   // instead of the regular default wallpaper.
   UpdateDisplay("1600x1200");
-  controller_->SetDefaultWallpaper(InitializeUser(regular_user_account_id),
-                                   std::string() /*wallpaper_files_id=*/,
+  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
+                                   wallpaper_files_id_1,
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(
-      regular_user_account_id, &wallpaper_info, true /* is_persistent */));
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
+                                                true /* is_persistent */));
   EXPECT_EQ(wallpaper_info, default_wallpaper_info);
-  EXPECT_EQ(wallpaper_dir_->GetPath().Append(guest_large_wallpaper_name),
-            GetWallpaperFilePath());
+  EXPECT_TRUE(CompareDecodeFilePaths(
+      {wallpaper_dir_->GetPath().Append(guest_large_wallpaper_name)}));
 
   UpdateDisplay("800x600");
-  controller_->SetDefaultWallpaper(InitializeUser(regular_user_account_id),
-                                   std::string() /*wallpaper_files_id=*/,
+  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
+                                   wallpaper_files_id_1,
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(wallpaper_dir_->GetPath().Append(guest_small_wallpaper_name),
-            GetWallpaperFilePath());
+  EXPECT_TRUE(CompareDecodeFilePaths(
+      {wallpaper_dir_->GetPath().Append(guest_small_wallpaper_name)}));
 }
 
 TEST_F(WallpaperControllerTest, IgnoreWallpaperRequestInKioskMode) {
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   const std::string kiosk_app = "kiosk";
-  const AccountId account_id = AccountId::FromUserEmail("user@test.com");
 
   // Simulate kiosk login.
   TestSessionControllerClient* session = GetSessionControllerClient();
@@ -944,148 +1048,234 @@
   // Verify that |SetCustomWallpaper| doesn't set wallpaper in kiosk mode, and
   // |account_id|'s wallpaper info is not updated.
   controller_->SetCustomWallpaper(
-      InitializeUser(account_id), std::string() /* wallpaper_files_id */,
-      "dummy_file_name", WALLPAPER_LAYOUT_CENTER, wallpaper::CUSTOMIZED,
-      *image.bitmap(), true /* show_wallpaper */);
+      InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1,
+      WALLPAPER_LAYOUT_CENTER, wallpaper::CUSTOMIZED, *image.bitmap(),
+      true /* show_wallpaper */);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
   wallpaper::WallpaperInfo wallpaper_info;
-  EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                  true /* is_persistent */));
 
   // Verify that |SetOnlineWallpaper| doesn't set wallpaper in kiosk mode, and
   // |account_id|'s wallpaper info is not updated.
-  controller_->SetOnlineWallpaper(InitializeUser(account_id), *image.bitmap(),
+  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), *image.bitmap(),
                                   "dummy_url", WALLPAPER_LAYOUT_CENTER,
                                   true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
-  EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                  true /*is_persistent=*/));
 
   // Verify that |SetDefaultWallpaper| doesn't set wallpaper in kiosk mode, and
   // |account_id|'s wallpaper info is not updated.
-  controller_->SetDefaultWallpaper(InitializeUser(account_id),
-                                   std::string() /*wallpaper_files_id=*/,
+  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
+                                   wallpaper_files_id_1,
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
-  EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                  true /*is_persistent=*/));
 }
 
 TEST_F(WallpaperControllerTest, IgnoreWallpaperRequestWhenPolicyIsEnforced) {
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
-  const std::string wallpaper_files_id = "dummy_file_id";
-  const std::string user_email = "user@test.com";
-  const AccountId account_id = AccountId::FromUserEmail("user@test.com");
-  SimulateUserLogin(user_email);
+  SimulateUserLogin(user_1);
 
   // Simulate setting a policy wallpaper by setting the wallpaper info.
   // TODO(crbug.com/776464): Replace this with a real |SetPolicyWallpaper| call.
   wallpaper::WallpaperInfo policy_wallpaper_info(
       "dummy_file_location", WALLPAPER_LAYOUT_CENTER, wallpaper::POLICY,
       base::Time::Now().LocalMidnight());
-  controller_->SetUserWallpaperInfo(account_id, policy_wallpaper_info,
+  controller_->SetUserWallpaperInfo(account_id_1, policy_wallpaper_info,
                                     true /*is_persistent=*/);
   EXPECT_TRUE(
-      controller_->IsPolicyControlled(account_id, true /*is_persistent=*/));
+      controller_->IsPolicyControlled(account_id_1, true /*is_persistent=*/));
 
   // Verify that |SetCustomWallpaper| doesn't set wallpaper when policy is
   // enforced, and |account_id|'s wallpaper info is not updated.
   controller_->SetCustomWallpaper(
-      InitializeUser(account_id), wallpaper_files_id, "dummy_file_name",
+      InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1,
       WALLPAPER_LAYOUT_CENTER, wallpaper::CUSTOMIZED, *image.bitmap(),
-      true /* show_wallpaper */);
+      true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
   wallpaper::WallpaperInfo wallpaper_info;
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 true /* is_persistent */));
   EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
 
   // Verify that |SetOnlineWallpaper| doesn't set wallpaper when policy is
   // enforced, and |account_id|'s wallpaper info is not updated.
-  controller_->SetOnlineWallpaper(InitializeUser(account_id), *image.bitmap(),
+  controller_->SetOnlineWallpaper(InitializeUser(account_id_1), *image.bitmap(),
                                   "dummy_url", WALLPAPER_LAYOUT_CENTER,
                                   true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
-                                                true /* is_persistent */));
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
+                                                true /*is_persistent=*/));
   EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
 
   // Verify that |SetDefaultWallpaper| doesn't set wallpaper when policy is
   // enforced, and |account_id|'s wallpaper info is not updated.
-  controller_->SetDefaultWallpaper(
-      InitializeUser(account_id), wallpaper_files_id, true /*show_wallpaper=*/);
+  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
+                                   wallpaper_files_id_1,
+                                   true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id, &wallpaper_info,
-                                                true /* is_persistent */));
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
+                                                true /*is_persistent=*/));
   EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
-
-  // Remove the custom wallpaper directory that may be created.
-  controller_->RemoveUserWallpaper(InitializeUser(account_id),
-                                   wallpaper_files_id);
 }
 
 TEST_F(WallpaperControllerTest, VerifyWallpaperCache) {
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
-  const std::string wallpaper_files_id = "dummy_file_id";
-  const std::string user1 = "user1@test.com";
-  const AccountId account_id1 = AccountId::FromUserEmail(user1);
+  SimulateUserLogin(user_1);
 
-  SimulateUserLogin(user1);
-
-  // |user1| doesn't have wallpaper cache in the beginning.
+  // |user_1| doesn't have wallpaper cache in the beginning.
   gfx::ImageSkia cached_wallpaper;
   EXPECT_FALSE(
-      controller_->GetWallpaperFromCache(account_id1, &cached_wallpaper));
+      controller_->GetWallpaperFromCache(account_id_1, &cached_wallpaper));
   base::FilePath path;
-  EXPECT_FALSE(controller_->GetPathFromCache(account_id1, &path));
+  EXPECT_FALSE(controller_->GetPathFromCache(account_id_1, &path));
 
   // Verify |SetOnlineWallpaper| updates wallpaper cache for |user1|.
   controller_->SetOnlineWallpaper(
-      InitializeUser(account_id1), *image.bitmap(), "dummy_file_location",
+      InitializeUser(account_id_1), *image.bitmap(), "dummy_file_location",
       WALLPAPER_LAYOUT_CENTER, true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_TRUE(
-      controller_->GetWallpaperFromCache(account_id1, &cached_wallpaper));
-  EXPECT_TRUE(controller_->GetPathFromCache(account_id1, &path));
+      controller_->GetWallpaperFromCache(account_id_1, &cached_wallpaper));
+  EXPECT_TRUE(controller_->GetPathFromCache(account_id_1, &path));
 
-  // After |user2| is logged in, |user1|'s wallpaper cache should still be kept
+  // After |user_2| is logged in, |user1|'s wallpaper cache should still be kept
   // (crbug.com/339576). Note the active user is still |user1|.
   TestSessionControllerClient* session = GetSessionControllerClient();
-  session->AddUserSession("user2@test.com");
+  session->AddUserSession(user_2);
   EXPECT_TRUE(
-      controller_->GetWallpaperFromCache(account_id1, &cached_wallpaper));
-  EXPECT_TRUE(controller_->GetPathFromCache(account_id1, &path));
+      controller_->GetWallpaperFromCache(account_id_1, &cached_wallpaper));
+  EXPECT_TRUE(controller_->GetPathFromCache(account_id_1, &path));
 
   // Verify |SetDefaultWallpaper| clears wallpaper cache.
-  controller_->SetDefaultWallpaper(InitializeUser(account_id1),
-                                   wallpaper_files_id,
+  controller_->SetDefaultWallpaper(InitializeUser(account_id_1),
+                                   wallpaper_files_id_1,
                                    true /*show_wallpaper=*/);
   EXPECT_FALSE(
-      controller_->GetWallpaperFromCache(account_id1, &cached_wallpaper));
-  EXPECT_FALSE(controller_->GetPathFromCache(account_id1, &path));
+      controller_->GetWallpaperFromCache(account_id_1, &cached_wallpaper));
+  EXPECT_FALSE(controller_->GetPathFromCache(account_id_1, &path));
 
   // Verify |SetCustomWallpaper| updates wallpaper cache for |user1|.
   controller_->SetCustomWallpaper(
-      InitializeUser(account_id1), wallpaper_files_id, "dummy_file_name",
+      InitializeUser(account_id_1), wallpaper_files_id_1, file_name_1,
       WALLPAPER_LAYOUT_CENTER, wallpaper::CUSTOMIZED, *image.bitmap(),
       true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_TRUE(
-      controller_->GetWallpaperFromCache(account_id1, &cached_wallpaper));
-  EXPECT_TRUE(controller_->GetPathFromCache(account_id1, &path));
+      controller_->GetWallpaperFromCache(account_id_1, &cached_wallpaper));
+  EXPECT_TRUE(controller_->GetPathFromCache(account_id_1, &path));
 
   // Verify |RemoveUserWallpaper| clears wallpaper cache.
-  controller_->RemoveUserWallpaper(InitializeUser(account_id1),
-                                   wallpaper_files_id);
+  controller_->RemoveUserWallpaper(InitializeUser(account_id_1),
+                                   wallpaper_files_id_1);
   EXPECT_FALSE(
-      controller_->GetWallpaperFromCache(account_id1, &cached_wallpaper));
-  EXPECT_FALSE(controller_->GetPathFromCache(account_id1, &path));
+      controller_->GetWallpaperFromCache(account_id_1, &cached_wallpaper));
+  EXPECT_FALSE(controller_->GetPathFromCache(account_id_1, &path));
+}
+
+// Tests that the appropriate wallpaper (large vs. small) is shown depending
+// on the desktop resolution.
+TEST_F(WallpaperControllerTest, ShowCustomWallpaperWithCorrectResolution) {
+  CreateDefaultWallpapers();
+  base::FilePath small_wallpaper_path =
+      GetCustomWallpaperPath(WallpaperController::kSmallWallpaperSubDir,
+                             wallpaper_files_id_1, file_name_1);
+
+  CreateAndSaveWallpapers(account_id_1);
+  controller_->ShowUserWallpaper(InitializeUser(account_id_1));
+  RunAllTasksUntilIdle();
+  EXPECT_EQ(1, GetWallpaperCount());
+
+  // Display is initialized to 800x600. The small resolution custom wallpaper is
+  // expected. A second decode request with small resolution default wallpaper
+  // is also expected. (Because unit tests don't support actual wallpaper
+  // decoding, it falls back the default wallpaper.)
+  EXPECT_TRUE(CompareDecodeFilePaths(
+      {small_wallpaper_path,
+       wallpaper_dir_->GetPath().Append(default_small_wallpaper_name)}));
+
+  // TODO(crbug.com/776464): Add tests for large resolution custom wallpapers
+  // after |UpdateWallpaper| is migrated.
+}
+
+// If clients call |ShowUserWallpaper| twice with the same account id, the
+// latter request should be prevented (See crbug.com/158383).
+TEST_F(WallpaperControllerTest, PreventReloadingSameWallpaper) {
+  CreateAndSaveWallpapers(account_id_1);
+  controller_->ShowUserWallpaper(InitializeUser(account_id_1));
+  RunAllTasksUntilIdle();
+  EXPECT_EQ(1, GetWallpaperCount());
+
+  controller_->ShowUserWallpaper(InitializeUser(account_id_1));
+  RunAllTasksUntilIdle();
+  // No wallpaper is set for the second |ShowUserWallpaper| request.
+  EXPECT_EQ(0, GetWallpaperCount());
+}
+
+// Tests that if a user who has a custom wallpaper is removed from the device,
+// only the directory that contains the user's custom wallpapers gets removed.
+// The other user's custom wallpaper is not affected.
+TEST_F(WallpaperControllerTest, RemoveUserWithCustomWallpaper) {
+  SimulateUserLogin(user_1);
+  base::FilePath small_wallpaper_path_1 =
+      GetCustomWallpaperPath(WallpaperController::kSmallWallpaperSubDir,
+                             wallpaper_files_id_1, file_name_1);
+  // Set a custom wallpaper for |user_1| and verify the wallpaper exists.
+  CreateAndSaveWallpapers(account_id_1);
+  EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
+
+  // Now login another user and set a custom wallpaper for the user.
+  SimulateUserLogin(user_2);
+  base::FilePath small_wallpaper_path_2 = GetCustomWallpaperPath(
+      WallpaperController::kSmallWallpaperSubDir, wallpaper_files_id_2,
+      GetDummyFileName(account_id_2));
+  CreateAndSaveWallpapers(account_id_2);
+  EXPECT_TRUE(base::PathExists(small_wallpaper_path_2));
+
+  // Simulate the removal of |user_2|.
+  controller_->RemoveUserWallpaper(InitializeUser(account_id_2),
+                                   wallpaper_files_id_2);
+  // Wait until all files under the user's custom wallpaper directory are
+  // removed.
+  WaitUntilCustomWallpapersDeleted(account_id_2);
+  EXPECT_FALSE(base::PathExists(small_wallpaper_path_2));
+
+  // Verify that the other user's wallpaper is not affected.
+  EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
+}
+
+// Tests that if a user who has a default wallpaper is removed from the device,
+// the other user's custom wallpaper is not affected.
+TEST_F(WallpaperControllerTest, RemoveUserWithDefaultWallpaper) {
+  SimulateUserLogin(user_1);
+  base::FilePath small_wallpaper_path_1 =
+      GetCustomWallpaperPath(WallpaperController::kSmallWallpaperSubDir,
+                             wallpaper_files_id_1, file_name_1);
+  // Set a custom wallpaper for |user_1| and verify the wallpaper exists.
+  CreateAndSaveWallpapers(account_id_1);
+  EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
+
+  // Now login another user and set a default wallpaper for the user.
+  SimulateUserLogin(user_2);
+  controller_->SetDefaultWallpaper(InitializeUser(account_id_2),
+                                   wallpaper_files_id_2,
+                                   true /*show_wallpaper=*/);
+
+  // Simulate the removal of |user_2|.
+  controller_->RemoveUserWallpaper(InitializeUser(account_id_2),
+                                   wallpaper_files_id_2);
+
+  // Verify that the other user's wallpaper is not affected.
+  EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
 }
 
 TEST_F(WallpaperControllerTest, WallpaperBlur) {
diff --git a/ash/wallpaper/wallpaper_decoder.cc b/ash/wallpaper/wallpaper_decoder.cc
index 39424416..d48a4ae3 100644
--- a/ash/wallpaper/wallpaper_decoder.cc
+++ b/ash/wallpaper/wallpaper_decoder.cc
@@ -20,6 +20,10 @@
 // TODO(crbug.com/776464): This should be changed to |ConvertToImageSkia| after
 // the use of |UserImage| in |WallpaperManager| is deprecated.
 void ConvertToUserImage(OnWallpaperDecoded callback, const SkBitmap& image) {
+  if (image.isNull()) {
+    std::move(callback).Run(std::make_unique<user_manager::UserImage>());
+    return;
+  }
   SkBitmap final_image = image;
   final_image.setImmutable();
   gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(final_image);
diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc
index 153d1e8..75eef56 100644
--- a/ash/wm/overview/window_grid.cc
+++ b/ash/wm/overview/window_grid.cc
@@ -496,6 +496,18 @@
   return false;
 }
 
+void WindowGrid::AddItem(aura::Window* window) {
+  DCHECK(!Contains(window));
+
+  window_observer_.Add(window);
+  window_state_observer_.Add(wm::GetWindowState(window));
+  window_list_.push_back(
+      std::make_unique<WindowSelectorItem>(window, window_selector_, this));
+  window_list_.back()->PrepareForOverview();
+
+  PositionWindows(/*animate=*/true);
+}
+
 void WindowGrid::RemoveItem(WindowSelectorItem* selector_item) {
   auto iter =
       std::find_if(window_list_.begin(), window_list_.end(),
@@ -538,14 +550,14 @@
 
 void WindowGrid::SetBoundsAndUpdatePositions(const gfx::Rect& bounds) {
   bounds_ = bounds;
-  PositionWindows(true /* animate */);
+  PositionWindows(/*animate=*/true);
 }
 
 void WindowGrid::SetBoundsAndUpdatePositionsIgnoringWindow(
     const gfx::Rect& bounds,
     WindowSelectorItem* ignored_item) {
   bounds_ = bounds;
-  PositionWindows(true /* animate */, ignored_item);
+  PositionWindows(/*animate=*/true, ignored_item);
 }
 
 void WindowGrid::SetSelectionWidgetVisibility(bool visible) {
diff --git a/ash/wm/overview/window_grid.h b/ash/wm/overview/window_grid.h
index 9911b39..665a332 100644
--- a/ash/wm/overview/window_grid.h
+++ b/ash/wm/overview/window_grid.h
@@ -93,6 +93,10 @@
   // this grid owns.
   bool Contains(const aura::Window* window) const;
 
+  // Adds |window| to the grid. Intended to be used by split view. |window|
+  // cannot already be on the grid.
+  void AddItem(aura::Window* window);
+
   // Removes |selector_item| from the grid.
   void RemoveItem(WindowSelectorItem* selector_item);
 
diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc
index bb446183..b0871e8 100644
--- a/ash/wm/overview/window_selector.cc
+++ b/ash/wm/overview/window_selector.cc
@@ -26,6 +26,7 @@
 #include "ash/wm/panels/panel_layout_manager.h"
 #include "ash/wm/splitview/split_view_overview_overlay.h"
 #include "ash/wm/switchable_windows.h"
+#include "ash/wm/tablet_mode/tablet_mode_window_state.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "base/auto_reset.h"
@@ -294,7 +295,7 @@
     // overview are observed. See http://crbug.com/384495.
     for (std::unique_ptr<WindowGrid>& window_grid : grid_list_) {
       window_grid->PrepareForOverview();
-      window_grid->PositionWindows(true);
+      window_grid->PositionWindows(/*animate=*/true);
     }
 
     search_image_ = gfx::CreateVectorIcon(
@@ -484,6 +485,30 @@
   return nullptr;
 }
 
+void WindowSelector::AddItem(aura::Window* window) {
+  // Early exit if a grid already contains |window|.
+  WindowGrid* grid = GetGridWithRootWindow(window->GetRootWindow());
+  if (!grid || grid->Contains(window))
+    return;
+
+  // This is meant to be called when a item in split view mode was previously
+  // snapped but should now be returned to the window grid (ie. split view
+  // divider dragged to either edge).
+  DCHECK(SplitViewController::ShouldAllowSplitView());
+  DCHECK(Shell::Get()->split_view_controller()->CanSnap(window));
+
+  // The dimensions of |window| will be very slim because of dragging the
+  // divider to the edge. Change the window dimensions to its tablet mode
+  // dimensions. Note: if split view is no longer constrained to tablet mode
+  // this will be need to updated.
+  TabletModeWindowState::UpdateWindowPosition(wm::GetWindowState(window));
+  grid->AddItem(window);
+
+  // Transfer focus from |window| to the text widget, to match the behavior of
+  // entering overview mode in the beginning.
+  wm::ActivateWindow(GetTextFilterWidgetWindow());
+}
+
 void WindowSelector::RemoveWindowSelectorItem(WindowSelectorItem* item) {
   if (item->GetWindow()->HasObserver(this)) {
     item->GetWindow()->RemoveObserver(this);
@@ -815,7 +840,7 @@
     SetBoundsForWindowGridsInScreen(
         GetGridBoundsInScreen(const_cast<aura::Window*>(grid->root_window())));
   }
-  PositionWindows(/* animate */ false);
+  PositionWindows(/*animate=*/false);
   RepositionTextFilterOnDisplayMetricsChange();
   if (split_view_overview_overlay_)
     split_view_overview_overlay_->OnDisplayBoundsChanged();
diff --git a/ash/wm/overview/window_selector.h b/ash/wm/overview/window_selector.h
index 079cfc8..31dfbcbb 100644
--- a/ash/wm/overview/window_selector.h
+++ b/ash/wm/overview/window_selector.h
@@ -103,6 +103,10 @@
   // nullptr if the window grid is not found.
   WindowGrid* GetGridWithRootWindow(aura::Window* root_window);
 
+  // Add |window| to the grid in |grid_list_| with the same root window. Does
+  // nothing if the grid already contains |window|.
+  void AddItem(aura::Window* window);
+
   // Removes the window selector item from the overview window grid.
   void RemoveWindowSelectorItem(WindowSelectorItem* item);
 
diff --git a/ash/wm/overview/window_selector_controller.h b/ash/wm/overview/window_selector_controller.h
index 806b79cc..86deabff 100644
--- a/ash/wm/overview/window_selector_controller.h
+++ b/ash/wm/overview/window_selector_controller.h
@@ -65,6 +65,8 @@
   void RemoveAndDestroyAnimationObserver(
       DelayedAnimationObserver* animation) override;
 
+  WindowSelector* window_selector() { return window_selector_.get(); }
+
  private:
   friend class WindowSelectorTest;
 
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index 5f5f438a..d2605dc 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -12,7 +12,6 @@
 #include "ash/display/screen_orientation_controller_chromeos.h"
 #include "ash/display/screen_orientation_controller_test_api.h"
 #include "ash/drag_drop/drag_drop_controller.h"
-#include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/config.h"
 #include "ash/public/cpp/window_properties.h"
 #include "ash/screen_util.h"
@@ -37,7 +36,6 @@
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
 #include "ash/wm/workspace/workspace_window_resizer.h"
-#include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
@@ -1940,8 +1938,6 @@
 
   void SetUp() override {
     WindowSelectorTest::SetUp();
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kAshEnableTabletSplitView);
     Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
   }
 
@@ -2855,6 +2851,8 @@
       CreateWindowWithMinimumSize(bounds, size));
   std::unique_ptr<aura::Window> window3(
       CreateWindowWithMinimumSize(bounds, size));
+  const int screen_width =
+      ScreenUtil::GetDisplayWorkAreaBoundsInParent(window1.get()).width();
   ToggleOverview();
 
   // Drag |window1| selector item to snap to left.
@@ -2876,9 +2874,10 @@
   // Test that split view mode is ended. Overview mode is still active.
   EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
   EXPECT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting());
-  // Test that |window1| has been moved out of the work area and is invisible.
-  EXPECT_LE(window1->bounds().x(), -kMinimumBoundSize);
-  EXPECT_EQ(window1->bounds().width(), kMinimumBoundSize);
+  // Test that |window1| has the dimensions of a tablet mode maxed window, so
+  // that when it is placed back on the grid it will not look skinny.
+  EXPECT_LE(window1->bounds().x(), 0);
+  EXPECT_EQ(window1->bounds().width(), screen_width);
 
   // Drag |window2| selector item to snap to right.
   WindowSelectorItem* selector_item2 =
@@ -2903,9 +2902,57 @@
   // Test that split view mode is ended. Overview mode is still active.
   EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
   EXPECT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting());
-  // Test that |window2| has been moved out of the work area and is invisible.
-  EXPECT_GE(window2->bounds().x(), work_area_rect.x());
-  EXPECT_EQ(window2->bounds().width(), kMinimumBoundSize);
+  // Test that |window2| has the dimensions of a tablet mode maxed window, so
+  // that when it is placed back on the grid it will not look skinny.
+  EXPECT_GE(window2->bounds().x(), 0);
+  EXPECT_EQ(window2->bounds().width(), screen_width);
+}
+
+// Verify that if the split view divider is dragged all the way to the edge, the
+// window being dragged gets returned to the overview list, if overview mode is
+// still active.
+TEST_F(SplitViewWindowSelectorTest,
+       DividerDraggedToEdgeReturnsWindowToOverviewList) {
+  const gfx::Rect bounds(0, 0, 400, 400);
+  std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
+  std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
+  std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
+
+  ToggleOverview();
+  // Drag |window1| selector item to snap to left. There should be two items on
+  // the overview grid afterwards, |window2| and |window3|.
+  const int grid_index = 0;
+  WindowSelectorItem* selector_item1 =
+      GetWindowItemForWindow(grid_index, window1.get());
+  DragWindowTo(selector_item1, gfx::Point(0, 0));
+  EXPECT_EQ(SplitViewController::LEFT_SNAPPED,
+            split_view_controller()->state());
+  EXPECT_TRUE(IsSelecting());
+  EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive());
+  ASSERT_TRUE(split_view_controller()->split_view_divider());
+  std::vector<aura::Window*> window_list =
+      window_selector_controller()->GetWindowsListInOverviewGridsForTesting();
+  EXPECT_EQ(2u, window_list.size());
+  EXPECT_TRUE(std::find(window_list.begin(), window_list.end(),
+                        window1.get()) == window_list.end());
+  EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
+
+  // Drag the divider to the left edge.
+  const gfx::Rect divider_bounds =
+      GetSplitViewDividerBounds(/*is_dragging=*/false);
+  GetEventGenerator().set_current_location(divider_bounds.CenterPoint());
+  GetEventGenerator().DragMouseTo(0, 0);
+
+  // Verify that it is still in overview mode and that |window1| is returned to
+  // the overview list.
+  EXPECT_TRUE(IsSelecting());
+  EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
+  window_list =
+      window_selector_controller()->GetWindowsListInOverviewGridsForTesting();
+  EXPECT_EQ(3u, window_list.size());
+  EXPECT_TRUE(std::find(window_list.begin(), window_list.end(),
+                        window1.get()) != window_list.end());
+  EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
 }
 
 }  // namespace ash
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index 5bbff42..c7fd8d1 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -80,8 +80,8 @@
 
 // static
 bool SplitViewController::ShouldAllowSplitView() {
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kAshEnableTabletSplitView)) {
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kAshDisableTabletSplitView)) {
     return false;
   }
   if (!Shell::Get()
@@ -327,10 +327,19 @@
   // Check if one of the snapped windows needs to be closed.
   if (ShouldEndSplitViewAfterResizing()) {
     aura::Window* active_window = GetActiveWindowAfterResizingUponExit();
+
+    // Track the window that needs to be put back into the overview list if we
+    // remain in overview mode.
+    aura::Window* insert_overview_window = nullptr;
+    if (Shell::Get()->window_selector_controller()->IsSelecting())
+      insert_overview_window = GetDefaultSnappedWindow();
     EndSplitView();
     if (active_window) {
       EndOverview();
       wm::ActivateWindow(active_window);
+    } else if (insert_overview_window) {
+      Shell::Get()->window_selector_controller()->window_selector()->AddItem(
+          insert_overview_window);
     }
   }
 }
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index c1e3e84..37c137c 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "ash/display/screen_orientation_controller_chromeos.h"
 #include "ash/display/screen_orientation_controller_test_api.h"
-#include "ash/public/cpp/ash_switches.h"
 #include "ash/screen_util.h"
 #include "ash/shell.h"
 #include "ash/system/overview/overview_button_tray.h"
@@ -20,7 +19,6 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
-#include "base/command_line.h"
 #include "services/ui/public/interfaces/window_manager_constants.mojom.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/test/test_window_delegate.h"
@@ -39,8 +37,6 @@
 
   // test::AshTestBase:
   void SetUp() override {
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kAshEnableTabletSplitView);
     AshTestBase::SetUp();
     Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
   }
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
index 91e38a1b..85eaa4c 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
@@ -1215,34 +1215,6 @@
   EXPECT_EQ(w1->bounds().ToString(), requested_bounds.ToString());
 }
 
-// Check that snapping operations get ignored.
-TEST_F(TabletModeWindowManagerTest, SnapModeTests) {
-  gfx::Rect rect(20, 140, 100, 100);
-  std::unique_ptr<aura::Window> w1(
-      CreateWindow(aura::client::WINDOW_TYPE_NORMAL, rect));
-  wm::WindowState* window_state = wm::GetWindowState(w1.get());
-  wm::WMEvent event_left(wm::WM_EVENT_SNAP_LEFT);
-  wm::WMEvent event_right(wm::WM_EVENT_SNAP_RIGHT);
-  window_state->OnWMEvent(&event_left);
-  EXPECT_TRUE(window_state->IsSnapped());
-
-  CreateTabletModeWindowManager();
-
-  // Fullscreen mode should now be off and it should not come back while in
-  // tablet mode.
-  EXPECT_FALSE(window_state->IsSnapped());
-  EXPECT_TRUE(window_state->IsMaximized());
-  window_state->OnWMEvent(&event_left);
-  EXPECT_FALSE(window_state->IsSnapped());
-  EXPECT_TRUE(window_state->IsMaximized());
-  window_state->OnWMEvent(&event_right);
-  EXPECT_FALSE(window_state->IsSnapped());
-  EXPECT_TRUE(window_state->IsMaximized());
-
-  DestroyTabletModeWindowManager();
-  EXPECT_TRUE(window_state->IsSnapped());
-}
-
 // Check that non maximizable windows cannot be dragged by the user.
 TEST_F(TabletModeWindowManagerTest, TryToDesktopSizeDragUnmaximizable) {
   gfx::Rect rect(10, 10, 100, 100);
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index dd20141..5efcc6a1 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -13,7 +13,6 @@
 #include "ash/app_list/test_app_list_presenter_impl.h"
 #include "ash/frame/custom_frame_view_ash.h"
 #include "ash/public/cpp/app_types.h"
-#include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/config.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/root_window_controller.h"
@@ -39,7 +38,6 @@
 #include "ash/wm/workspace/backdrop_delegate.h"
 #include "ash/wm/workspace/workspace_window_resizer.h"
 #include "ash/wm/workspace_controller_test_api.h"
-#include "base/command_line.h"
 #include "base/run_loop.h"
 #include "chromeos/audio/chromeos_sounds.h"
 #include "ui/app_list/app_list_features.h"
@@ -1737,8 +1735,6 @@
 
 // Test that backdrop works in split view mode.
 TEST_F(WorkspaceLayoutManagerBackdropTest, BackdropForSplitScreenTest) {
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kAshEnableTabletSplitView);
   ShowTopWindowBackdropForContainer(default_container(), true);
   Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 0150c15..27697fc 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2671,7 +2671,6 @@
       "android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
       "android/java/src/org/chromium/base/library_loader/Linker.java",
       "android/java/src/org/chromium/base/library_loader/LoaderErrors.java",
-      "android/java/src/org/chromium/base/library_loader/ModernLinker.java",
       "android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
       "android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
       "android/java/src/org/chromium/base/metrics/CachedMetrics.java",
diff --git a/base/android/java/src/org/chromium/base/PathUtils.java b/base/android/java/src/org/chromium/base/PathUtils.java
index da59355..64fcc0d 100644
--- a/base/android/java/src/org/chromium/base/PathUtils.java
+++ b/base/android/java/src/org/chromium/base/PathUtils.java
@@ -14,6 +14,7 @@
 import org.chromium.base.annotations.MainDex;
 import org.chromium.base.metrics.RecordHistogram;
 
+import java.io.File;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -24,14 +25,11 @@
 @MainDex
 public abstract class PathUtils {
     private static final String THUMBNAIL_DIRECTORY_NAME = "textures";
-    private static final String DOWNLOAD_INTERNAL_DIRECTORY_NAME = "download_internal";
 
     private static final int DATA_DIRECTORY = 0;
     private static final int THUMBNAIL_DIRECTORY = 1;
-    private static final int DATABASE_DIRECTORY = 2;
-    private static final int CACHE_DIRECTORY = 3;
-    private static final int DOWNLOAD_INTERNAL_DIRECTORY = 4;
-    private static final int NUM_DIRECTORIES = 5;
+    private static final int CACHE_DIRECTORY = 2;
+    private static final int NUM_DIRECTORIES = 3;
     private static final AtomicBoolean sInitializationStarted = new AtomicBoolean();
     private static AsyncTask<Void, Void, String[]> sDirPathFetchTask;
 
@@ -39,6 +37,7 @@
     // need the values, we will need the suffix so that we can restart the task synchronously on
     // the UI thread.
     private static String sDataDirectorySuffix;
+    private static String sCacheSubDirectory;
 
     // Prevent instantiation.
     private PathUtils() {}
@@ -99,11 +98,13 @@
                 sDataDirectorySuffix, Context.MODE_PRIVATE).getPath();
         paths[THUMBNAIL_DIRECTORY] = appContext.getDir(
                 THUMBNAIL_DIRECTORY_NAME, Context.MODE_PRIVATE).getPath();
-        paths[DOWNLOAD_INTERNAL_DIRECTORY] =
-                appContext.getDir(DOWNLOAD_INTERNAL_DIRECTORY_NAME, Context.MODE_PRIVATE).getPath();
-        paths[DATABASE_DIRECTORY] = appContext.getDatabasePath("foo").getParent();
         if (appContext.getCacheDir() != null) {
-            paths[CACHE_DIRECTORY] = appContext.getCacheDir().getPath();
+            if (sCacheSubDirectory == null) {
+                paths[CACHE_DIRECTORY] = appContext.getCacheDir().getPath();
+            } else {
+                paths[CACHE_DIRECTORY] =
+                        new File(appContext.getCacheDir(), sCacheSubDirectory).getPath();
+            }
         }
         return paths;
     }
@@ -118,14 +119,16 @@
      * need to try to re-execute later.
      *
      * @param suffix The private data directory suffix.
+     * @param cacheSubDir The subdirectory in the cache directory to use, if non-null.
      * @see Context#getDir(String, int)
      */
-    public static void setPrivateDataDirectorySuffix(String suffix) {
+    public static void setPrivateDataDirectorySuffix(String suffix, String cacheSubDir) {
         // This method should only be called once, but many tests end up calling it multiple times,
         // so adding a guard here.
         if (!sInitializationStarted.getAndSet(true)) {
             assert ContextUtils.getApplicationContext() != null;
             sDataDirectorySuffix = suffix;
+            sCacheSubDirectory = cacheSubDir;
             sDirPathFetchTask = new AsyncTask<Void, Void, String[]>() {
                 @Override
                 protected String[] doInBackground(Void... unused) {
@@ -135,6 +138,10 @@
         }
     }
 
+    public static void setPrivateDataDirectorySuffix(String suffix) {
+        setPrivateDataDirectorySuffix(suffix, null);
+    }
+
     /**
      * @param index The index of the cached directory path.
      * @return The directory path requested.
@@ -153,15 +160,6 @@
     }
 
     /**
-     * @return the private directory that is used to store application database.
-     */
-    @CalledByNative
-    public static String getDatabaseDirectory() {
-        assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
-        return getDirectoryPath(DATABASE_DIRECTORY);
-    }
-
-    /**
      * @return the cache directory.
      */
     @CalledByNative
@@ -176,12 +174,6 @@
         return getDirectoryPath(THUMBNAIL_DIRECTORY);
     }
 
-    @CalledByNative
-    public static String getDownloadInternalDirectory() {
-        assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
-        return getDirectoryPath(DOWNLOAD_INTERNAL_DIRECTORY);
-    }
-
     /**
      * @return the public downloads directory.
      */
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index e1b7838..bdbddfa 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -8,8 +8,11 @@
 import android.content.Context;
 import android.os.AsyncTask;
 import android.os.Build;
+import android.os.Process;
 import android.os.StrictMode;
 import android.os.SystemClock;
+import android.support.annotation.NonNull;
+import android.support.annotation.RequiresApi;
 import android.system.Os;
 
 import org.chromium.base.BuildConfig;
@@ -332,7 +335,8 @@
 
     // Helper for loadAlreadyLocked(). Load a native shared library with the Chromium linker.
     // Sets UMA flags depending on the results of loading.
-    private void loadLibrary(Linker linker, @Nullable String zipFilePath, String libFilePath) {
+    private void loadLibraryWithCustomLinker(
+            Linker linker, @Nullable String zipFilePath, String libFilePath) {
         if (linker.isUsingBrowserSharedRelros()) {
             // If the browser is set to attempt shared RELROs then we try first with shared
             // RELROs enabled, and if that fails then retry without.
@@ -394,7 +398,7 @@
 
                         try {
                             // Load the library using this Linker. May throw UnsatisfiedLinkError.
-                            loadLibrary(linker, zipFilePath, libFilePath);
+                            loadLibraryWithCustomLinker(linker, zipFilePath, libFilePath);
                         } catch (UnsatisfiedLinkError e) {
                             Log.e(TAG, "Unable to load library: " + library);
                             throw(e);
@@ -405,10 +409,19 @@
                 } else {
                     setEnvForNative();
                     preloadAlreadyLocked(appContext);
+
                     // Load libraries using the system linker.
                     for (String library : NativeLibraries.LIBRARIES) {
                         try {
-                            System.loadLibrary(library);
+                            if (!Linker.isInZipFile()) {
+                                System.loadLibrary(library);
+                            } else {
+                                // Load directly from the APK.
+                                String zipFilePath = appContext.getApplicationInfo().sourceDir;
+                                String libraryName = makeLibraryPathInZipFile(library, zipFilePath);
+                                Log.i(TAG, "libraryName: " + libraryName);
+                                System.load(libraryName);
+                            }
                         } catch (UnsatisfiedLinkError e) {
                             Log.e(TAG, "Unable to load library: " + library);
                             throw(e);
@@ -430,6 +443,39 @@
         }
     }
 
+    @RequiresApi(api = Build.VERSION_CODES.M)
+    @NonNull
+    private static String makeLibraryPathInZipFile(String library, String zipFilePath) {
+        assert Linker.isInZipFile();
+
+        // Determine whether the process is running in 32bit mode. The API is available starting
+        // from M, on L- there is no need to construct the full path inside the APK, so this
+        // path is omitted.
+        boolean is32BitProcess = !Process.is64Bit();
+
+        // Determine the ABI string that Android uses to find native libraries. Values are described
+        // in: https://developer.android.com/ndk/guides/abis.html
+        // The 'armeabi' is omitted here because it is not supported in Chrome/WebView, while Cronet
+        // and Cast load the native library via other paths.
+        String cpuAbi;
+        switch (NativeLibraries.sCpuFamily) {
+            case NativeLibraries.CPU_FAMILY_ARM:
+                cpuAbi = is32BitProcess ? "armeabi-v7a" : "arm64-v8a";
+                break;
+            case NativeLibraries.CPU_FAMILY_X86:
+                cpuAbi = is32BitProcess ? "x86" : "x86_64";
+                break;
+            case NativeLibraries.CPU_FAMILY_MIPS:
+                cpuAbi = is32BitProcess ? "mips" : "mips64";
+                break;
+            default:
+                throw new RuntimeException("Unknown CPU ABI for native libraries");
+        }
+
+        // Combine the above into the final path to the library in the APK.
+        return zipFilePath + "!/lib/" + cpuAbi + "/crazy." + System.mapLibraryName(library);
+    }
+
     // The WebView requires the Command Line to be switched over before
     // initialization is done. This is okay in the WebView's case since the
     // JNI is already loaded by this point.
@@ -491,7 +537,7 @@
     // Record Chromium linker histogram state for the main browser process. Called from
     // onNativeInitializationComplete().
     private void recordBrowserProcessHistogram() {
-        if (Linker.getInstance().isUsed()) {
+        if (Linker.isUsed()) {
             nativeRecordChromiumAndroidLinkerBrowserHistogram(
                     mIsUsingBrowserSharedRelros,
                     mLoadAtFixedAddressFailed,
@@ -506,7 +552,7 @@
     // Returns the device's status for loading a library directly from the APK file.
     // This method can only be called when the Chromium linker is used.
     private int getLibraryLoadFromApkStatus() {
-        assert Linker.getInstance().isUsed();
+        assert Linker.isUsed();
 
         if (mLibraryWasLoadedFromApk) {
             return LibraryLoadFromApkStatusCodes.SUCCESSFUL;
@@ -522,7 +568,7 @@
     // RecordChromiumAndroidLinkerRendererHistogram() will record it correctly.
     public void registerRendererProcessHistogram(boolean requestedSharedRelro,
                                                  boolean loadAtFixedAddressFailed) {
-        if (Linker.getInstance().isUsed()) {
+        if (Linker.isUsed()) {
             nativeRegisterChromiumAndroidLinkerRendererHistogram(requestedSharedRelro,
                                                                  loadAtFixedAddressFailed,
                                                                  mLibraryLoadTimeMs);
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java
index 827313d..48bafd6 100644
--- a/base/android/java/src/org/chromium/base/library_loader/Linker.java
+++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -10,7 +10,6 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 
-import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.annotations.AccessedByNative;
 
@@ -153,7 +152,7 @@
     private static final String LINKER_JNI_LIBRARY = "chromium_android_linker";
 
     // Constants used to control the behaviour of the browser process with
-    // regards to the shared RELRO section. Not applicable to ModernLinker.
+    // regards to the shared RELRO section.
     //   NEVER        -> The browser never uses it itself.
     //   LOW_RAM_ONLY -> It is only used on devices with low RAM.
     //   ALWAYS       -> It is always used.
@@ -164,13 +163,12 @@
 
     // Configuration variable used to control how the browser process uses the
     // shared RELRO. Only change this while debugging linker-related issues.
-    // Not used by ModernLinker.
     // NOTE: This variable's name is known and expected by the Linker test scripts.
     public static final int BROWSER_SHARED_RELRO_CONFIG =
             BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY;
 
     // Constants used to control the memory device config. Can be set explicitly
-    // by setMemoryDeviceConfigForTesting(). Not applicable to ModernLinker.
+    // by setMemoryDeviceConfigForTesting().
     //   INIT         -> Value is undetermined (will check at runtime).
     //   LOW          -> This is a low-memory device.
     //   NORMAL       -> This is not a low-memory device.
@@ -181,7 +179,6 @@
     // Indicates if this is a low-memory device or not. The default is to
     // determine this by probing the system at runtime, but this can be forced
     // for testing by calling setMemoryDeviceConfigForTesting().
-    // Not used by ModernLinker.
     protected int mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_INIT;
 
     // Set to true to enable debug logs.
@@ -208,13 +205,6 @@
     // ensure that we don't try to load outside the area originally requested.
     protected static final int ADDRESS_SPACE_RESERVATION = 192 * 1024 * 1024;
 
-    // Constants used to indicate a given Linker implementation, for testing.
-    //   LEGACY       -> Always uses the LegacyLinker implementation.
-    //   MODERN       -> Always uses the ModernLinker implementation.
-    // NOTE: These names are known and expected by the Linker test scripts.
-    public static final int LINKER_IMPLEMENTATION_LEGACY = 1;
-    public static final int LINKER_IMPLEMENTATION_MODERN = 2;
-
     // Singleton.
     private static Linker sSingleton;
     private static Object sSingletonLock = new Object();
@@ -223,35 +213,26 @@
     protected Linker() { }
 
     /**
-     * Get singleton instance. Returns either a LegacyLinker or a ModernLinker.
+     * Get singleton instance. Returns a LegacyLinker.
      *
-     * Returns a ModernLinker if running on Android M or later, otherwise returns
-     * a LegacyLinker.
+     * On N+ Monochrome is selected by Play Store. With Monochrome this code is not used, instead
+     * Chrome asks the WebView to provide the library (and the shared RELRO). If the WebView fails
+     * to provide the library, the system linker is used as a fallback.
      *
-     * ModernLinker requires OS features from Android M and later: a system linker
-     * that handles packed relocations and load from APK, and android_dlopen_ext()
-     * for shared RELRO support. It cannot run on Android releases earlier than M.
-     *
-     * LegacyLinker runs on all Android releases but it is slower and more complex
-     * than ModernLinker, so ModernLinker is preferred for Android M and later.
+     * LegacyLinker runs on all Android releases, but is incompatible with GVR library on N+.
+     * LegacyLinker is preferred on M- because it does not write the shared RELRO to disk at
+     * almost every cold startup.
      *
      * @return the Linker implementation instance.
      */
     public static final Linker getInstance() {
+        // TODO(pasko): The linker is created dynamically for historical reasons. Formerly there was
+        // a runtime choice between LegacyLinker and ModernLinker. To simplify, move the
+        // LegacyLinker logic into the Linker.
         synchronized (sSingletonLock) {
             if (sSingleton == null) {
-                // With incremental install, it's important to fall back to the "normal"
-                // library loading path in order for the libraries to be found.
-                String appClass =
-                        ContextUtils.getApplicationContext().getApplicationInfo().className;
-                boolean isIncrementalInstall =
-                        appClass != null && appClass.contains("incrementalinstall");
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !isIncrementalInstall) {
-                    sSingleton = ModernLinker.create();
-                } else {
-                    sSingleton = LegacyLinker.create();
-                }
-                Log.i(TAG, "Using linker: " + sSingleton.getClass().getName());
+                sSingleton = LegacyLinker.create();
+                Log.i(TAG, "Using linker: LegacyLinker");
             }
             return sSingleton;
         }
@@ -293,56 +274,6 @@
     }
 
     /**
-     * Set Linker implementation type.
-     * For testing. Sets either a LegacyLinker or a ModernLinker. Must be called
-     * before getInstance().
-     *
-     * @param type LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN
-     */
-    public static final void setImplementationForTesting(int type) {
-        // Sanity check. This method may only be called during tests.
-        assertLinkerTestsAreEnabled();
-        assertForTesting(type == LINKER_IMPLEMENTATION_LEGACY
-                         || type == LINKER_IMPLEMENTATION_MODERN);
-
-        synchronized (sSingletonLock) {
-            assertForTesting(sSingleton == null);
-
-            if (type == LINKER_IMPLEMENTATION_MODERN) {
-                sSingleton = ModernLinker.create();
-            } else if (type == LINKER_IMPLEMENTATION_LEGACY) {
-                sSingleton = LegacyLinker.create();
-            }
-            Log.i(TAG, "Forced linker: " + sSingleton.getClass().getName());
-        }
-    }
-
-    /**
-     * Get Linker implementation type.
-     * For testing.
-     *
-     * @return LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN
-     */
-    public final int getImplementationForTesting() {
-        // Sanity check. This method may only be called during tests.
-        assertLinkerTestsAreEnabled();
-
-        synchronized (sSingletonLock) {
-            assertForTesting(sSingleton == this);
-
-            if (sSingleton instanceof ModernLinker) {
-                return LINKER_IMPLEMENTATION_MODERN;
-            } else if (sSingleton instanceof LegacyLinker) {
-                return LINKER_IMPLEMENTATION_LEGACY;
-            } else {
-                Log.wtf(TAG, "Invalid linker: " + sSingleton.getClass().getName());
-                assertForTesting(false);
-            }
-            return 0;
-        }
-    }
-
-    /**
      * A public interface used to run runtime linker tests after loading
      * libraries. Should only be used to implement the linker unit tests,
      * which is controlled by the value of NativeLibraries.sEnableLinkerTests
@@ -397,32 +328,30 @@
     }
 
     /**
-     * Set up the Linker for a test.
-     * Convenience function that calls setImplementationForTesting() to force an
-     * implementation, and then setTestRunnerClassNameForTesting() to set the test
-     * class name.
+     * Sets the test class name.
      *
-     * On first call, instantiates a Linker of the requested type and sets its test
-     * runner class name. On subsequent calls, checks that the singleton produced by
-     * the first call matches the requested type and test runner class name.
+     * On the first call, instantiates a Linker and sets its test runner class name. On subsequent
+     * calls, checks that the singleton produced by the first call matches the test runner class
+     * name.
      */
-    public static final void setupForTesting(int type, String testRunnerClassName) {
+    public static final void setupForTesting(String testRunnerClassName) {
         if (DEBUG) {
-            Log.i(TAG, "setupForTesting(" + type + ", " + testRunnerClassName + ") called");
+            Log.i(TAG, "setupForTesting(" + testRunnerClassName + ") called");
         }
         // Sanity check. This method may only be called during tests.
         assertLinkerTestsAreEnabled();
 
         synchronized (sSingletonLock) {
-            // If this is the first call, configure the Linker to the given type and test class.
+            // If this is the first call, instantiate the Linker and the test class.
             if (sSingleton == null) {
-                setImplementationForTesting(type);
+                assertLinkerTestsAreEnabled();
+                assertForTesting(sSingleton == null);
+                sSingleton = LegacyLinker.create();
                 sSingleton.setTestRunnerClassNameForTesting(testRunnerClassName);
                 return;
             }
 
             // If not the first call, check that the Linker configuration matches this request.
-            assertForTesting(sSingleton.getImplementationForTesting() == type);
             String ourTestRunnerClassName = sSingleton.getTestRunnerClassNameForTesting();
             if (testRunnerClassName == null) {
                 assertForTesting(ourTestRunnerClassName == null);
@@ -597,7 +526,7 @@
      */
     public static boolean isInZipFile() {
         // The auto-generated NativeLibraries.sUseLibraryInZipFile variable will be true
-        // if the library remains embedded in the APK zip file on the target.
+        // iff the library remains embedded in the APK zip file on the target.
         return NativeLibraries.sUseLibraryInZipFile;
     }
 
@@ -607,6 +536,19 @@
      * libraries instead.
      */
     public static boolean isUsed() {
+        // A non-monochrome APK (such as ChromePublic.apk or ChromeModernPublic.apk) on N+ cannot
+        // use the LegacyLinker because the latter is incompatible with the GVR library. Fall back
+        // to using System.loadLibrary() or System.load() at the cost of no RELRO sharing.
+        //
+        // A non-monochrome APK (such as ChromePublic.apk) can be installed on N+ in these
+        // circumstances:
+        // * installing APK manually
+        // * after OTA from M to N
+        // * side-installing Chrome (possibly from another release channel)
+        // * Play Store bugs leading to incorrect APK flavor being installed
+        //
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) return false;
+
         // The auto-generated NativeLibraries.sUseLinker variable will be true if the
         // build has not explicitly disabled Linker features.
         return NativeLibraries.sUseLinker;
diff --git a/base/android/java/src/org/chromium/base/library_loader/ModernLinker.java b/base/android/java/src/org/chromium/base/library_loader/ModernLinker.java
deleted file mode 100644
index 2f3b9598b..0000000
--- a/base/android/java/src/org/chromium/base/library_loader/ModernLinker.java
+++ /dev/null
@@ -1,485 +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.
-
-package org.chromium.base.library_loader;
-
-import android.os.Bundle;
-import android.os.SystemClock;
-
-import org.chromium.base.Log;
-import org.chromium.base.PathUtils;
-
-import java.util.HashMap;
-import java.util.Locale;
-
-import javax.annotation.Nullable;
-
-/*
- * For more, see Technical note, Security considerations, and the explanation
- * of how this class is supposed to be used in Linker.java.
- */
-
-/**
- * Provides a concrete implementation of the Chromium Linker.
- *
- * This Linker implementation uses the Android M and later system linker to map and then
- * run Chrome for Android.
- *
- * For more on the operations performed by the Linker, see {@link Linker}.
- */
-class ModernLinker extends Linker {
-    // Log tag for this class.
-    private static final String TAG = "LibraryLoader";
-
-    // Becomes true after linker initialization.
-    private boolean mInitialized;
-
-    // Becomes true to indicate this process needs to wait for a shared RELRO in LibraryLoad().
-    private boolean mWaitForSharedRelros;
-
-    // The map of all RELRO sections either created or used in this process.
-    private HashMap<String, LibInfo> mSharedRelros;
-
-    // Cached Bundle representation of the RELRO sections map for transfer across processes.
-    private Bundle mSharedRelrosBundle;
-
-    // Set to true if this runs in the browser process. Disabled by initServiceProcess().
-    private boolean mInBrowserProcess = true;
-
-    // Current common random base load address. A value of -1 indicates not yet initialized.
-    private long mBaseLoadAddress = -1;
-
-    // Current fixed-location load address for the next library called by loadLibrary().
-    // Initialized to mBaseLoadAddress in prepareLibraryLoad(), and then adjusted as each
-    // library is loaded by loadLibrary().
-    private long mCurrentLoadAddress = -1;
-
-    // Becomes true once prepareLibraryLoad() has been called.
-    private boolean mPrepareLibraryLoadCalled;
-
-    // The map of libraries that are currently loaded in this process.
-    private HashMap<String, LibInfo> mLoadedLibraries;
-
-    // Private singleton constructor, and singleton factory method.
-    private ModernLinker() { }
-    static Linker create() {
-        return new ModernLinker();
-    }
-
-    // Used internally to initialize the linker's data. Assumes lock is held.
-    private void ensureInitializedLocked() {
-        assert Thread.holdsLock(mLock);
-        assert NativeLibraries.sUseLinker;
-
-        // On first call, load libchromium_android_linker.so. Cannot be done in the
-        // constructor because the instance is constructed on the UI thread.
-        if (!mInitialized) {
-            loadLinkerJniLibrary();
-            mInitialized = true;
-        }
-    }
-
-    /**
-     * Call this method to determine if the linker will try to use shared RELROs
-     * for the browser process.
-     */
-    @Override
-    public boolean isUsingBrowserSharedRelros() {
-        // This Linker does not attempt to share RELROS between the browser and
-        // the renderers, but only between renderers.
-        return false;
-    }
-
-    /**
-     * Call this method just before loading any native shared libraries in this process.
-     * Loads the Linker's JNI library, and initializes the variables involved in the
-     * implementation of shared RELROs.
-     */
-    @Override
-    public void prepareLibraryLoad() {
-        if (DEBUG) {
-            Log.i(TAG, "prepareLibraryLoad() called");
-        }
-        assert NativeLibraries.sUseLinker;
-
-        synchronized (mLock) {
-            assert !mPrepareLibraryLoadCalled;
-            ensureInitializedLocked();
-
-            // If in the browser, generate a random base load address for service processes
-            // and create an empty shared RELROs map. For service processes, the shared
-            // RELROs map must remain null until set by useSharedRelros().
-            if (mInBrowserProcess) {
-                setupBaseLoadAddressLocked();
-                mSharedRelros = new HashMap<String, LibInfo>();
-            }
-
-            // Create an empty loaded libraries map.
-            mLoadedLibraries = new HashMap<String, LibInfo>();
-
-            // Start the current load address at the base load address.
-            mCurrentLoadAddress = mBaseLoadAddress;
-
-            mPrepareLibraryLoadCalled = true;
-        }
-    }
-
-    /**
-     * Call this method just after loading all native shared libraries in this process.
-     * If not in the browser, closes the LibInfo entries used for RELRO sharing.
-     */
-    @Override
-    public void finishLibraryLoad() {
-        if (DEBUG) {
-            Log.i(TAG, "finishLibraryLoad() called");
-        }
-
-        synchronized (mLock) {
-            assert mPrepareLibraryLoadCalled;
-
-            // Close shared RELRO file descriptors if not in the browser.
-            if (!mInBrowserProcess && mSharedRelros != null) {
-                closeLibInfoMap(mSharedRelros);
-                mSharedRelros = null;
-            }
-
-            // If testing, run tests now that all libraries are loaded and initialized.
-            if (NativeLibraries.sEnableLinkerTests) {
-                runTestRunnerClassForTesting(0, mInBrowserProcess);
-            }
-        }
-    }
-
-    // Used internally to wait for shared RELROs. Returns once useSharedRelros() has been
-    // called to supply a valid shared RELROs bundle.
-    private void waitForSharedRelrosLocked() {
-        if (DEBUG) {
-            Log.i(TAG, "waitForSharedRelros called");
-        }
-        assert Thread.holdsLock(mLock);
-
-        // Return immediately if shared RELROs are already available.
-        if (mSharedRelros != null) {
-            return;
-        }
-
-        // Wait until notified by useSharedRelros() that shared RELROs have arrived.
-        long startTime = DEBUG ? SystemClock.uptimeMillis() : 0;
-        while (mSharedRelros == null) {
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                // Restore the thread's interrupt status.
-                Thread.currentThread().interrupt();
-            }
-        }
-
-        if (DEBUG) {
-            Log.i(TAG, String.format(
-                    Locale.US, "Time to wait for shared RELRO: %d ms",
-                    SystemClock.uptimeMillis() - startTime));
-        }
-    }
-
-    /**
-     * Call this to send a Bundle containing the shared RELRO sections to be
-     * used in this process. If initServiceProcess() was previously called,
-     * libraryLoad() will wait until this method is called in another
-     * thread with a non-null value.
-     *
-     * @param bundle The Bundle instance containing a map of shared RELRO sections
-     * to use in this process.
-     */
-    @Override
-    public void useSharedRelros(Bundle bundle) {
-        if (DEBUG) {
-            Log.i(TAG, "useSharedRelros() called with " + bundle);
-        }
-
-        synchronized (mLock) {
-            mSharedRelros = createLibInfoMapFromBundle(bundle);
-            mLock.notifyAll();
-        }
-    }
-
-    /**
-     * Call this to retrieve the shared RELRO sections created in this process,
-     * after loading all libraries.
-     *
-     * @return a new Bundle instance, or null if RELRO sharing is disabled on
-     * this system, or if initServiceProcess() was called previously.
-     */
-    @Override
-    public Bundle getSharedRelros() {
-        if (DEBUG) {
-            Log.i(TAG, "getSharedRelros() called");
-        }
-        synchronized (mLock) {
-            if (!mInBrowserProcess) {
-                if (DEBUG) {
-                    Log.i(TAG, "Not in browser, so returning null Bundle");
-                }
-                return null;
-            }
-
-            // Create a new Bundle containing RELRO section information for all the shared
-            // RELROs created while loading libraries.
-            if (mSharedRelrosBundle == null && mSharedRelros != null) {
-                mSharedRelrosBundle = createBundleFromLibInfoMap(mSharedRelros);
-                if (DEBUG) {
-                    Log.i(TAG, "Shared RELRO bundle created from map: " + mSharedRelrosBundle);
-                }
-            }
-            if (DEBUG) {
-                Log.i(TAG, "Returning " + mSharedRelrosBundle);
-            }
-            return mSharedRelrosBundle;
-        }
-    }
-
-
-    /**
-     * Call this method before loading any libraries to indicate that this
-     * process shall neither create or reuse shared RELRO sections.
-     */
-    @Override
-    public void disableSharedRelros() {
-        if (DEBUG) {
-            Log.i(TAG, "disableSharedRelros() called");
-        }
-        synchronized (mLock) {
-            // Mark this as a service process, and disable wait for shared RELRO.
-            mInBrowserProcess = false;
-            mWaitForSharedRelros = false;
-        }
-    }
-
-    /**
-     * Call this method before loading any libraries to indicate that this
-     * process is ready to reuse shared RELRO sections from another one.
-     * Typically used when starting service processes.
-     *
-     * @param baseLoadAddress the base library load address to use.
-     */
-    @Override
-    public void initServiceProcess(long baseLoadAddress) {
-        if (DEBUG) {
-            Log.i(TAG, String.format(
-                    Locale.US, "initServiceProcess(0x%x) called",
-                    baseLoadAddress));
-        }
-        synchronized (mLock) {
-            assert !mPrepareLibraryLoadCalled;
-
-            // Mark this as a service process, and flag wait for shared RELRO.
-            // Save the base load address passed in.
-            mInBrowserProcess = false;
-            mWaitForSharedRelros = true;
-            mBaseLoadAddress = baseLoadAddress;
-        }
-    }
-
-    /**
-     * Retrieve the base load address for libraries that share RELROs.
-     *
-     * @return a common, random base load address, or 0 if RELRO sharing is
-     * disabled.
-     */
-    @Override
-    public long getBaseLoadAddress() {
-        synchronized (mLock) {
-            ensureInitializedLocked();
-            setupBaseLoadAddressLocked();
-            if (DEBUG) {
-                Log.i(TAG, String.format(
-                        Locale.US, "getBaseLoadAddress() returns 0x%x",
-                        mBaseLoadAddress));
-            }
-            return mBaseLoadAddress;
-        }
-    }
-
-    // Used internally to lazily setup the common random base load address.
-    private void setupBaseLoadAddressLocked() {
-        assert Thread.holdsLock(mLock);
-
-        // No-op if the base load address is already set up.
-        if (mBaseLoadAddress == -1) {
-            mBaseLoadAddress = getRandomBaseLoadAddress();
-        }
-        if (mBaseLoadAddress == 0) {
-            // If the random address is 0 there are issues with finding enough
-            // free address space, so disable RELRO shared / fixed load addresses.
-            Log.w(TAG, "Disabling shared RELROs due address space pressure");
-            mWaitForSharedRelros = false;
-        }
-    }
-
-    /**
-     * Load a native shared library with the Chromium linker. If the zip file
-     * is not null, the shared library must be uncompressed and page aligned
-     * inside the zipfile. The library must not be the Chromium linker library.
-     *
-     * If asked to wait for shared RELROs, this function will block library loads
-     * until the shared RELROs bundle is received by useSharedRelros().
-     *
-     * @param zipFilePath The path of the zip file containing the library (or null).
-     * @param libFilePath The path of the library (possibly in the zip file).
-     * @param isFixedAddressPermitted If true, uses a fixed load address if one was
-     * supplied, otherwise ignores the fixed address and loads wherever available.
-     */
-    @Override
-    void loadLibraryImpl(@Nullable String zipFilePath,
-                         String libFilePath,
-                         boolean isFixedAddressPermitted) {
-        if (DEBUG) {
-            Log.i(TAG, "loadLibraryImpl: "
-                    + zipFilePath + ", " + libFilePath + ", " + isFixedAddressPermitted);
-        }
-
-        synchronized (mLock) {
-            assert mPrepareLibraryLoadCalled;
-
-            String dlopenExtPath;
-            if (zipFilePath != null) {
-                // The android_dlopen_ext() function understands strings with the format
-                // <zip_path>!/<file_path> to represent the file_path element within the zip
-                // file at zip_path. This enables directly loading from APK. We add the
-                // "crazy." prefix to the path in the zip file to prevent the Android package
-                // manager from seeing this as a library and so extracting it from the APK.
-                String cpuAbi = nativeGetCpuAbi();
-                dlopenExtPath = zipFilePath + "!/lib/" + cpuAbi + "/crazy." + libFilePath;
-            } else {
-                // Not loading from APK directly, so simply pass the library name to
-                // android_dlopen_ext().
-                dlopenExtPath = libFilePath;
-            }
-
-            if (mLoadedLibraries.containsKey(dlopenExtPath)) {
-                if (DEBUG) {
-                    Log.i(TAG, "Not loading " + libFilePath + " twice");
-                }
-                return;
-            }
-
-            // If not in the browser, shared RELROs are not disabled, and fixed addresses
-            // have not been disallowed, load the library at a fixed address. Otherwise,
-            // load anywhere.
-            long loadAddress = 0;
-            if (!mInBrowserProcess && mWaitForSharedRelros && isFixedAddressPermitted) {
-                loadAddress = mCurrentLoadAddress;
-
-                // For multiple libraries, ensure we stay within reservation range.
-                if (loadAddress > mBaseLoadAddress + ADDRESS_SPACE_RESERVATION) {
-                    String errorMessage = "Load address outside reservation, for: " + libFilePath;
-                    Log.e(TAG, errorMessage);
-                    throw new UnsatisfiedLinkError(errorMessage);
-                }
-            }
-
-            LibInfo libInfo = new LibInfo();
-
-            if (mInBrowserProcess && mCurrentLoadAddress != 0) {
-                // We are in the browser, and with a current load address that indicates that
-                // there is enough address space for shared RELRO to operate. Create the
-                // shared RELRO, and store it in the map.
-                String relroPath = PathUtils.getDataDirectory() + "/RELRO:" + libFilePath;
-                if (nativeCreateSharedRelro(dlopenExtPath,
-                                            mCurrentLoadAddress, relroPath, libInfo)) {
-                    mSharedRelros.put(dlopenExtPath, libInfo);
-                } else {
-                    String errorMessage = "Unable to create shared relro: " + relroPath;
-                    Log.w(TAG, errorMessage);
-                }
-            } else if (!mInBrowserProcess && mCurrentLoadAddress != 0 && mWaitForSharedRelros) {
-                // We are in a service process, again with a current load address that is
-                // suitable for shared RELRO, and we are to wait for shared RELROs. So
-                // do that, then use the map we receive to provide libinfo for library load.
-                waitForSharedRelrosLocked();
-                if (mSharedRelros.containsKey(dlopenExtPath)) {
-                    libInfo = mSharedRelros.get(dlopenExtPath);
-                }
-            }
-
-            // Load the library. In the browser, loadAddress is 0, so nativeLoadLibrary()
-            // will load without shared RELRO. Otherwise, it uses shared RELRO if the attached
-            // libInfo is usable.
-            if (!nativeLoadLibrary(dlopenExtPath, loadAddress, libInfo)) {
-                String errorMessage = "Unable to load library: " + dlopenExtPath;
-                Log.e(TAG, errorMessage);
-                throw new UnsatisfiedLinkError(errorMessage);
-            }
-
-            // Print the load address to the logcat when testing the linker. The format
-            // of the string is expected by the Python test_runner script as one of:
-            //    BROWSER_LIBRARY_ADDRESS: <library-name> <address>
-            //    RENDERER_LIBRARY_ADDRESS: <library-name> <address>
-            // Where <library-name> is the library name, and <address> is the hexadecimal load
-            // address.
-            if (NativeLibraries.sEnableLinkerTests) {
-                String tag = mInBrowserProcess ? "BROWSER_LIBRARY_ADDRESS"
-                                               : "RENDERER_LIBRARY_ADDRESS";
-                Log.i(TAG, String.format(
-                        Locale.US, "%s: %s %x", tag, libFilePath, libInfo.mLoadAddress));
-            }
-
-            if (loadAddress != 0 && mCurrentLoadAddress != 0) {
-                // Compute the next current load address. If mCurrentLoadAddress
-                // is not 0, this is an explicit library load address.
-                mCurrentLoadAddress = libInfo.mLoadAddress + libInfo.mLoadSize
-                                      + BREAKPAD_GUARD_REGION_BYTES;
-            }
-
-            mLoadedLibraries.put(dlopenExtPath, libInfo);
-            if (DEBUG) {
-                Log.i(TAG, "Library details " + libInfo.toString());
-            }
-        }
-    }
-
-    /**
-     * Native method to return the CPU ABI.
-     * Obtaining it from the linker's native code means that we always correctly
-     * match the loaded library's ABI to the linker's ABI.
-     *
-     * @return CPU ABI string.
-     */
-    private static native String nativeGetCpuAbi();
-
-    /**
-     * Native method used to load a library.
-     *
-     * @param dlopenExtPath For load from APK, the path to the enclosing
-     * zipfile concatenated with "!/" and the path to the library within the zipfile;
-     * otherwise the platform specific library name (e.g. libfoo.so).
-     * @param loadAddress Explicit load address, or 0 for randomized one.
-     * @param libInfo If not null, the mLoadAddress and mLoadSize fields
-     * of this LibInfo instance will set on success.
-     * @return true for success, false otherwise.
-     */
-    private static native boolean nativeLoadLibrary(String dlopenExtPath,
-                                                    long loadAddress,
-                                                    LibInfo libInfo);
-
-    /**
-     * Native method used to create a shared RELRO section.
-     * Creates a shared RELRO file for the given library. Done by loading a
-     * a new temporary library at the specified address, saving the RELRO section
-     * from it, then unloading.
-     *
-     * @param dlopenExtPath For load from APK, the path to the enclosing
-     * zipfile concatenated with "!/" and the path to the library within the zipfile;
-     * otherwise the platform specific library name (e.g. libfoo.so).
-     * @param loadAddress load address, which can be different from the one
-     * used to load the library in the current process!
-     * @param relroPath Path to the shared RELRO file for this library.
-     * @param libInfo libInfo instance. On success, the mRelroStart, mRelroSize
-     * and mRelroFd will be set.
-     * @return true on success, false otherwise.
-     */
-    private static native boolean nativeCreateSharedRelro(String dlopenExtPath,
-                                                          long loadAddress,
-                                                          String relroPath,
-                                                          LibInfo libInfo);
-}
diff --git a/base/android/java/templates/NativeLibraries.template b/base/android/java/templates/NativeLibraries.template
index 56022042..68277df7 100644
--- a/base/android/java/templates/NativeLibraries.template
+++ b/base/android/java/templates/NativeLibraries.template
@@ -42,6 +42,11 @@
      * the sources of each and every Chromium-based target.
      */
 
+    public static final int CPU_FAMILY_UNKNOWN = 0;
+    public static final int CPU_FAMILY_ARM = 1;
+    public static final int CPU_FAMILY_MIPS = 2;
+    public static final int CPU_FAMILY_X86 = 3;
+
 #if defined(ENABLE_CHROMIUM_LINKER_LIBRARY_IN_ZIP_FILE) && \
     !defined(ENABLE_CHROMIUM_LINKER)
 #error "Must have ENABLE_CHROMIUM_LINKER to enable library in zip file"
@@ -89,4 +94,16 @@
 #else
       "";
 #endif
+
+    public static int sCpuFamily =
+#if defined(ANDROID_APP_CPU_FAMILY_ARM)
+        CPU_FAMILY_ARM;
+#elif defined(ANDROID_APP_CPU_FAMILY_X86)
+        CPU_FAMILY_X86;
+#elif defined(ANDROID_APP_CPU_FAMILY_MIPS)
+        CPU_FAMILY_MIPS;
+#else
+        CPU_FAMILY_UNKNOWN;
+#endif
+
 }
diff --git a/base/android/linker/BUILD.gn b/base/android/linker/BUILD.gn
index 5f85cc2..f664045 100644
--- a/base/android/linker/BUILD.gn
+++ b/base/android/linker/BUILD.gn
@@ -13,8 +13,6 @@
     "legacy_linker_jni.h",
     "linker_jni.cc",
     "linker_jni.h",
-    "modern_linker_jni.cc",
-    "modern_linker_jni.h",
   ]
 
   # The NDK contains the crazy_linker here:
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc
index 86142a3..cc424ee3 100644
--- a/base/android/linker/linker_jni.cc
+++ b/base/android/linker/linker_jni.cc
@@ -20,7 +20,6 @@
 #include <string.h>
 
 #include "legacy_linker_jni.h"
-#include "modern_linker_jni.h"
 
 namespace chromium_android_linker {
 
@@ -224,8 +223,7 @@
   }
 
   // Initialize linker base and implementations.
-  if (!LinkerJNIInit(vm, env)
-      || !LegacyLinkerJNIInit(vm, env) || !ModernLinkerJNIInit(vm, env)) {
+  if (!LinkerJNIInit(vm, env) || !LegacyLinkerJNIInit(vm, env)) {
     return -1;
   }
 
diff --git a/base/android/linker/modern_linker_jni.cc b/base/android/linker/modern_linker_jni.cc
deleted file mode 100644
index 5218fbd..0000000
--- a/base/android/linker/modern_linker_jni.cc
+++ /dev/null
@@ -1,643 +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.
-
-// This is the version of the Android-specific Chromium linker that uses
-// the Android M and later system linker to load libraries.
-
-// This source code *cannot* depend on anything from base/ or the C++
-// STL, to keep the final library small, and avoid ugly dependency issues.
-
-#include "modern_linker_jni.h"
-
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <jni.h>
-#include <limits.h>
-#include <link.h>
-#include <stddef.h>
-#include <string.h>
-
-#include "android_dlext.h"
-#include "linker_jni.h"
-
-#define PAGE_START(x) ((x) & PAGE_MASK)
-#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE - 1))
-
-namespace chromium_android_linker {
-namespace {
-
-// Record of the Java VM passed to JNI_OnLoad().
-static JavaVM* s_java_vm = nullptr;
-
-// Get the CPU ABI string for which the linker is running.
-//
-// The returned string is used to construct the path to libchrome.so when
-// loading directly from APK.
-//
-// |env| is the current JNI environment handle.
-// |clazz| is the static class handle for org.chromium.base.Linker,
-// and is ignored here.
-// Returns the CPU ABI string for which the linker is running.
-jstring GetCpuAbi(JNIEnv* env, jclass clazz) {
-#if defined(__arm__) && defined(__ARM_ARCH_7A__)
-  static const char* kCurrentAbi = "armeabi-v7a";
-#elif defined(__arm__)
-  static const char* kCurrentAbi = "armeabi";
-#elif defined(__i386__)
-  static const char* kCurrentAbi = "x86";
-#elif defined(__mips__)
-  static const char* kCurrentAbi = "mips";
-#elif defined(__x86_64__)
-  static const char* kCurrentAbi = "x86_64";
-#elif defined(__aarch64__)
-  static const char* kCurrentAbi = "arm64-v8a";
-#else
-#error "Unsupported target abi"
-#endif
-  return env->NewStringUTF(kCurrentAbi);
-}
-
-// Convenience wrapper around dlsym() on the main executable. Returns
-// the address of the requested symbol, or nullptr if not found. Status
-// is available from dlerror().
-void* Dlsym(const char* symbol_name) {
-  static void* handle = nullptr;
-
-  if (!handle)
-    handle = dlopen(nullptr, RTLD_NOW);
-
-  void* result = dlsym(handle, symbol_name);
-  return result;
-}
-
-// dl_iterate_phdr() wrapper, accessed via dlsym lookup. Done this way.
-// so that this code compiles for Android versions that are too early to
-// offer it. Checks in LibraryLoader.java should ensure that we
-// never reach here at runtime on Android versions that are too old to
-// supply dl_iterate_phdr; that is, earlier than Android M. Returns
-// false if no dl_iterate_phdr() is available, otherwise true with the
-// return value from dl_iterate_phdr() in |status|.
-bool DlIteratePhdr(int (*callback)(dl_phdr_info*, size_t, void*),
-                   void* data,
-                   int* status) {
-  using DlIteratePhdrCallback = int (*)(dl_phdr_info*, size_t, void*);
-  using DlIteratePhdrFunctionPtr = int (*)(DlIteratePhdrCallback, void*);
-  static DlIteratePhdrFunctionPtr function_ptr = nullptr;
-
-  if (!function_ptr) {
-    function_ptr =
-        reinterpret_cast<DlIteratePhdrFunctionPtr>(Dlsym("dl_iterate_phdr"));
-    if (!function_ptr) {
-      LOG_ERROR("dlsym: dl_iterate_phdr: %s", dlerror());
-      return false;
-    }
-  }
-
-  *status = (*function_ptr)(callback, data);
-  return true;
-}
-
-// Convenience struct wrapper round android_dlextinfo.
-struct AndroidDlextinfo {
-  AndroidDlextinfo(int flags,
-                   void* reserved_addr, size_t reserved_size, int relro_fd) {
-    memset(&extinfo, 0, sizeof(extinfo));
-    extinfo.flags = flags;
-    extinfo.reserved_addr = reserved_addr;
-    extinfo.reserved_size = reserved_size;
-    extinfo.relro_fd = relro_fd;
-  }
-
-  android_dlextinfo extinfo;
-};
-
-// android_dlopen_ext() wrapper, accessed via dlsym lookup. Returns false
-// if no android_dlopen_ext() is available, otherwise true with the return
-// value from android_dlopen_ext() in |status|.
-bool AndroidDlopenExt(const char* filename,
-                      int flag,
-                      const AndroidDlextinfo* dlextinfo,
-                      void** status) {
-  using DlopenExtFunctionPtr = void* (*)(const char*,
-                                         int, const android_dlextinfo*);
-  static DlopenExtFunctionPtr function_ptr = nullptr;
-
-  if (!function_ptr) {
-    function_ptr =
-        reinterpret_cast<DlopenExtFunctionPtr>(Dlsym("android_dlopen_ext"));
-    if (!function_ptr) {
-      LOG_ERROR("dlsym: android_dlopen_ext: %s", dlerror());
-      return false;
-    }
-  }
-
-  const android_dlextinfo* extinfo = &dlextinfo->extinfo;
-  LOG_INFO("android_dlopen_ext:"
-           " flags=0x%llx, reserved_addr=%p, reserved_size=%d, relro_fd=%d",
-           static_cast<long long>(extinfo->flags),
-           extinfo->reserved_addr,
-           static_cast<int>(extinfo->reserved_size),
-           extinfo->relro_fd);
-
-  *status = (*function_ptr)(filename, flag, extinfo);
-  return true;
-}
-
-// Callback data for FindLoadedLibrarySize().
-struct CallbackData {
-  explicit CallbackData(void* address)
-      : load_address(address), load_size(0), min_vaddr(0) { }
-
-  const void* load_address;
-  size_t load_size;
-  size_t min_vaddr;
-};
-
-// Callback for dl_iterate_phdr(). Read phdrs to identify whether or not
-// this library's load address matches the |load_address| passed in
-// |data|. If yes, pass back load size and min vaddr via |data|. A non-zero
-// return value terminates iteration.
-int FindLoadedLibrarySize(dl_phdr_info* info, size_t size UNUSED, void* data) {
-  CallbackData* callback_data = reinterpret_cast<CallbackData*>(data);
-
-  // Use max and min vaddr to compute the library's load size.
-  ElfW(Addr) min_vaddr = ~0;
-  ElfW(Addr) max_vaddr = 0;
-
-  bool is_matching = false;
-  for (size_t i = 0; i < info->dlpi_phnum; ++i) {
-    const ElfW(Phdr)* phdr = &info->dlpi_phdr[i];
-    if (phdr->p_type != PT_LOAD)
-      continue;
-
-    // See if this segment's load address matches what we passed to
-    // android_dlopen_ext as extinfo.reserved_addr.
-    void* load_addr = reinterpret_cast<void*>(info->dlpi_addr + phdr->p_vaddr);
-    if (load_addr == callback_data->load_address)
-      is_matching = true;
-
-    if (phdr->p_vaddr < min_vaddr)
-      min_vaddr = phdr->p_vaddr;
-    if (phdr->p_vaddr + phdr->p_memsz > max_vaddr)
-      max_vaddr = phdr->p_vaddr + phdr->p_memsz;
-  }
-
-  // If this library matches what we seek, return its load size.
-  if (is_matching) {
-    callback_data->load_size = PAGE_END(max_vaddr) - PAGE_START(min_vaddr);
-    callback_data->min_vaddr = min_vaddr;
-    return true;
-  }
-
-  return false;
-}
-
-// Helper class for anonymous memory mapping.
-class ScopedAnonymousMmap {
- public:
-  ScopedAnonymousMmap(void* addr, size_t size);
-
-  ~ScopedAnonymousMmap() { munmap(addr_, size_); }
-
-  void* GetAddr() const { return effective_addr_; }
-  void Release() { addr_ = nullptr; size_ = 0; effective_addr_ = nullptr; }
-
- private:
-  void* addr_;
-  size_t size_;
-
-  // The effective_addr_ is the address seen by client code. It may or may
-  // not be the same as addr_, the real start of the anonymous mapping.
-  void* effective_addr_;
-};
-
-// ScopedAnonymousMmap constructor. |addr| is a requested mapping address, or
-// zero if any address will do, and |size| is the size of mapping required.
-ScopedAnonymousMmap::ScopedAnonymousMmap(void* addr, size_t size) {
-#if RESERVE_BREAKPAD_GUARD_REGION
-  // Increase size to extend the address reservation mapping so that it will
-  // also include a guard region from load_bias_ to start_addr. If loading
-  // at a fixed address, move our requested address back by the guard region
-  // size.
-  size += kBreakpadGuardRegionBytes;
-  if (addr) {
-    if (addr < reinterpret_cast<void*>(kBreakpadGuardRegionBytes)) {
-      LOG_ERROR("Fixed address %p is too low to accommodate Breakpad guard",
-                addr);
-      addr_ = MAP_FAILED;
-      size_ = 0;
-      return;
-    }
-    addr = reinterpret_cast<void*>(
-        reinterpret_cast<uintptr_t>(addr) - kBreakpadGuardRegionBytes);
-  }
-  LOG_INFO("Added %d to size, for Breakpad guard",
-           static_cast<int>(kBreakpadGuardRegionBytes));
-#endif
-
-  addr_ = mmap(addr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  if (addr_ != MAP_FAILED) {
-    size_ = size;
-  } else {
-    LOG_INFO("mmap failed: %s", strerror(errno));
-    size_ = 0;
-  }
-  effective_addr_ = addr_;
-
-#if RESERVE_BREAKPAD_GUARD_REGION
-  // If we increased size to accommodate a Breakpad guard region, move
-  // the effective address, if valid, upwards by the size of the guard region.
-  if (addr_ == MAP_FAILED)
-    return;
-  if (addr_ < reinterpret_cast<void*>(kBreakpadGuardRegionBytes)) {
-    LOG_ERROR("Map address %p is too low to accommodate Breakpad guard",
-              addr_);
-    effective_addr_ = MAP_FAILED;
-  } else {
-    effective_addr_ = reinterpret_cast<void*>(
-        reinterpret_cast<uintptr_t>(addr_) + kBreakpadGuardRegionBytes);
-  }
-#endif
-}
-
-// Helper for LoadLibrary(). Return the actual size of the library loaded
-// at |addr| in |load_size|, and the min vaddr in |min_vaddr|. Returns false
-// if the library appears not to be loaded.
-bool GetLibraryLoadSize(void* addr, size_t* load_size, size_t* min_vaddr) {
-  LOG_INFO("Called for %p", addr);
-
-  // Find the real load size and min vaddr for the library loaded at |addr|.
-  CallbackData callback_data(addr);
-  int status = 0;
-  if (!DlIteratePhdr(&FindLoadedLibrarySize, &callback_data, &status)) {
-    LOG_ERROR("No dl_iterate_phdr function found");
-    return false;
-  }
-  if (!status) {
-    LOG_ERROR("Failed to find library at address %p", addr);
-    return false;
-  }
-
-  *load_size = callback_data.load_size;
-  *min_vaddr = callback_data.min_vaddr;
-  return true;
-}
-
-// Helper for LoadLibrary(). We reserve an address space larger than
-// needed. After library loading we want to trim that reservation to only
-// what is needed. Failure to trim should not occur, but if it does then
-// everything will still run, so we treat it as a warning rather than
-// an error.
-void ResizeReservedAddressSpace(void* addr,
-                                size_t reserved_size,
-                                size_t load_size,
-                                size_t min_vaddr) {
-  LOG_INFO("Called for %p, reserved %d, loaded %d, min_vaddr %d",
-           addr, static_cast<int>(reserved_size),
-           static_cast<int>(load_size), static_cast<int>(min_vaddr));
-
-  const uintptr_t uintptr_addr = reinterpret_cast<uintptr_t>(addr);
-
-  if (reserved_size > load_size) {
-    // Unmap the part of the reserved address space that is beyond the end of
-    // the loaded library data.
-    void* unmap = reinterpret_cast<void*>(uintptr_addr + load_size);
-    const size_t length = reserved_size - load_size;
-    if (munmap(unmap, length) == -1) {
-      LOG_ERROR("WARNING: unmap of %d bytes at %p failed: %s",
-                static_cast<int>(length), unmap, strerror(errno));
-    }
-  } else {
-    LOG_ERROR("WARNING: library reservation was too small");
-  }
-
-#if RESERVE_BREAKPAD_GUARD_REGION
-  if (kBreakpadGuardRegionBytes > min_vaddr) {
-    // Unmap the part of the reserved address space that is ahead of where we
-    // actually need the guard region to start. Resizes the guard region to
-    // min_vaddr bytes.
-    void* unmap =
-        reinterpret_cast<void*>(uintptr_addr - kBreakpadGuardRegionBytes);
-    const size_t length = kBreakpadGuardRegionBytes - min_vaddr;
-    if (munmap(unmap, length) == -1) {
-      LOG_ERROR("WARNING: unmap of %d bytes at %p failed: %s",
-                static_cast<int>(length), unmap, strerror(errno));
-    }
-  } else {
-    LOG_ERROR("WARNING: breakpad guard region reservation was too small");
-  }
-#endif
-}
-
-// Load a library with the chromium linker, using android_dlopen_ext().
-//
-// android_dlopen_ext() understands how to directly load from a zipfile,
-// based on the format of |dlopen_ext_path|. If it contains a "!/" separator
-// then the string indicates <zip_path>!/<file_path> and indicates the
-// file_path element within the zip file at zip_path. A library in a
-// zipfile must be uncompressed and page aligned. The library is expected
-// to be lib/<abi_tag>/crazy.<basename>. The <abi_tag> used will be the
-// same as the abi for this linker. The "crazy." prefix is included
-// so that the Android Package Manager doesn't extract the library into
-// /data/app-lib.
-//
-// If |dlopen_ext_path| contains no "!/" separator then android_dlopen_ext()
-// assumes that it is a normal path to a standalone library file.
-//
-// Loading the library will also call its JNI_OnLoad() method, which
-// shall register its methods. Note that lazy native method resolution
-// will _not_ work after this, because Dalvik uses the system's dlsym()
-// which won't see the new library, so explicit registration is mandatory.
-//
-// |env| is the current JNI environment handle.
-// |clazz| is the static class handle for org.chromium.base.Linker,
-// and is ignored here.
-// |dlopen_ext_path| is the library identifier (e.g. libfoo.so).
-// |load_address| is an explicit load address.
-// |relro_path| is the path to the file into which RELRO data is held.
-// |lib_info_obj| is a LibInfo handle used to communicate information
-// with the Java side.
-// Return true on success.
-jboolean LoadLibrary(JNIEnv* env,
-                     jclass clazz,
-                     jstring dlopen_ext_path,
-                     jlong load_address,
-                     jobject lib_info_obj) {
-  String dlopen_library_path(env, dlopen_ext_path);
-  LOG_INFO("Called for %s, at address 0x%llx",
-           dlopen_library_path.c_str(), load_address);
-
-  if (!IsValidAddress(load_address)) {
-    LOG_ERROR("Invalid address 0x%llx", load_address);
-    return false;
-  }
-
-  const size_t size = kAddressSpaceReservationSize;
-  void* wanted_addr = reinterpret_cast<void*>(load_address);
-
-  // Reserve the address space into which we load the library.
-  ScopedAnonymousMmap mapping(wanted_addr, size);
-  void* addr = mapping.GetAddr();
-  if (addr == MAP_FAILED) {
-    LOG_ERROR("Failed to reserve space for load");
-    return false;
-  }
-  if (wanted_addr && addr != wanted_addr) {
-    LOG_ERROR("Failed to obtain fixed address for load");
-    return false;
-  }
-
-  // Build dlextinfo to load the library into the reserved space, using
-  // the shared RELRO if supplied and if its start address matches addr.
-  int relro_fd = -1;
-  int flags = ANDROID_DLEXT_RESERVED_ADDRESS;
-  if (wanted_addr && lib_info_obj) {
-    void* relro_start;
-    s_lib_info_fields.GetRelroInfo(env, lib_info_obj,
-                                   reinterpret_cast<size_t*>(&relro_start),
-                                   nullptr, &relro_fd);
-    if (relro_fd != -1 && relro_start == addr) {
-      flags |= ANDROID_DLEXT_USE_RELRO;
-    }
-  }
-  AndroidDlextinfo dlextinfo(flags, addr, size, relro_fd);
-
-  // Load the library into the reserved space.
-  const char* path = dlopen_library_path.c_str();
-  void* handle = nullptr;
-  if (!AndroidDlopenExt(path, RTLD_NOW, &dlextinfo, &handle)) {
-    LOG_ERROR("No android_dlopen_ext function found");
-    return false;
-  }
-  if (handle == nullptr) {
-    LOG_ERROR("android_dlopen_ext: %s", dlerror());
-    return false;
-  }
-
-  // For https://crbug.com/568880.
-  //
-  // Release the scoped mapping. Now that the library has loaded we can no
-  // longer assume we have control of all of this area. libdl knows addr and
-  // has loaded the library into some portion of the reservation. It will
-  // not expect that portion of memory to be arbitrarily unmapped.
-  mapping.Release();
-
-  // After loading we can find the actual size of the library. It should
-  // be less than the space we reserved for it.
-  size_t load_size = 0;
-  size_t min_vaddr = 0;
-  if (!GetLibraryLoadSize(addr, &load_size, &min_vaddr)) {
-    LOG_ERROR("Unable to find size for load at %p", addr);
-    return false;
-  }
-
-  // Trim the reservation mapping to match the library's actual size. Failure
-  // to resize is not a fatal error. At worst we lose a portion of virtual
-  // address space that we might otherwise have recovered. Note that trimming
-  // the mapping here requires that we have already released the scoped
-  // mapping.
-  ResizeReservedAddressSpace(addr, size, load_size, min_vaddr);
-
-  // Locate and if found then call the loaded library's JNI_OnLoad() function.
-  using JNI_OnLoadFunctionPtr = int (*)(void* vm, void* reserved);
-  auto jni_onload =
-      reinterpret_cast<JNI_OnLoadFunctionPtr>(dlsym(handle, "JNI_OnLoad"));
-  if (jni_onload != nullptr) {
-    // Check that JNI_OnLoad returns a usable JNI version.
-    int jni_version = (*jni_onload)(s_java_vm, nullptr);
-    if (jni_version < JNI_VERSION_1_4) {
-      LOG_ERROR("JNI version is invalid: %d", jni_version);
-      return false;
-    }
-  }
-
-  // Note the load address and load size in the supplied libinfo object.
-  const size_t cast_addr = reinterpret_cast<size_t>(addr);
-  s_lib_info_fields.SetLoadInfo(env, lib_info_obj, cast_addr, load_size);
-
-  LOG_INFO("Success loading library %s", dlopen_library_path.c_str());
-  return true;
-}
-
-// Create a shared RELRO file for a library, using android_dlopen_ext().
-//
-// Loads the library similarly to LoadLibrary() above, by reserving address
-// space and then using android_dlopen_ext() to load into the reserved
-// area. Adds flags to android_dlopen_ext() to saved the library's RELRO
-// memory into the given file path, then unload the library and returns.
-//
-// Does not call JNI_OnLoad() or otherwise execute any code from the library.
-//
-// |env| is the current JNI environment handle.
-// |clazz| is the static class handle for org.chromium.base.Linker,
-// and is ignored here.
-// |dlopen_ext_path| is the library identifier (e.g. libfoo.so).
-// |load_address| is an explicit load address.
-// |relro_path| is the path to the file into which RELRO data is written.
-// |lib_info_obj| is a LibInfo handle used to communicate information
-// with the Java side.
-// Return true on success.
-jboolean CreateSharedRelro(JNIEnv* env,
-                           jclass clazz,
-                           jstring dlopen_ext_path,
-                           jlong load_address,
-                           jstring relro_path,
-                           jobject lib_info_obj) {
-  String dlopen_library_path(env, dlopen_ext_path);
-  LOG_INFO("Called for %s, at address 0x%llx",
-           dlopen_library_path.c_str(), load_address);
-
-  if (!IsValidAddress(load_address) || load_address == 0) {
-    LOG_ERROR("Invalid address 0x%llx", load_address);
-    return false;
-  }
-
-  const size_t size = kAddressSpaceReservationSize;
-  void* wanted_addr = reinterpret_cast<void*>(load_address);
-
-  // Reserve the address space into which we load the library.
-  ScopedAnonymousMmap mapping(wanted_addr, size);
-  void* addr = mapping.GetAddr();
-  if (addr == MAP_FAILED) {
-    LOG_ERROR("Failed to reserve space for load");
-    return false;
-  }
-  if (addr != wanted_addr) {
-    LOG_ERROR("Failed to obtain fixed address for load");
-    return false;
-  }
-
-  // Open the shared RELRO file for write. Overwrites any prior content.
-  String shared_relro_path(env, relro_path);
-  const char* filepath = shared_relro_path.c_str();
-  unlink(filepath);
-  int relro_fd = open(filepath, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-  if (relro_fd == -1) {
-    LOG_ERROR("open: %s: %s", filepath, strerror(errno));
-    return false;
-  }
-
-  // Use android_dlopen_ext() to create the shared RELRO.
-  const int flags = ANDROID_DLEXT_RESERVED_ADDRESS
-                    | ANDROID_DLEXT_WRITE_RELRO;
-  AndroidDlextinfo dlextinfo(flags, addr, size, relro_fd);
-
-  const char* path = dlopen_library_path.c_str();
-  void* handle = nullptr;
-  if (!AndroidDlopenExt(path, RTLD_NOW, &dlextinfo, &handle)) {
-    LOG_ERROR("No android_dlopen_ext function found");
-    close(relro_fd);
-    return false;
-  }
-  if (handle == nullptr) {
-    LOG_ERROR("android_dlopen_ext: %s", dlerror());
-    close(relro_fd);
-    return false;
-  }
-
-  // For https://crbug.com/568880.
-  //
-  // Release the scoped mapping. See comment in LoadLibrary() above for more.
-  mapping.Release();
-
-  // For https://crbug.com/568880.
-  //
-  // Unload the library from this address. Calling dlclose() will unmap the
-  // part of the reservation occupied by the libary, but will leave the
-  // remainder of the reservation mapped, and we have no effective way of
-  // unmapping the leftover portions because we don't know where dlclose's
-  // unmap ended.
-  //
-  // For now we live with this. It is a loss of some virtual address space
-  // (but not actual memory), and because it occurs only once and only in
-  // the browser process, and never in renderer processes, it is not a
-  // significant issue.
-  //
-  // TODO(simonb): Between mapping.Release() and here, consider calling the
-  // functions that trim the reservation down to the size of the loaded
-  // library. This may help recover some or all of the virtual address space
-  // that is otherwise lost.
-  dlclose(handle);
-
-  // Reopen the shared RELRO fd in read-only mode. This ensures that nothing
-  // can write to it through the RELRO fd that we return in libinfo.
-  close(relro_fd);
-  relro_fd = open(filepath, O_RDONLY);
-  if (relro_fd == -1) {
-    LOG_ERROR("open: %s: %s", filepath, strerror(errno));
-    return false;
-  }
-
-  // Delete the directory entry for the RELRO file. The fd we hold ensures
-  // that its data remains intact.
-  if (unlink(filepath) == -1) {
-    LOG_ERROR("unlink: %s: %s", filepath, strerror(errno));
-    return false;
-  }
-
-  // Note the shared RELRO fd in the supplied libinfo object. In this
-  // implementation the RELRO start is set to the library's load address,
-  // and the RELRO size is unused.
-  const size_t cast_addr = reinterpret_cast<size_t>(addr);
-  s_lib_info_fields.SetRelroInfo(env, lib_info_obj, cast_addr, 0, relro_fd);
-
-  LOG_INFO("Success creating shared RELRO %s", shared_relro_path.c_str());
-  return true;
-}
-
-const JNINativeMethod kNativeMethods[] = {
-    {"nativeGetCpuAbi",
-     "("
-     ")"
-     "Ljava/lang/String;",
-     reinterpret_cast<void*>(&GetCpuAbi)},
-    {"nativeLoadLibrary",
-     "("
-     "Ljava/lang/String;"
-     "J"
-     "Lorg/chromium/base/library_loader/Linker$LibInfo;"
-     ")"
-     "Z",
-     reinterpret_cast<void*>(&LoadLibrary)},
-    {"nativeCreateSharedRelro",
-     "("
-     "Ljava/lang/String;"
-     "J"
-     "Ljava/lang/String;"
-     "Lorg/chromium/base/library_loader/Linker$LibInfo;"
-     ")"
-     "Z",
-     reinterpret_cast<void*>(&CreateSharedRelro)},
-};
-
-const size_t kNumNativeMethods =
-    sizeof(kNativeMethods) / sizeof(kNativeMethods[0]);
-
-}  // namespace
-
-bool ModernLinkerJNIInit(JavaVM* vm, JNIEnv* env) {
-  LOG_INFO("Entering");
-
-  // Register native methods.
-  jclass linker_class;
-  if (!InitClassReference(env,
-                          "org/chromium/base/library_loader/ModernLinker",
-                          &linker_class))
-    return false;
-
-  LOG_INFO("Registering native methods");
-  if (env->RegisterNatives(linker_class, kNativeMethods, kNumNativeMethods) < 0)
-    return false;
-
-  // Record the Java VM handle.
-  s_java_vm = vm;
-
-  return true;
-}
-
-}  // namespace chromium_android_linker
diff --git a/base/android/linker/modern_linker_jni.h b/base/android/linker/modern_linker_jni.h
deleted file mode 100644
index 74eb586..0000000
--- a/base/android/linker/modern_linker_jni.h
+++ /dev/null
@@ -1,21 +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.
-
-#ifndef BASE_ANDROID_LINKER_MODERN_LINKER_JNI_H_
-#define BASE_ANDROID_LINKER_MODERN_LINKER_JNI_H_
-
-#include <jni.h>
-
-namespace chromium_android_linker {
-
-// JNI_OnLoad() initialization hook for the modern linker.
-// Sets up JNI and other initializations for native linker code.
-// |vm| is the Java VM handle passed to JNI_OnLoad().
-// |env| is the current JNI environment handle.
-// On success, returns true.
-extern bool ModernLinkerJNIInit(JavaVM* vm, JNIEnv* env);
-
-}  // namespace chromium_android_linker
-
-#endif  // BASE_ANDROID_LINKER_MODERN_LINKER_JNI_H_
diff --git a/base/android/path_utils.cc b/base/android/path_utils.cc
index 5ec06ed..3e2dbb76 100644
--- a/base/android/path_utils.cc
+++ b/base/android/path_utils.cc
@@ -22,14 +22,6 @@
   return true;
 }
 
-bool GetDatabaseDirectory(FilePath* result) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> path = Java_PathUtils_getDatabaseDirectory(env);
-  FilePath data_path(ConvertJavaStringToUTF8(path));
-  *result = data_path;
-  return true;
-}
-
 bool GetCacheDirectory(FilePath* result) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jstring> path = Java_PathUtils_getCacheDirectory(env);
@@ -47,15 +39,6 @@
   return true;
 }
 
-bool GetDownloadInternalDirectory(FilePath* result) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> path =
-      Java_PathUtils_getDownloadInternalDirectory(env);
-  FilePath download_internal_path(ConvertJavaStringToUTF8(path));
-  *result = download_internal_path;
-  return true;
-}
-
 bool GetDownloadsDirectory(FilePath* result) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jstring> path = Java_PathUtils_getDownloadsDirectory(env);
diff --git a/base/android/path_utils.h b/base/android/path_utils.h
index 4fbc0c3..c89df171 100644
--- a/base/android/path_utils.h
+++ b/base/android/path_utils.h
@@ -21,10 +21,6 @@
 // PathService::Get(base::DIR_ANDROID_APP_DATA, ...) gets the data dir.
 BASE_EXPORT bool GetDataDirectory(FilePath* result);
 
-// Retrieves the absolute path to the database directory that Android
-// framework's SQLiteDatabase class uses when creating database files.
-BASE_EXPORT bool GetDatabaseDirectory(FilePath* result);
-
 // Retrieves the absolute path to the cache directory. The result is placed in
 // the FilePath pointed to by 'result'. This method is dedicated for
 // base_paths_android.c, Using PathService::Get(base::DIR_CACHE, ...) gets the
@@ -35,10 +31,6 @@
 // in the FilePath pointed to by 'result'.
 BASE_EXPORT bool GetThumbnailCacheDirectory(FilePath* result);
 
-// Retrieves the path to the downloads internal directory. The result is placed
-// in the FilePath pointed to by 'result'.
-BASE_EXPORT bool GetDownloadInternalDirectory(FilePath* result);
-
 // Retrieves the path to the public downloads directory. The result is placed
 // in the FilePath pointed to by 'result'.
 BASE_EXPORT bool GetDownloadsDirectory(FilePath* result);
diff --git a/base/pickle.h b/base/pickle.h
index 4fe98d42..eff2092 100644
--- a/base/pickle.h
+++ b/base/pickle.h
@@ -263,6 +263,10 @@
   }
 
  protected:
+  // Returns size of the header, which can have default value, set by user or
+  // calculated by passed raw data.
+  size_t header_size() const { return header_size_; }
+
   char* mutable_payload() {
     return reinterpret_cast<char*>(header_) + header_size_;
   }
diff --git a/base/test/launcher/test_results_tracker.cc b/base/test/launcher/test_results_tracker.cc
index 1acd657..a7e590c 100644
--- a/base/test/launcher/test_results_tracker.cc
+++ b/base/test/launcher/test_results_tracker.cc
@@ -453,8 +453,22 @@
 
   // File::Flush() will call fsync(). This is important on Fuchsia to ensure
   // that the file is written to the disk - the system running under qemu will
-  // shutdown shortly after the test completes.
-  return output.Flush();
+  // shutdown shortly after the test completes. On Fuchsia fsync() times out
+  // after 15 seconds. Apparently this may not be enough in some cases,
+  // particularly when running net_unittests on buildbots, see
+  // https://crbug.com/796318. Try calling fsync() more than once to workaround
+  // this issue.
+  //
+  // TODO(sergeyu): Figure out a better solution.
+  int flush_attempts_left = 4;
+  while (flush_attempts_left-- > 0) {
+    if (output.Flush())
+      return true;
+    LOG(ERROR) << "fsync() failed when saving test output summary. "
+               << ((flush_attempts_left > 0) ? "Retrying." : " Giving up.");
+  }
+
+  return false;
 }
 
 TestResultsTracker::TestStatusMap
diff --git a/base/test/scoped_feature_list.cc b/base/test/scoped_feature_list.cc
index 77f977c..ac526ff 100644
--- a/base/test/scoped_feature_list.cc
+++ b/base/test/scoped_feature_list.cc
@@ -21,7 +21,7 @@
 namespace {
 
 std::vector<StringPiece> GetFeatureVector(
-    const std::initializer_list<Feature>& features) {
+    const std::vector<Feature>& features) {
   std::vector<StringPiece> output;
   for (const Feature& feature : features) {
     output.push_back(feature.name);
@@ -117,8 +117,8 @@
 }
 
 void ScopedFeatureList::InitWithFeatures(
-    const std::initializer_list<Feature>& enabled_features,
-    const std::initializer_list<Feature>& disabled_features) {
+    const std::vector<Feature>& enabled_features,
+    const std::vector<Feature>& disabled_features) {
   InitWithFeaturesAndFieldTrials(enabled_features, {}, disabled_features);
 }
 
@@ -137,9 +137,9 @@
 }
 
 void ScopedFeatureList::InitWithFeaturesAndFieldTrials(
-    const std::initializer_list<Feature>& enabled_features,
-    const std::initializer_list<FieldTrial*>& trials_for_enabled_features,
-    const std::initializer_list<Feature>& disabled_features) {
+    const std::vector<Feature>& enabled_features,
+    const std::vector<FieldTrial*>& trials_for_enabled_features,
+    const std::vector<Feature>& disabled_features) {
   DCHECK_LE(trials_for_enabled_features.size(), enabled_features.size());
 
   Features merged_features;
@@ -167,7 +167,8 @@
 
   // Add the field trial overrides. This assumes that |enabled_features| are at
   // the begining of |merged_features.enabled_feature_list|, in the same order.
-  FieldTrial* const* trial_it = trials_for_enabled_features.begin();
+  std::vector<FieldTrial*>::const_iterator trial_it =
+      trials_for_enabled_features.begin();
   auto feature_it = merged_features.enabled_feature_list.begin();
   std::vector<std::unique_ptr<std::string>> features_with_trial;
   features_with_trial.reserve(trials_for_enabled_features.size());
diff --git a/base/test/scoped_feature_list.h b/base/test/scoped_feature_list.h
index d94633f..4d24f1fd 100644
--- a/base/test/scoped_feature_list.h
+++ b/base/test/scoped_feature_list.h
@@ -5,10 +5,10 @@
 #ifndef BASE_TEST_SCOPED_FEATURE_LIST_H_
 #define BASE_TEST_SCOPED_FEATURE_LIST_H_
 
-#include <initializer_list>
 #include <map>
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/feature_list.h"
 #include "base/memory/ref_counted.h"
@@ -63,9 +63,8 @@
   // continue to apply, unless they conflict with the overrides passed into this
   // method. This is important for testing potentially unexpected feature
   // interactions.
-  void InitWithFeatures(
-      const std::initializer_list<Feature>& enabled_features,
-      const std::initializer_list<Feature>& disabled_features);
+  void InitWithFeatures(const std::vector<Feature>& enabled_features,
+                        const std::vector<Feature>& disabled_features);
 
   // Initializes and registers a FeatureList instance based on present
   // FeatureList and overridden with single enabled feature.
@@ -95,9 +94,9 @@
   // features.
   // Trials are expected to outlive the ScopedFeatureList.
   void InitWithFeaturesAndFieldTrials(
-      const std::initializer_list<Feature>& enabled_features,
-      const std::initializer_list<FieldTrial*>& trials_for_enabled_features,
-      const std::initializer_list<Feature>& disabled_features);
+      const std::vector<Feature>& enabled_features,
+      const std::vector<FieldTrial*>& trials_for_enabled_features,
+      const std::vector<Feature>& disabled_features);
 
   // Initializes and registers a FeatureList instance based on present
   // FeatureList and overridden with single enabled feature and associated field
diff --git a/build/android/gradle/android.jinja b/build/android/gradle/android.jinja
index 2fa40d1..3fad651 100644
--- a/build/android/gradle/android.jinja
+++ b/build/android/gradle/android.jinja
@@ -70,8 +70,13 @@
 
 {{ expand_sourceset(main, 'main') }}
 {{ expand_sourceset(test, 'test') }}
-{{ expand_sourceset(android_test, 'androidTest') }}
+
+{% if android_test is defined %}
+{% for t in android_test %}
+{{ expand_sourceset(t, 'androidTest') }}
+{% endfor %}
     }
+{% endif %}
 
     defaultConfig {
         vectorDrawables.useSupportLibrary = true
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py
index c2e26ab..c8f4731 100755
--- a/build/android/gradle/generate_gradle.py
+++ b/build/android/gradle/generate_gradle.py
@@ -7,6 +7,7 @@
 
 import argparse
 import codecs
+import collections
 import glob
 import logging
 import os
@@ -151,7 +152,7 @@
     self._build_config = None
     self._java_files = None
     self._all_entries = None
-    self.android_test_entry = None
+    self.android_test_entries = None
 
   @classmethod
   def FromGnTarget(cls, gn_target):
@@ -565,13 +566,14 @@
   if bootclasspath:
     # Must use absolute path here.
     variables['bootclasspath'] = _RebasePath(bootclasspath)
-  if entry.android_test_entry:
-    variables['android_test'] = generator.Generate(
-        entry.android_test_entry)
-    for key, value in variables['android_test'].iteritems():
-      if isinstance(value, list):
-        variables['android_test'][key] = sorted(
-            set(value) - set(variables['main'][key]))
+  if entry.android_test_entries:
+    variables['android_test'] = []
+    for e in entry.android_test_entries:
+      test_entry = generator.Generate(e)
+      variables['android_test'].append(test_entry)
+      for key, value in test_entry.iteritems():
+        if isinstance(value, list):
+          test_entry[key] = sorted(set(value) - set(variables['main'][key]))
 
   return jinja_processor.Render(
       _TemplatePath(target_type.split('_')[0]), variables)
@@ -607,10 +609,10 @@
       'java_excludes': ['**/*.java'],
       'res_dirs': Relativize(res_dirs),
   }
-  variables['android_test'] = {
+  variables['android_test'] = [{
       'java_dirs': Relativize(test_java_dirs),
       'java_excludes': ['**/*.java'],
-  }
+  }]
   data = jinja_processor.Render(
       _TemplatePath(target_type.split('_')[0]), variables)
   _WriteFile(
@@ -685,22 +687,22 @@
     - e.g. base_junit_tests > base_junit_test_support > base_java
   """
   combined_entries = []
-  android_test_entries = {}
+  android_test_entries = collections.defaultdict(list)
   for entry in entries:
     target_name = entry.GnTarget()
     if (target_name.endswith('_test_apk__apk') and
         'apk_under_test' in entry.Gradle()):
       apk_name = entry.Gradle()['apk_under_test']
-      android_test_entries[apk_name] = entry
+      android_test_entries[apk_name].append(entry)
     else:
       combined_entries.append(entry)
   for entry in combined_entries:
     target_name = entry.DepsInfo()['name']
     if target_name in android_test_entries:
-      entry.android_test_entry = android_test_entries[target_name]
+      entry.android_test_entries = android_test_entries[target_name]
       del android_test_entries[target_name]
   # Add unmatched test entries as individual targets.
-  combined_entries.extend(android_test_entries.values())
+  combined_entries.extend(e for l in android_test_entries.values() for e in l)
   return combined_entries
 
 
diff --git a/build/android/gyp/lint.py b/build/android/gyp/lint.py
index b1c1241..2ad01c1b 100755
--- a/build/android/gyp/lint.py
+++ b/build/android/gyp/lint.py
@@ -25,7 +25,7 @@
                 manifest_path, result_path, product_dir, sources, jar_path,
                 cache_dir, android_sdk_version, srcjars, resource_sources,
                 disable=None, classpath=None, can_fail_build=False,
-                silent=False):
+                include_unexpected=False, silent=False):
   def _RebasePath(path):
     """Returns relative path to top-level src dir.
 
@@ -193,9 +193,17 @@
       # We drop all lines that contain _JAVA_OPTIONS from the output
       stderr_filter = lambda l: re.sub(r'.*_JAVA_OPTIONS.*\n?', '', l)
 
+    def fail_func(returncode, stderr):
+      if returncode != 0:
+        return True
+      if (include_unexpected and
+          'Unexpected failure during lint analysis' in stderr):
+        return True
+      return False
+
     try:
       build_utils.CheckOutput(cmd, cwd=_SRC_ROOT, env=env or None,
-                              stderr_filter=stderr_filter)
+                              stderr_filter=stderr_filter, fail_func=fail_func)
     except build_utils.CalledProcessError:
       # There is a problem with lint usage
       if not os.path.exists(result_path):
@@ -236,11 +244,14 @@
         raise
 
       _ProcessResultFile()
-      msg = ('\nLint found %d new issues.\n'
-             ' - For full explanation, please refer to %s\n'
-             ' - For more information about lint and how to fix lint issues,'
-             ' please refer to %s\n' %
-             (num_issues, _RebasePath(result_path), _LINT_MD_URL))
+      if num_issues == 0 and include_unexpected:
+        msg = 'Please refer to output above for unexpected lint failures.\n'
+      else:
+        msg = ('\nLint found %d new issues.\n'
+               ' - For full explanation, please refer to %s\n'
+               ' - For more information about lint and how to fix lint issues,'
+               ' please refer to %s\n' %
+               (num_issues, _RebasePath(result_path), _LINT_MD_URL))
       if not silent:
         print >> sys.stderr, msg
       if can_fail_build:
@@ -271,6 +282,9 @@
   parser.add_argument('--can-fail-build', action='store_true',
                       help='If set, script will exit with nonzero exit status'
                            ' if lint errors are present')
+  parser.add_argument('--include-unexpected-failures', action='store_true',
+                      help='If set, script will exit with nonzero exit status'
+                           ' if lint itself crashes with unexpected failures.')
   parser.add_argument('--config-path',
                       help='Path to lint suppressions file.')
   parser.add_argument('--disable',
@@ -347,6 +361,7 @@
 
   input_strings = [
     args.can_fail_build,
+    args.include_unexpected_failures,
     args.silent,
   ]
   if args.android_sdk_version:
@@ -375,6 +390,7 @@
                           disable=disable,
                           classpath=classpath,
                           can_fail_build=args.can_fail_build,
+                          include_unexpected=args.include_unexpected_failures,
                           silent=args.silent),
       args,
       input_paths=input_paths,
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
index b120234..0f103b8e 100755
--- a/build/android/gyp/process_resources.py
+++ b/build/android/gyp/process_resources.py
@@ -488,11 +488,24 @@
   return returncode != 0 or stderr
 
 
-def _ZipResources(resource_dirs, zip_path):
+def _GenerateGlobs(pattern):
+  # This function processes the aapt ignore assets pattern into a list of globs
+  # to be used to exclude files on the python side. It removes the '!', which is
+  # used by aapt to mean 'not chatty' so it does not output if the file is
+  # ignored (we dont output anyways, so it is not required). This function does
+  # not handle the <dir> and <file> prefixes used by aapt and are assumed not to
+  # be included in the pattern string.
+  return pattern.replace('!', '').split(':')
+
+
+def _ZipResources(resource_dirs, zip_path, ignore_pattern):
   # Python zipfile does not provide a way to replace a file (it just writes
   # another file with the same name). So, first collect all the files to put
   # in the zip (with proper overriding), and then zip them.
+  # ignore_pattern is a string of ':' delimited list of globs used to ignore
+  # files that should not be part of the final resource zip.
   files_to_zip = dict()
+  globs = _GenerateGlobs(ignore_pattern)
   for d in resource_dirs:
     for root, _, files in os.walk(d):
       for f in files:
@@ -501,6 +514,8 @@
         if parent_dir != '.':
           archive_path = os.path.join(parent_dir, f)
         path = os.path.join(root, f)
+        if build_utils.MatchesGlob(archive_path, globs):
+          continue
         files_to_zip[archive_path] = path
   build_utils.DoZip(files_to_zip.iteritems(), zip_path)
 
@@ -844,7 +859,8 @@
     _CrunchDirectory(options.aapt_path, input_dir, crunch_dir)
 
   if options.resource_zip_out:
-    _ZipResources(zip_resource_dirs, options.resource_zip_out)
+    _ZipResources(zip_resource_dirs, options.resource_zip_out,
+                  build_utils.AAPT_IGNORE_PATTERN)
 
   # Only creates an R.txt
   build_utils.CheckOutput(
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index 5be45e5..dec818ee 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -30,10 +30,14 @@
 
 COLORAMA_ROOT = os.path.join(host_paths.DIR_SOURCE_ROOT,
                              'third_party', 'colorama', 'src')
-# aapt should ignore OWNERS and python files in addition the default ignore
-# pattern.
-AAPT_IGNORE_PATTERN = ('!OWNERS:!*.py:!*.pyc:!.svn:!.git:!.ds_store:!*.scc:' +
-                       '.*:<dir>_*:!CVS:!thumbs.db::!*~:!*.d.stamp')
+AAPT_IGNORE_PATTERN = ':'.join([
+    'OWNERS',  # Allow OWNERS files within res/
+    '*.py',  # PRESUBMIT.py sometimes exist.
+    '*.pyc',
+    '*~',  # Some editors create these as temp files.
+    '.*',  # Never makes sense to include dot(files/dirs).
+    '*.d.stamp', # Ignore stamp files
+    ])
 HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0)
 _HERMETIC_FILE_ATTR = (0644 << 16L)
 
diff --git a/build/android/pylib/linker/linker_test_instance.py b/build/android/pylib/linker/linker_test_instance.py
index ce696f2..1de3e17 100644
--- a/build/android/pylib/linker/linker_test_instance.py
+++ b/build/android/pylib/linker/linker_test_instance.py
@@ -9,7 +9,6 @@
 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH):
   import unittest_util
 
-_MODERN_LINKER_MINIMUM_SDK_INT = 23
 
 class LinkerTestInstance(test_instance.TestInstance):
 
@@ -26,15 +25,11 @@
   def test_filter(self):
     return self._test_filter
 
-  def GetTests(self, min_device_sdk):
+  def GetTests(self):
     tests = [
-      test_case.LinkerSharedRelroTest(is_modern_linker=False,
-                                      is_low_memory=False),
-      test_case.LinkerSharedRelroTest(is_modern_linker=False,
-                                      is_low_memory=True)
+      test_case.LinkerSharedRelroTest(is_low_memory=False),
+      test_case.LinkerSharedRelroTest(is_low_memory=True)
     ]
-    if min_device_sdk >= _MODERN_LINKER_MINIMUM_SDK_INT:
-      tests.append(test_case.LinkerSharedRelroTest(is_modern_linker=True))
 
     if self._test_filter:
       filtered_names = unittest_util.FilterTestNames(
diff --git a/build/android/pylib/linker/test_case.py b/build/android/pylib/linker/test_case.py
index f4ae7c65..cf16a738 100644
--- a/build/android/pylib/linker/test_case.py
+++ b/build/android/pylib/linker/test_case.py
@@ -124,17 +124,12 @@
 class LinkerTestCaseBase(object):
   """Base class for linker test cases."""
 
-  def __init__(self, is_modern_linker=False, is_low_memory=False):
+  def __init__(self, is_low_memory=False):
     """Create a test case.
     Args:
-      is_modern_linker: True to test ModernLinker, False to test LegacyLinker.
       is_low_memory: True to simulate a low-memory device, False otherwise.
     """
-    self.is_modern_linker = is_modern_linker
-    if is_modern_linker:
-      test_suffix = 'ForModernLinker'
-    else:
-      test_suffix = 'ForLegacyLinker'
+    test_suffix = 'ForLegacyLinker'
     self.is_low_memory = is_low_memory
     if is_low_memory:
       test_suffix += 'LowMemoryDevice'
@@ -166,11 +161,7 @@
     print '[ %-*s ] %s' % (margin, 'RUN', self.tagged_name)
     logging.info('Running linker test: %s', self.tagged_name)
 
-    # Create command-line file on device.
-    if self.is_modern_linker:
-      command_line_flags = '--use-linker=modern'
-    else:
-      command_line_flags = '--use-linker=legacy'
+    command_line_flags = '--use-linker=legacy'
     if self.is_low_memory:
       command_line_flags += ' --low-memory-device'
     device.WriteFile(_COMMAND_LINE_FILE, command_line_flags)
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 416e5a4..f079468c 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
@@ -812,18 +812,11 @@
 
   #override
   def _ShouldRetry(self, test, result):
-    def not_run(res):
-      if isinstance(res, list):
-        return any(not_run(r) for r in res)
-      return res.GetType() == base_test_result.ResultType.NOTRUN
-
-    if 'RetryOnFailure' in test.get('annotations', {}) or not_run(result):
-      return True
-
-    # TODO(jbudorick): Remove this log message once @RetryOnFailure has been
-    # enabled for a while. See crbug.com/619055 for more details.
-    logging.error('Default retries are being phased out. crbug.com/619055')
-    return False
+    # We've tried to disable retries in the past with mixed results.
+    # See crbug.com/619055 for historical context and crbug.com/797002
+    # for ongoing efforts.
+    del test, result
+    return True
 
   #override
   def _ShouldShard(self):
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py b/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py
index d7cb372..82db02e 100755
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py
@@ -16,6 +16,9 @@
 
 class LocalDeviceInstrumentationTestRunTest(unittest.TestCase):
 
+  # TODO(crbug.com/797002): Decide whether the _ShouldRetry hook is worth
+  # retaining and remove these tests if not.
+
   def testShouldRetry_failure(self):
     env = mock_environment.MockEnvironment()
     ti = mock_test_instance.MockTestInstance()
@@ -29,7 +32,7 @@
     }
     result = base_test_result.BaseTestResult(
         'SadTest.testFailure', base_test_result.ResultType.FAIL)
-    self.assertFalse(obj._ShouldRetry(test, result))
+    self.assertTrue(obj._ShouldRetry(test, result))
 
   def testShouldRetry_retryOnFailure(self):
     env = mock_environment.MockEnvironment()
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 0084ccc..d249b3204 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -794,6 +794,10 @@
         rebase_path(_config_path, root_build_dir),
         "--result-path",
         rebase_path(_result_path, root_build_dir),
+
+        # The following option should be turned on after all unexpected failures
+        # are resolved.
+        #"--include-unexpected-failures",
       ]
       if (defined(invoker.android_manifest)) {
         inputs += [ invoker.android_manifest ]
@@ -2271,17 +2275,6 @@
              "main_class cannot be used for target of type ${invoker.type}")
     }
 
-    if (_has_sources) {
-      _emma_instrument = emma_coverage && !_chromium_code && _has_sources
-      if (defined(invoker.emma_never_instrument)) {
-        _emma_instrument = !invoker.emma_never_instrument && _emma_instrument
-      }
-      if (_emma_instrument) {
-        _instrumented_jar_path =
-            "$target_gen_dir/$_main_target_name.instrumented.jar"
-      }
-    }
-
     if (_is_prebuilt || _has_sources) {
       if (defined(invoker.output_name)) {
         _output_name = invoker.output_name
@@ -2365,6 +2358,15 @@
       sources = []
     }
 
+    _emma_instrument = emma_coverage && !_chromium_code && _java_files != []
+    if (defined(invoker.emma_never_instrument)) {
+      _emma_instrument = !invoker.emma_never_instrument && _emma_instrument
+    }
+    if (_emma_instrument) {
+      _instrumented_jar_path =
+          "$target_gen_dir/$_main_target_name.instrumented.jar"
+    }
+
     if (_java_files != []) {
       _java_sources_file = "$target_gen_dir/$_main_target_name.sources"
       if (defined(invoker.java_sources_file)) {
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 3c85a36..cec570c 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -2013,6 +2013,15 @@
               "@FileArg($_rebased_ordered_libraries_json:java_libraries_list)",
           "NATIVE_LIBRARIES_VERSION_NUMBER=$_native_lib_version_arg",
         ]
+        if (current_cpu == "arm" || current_cpu == "arm64") {
+          defines += [ "ANDROID_APP_CPU_FAMILY_ARM" ]
+        } else if (current_cpu == "x86" || current_cpu == "x64") {
+          defines += [ "ANDROID_APP_CPU_FAMILY_X86" ]
+        } else if (current_cpu == "mipsel" || current_cpu == "mips64el") {
+          defines += [ "ANDROID_APP_CPU_FAMILY_MIPS" ]
+        } else {
+          assert(false, "Unsupported CPU family")
+        }
         if (_use_chromium_linker) {
           defines += [ "ENABLE_CHROMIUM_LINKER" ]
         }
diff --git a/build/linux/unbundle/fontconfig.gn b/build/linux/unbundle/fontconfig.gn
new file mode 100644
index 0000000..c1e2298
--- /dev/null
+++ b/build/linux/unbundle/fontconfig.gn
@@ -0,0 +1,13 @@
+# 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.
+
+assert(is_linux)
+
+config("fontconfig_config") {
+  libs = [ "fontconfig" ]
+}
+
+group("fontconfig") {
+  public_configs = [ ":fontconfig_config" ]
+}
diff --git a/build/linux/unbundle/harfbuzz-ng.gn b/build/linux/unbundle/harfbuzz-ng.gn
index 5c422db..b4ba17a 100644
--- a/build/linux/unbundle/harfbuzz-ng.gn
+++ b/build/linux/unbundle/harfbuzz-ng.gn
@@ -1,42 +1,13 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
+# 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("//build/config/linux/pkg_config.gni")
-import("//build/shim_headers.gni")
-
-pkg_config("system_harfbuzz") {
-  packages = [
-    "harfbuzz",
-    "harfbuzz-icu",
-  ]
-}
-
-shim_headers("harfbuzz_shim") {
-  root_path = "src"
-  headers = [ "hb.h" ]
-}
-
-group("harfbuzz-ng") {
-  public_deps = [
-    ":harfbuzz-ng-ft",
-    ":harfbuzz-ng-without-freetype",
-  ]
-}
-
-source_set("harfbuzz-ng-ft") {
-  deps = [
-    ":harfbuzz_shim",
-  ]
-  public_configs = [ ":system_harfbuzz" ]
-}
-
-source_set("harfbuzz-ng-without-freetype") {
-  deps = [
-    ":harfbuzz_shim",
-  ]
-  public_configs = [ ":system_harfbuzz" ]
-}
-
-config("pangoft2_link_hack") {
+declare_args() {
+  # Blink uses a cutting-edge version of Harfbuzz (version listed in
+  # third_party/harfbuzz-ng/README.chromium); most Linux distros do not contain
+  # a new enough version of the code to work correctly. However, ChromeOS
+  # chroots (i.e. real ChromeOS builds for devices) do contain a new enough
+  # version of the library, and so this variable exists so that ChromeOS can
+  # build against the system lib and keep binary sizes smaller.
+  use_system_harfbuzz = true
 }
diff --git a/build/linux/unbundle/replace_gn_files.py b/build/linux/unbundle/replace_gn_files.py
index 773eb00..76b79c4 100755
--- a/build/linux/unbundle/replace_gn_files.py
+++ b/build/linux/unbundle/replace_gn_files.py
@@ -19,8 +19,9 @@
 REPLACEMENTS = {
   'ffmpeg': 'third_party/ffmpeg/BUILD.gn',
   'flac': 'third_party/flac/BUILD.gn',
+  'fontconfig': 'third_party/fontconfig/BUILD.gn',
   'freetype': 'build/config/freetype/freetype.gni',
-  'harfbuzz-ng': 'third_party/harfbuzz-ng/BUILD.gn',
+  'harfbuzz-ng': 'third_party/harfbuzz-ng/harfbuzz.gni',
   'icu': 'third_party/icu/BUILD.gn',
   'libdrm': 'third_party/libdrm/BUILD.gn',
   'libevent': 'base/third_party/libevent/BUILD.gn',
diff --git a/build/sanitizers/lsan_suppressions.cc b/build/sanitizers/lsan_suppressions.cc
index d2464717..d54f4e0 100644
--- a/build/sanitizers/lsan_suppressions.cc
+++ b/build/sanitizers/lsan_suppressions.cc
@@ -94,6 +94,9 @@
     "leak:blink::DOMWrapperWorld::Create\n"
     "leak:blink::ScriptState::Create\n"
 
+    // https://crbug.com/795148
+    "leak:third_party/fontconfig/\n"
+
     // PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS.
 
     // End of suppressions.
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index be1830a..e0404b4 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -251,6 +251,9 @@
     "race:base::i18n::IsRTL\n"
     "race:base::i18n::SetICUDefaultLocale\n"
 
+    // http://crbug.com/795110
+    "race:third_party/fontconfig/*\n"
+
     //
     "race:third_party/harfbuzz-ng/src/*\n"
 
diff --git a/build/util/lib/common/unittest_util.py b/build/util/lib/common/unittest_util.py
index 010252b..9683ab7 100644
--- a/build/util/lib/common/unittest_util.py
+++ b/build/util/lib/common/unittest_util.py
@@ -5,6 +5,7 @@
 """Utilities for dealing with the python unittest module."""
 
 import fnmatch
+import re
 import sys
 import unittest
 
@@ -136,13 +137,18 @@
   if len(pattern_groups) > 1:
     negative_patterns = pattern_groups[1].split(':')
 
+  neg_pats = None
+  if negative_patterns:
+    neg_pats = re.compile('|'.join(fnmatch.translate(p) for p in
+                                   negative_patterns))
+
   tests = []
   test_set = set()
   for pattern in positive_patterns:
     pattern_tests = [
         test for test in all_tests
         if (fnmatch.fnmatch(test, pattern)
-            and not any(fnmatch.fnmatch(test, p) for p in negative_patterns)
+            and not (neg_pats and neg_pats.match(test))
             and test not in test_set)]
     tests.extend(pattern_tests)
     test_set.update(pattern_tests)
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 4aaca367..2facc6f 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -545,7 +545,7 @@
     "//components/viz/test:test_support",
     "//gpu/command_buffer/client:gles2_c_lib",
     "//gpu/command_buffer/client:gles2_implementation",
-    "//gpu/command_buffer/common:gles2_utils",
+    "//gpu/command_buffer/common",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings",
     "//media",
@@ -742,7 +742,6 @@
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/client:gles2_interface",
     "//gpu/command_buffer/client:raster_interface",
-    "//gpu/command_buffer/common:gles2_utils",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings",
     "//media",
@@ -795,7 +794,6 @@
     "//gpu",
     "//gpu:test_support",
     "//gpu/command_buffer/client:gles2_implementation",
-    "//gpu/command_buffer/common:gles2_utils",
     "//media",
     "//mojo/edk/system",
     "//mojo/public/cpp/bindings",
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index d9816d60..7a9cafe 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -88,6 +88,7 @@
 }
 
 void HeadsUpDisplayLayerImpl::AcquireResource(
+    DrawMode draw_mode,
     ResourceProvider* resource_provider) {
   for (auto& resource : resources_) {
     if (!resource_provider->InUseByConsumer(resource->id())) {
@@ -97,9 +98,20 @@
   }
 
   auto resource = std::make_unique<ScopedResource>(resource_provider);
-  resource->Allocate(
-      internal_content_bounds_, viz::ResourceTextureHint::kFramebuffer,
-      resource_provider->best_render_buffer_format(), gfx::ColorSpace());
+  switch (draw_mode) {
+    case DRAW_MODE_NONE:
+    case DRAW_MODE_RESOURCELESS_SOFTWARE:
+      NOTREACHED();
+      break;
+    case DRAW_MODE_HARDWARE:
+      resource->AllocateGpuTexture(
+          internal_content_bounds_, viz::ResourceTextureHint::kFramebuffer,
+          resource_provider->best_render_buffer_format(), gfx::ColorSpace());
+      break;
+    case DRAW_MODE_SOFTWARE:
+      resource->AllocateSoftware(internal_content_bounds_, gfx::ColorSpace());
+      break;
+  }
   resources_.push_back(std::move(resource));
 }
 
@@ -125,7 +137,7 @@
                 resource_provider->max_texture_size()));
 
   ReleaseUnmatchedSizeResources(resource_provider);
-  AcquireResource(resource_provider);
+  AcquireResource(draw_mode, resource_provider);
   return LayerImpl::WillDraw(draw_mode, resource_provider);
 }
 
diff --git a/cc/layers/heads_up_display_layer_impl.h b/cc/layers/heads_up_display_layer_impl.h
index f32753c..24d6641 100644
--- a/cc/layers/heads_up_display_layer_impl.h
+++ b/cc/layers/heads_up_display_layer_impl.h
@@ -133,7 +133,7 @@
                      const std::string& label_text) const;
   void DrawDebugRects(SkCanvas* canvas, DebugRectHistory* debug_rect_history);
 
-  void AcquireResource(ResourceProvider* resource_provider);
+  void AcquireResource(DrawMode draw_mode, ResourceProvider* resource_provider);
   void ReleaseUnmatchedSizeResources(ResourceProvider* resource_provider);
 
   std::vector<std::unique_ptr<ScopedResource>> resources_;
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc
index 5010c16..b16abc4 100644
--- a/cc/paint/oop_pixeltest.cc
+++ b/cc/paint/oop_pixeltest.cc
@@ -16,7 +16,7 @@
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/shared_memory_limits.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/config/gpu_switches.h"
 #include "gpu/ipc/gl_in_process_context.h"
 #include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
@@ -37,7 +37,7 @@
  public:
   void SetUp() override {
     bool is_offscreen = true;
-    gpu::gles2::ContextCreationAttribHelper attribs;
+    gpu::ContextCreationAttribs attribs;
     attribs.alpha_size = -1;
     attribs.depth_size = 24;
     attribs.stencil_size = 8;
diff --git a/cc/paint/transfer_cache_unittest.cc b/cc/paint/transfer_cache_unittest.cc
index 5ba4fd2..d716eb4 100644
--- a/cc/paint/transfer_cache_unittest.cc
+++ b/cc/paint/transfer_cache_unittest.cc
@@ -16,7 +16,7 @@
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/shared_memory_limits.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/service/service_transfer_cache.h"
 #include "gpu/config/gpu_switches.h"
 #include "gpu/ipc/gl_in_process_context.h"
@@ -33,7 +33,7 @@
       : testing::Test(), test_client_entry_(std::vector<uint8_t>(100)) {}
   void SetUp() override {
     bool is_offscreen = true;
-    gpu::gles2::ContextCreationAttribHelper attribs;
+    gpu::ContextCreationAttribs attribs;
     attribs.alpha_size = -1;
     attribs.depth_size = 24;
     attribs.stencil_size = 8;
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc
index 526e019..6ed05d0b 100644
--- a/cc/raster/raster_buffer_provider_perftest.cc
+++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -264,8 +264,8 @@
     for (unsigned i = 0; i < num_raster_tasks; ++i) {
       auto resource =
           std::make_unique<ScopedResource>(resource_provider_.get());
-      resource->Allocate(size, viz::ResourceTextureHint::kDefault,
-                         viz::RGBA_8888, gfx::ColorSpace());
+      resource->AllocateGpuTexture(size, viz::ResourceTextureHint::kDefault,
+                                   viz::RGBA_8888, gfx::ColorSpace());
 
       // No tile ids are given to support partial updates.
       std::unique_ptr<RasterBuffer> raster_buffer;
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc
index b651738a..e44b898 100644
--- a/cc/raster/raster_buffer_provider_unittest.cc
+++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -223,12 +223,14 @@
   std::unique_ptr<ScopedResource> AllocateResource(const gfx::Size& size) {
     auto resource = std::make_unique<ScopedResource>(resource_provider_.get());
     if (GetParam() == RASTER_BUFFER_PROVIDER_TYPE_ZERO_COPY) {
-      resource->AllocateWithGpuMemoryBuffer(
+      resource->AllocateGpuMemoryBuffer(
           size, viz::RGBA_8888, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
           gfx::ColorSpace());
+    } else if (GetParam() == RASTER_BUFFER_PROVIDER_TYPE_BITMAP) {
+      resource->AllocateSoftware(size, gfx::ColorSpace());
     } else {
-      resource->Allocate(size, viz::ResourceTextureHint::kDefault,
-                         viz::RGBA_8888, gfx::ColorSpace());
+      resource->AllocateGpuTexture(size, viz::ResourceTextureHint::kDefault,
+                                   viz::RGBA_8888, gfx::ColorSpace());
     }
     return resource;
   }
diff --git a/cc/resources/layer_tree_resource_provider_unittest.cc b/cc/resources/layer_tree_resource_provider_unittest.cc
index 3207e64..0f41a4d 100644
--- a/cc/resources/layer_tree_resource_provider_unittest.cc
+++ b/cc/resources/layer_tree_resource_provider_unittest.cc
@@ -350,9 +350,15 @@
   viz::ResourceId tran_id = provider().ImportResource(
       tran, viz::SingleReleaseCallback::Create(base::Bind(
                 &MockReleaseCallback::Released, base::Unretained(&release))));
-  viz::ResourceId norm_id = provider().CreateResource(
-      gfx::Size(3, 4), viz::ResourceTextureHint::kDefault, viz::RGBA_8888,
-      gfx::ColorSpace());
+  viz::ResourceId norm_id;
+  if (use_gpu()) {
+    norm_id = provider().CreateGpuTextureResource(
+        gfx::Size(3, 4), viz::ResourceTextureHint::kDefault, viz::RGBA_8888,
+        gfx::ColorSpace());
+  } else {
+    norm_id =
+        provider().CreateBitmapResource(gfx::Size(3, 4), gfx::ColorSpace());
+  }
   provider().AllocateForTesting(norm_id);
 
   // Export the resources.
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc
index cacbc523..ab9801e2 100644
--- a/cc/resources/resource_pool.cc
+++ b/cc/resources/resource_pool.cc
@@ -110,11 +110,13 @@
 }
 
 ResourcePool::ResourcePool(ResourceProvider* resource_provider,
+                           bool gpu_resources,
                            base::SingleThreadTaskRunner* task_runner,
                            viz::ResourceTextureHint hint,
                            const base::TimeDelta& expiration_delay,
                            bool disallow_non_exact_reuse)
     : resource_provider_(resource_provider),
+      use_gpu_resources_(gpu_resources),
       use_gpu_memory_buffers_(false),
       hint_(hint),
       task_runner_(task_runner),
@@ -189,10 +191,12 @@
       PoolResource::Create(resource_provider_);
 
   if (use_gpu_memory_buffers_) {
-    pool_resource->AllocateWithGpuMemoryBuffer(size, format, usage_,
-                                               color_space);
+    pool_resource->AllocateGpuMemoryBuffer(size, format, usage_, color_space);
+  } else if (use_gpu_resources_) {
+    pool_resource->AllocateGpuTexture(size, hint_, format, color_space);
   } else {
-    pool_resource->Allocate(size, hint_, format, color_space);
+    DCHECK_EQ(format, viz::RGBA_8888);
+    pool_resource->AllocateSoftware(size, color_space);
   }
 
   DCHECK(ResourceUtil::VerifySizeInBytes<size_t>(pool_resource->size(),
diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h
index e5d945e5..402622fb 100644
--- a/cc/resources/resource_pool.h
+++ b/cc/resources/resource_pool.h
@@ -43,13 +43,14 @@
 
   static std::unique_ptr<ResourcePool> Create(
       ResourceProvider* resource_provider,
+      bool gpu_resources,
       base::SingleThreadTaskRunner* task_runner,
       viz::ResourceTextureHint hint,
       const base::TimeDelta& expiration_delay,
       bool disallow_non_exact_reuse) {
-    return base::WrapUnique(new ResourcePool(resource_provider, task_runner,
-                                             hint, expiration_delay,
-                                             disallow_non_exact_reuse));
+    return base::WrapUnique(
+        new ResourcePool(resource_provider, gpu_resources, task_runner, hint,
+                         expiration_delay, disallow_non_exact_reuse));
   }
 
   ~ResourcePool() override;
@@ -115,6 +116,7 @@
 
   // Constructor for creating standard resources.
   ResourcePool(ResourceProvider* resource_provider,
+               bool gpu_resources,
                base::SingleThreadTaskRunner* task_runner,
                viz::ResourceTextureHint hint,
                const base::TimeDelta& expiration_delay,
@@ -177,6 +179,7 @@
   base::TimeTicks GetUsageTimeForLRUResource() const;
 
   ResourceProvider* resource_provider_ = nullptr;
+  bool use_gpu_resources_ = false;
   bool use_gpu_memory_buffers_ = false;
   gfx::BufferUsage usage_ = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
   viz::ResourceTextureHint hint_ = viz::ResourceTextureHint::kDefault;
diff --git a/cc/resources/resource_pool_unittest.cc b/cc/resources/resource_pool_unittest.cc
index 50e036b..db930ce 100644
--- a/cc/resources/resource_pool_unittest.cc
+++ b/cc/resources/resource_pool_unittest.cc
@@ -13,7 +13,6 @@
 #include "cc/resources/scoped_resource.h"
 #include "cc/test/fake_resource_provider.h"
 #include "cc/test/test_context_provider.h"
-#include "cc/test/test_shared_bitmap_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
@@ -23,12 +22,11 @@
   void SetUp() override {
     context_provider_ = TestContextProvider::Create();
     context_provider_->BindToCurrentThread();
-    shared_bitmap_manager_.reset(new TestSharedBitmapManager);
-    resource_provider_ = FakeResourceProvider::Create(
-        context_provider_.get(), shared_bitmap_manager_.get());
+    resource_provider_ =
+        FakeResourceProvider::Create(context_provider_.get(), nullptr);
     task_runner_ = base::ThreadTaskRunnerHandle::Get();
     resource_pool_ =
-        ResourcePool::Create(resource_provider_.get(), task_runner_.get(),
+        ResourcePool::Create(resource_provider_.get(), true, task_runner_.get(),
                              viz::ResourceTextureHint::kDefault,
                              ResourcePool::kDefaultExpirationDelay, false);
   }
@@ -41,7 +39,6 @@
   }
 
   scoped_refptr<TestContextProvider> context_provider_;
-  std::unique_ptr<viz::SharedBitmapManager> shared_bitmap_manager_;
   std::unique_ptr<ResourceProvider> resource_provider_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   std::unique_ptr<ResourcePool> resource_pool_;
@@ -161,7 +158,7 @@
   // Set a quick resource expiration delay so that this test doesn't take long
   // to run.
   resource_pool_ =
-      ResourcePool::Create(resource_provider_.get(), task_runner_.get(),
+      ResourcePool::Create(resource_provider_.get(), true, task_runner_.get(),
                            viz::ResourceTextureHint::kDefault,
                            base::TimeDelta::FromMilliseconds(10), false);
 
@@ -202,7 +199,7 @@
   // Set a quick resource expiration delay so that this test doesn't take long
   // to run.
   resource_pool_ =
-      ResourcePool::Create(resource_provider_.get(), task_runner_.get(),
+      ResourcePool::Create(resource_provider_.get(), true, task_runner_.get(),
                            viz::ResourceTextureHint::kDefault,
                            base::TimeDelta::FromMilliseconds(100), false);
 
@@ -412,7 +409,7 @@
   gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
 
   resource_pool_ =
-      ResourcePool::Create(resource_provider_.get(), task_runner_.get(),
+      ResourcePool::Create(resource_provider_.get(), true, task_runner_.get(),
                            viz::ResourceTextureHint::kDefault,
                            base::TimeDelta::FromMilliseconds(100), true);
 
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index d05cf7f..e46cde82 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -338,53 +338,13 @@
   }
 }
 
-viz::ResourceId ResourceProvider::CreateResource(
-    const gfx::Size& size,
-    viz::ResourceTextureHint hint,
-    viz::ResourceFormat format,
-    const gfx::ColorSpace& color_space) {
-  DCHECK(!size.IsEmpty());
-
-  if (compositor_context_provider_)
-    return CreateGpuTextureResource(size, hint, format, color_space);
-
-  DCHECK_EQ(viz::RGBA_8888, format);
-  return CreateBitmapResource(size, color_space);
-}
-
-viz::ResourceId ResourceProvider::CreateGpuMemoryBufferResource(
-    const gfx::Size& size,
-    viz::ResourceTextureHint hint,
-    viz::ResourceFormat format,
-    gfx::BufferUsage usage,
-    const gfx::ColorSpace& color_space) {
-  DCHECK(!size.IsEmpty());
-  DCHECK(compositor_context_provider_);
-  DCHECK_LE(size.width(), settings_.max_texture_size);
-  DCHECK_LE(size.height(), settings_.max_texture_size);
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  viz::ResourceId id = next_id_++;
-  viz::internal::Resource* resource = InsertResource(
-      id, viz::internal::Resource(size, viz::internal::Resource::INTERNAL, hint,
-                                  viz::ResourceType::kGpuMemoryBuffer, format,
-                                  color_space));
-  resource->target = GetImageTextureTarget(usage, format);
-  resource->buffer_format = BufferFormat(format);
-  resource->usage = usage;
-  resource->is_overlay_candidate = true;
-  // GpuMemoryBuffer provides direct access to the memory used by the GPU. Read
-  // lock fences are required to ensure that we're not trying to map a buffer
-  // that is currently in-use by the GPU.
-  resource->read_lock_fences_enabled = true;
-  return id;
-}
-
 viz::ResourceId ResourceProvider::CreateGpuTextureResource(
     const gfx::Size& size,
     viz::ResourceTextureHint hint,
     viz::ResourceFormat format,
     const gfx::ColorSpace& color_space) {
+  DCHECK(compositor_context_provider_);
+  DCHECK(!size.IsEmpty());
   DCHECK_LE(size.width(), settings_.max_texture_size);
   DCHECK_LE(size.height(), settings_.max_texture_size);
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -409,11 +369,43 @@
   return id;
 }
 
+viz::ResourceId ResourceProvider::CreateGpuMemoryBufferResource(
+    const gfx::Size& size,
+    viz::ResourceTextureHint hint,
+    viz::ResourceFormat format,
+    gfx::BufferUsage usage,
+    const gfx::ColorSpace& color_space) {
+  DCHECK(compositor_context_provider_);
+  DCHECK(!size.IsEmpty());
+  DCHECK(compositor_context_provider_);
+  DCHECK_LE(size.width(), settings_.max_texture_size);
+  DCHECK_LE(size.height(), settings_.max_texture_size);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  viz::ResourceId id = next_id_++;
+  viz::internal::Resource* resource = InsertResource(
+      id, viz::internal::Resource(size, viz::internal::Resource::INTERNAL, hint,
+                                  viz::ResourceType::kGpuMemoryBuffer, format,
+                                  color_space));
+  resource->target = GetImageTextureTarget(usage, format);
+  resource->buffer_format = BufferFormat(format);
+  resource->usage = usage;
+  resource->is_overlay_candidate = true;
+  // GpuMemoryBuffer provides direct access to the memory used by the GPU. Read
+  // lock fences are required to ensure that we're not trying to map a buffer
+  // that is currently in-use by the GPU.
+  resource->read_lock_fences_enabled = true;
+  return id;
+}
+
 viz::ResourceId ResourceProvider::CreateBitmapResource(
     const gfx::Size& size,
     const gfx::ColorSpace& color_space) {
+  DCHECK(!compositor_context_provider_);
+  DCHECK(!size.IsEmpty());
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
+  // TODO(danakj): Allocate this outside ResourceProvider.
   std::unique_ptr<viz::SharedBitmap> bitmap =
       shared_bitmap_manager_->AllocateSharedBitmap(size);
   DCHECK(bitmap);
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index 4fbf80c0..e6edffd 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -100,9 +100,12 @@
   void DidLoseContextProvider() { lost_context_provider_ = true; }
 
   int max_texture_size() const { return settings_.max_texture_size; }
+  // Use this format for making resources that will be rastered and uploaded to
+  // from software bitmaps.
   viz::ResourceFormat best_texture_format() const {
     return settings_.best_texture_format;
   }
+  // Use this format for making resources that will be rastered to on the Gpu.
   viz::ResourceFormat best_render_buffer_format() const {
     return settings_.best_render_buffer_format;
   }
@@ -135,20 +138,18 @@
   GLenum GetResourceTextureTarget(viz::ResourceId id);
   viz::ResourceTextureHint GetTextureHint(viz::ResourceId id);
 
-  // Creates a resource of the default resource type.
-  viz::ResourceId CreateResource(const gfx::Size& size,
-                                 viz::ResourceTextureHint hint,
-                                 viz::ResourceFormat format,
-                                 const gfx::ColorSpace& color_space);
-
-  // Creates a resource for a particular texture target (the distinction between
-  // texture targets has no effect in software mode).
+  viz::ResourceId CreateGpuTextureResource(const gfx::Size& size,
+                                           viz::ResourceTextureHint hint,
+                                           viz::ResourceFormat format,
+                                           const gfx::ColorSpace& color_space);
   viz::ResourceId CreateGpuMemoryBufferResource(
       const gfx::Size& size,
       viz::ResourceTextureHint hint,
       viz::ResourceFormat format,
       gfx::BufferUsage usage,
       const gfx::ColorSpace& color_space);
+  viz::ResourceId CreateBitmapResource(const gfx::Size& size,
+                                       const gfx::ColorSpace& color_space);
 
   void DeleteResource(viz::ResourceId id);
   // In the case of GPU resources, we may need to flush the GL context to ensure
@@ -452,14 +453,6 @@
 #endif
 
  private:
-  viz::ResourceId CreateGpuTextureResource(const gfx::Size& size,
-                                           viz::ResourceTextureHint hint,
-                                           viz::ResourceFormat format,
-                                           const gfx::ColorSpace& color_space);
-
-  viz::ResourceId CreateBitmapResource(const gfx::Size& size,
-                                       const gfx::ColorSpace& color_space);
-
   void CreateTexture(viz::internal::Resource* resource);
 
   bool IsGLContextLost() const;
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index 24e8dc3..abad205 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -401,41 +401,36 @@
   }
 }
 
-class ResourceProviderTest : public testing::TestWithParam<viz::ResourceType> {
+class ResourceProviderTest : public testing::TestWithParam<bool> {
  public:
   explicit ResourceProviderTest(bool child_needs_sync_token)
-      : child_needs_sync_token_(child_needs_sync_token),
+      : use_gpu_(GetParam()),
+        child_needs_sync_token_(child_needs_sync_token),
         shared_data_(ContextSharedData::Create()) {
-    switch (GetParam()) {
-      case viz::ResourceType::kGpuMemoryBuffer:
-      case viz::ResourceType::kTexture: {
-        auto context3d(ResourceProviderContext::Create(shared_data_.get()));
-        context3d_ = context3d.get();
-        context_provider_ = TestContextProvider::Create(std::move(context3d));
-        context_provider_->UnboundTestContext3d()
-            ->set_support_texture_format_bgra8888(true);
-        context_provider_->BindToCurrentThread();
+    if (use_gpu_) {
+      auto context3d(ResourceProviderContext::Create(shared_data_.get()));
+      context3d_ = context3d.get();
+      context_provider_ = TestContextProvider::Create(std::move(context3d));
+      context_provider_->UnboundTestContext3d()
+          ->set_support_texture_format_bgra8888(true);
+      context_provider_->BindToCurrentThread();
 
-        auto child_context_owned =
-            ResourceProviderContext::Create(shared_data_.get());
-        child_context_ = child_context_owned.get();
-        child_context_provider_ =
-            TestContextProvider::Create(std::move(child_context_owned));
-        child_context_provider_->UnboundTestContext3d()
-            ->set_support_texture_format_bgra8888(true);
-        child_context_provider_->BindToCurrentThread();
-        break;
-      }
-      case viz::ResourceType::kBitmap:
-        break;
+      auto child_context_owned =
+          ResourceProviderContext::Create(shared_data_.get());
+      child_context_ = child_context_owned.get();
+      child_context_provider_ =
+          TestContextProvider::Create(std::move(child_context_owned));
+      child_context_provider_->UnboundTestContext3d()
+          ->set_support_texture_format_bgra8888(true);
+      child_context_provider_->BindToCurrentThread();
+      gpu_memory_buffer_manager_ =
+          std::make_unique<viz::TestGpuMemoryBufferManager>();
+      child_gpu_memory_buffer_manager_ =
+          gpu_memory_buffer_manager_->CreateClientGpuMemoryBufferManager();
+    } else {
+      shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
     }
 
-    shared_bitmap_manager_.reset(new TestSharedBitmapManager);
-    gpu_memory_buffer_manager_ =
-        std::make_unique<viz::TestGpuMemoryBufferManager>();
-    child_gpu_memory_buffer_manager_ =
-        gpu_memory_buffer_manager_->CreateClientGpuMemoryBufferManager();
-
     resource_provider_ = std::make_unique<DisplayResourceProvider>(
         context_provider_.get(), shared_bitmap_manager_.get(),
         gpu_memory_buffer_manager_.get(), CreateResourceSettings());
@@ -445,6 +440,8 @@
 
   ResourceProviderTest() : ResourceProviderTest(true) {}
 
+  bool use_gpu() const { return use_gpu_; }
+
   void MakeChildResourceProvider() {
     child_resource_provider_ = std::make_unique<LayerTreeResourceProvider>(
         child_context_provider_.get(), shared_bitmap_manager_.get(),
@@ -476,7 +473,7 @@
                                      bool* lost_resource,
                                      bool* release_called,
                                      gpu::SyncToken* sync_token) {
-    if (GetParam() == viz::ResourceType::kTexture) {
+    if (use_gpu()) {
       unsigned texture = child_context_->createTexture();
       gpu::Mailbox gpu_mailbox;
       child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
@@ -534,8 +531,9 @@
   }
 
  protected:
-  bool child_needs_sync_token_;
-  std::unique_ptr<ContextSharedData> shared_data_;
+  const bool use_gpu_;
+  const bool child_needs_sync_token_;
+  const std::unique_ptr<ContextSharedData> shared_data_;
   ResourceProviderContext* context3d_ = nullptr;
   ResourceProviderContext* child_context_ = nullptr;
   scoped_refptr<TestContextProvider> context_provider_;
@@ -548,37 +546,53 @@
   std::unique_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
 };
 
-void CheckCreateResource(viz::ResourceType expected_default_type,
-                         LayerTreeResourceProvider* child_resource_provider,
-                         ResourceProviderContext* context) {
-  DCHECK_EQ(child_resource_provider->IsSoftware(),
-            expected_default_type == viz::ResourceType::kBitmap);
+TEST_P(ResourceProviderTest, Basic) {
+  DCHECK_EQ(resource_provider_->IsSoftware(), !use_gpu());
 
   gfx::Size size(1, 1);
   viz::ResourceFormat format = viz::RGBA_8888;
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  viz::ResourceId id = child_resource_provider->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
-  EXPECT_EQ(1, static_cast<int>(child_resource_provider->num_resources()));
-  if (expected_default_type == viz::ResourceType::kTexture)
-    EXPECT_EQ(0u, context->NumTextures());
+  viz::ResourceId id;
+  if (!use_gpu()) {
+    id =
+        child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
+  } else {
+    id = child_resource_provider_->CreateGpuTextureResource(
+        size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  }
+  EXPECT_EQ(1, static_cast<int>(child_resource_provider_->num_resources()));
+  if (use_gpu())
+    EXPECT_EQ(0u, context()->NumTextures());
 
   uint8_t data[4] = {1, 2, 3, 4};
-  child_resource_provider->CopyToResource(id, data, size);
+  child_resource_provider_->CopyToResource(id, data, size);
+  if (use_gpu())
+    EXPECT_EQ(1u, context()->NumTextures());
 
-  if (expected_default_type == viz::ResourceType::kTexture)
-    EXPECT_EQ(1u, context->NumTextures());
+  // Give the resource to the parent to read its pixels.
+  std::vector<viz::ReturnedResource> returned_to_child;
+  int child_id =
+      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+  std::vector<viz::TransferableResource> list;
+  child_resource_provider_->PrepareSendToParent({id}, &list);
+  resource_provider_->ReceiveFromChild(child_id, list);
+  auto id_map = resource_provider_->GetChildToParentMap(child_id);
 
-  child_resource_provider->DeleteResource(id);
-  EXPECT_EQ(0, static_cast<int>(child_resource_provider->num_resources()));
-  if (expected_default_type == viz::ResourceType::kTexture)
-    EXPECT_EQ(0u, context->NumTextures());
-}
+  uint8_t result[4] = {0};
+  GetResourcePixels(resource_provider_.get(), context(), id_map[id], size,
+                    format, result);
+  EXPECT_EQ(0, memcmp(data, result, pixel_size));
 
-TEST_P(ResourceProviderTest, Basic) {
-  CheckCreateResource(GetParam(), child_resource_provider_.get(), context());
+  // Give it back to the child.
+  resource_provider_->DeclareUsedResourcesFromChild(child_id, {});
+  child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+
+  child_resource_provider_->DeleteResource(id);
+  EXPECT_EQ(0, static_cast<int>(child_resource_provider_->num_resources()));
+  if (use_gpu())
+    EXPECT_EQ(0u, context()->NumTextures());
 }
 
 TEST_P(ResourceProviderTest, SimpleUpload) {
@@ -587,8 +601,13 @@
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(16U, pixel_size);
 
-  viz::ResourceId id = resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  viz::ResourceId id;
+  if (use_gpu()) {
+    id = resource_provider_->CreateGpuTextureResource(
+        size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  } else {
+    id = resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
+  }
 
   uint8_t image[16] = {0};
   resource_provider_->CopyToResource(id, image, size);
@@ -614,7 +633,7 @@
 }
 
 TEST_P(ResourceProviderTest, TransferGLResources) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   gfx::Size size(1, 1);
   // Use some non-default format to detect when defaults aren't changed
@@ -624,12 +643,12 @@
   ASSERT_EQ(4U, pixel_size);
 
   gfx::ColorSpace color_space1 = gfx::ColorSpace::CreateSRGB();
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
+  viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, color_space1);
   uint8_t data1[4] = { 1, 2, 3, 4 };
   child_resource_provider_->CopyToResource(id1, data1, size);
 
-  viz::ResourceId id2 = child_resource_provider_->CreateResource(
+  viz::ResourceId id2 = child_resource_provider_->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   uint8_t data2[4] = { 5, 5, 5, 5 };
   child_resource_provider_->CopyToResource(id2, data2, size);
@@ -849,7 +868,7 @@
 
 #if defined(OS_ANDROID)
 TEST_P(ResourceProviderTest, OverlayPromotionHint) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   GLuint external_texture_id = child_context_->createExternalTexture();
@@ -949,32 +968,35 @@
 }
 #endif
 
-class ResourceProviderTestNoSyncToken : public ResourceProviderTest {
- public:
-  ResourceProviderTestNoSyncToken() : ResourceProviderTest(false) {
-    EXPECT_EQ(viz::ResourceType::kTexture, GetParam());
-  }
-};
+TEST_P(ResourceProviderTest, TransferGLResources_NoSyncToken) {
+  if (!use_gpu())
+    return;
 
-TEST_P(ResourceProviderTestNoSyncToken, TransferGLResources) {
+  bool need_sync_tokens = false;
+  auto no_token_resource_provider = std::make_unique<LayerTreeResourceProvider>(
+      child_context_provider_.get(), shared_bitmap_manager_.get(),
+      gpu_memory_buffer_manager_.get(), need_sync_tokens,
+      CreateResourceSettings());
+
   gfx::Size size(1, 1);
   viz::ResourceFormat format = viz::RGBA_8888;
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
+  viz::ResourceId id1 = no_token_resource_provider->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   uint8_t data1[4] = {1, 2, 3, 4};
-  child_resource_provider_->CopyToResource(id1, data1, size);
+  no_token_resource_provider->CopyToResource(id1, data1, size);
 
-  viz::ResourceId id2 = child_resource_provider_->CreateGpuMemoryBufferResource(
-      size, viz::ResourceTextureHint::kDefault, format,
-      gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace());
+  viz::ResourceId id2 =
+      no_token_resource_provider->CreateGpuMemoryBufferResource(
+          size, viz::ResourceTextureHint::kDefault, format,
+          gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace());
   {
     // Ensure locking the memory buffer doesn't create an unnecessary sync
     // point.
     LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
-        child_resource_provider_.get(), id2);
+        no_token_resource_provider.get(), id2);
     EXPECT_TRUE(lock.GetGpuMemoryBuffer());
   }
 
@@ -988,7 +1010,7 @@
   gpu::SyncToken external_sync_token;
   child_context_->genSyncToken(external_sync_token.GetData());
   EXPECT_TRUE(external_sync_token.HasData());
-  viz::ResourceId id3 = child_resource_provider_->ImportResource(
+  viz::ResourceId id3 = no_token_resource_provider->ImportResource(
       viz::TransferableResource::MakeGL(external_mailbox, GL_LINEAR,
                                         GL_TEXTURE_EXTERNAL_OES,
                                         external_sync_token),
@@ -1005,8 +1027,8 @@
     resource_ids_to_transfer.push_back(id2);
     resource_ids_to_transfer.push_back(id3);
     std::vector<viz::TransferableResource> list;
-    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
-                                                  &list);
+    no_token_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
+                                                    &list);
     ASSERT_EQ(3u, list.size());
     // Standard resources shouldn't require creating and sending a sync point.
     EXPECT_FALSE(list[0].mailbox_holder.sync_token.HasData());
@@ -1048,20 +1070,16 @@
     EXPECT_FALSE(returned_to_child[0].lost);
     EXPECT_FALSE(returned_to_child[1].lost);
     EXPECT_FALSE(returned_to_child[2].lost);
-    child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+    no_token_resource_provider->ReceiveReturnsFromParent(returned_to_child);
     returned_to_child.clear();
   }
 
   resource_provider_->DestroyChild(child_id);
 }
 
-INSTANTIATE_TEST_CASE_P(ResourceProviderTests,
-                        ResourceProviderTestNoSyncToken,
-                        ::testing::Values(viz::ResourceType::kTexture));
-
 // Test that SetBatchReturnResources batching works.
 TEST_P(ResourceProviderTest, SetBatchPreventsReturn) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   gfx::Size size(1, 1);
   viz::ResourceFormat format = viz::RGBA_8888;
@@ -1075,7 +1093,7 @@
   ResourceProvider::ResourceIdArray resource_ids_to_transfer;
   viz::ResourceId ids[2];
   for (size_t i = 0; i < arraysize(ids); i++) {
-    ids[i] = child_resource_provider_->CreateResource(
+    ids[i] = child_resource_provider_->CreateGpuTextureResource(
         size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
     child_resource_provider_->CopyToResource(ids[i], data1, size);
     resource_ids_to_transfer.push_back(ids[i]);
@@ -1127,12 +1145,12 @@
 }
 
 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   gfx::Size size(1, 1);
   viz::ResourceFormat format = viz::RGBA_8888;
 
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
+  viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   uint8_t data1[4] = {1, 2, 3, 4};
   child_resource_provider_->CopyToResource(id1, data1, size);
@@ -1194,12 +1212,12 @@
 };
 
 TEST_P(ResourceProviderTest, ReadLockFenceStopsReturnToChildOrDelete) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   gfx::Size size(1, 1);
   viz::ResourceFormat format = viz::RGBA_8888;
 
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
+  viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   uint8_t data1[4] = {1, 2, 3, 4};
   child_resource_provider_->CopyToResource(id1, data1, size);
@@ -1252,18 +1270,18 @@
 }
 
 TEST_P(ResourceProviderTest, ReadLockFenceDestroyChild) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   gfx::Size size(1, 1);
   viz::ResourceFormat format = viz::RGBA_8888;
 
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
+  viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   uint8_t data[4] = {1, 2, 3, 4};
   child_resource_provider_->CopyToResource(id1, data, size);
   child_resource_provider_->EnableReadLockFencesForTesting(id1);
 
-  viz::ResourceId id2 = child_resource_provider_->CreateResource(
+  viz::ResourceId id2 = child_resource_provider_->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   child_resource_provider_->CopyToResource(id2, data, size);
 
@@ -1319,18 +1337,18 @@
 }
 
 TEST_P(ResourceProviderTest, ReadLockFenceContextLost) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   gfx::Size size(1, 1);
   viz::ResourceFormat format = viz::RGBA_8888;
 
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
+  viz::ResourceId id1 = child_resource_provider_->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   uint8_t data[4] = {1, 2, 3, 4};
   child_resource_provider_->CopyToResource(id1, data, size);
   child_resource_provider_->EnableReadLockFencesForTesting(id1);
 
-  viz::ResourceId id2 = child_resource_provider_->CreateResource(
+  viz::ResourceId id2 = child_resource_provider_->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   child_resource_provider_->CopyToResource(id2, data, size);
 
@@ -1379,7 +1397,7 @@
 }
 
 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
-  if (GetParam() != viz::ResourceType::kBitmap)
+  if (use_gpu())
     return;
 
   gfx::Size size(1, 1);
@@ -1387,13 +1405,13 @@
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  viz::ResourceId id1 =
+      child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
   uint8_t data1[4] = { 1, 2, 3, 4 };
   child_resource_provider_->CopyToResource(id1, data1, size);
 
-  viz::ResourceId id2 = child_resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  viz::ResourceId id2 =
+      child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
   uint8_t data2[4] = { 5, 5, 5, 5 };
   child_resource_provider_->CopyToResource(id2, data2, size);
 
@@ -1547,7 +1565,7 @@
 }
 
 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
-  if (GetParam() != viz::ResourceType::kBitmap)
+  if (use_gpu())
     return;
 
   scoped_refptr<TestContextProvider> child_context_provider =
@@ -1565,8 +1583,9 @@
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  viz::ResourceId id1 = child_resource_provider->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  viz::ResourceId id1 = child_resource_provider->CreateGpuTextureResource(
+      size, viz::ResourceTextureHint::kDefault, viz::RGBA_8888,
+      gfx::ColorSpace());
   uint8_t data1[4] = { 1, 2, 3, 4 };
   child_resource_provider->CopyToResource(id1, data1, size);
 
@@ -1604,7 +1623,7 @@
 }
 
 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
-  if (GetParam() != viz::ResourceType::kBitmap)
+  if (use_gpu())
     return;
 
   gfx::Size size(1, 1);
@@ -1612,8 +1631,8 @@
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  viz::ResourceId id1 =
+      child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
   uint8_t data1[4] = { 1, 2, 3, 4 };
   child_resource_provider_->CopyToResource(id1, data1, size);
 
@@ -1660,13 +1679,22 @@
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  viz::ResourceId id1;
+  viz::ResourceId id2;
+  if (use_gpu()) {
+    id1 = child_resource_provider_->CreateGpuTextureResource(
+        size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+    id2 = child_resource_provider_->CreateGpuTextureResource(
+        size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  } else {
+    id1 =
+        child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
+    id2 =
+        child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
+  }
+
   uint8_t data1[4] = { 1, 2, 3, 4 };
   child_resource_provider_->CopyToResource(id1, data1, size);
-
-  viz::ResourceId id2 = child_resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   uint8_t data2[4] = {5, 5, 5, 5};
   child_resource_provider_->CopyToResource(id2, data2, size);
 
@@ -1683,7 +1711,7 @@
     child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
                                                   &list);
     ASSERT_EQ(2u, list.size());
-    if (GetParam() == viz::ResourceType::kTexture) {
+    if (use_gpu()) {
       EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
       EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData());
     }
@@ -1717,13 +1745,22 @@
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  viz::ResourceId id1 = child_resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  viz::ResourceId id1;
+  viz::ResourceId id2;
+  if (use_gpu()) {
+    id1 = child_resource_provider_->CreateGpuTextureResource(
+        size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+    id2 = child_resource_provider_->CreateGpuTextureResource(
+        size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  } else {
+    id1 =
+        child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
+    id2 =
+        child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
+  }
+
   uint8_t data1[4] = {1, 2, 3, 4};
   child_resource_provider_->CopyToResource(id1, data1, size);
-
-  viz::ResourceId id2 = child_resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   uint8_t data2[4] = {5, 5, 5, 5};
   child_resource_provider_->CopyToResource(id2, data2, size);
 
@@ -1740,7 +1777,7 @@
     child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
                                                   &list);
     ASSERT_EQ(2u, list.size());
-    if (GetParam() == viz::ResourceType::kTexture) {
+    if (use_gpu()) {
       EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
       EXPECT_TRUE(list[1].mailbox_holder.sync_token.HasData());
     }
@@ -1768,8 +1805,15 @@
   size_t pixel_size = TextureSizeBytes(size, format);
   ASSERT_EQ(4U, pixel_size);
 
-  viz::ResourceId id = child_resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  viz::ResourceId id;
+  if (use_gpu()) {
+    id = child_resource_provider_->CreateGpuTextureResource(
+        size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  } else {
+    id =
+        child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
+  }
+
   uint8_t data[4] = { 1, 2, 3, 4 };
   child_resource_provider_->CopyToResource(id, data, size);
 
@@ -1785,7 +1829,7 @@
     child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
                                                   &list);
     ASSERT_EQ(1u, list.size());
-    if (GetParam() == viz::ResourceType::kTexture)
+    if (use_gpu())
       EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData());
     EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
     resource_provider_->ReceiveFromChild(child_id, list);
@@ -1807,7 +1851,7 @@
     resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
 
     ASSERT_EQ(1u, returned_to_child.size());
-    if (GetParam() == viz::ResourceType::kTexture)
+    if (use_gpu())
       EXPECT_TRUE(returned_to_child[0].sync_token.HasData());
     child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
     EXPECT_EQ(0u, child_resource_provider_->num_resources());
@@ -1849,7 +1893,7 @@
     size_t pixel_size = TextureSizeBytes(size, format);
     ASSERT_EQ(4U, pixel_size);
 
-    viz::ResourceId id = child_resource_provider->CreateResource(
+    viz::ResourceId id = child_resource_provider->CreateGpuTextureResource(
         size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
 
     // The new texture is created with GL_LINEAR.
@@ -1950,14 +1994,14 @@
 };
 
 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
 }
 
 TEST_P(ResourceProviderTest, TransferMailboxResources) {
   // Other mailbox transfers tested elsewhere.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   unsigned texture = context()->createTexture();
   context()->bindTexture(GL_TEXTURE_2D, texture);
@@ -2089,11 +2133,19 @@
 TEST_P(ResourceProviderTest, LostResourceInParent) {
   gfx::Size size(1, 1);
   viz::ResourceFormat format = viz::RGBA_8888;
-  viz::ResourceId resource = child_resource_provider_->CreateResource(
-      size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
-  child_resource_provider_->AllocateForTesting(resource);
+
+  viz::ResourceId id;
+  if (use_gpu()) {
+    id = child_resource_provider_->CreateGpuTextureResource(
+        size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
+  } else {
+    id =
+        child_resource_provider_->CreateBitmapResource(size, gfx::ColorSpace());
+  }
+
+  child_resource_provider_->AllocateForTesting(id);
   // Expect a GL resource to be lost.
-  bool should_lose_resource = GetParam() == viz::ResourceType::kTexture;
+  bool should_lose_resource = use_gpu();
 
   std::vector<viz::ReturnedResource> returned_to_child;
   int child_id =
@@ -2101,7 +2153,7 @@
   {
     // Transfer the resource to the parent.
     ResourceProvider::ResourceIdArray resource_ids_to_transfer;
-    resource_ids_to_transfer.push_back(resource);
+    resource_ids_to_transfer.push_back(id);
     std::vector<viz::TransferableResource> list;
     child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
                                                   &list);
@@ -2109,7 +2161,7 @@
 
     resource_provider_->ReceiveFromChild(child_id, list);
     viz::ResourceIdSet resource_ids_to_receive;
-    resource_ids_to_receive.insert(resource);
+    resource_ids_to_receive.insert(id);
     resource_provider_->DeclareUsedResourcesFromChild(child_id,
                                                       resource_ids_to_receive);
   }
@@ -2133,11 +2185,11 @@
   }
 
   // A GL resource should be lost.
-  EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
+  EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(id));
 
   // Lost resources stay in use in the parent forever.
   EXPECT_EQ(should_lose_resource,
-            child_resource_provider_->InUseByConsumer(resource));
+            child_resource_provider_->InUseByConsumer(id));
 }
 
 
@@ -2181,8 +2233,7 @@
 
     ASSERT_EQ(1u, returned_to_child.size());
     // Losing an output surface only loses hardware resources.
-    EXPECT_EQ(returned_to_child[0].lost,
-              GetParam() == viz::ResourceType::kTexture);
+    EXPECT_EQ(returned_to_child[0].lost, use_gpu());
     child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
     returned_to_child.clear();
   }
@@ -2190,7 +2241,7 @@
   // Delete the resource in the child. Expect the resource to be lost if it's
   // a GL texture.
   child_resource_provider_->RemoveImportedResource(resource);
-  EXPECT_EQ(lost_resource, GetParam() == viz::ResourceType::kTexture);
+  EXPECT_EQ(lost_resource, use_gpu());
 }
 
 TEST_P(ResourceProviderTest, Shutdown) {
@@ -2251,11 +2302,13 @@
 
     // If the resource was exported and returned, then it should come with a
     // sync token.
-    if (GetParam() == viz::ResourceType::kTexture &&
-        (i == kShutdownAfterExportAndReturn ||
-         i == kShutdownAfterExportAndReturnWithLostResource ||
-         i == kShutdownAfterContextLossAfterExportAndReturn)) {
-      EXPECT_LE(sync_token.release_count(), release_sync_token.release_count());
+    if (use_gpu()) {
+      if (i == kShutdownAfterExportAndReturn ||
+          i == kShutdownAfterExportAndReturnWithLostResource ||
+          i == kShutdownAfterContextLossAfterExportAndReturn) {
+        EXPECT_LE(sync_token.release_count(),
+                  release_sync_token.release_count());
+      }
     }
 
     // We always get the ReleaseCallback called.
@@ -2271,7 +2324,7 @@
 
 TEST_P(ResourceProviderTest, ScopedSampler) {
   // Sampling is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned(std::make_unique<TextureStateTrackingContext>());
@@ -2287,7 +2340,7 @@
   viz::ResourceFormat format = viz::RGBA_8888;
   int texture_id = 1;
 
-  viz::ResourceId id = resource_provider->CreateResource(
+  viz::ResourceId id = resource_provider->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
 
   // Check that the texture gets created with the right sampler settings.
@@ -2345,7 +2398,7 @@
 
 TEST_P(ResourceProviderTest, ManagedResource) {
   // Sampling is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned(std::make_unique<TextureStateTrackingContext>());
@@ -2363,7 +2416,7 @@
   int texture_id = 1;
 
   // Check that the texture gets created with the right sampler settings.
-  viz::ResourceId id = resource_provider->CreateResource(
+  viz::ResourceId id = resource_provider->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
   EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
   EXPECT_CALL(*context,
@@ -2384,7 +2437,7 @@
 
 TEST_P(ResourceProviderTest, TextureWrapMode) {
   // Sampling is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned(std::make_unique<TextureStateTrackingContext>());
@@ -2402,7 +2455,7 @@
 
   for (int texture_id = 1; texture_id <= 2; ++texture_id) {
     // Check that the texture gets created with the right sampler settings.
-    viz::ResourceId id = resource_provider->CreateResource(
+    viz::ResourceId id = resource_provider->CreateGpuTextureResource(
         size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
     EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
     EXPECT_CALL(*context,
@@ -2422,7 +2475,7 @@
 
 TEST_P(ResourceProviderTest, TextureHint) {
   // Sampling is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned(std::make_unique<TextureStateTrackingContext>());
@@ -2446,7 +2499,7 @@
   };
   for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
     // Check that the texture gets created with the right sampler settings.
-    viz::ResourceId id = resource_provider->CreateResource(
+    viz::ResourceId id = resource_provider->CreateGpuTextureResource(
         size, hints[texture_id - 1], format, gfx::ColorSpace());
     EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
     EXPECT_CALL(*context,
@@ -2476,7 +2529,7 @@
 }
 
 TEST_P(ResourceProviderTest, ImportedResource_SharedMemory) {
-  if (GetParam() != viz::ResourceType::kBitmap)
+  if (use_gpu())
     return;
 
   gfx::Size size(64, 64);
@@ -2674,7 +2727,7 @@
 
 TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_LinearToLinear) {
   // Mailboxing is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   ResourceProviderTestImportedResourceGLFilters::RunTest(
@@ -2684,7 +2737,7 @@
 
 TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_NearestToNearest) {
   // Mailboxing is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   ResourceProviderTestImportedResourceGLFilters::RunTest(
@@ -2694,7 +2747,7 @@
 
 TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_NearestToLinear) {
   // Mailboxing is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   ResourceProviderTestImportedResourceGLFilters::RunTest(
@@ -2704,7 +2757,7 @@
 
 TEST_P(ResourceProviderTest, ImportedResource_GLTexture2D_LinearToNearest) {
   // Mailboxing is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   ResourceProviderTestImportedResourceGLFilters::RunTest(
@@ -2714,7 +2767,7 @@
 
 TEST_P(ResourceProviderTest, ImportedResource_GLTextureExternalOES) {
   // Mailboxing is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned(std::make_unique<TextureStateTrackingContext>());
@@ -2822,7 +2875,7 @@
 
 TEST_P(ResourceProviderTest, WaitSyncTokenIfNeeded_ResourceFromChild) {
   // Mailboxing is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned(std::make_unique<TextureStateTrackingContext>());
@@ -2879,7 +2932,7 @@
 
 TEST_P(ResourceProviderTest, WaitSyncTokenIfNeeded_WithSyncToken) {
   // Mailboxing is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned(std::make_unique<TextureStateTrackingContext>());
@@ -2923,7 +2976,7 @@
 TEST_P(ResourceProviderTest,
        ImportedResource_WaitSyncTokenIfNeeded_NoSyncToken) {
   // Mailboxing is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned(std::make_unique<TextureStateTrackingContext>());
@@ -2961,7 +3014,7 @@
 
 TEST_P(ResourceProviderTest, ImportedResource_PrepareSendToParent_NoSyncToken) {
   // Mailboxing is only supported for GL textures.
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned(std::make_unique<TextureStateTrackingContext>());
@@ -3074,7 +3127,7 @@
 };
 
 TEST_P(ResourceProviderTest, TextureAllocation) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
@@ -3096,7 +3149,7 @@
 
   EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
   // Lazy allocation. Don't allocate when creating the resource.
-  id = resource_provider->CreateResource(
+  id = resource_provider->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
 
   EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
@@ -3110,7 +3163,7 @@
   EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
 
   // Do allocate when we set the pixels.
-  id = resource_provider->CreateResource(
+  id = resource_provider->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
 
   EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
@@ -3128,7 +3181,7 @@
 }
 
 TEST_P(ResourceProviderTest, TextureStorageAllocation) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   auto context_owned =
@@ -3145,7 +3198,7 @@
       gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
       CreateResourceSettings()));
 
-  viz::ResourceId id = resource_provider->CreateResource(
+  viz::ResourceId id = resource_provider->CreateGpuTextureResource(
       gfx::Size(2, 2), viz::ResourceTextureHint::kDefault, viz::RGBA_8888,
       gfx::ColorSpace());
 
@@ -3162,7 +3215,7 @@
 }
 
 TEST_P(ResourceProviderTest, ScopedWriteLockGpuMemoryBuffer) {
-  if (GetParam() != viz::ResourceType::kGpuMemoryBuffer)
+  if (!use_gpu())
     return;
 
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
@@ -3177,10 +3230,10 @@
   const unsigned kTextureId = 123u;
   const unsigned kImageId = 234u;
 
-  auto resource_provider(std::make_unique<LayerTreeResourceProvider>(
+  auto resource_provider = std::make_unique<LayerTreeResourceProvider>(
       context_provider.get(), shared_bitmap_manager_.get(),
       gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
-      CreateResourceSettings()));
+      CreateResourceSettings());
 
   viz::ResourceId id = resource_provider->CreateGpuMemoryBufferResource(
       gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kDefault, format,
@@ -3188,11 +3241,6 @@
 
   InSequence sequence;
 
-  {
-    LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
-        resource_provider.get(), id);
-    EXPECT_TRUE(lock.GetGpuMemoryBuffer());
-  }
   // Create texture and image upon releasing the lock.
   EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId));
   EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
@@ -3201,17 +3249,24 @@
   EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
       .WillOnce(Return(kImageId));
   EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
-  Mock::VerifyAndClearExpectations(context);
 
   {
     LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
         resource_provider.get(), id);
     EXPECT_TRUE(lock.GetGpuMemoryBuffer());
   }
+  Mock::VerifyAndClearExpectations(context);
+
   // Upload to GPU again since image is dirty after the write lock.
   EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId));
   EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
   EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId));
+
+  {
+    LayerTreeResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
+        resource_provider.get(), id);
+    EXPECT_TRUE(lock.GetGpuMemoryBuffer());
+  }
   Mock::VerifyAndClearExpectations(context);
 
   EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId));
@@ -3219,7 +3274,7 @@
 }
 
 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
@@ -3236,7 +3291,7 @@
       CreateResourceSettings()));
   int texture_id = 123;
 
-  viz::ResourceId id = resource_provider->CreateResource(
+  viz::ResourceId id = resource_provider->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, viz::ETC1, gfx::ColorSpace());
   EXPECT_NE(0u, id);
   EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
@@ -3248,7 +3303,7 @@
 }
 
 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
@@ -3266,7 +3321,7 @@
   int texture_id = 123;
   uint8_t pixels[8];
 
-  viz::ResourceId id = resource_provider->CreateResource(
+  viz::ResourceId id = resource_provider->CreateGpuTextureResource(
       size, viz::ResourceTextureHint::kDefault, viz::ETC1, gfx::ColorSpace());
   EXPECT_NE(0u, id);
   EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
@@ -3282,8 +3337,7 @@
 
 INSTANTIATE_TEST_CASE_P(ResourceProviderTests,
                         ResourceProviderTest,
-                        ::testing::Values(viz::ResourceType::kTexture,
-                                          viz::ResourceType::kBitmap));
+                        ::testing::Values(true, false));
 
 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
  public:
@@ -3315,7 +3369,7 @@
         kDelegatedSyncPointsRequired,
         CreateResourceSettings(kTextureAllocationChunkSize)));
 
-    viz::ResourceId id = resource_provider->CreateResource(
+    viz::ResourceId id = resource_provider->CreateGpuTextureResource(
         size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
     resource_provider->AllocateForTesting(id);
     Mock::VerifyAndClearExpectations(context);
@@ -3331,7 +3385,7 @@
         kDelegatedSyncPointsRequired,
         CreateResourceSettings(kTextureAllocationChunkSize)));
 
-    viz::ResourceId id = resource_provider->CreateResource(
+    viz::ResourceId id = resource_provider->CreateGpuTextureResource(
         size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
     resource_provider->AllocateForTesting(id);
     Mock::VerifyAndClearExpectations(context);
@@ -3342,7 +3396,7 @@
 }
 
 TEST_P(ResourceProviderTest, GetSyncTokenForResources) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   gfx::Size size(1, 1);
@@ -3353,7 +3407,7 @@
 
   ResourceProvider::ResourceIdArray array;
   for (uint32_t i = 0; i < arraysize(release_counts); ++i) {
-    viz::ResourceId id = child_resource_provider_->CreateResource(
+    viz::ResourceId id = child_resource_provider_->CreateGpuTextureResource(
         size, viz::ResourceTextureHint::kDefault, format, gfx::ColorSpace());
     array.push_back(id);
 
@@ -3371,7 +3425,7 @@
 }
 
 TEST_P(ResourceProviderTest, ScopedWriteLockGL) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
       new StrictMock<AllocationTrackingContext3D>);
@@ -3389,7 +3443,7 @@
       gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
       CreateResourceSettings()));
 
-  viz::ResourceId id = resource_provider->CreateResource(
+  viz::ResourceId id = resource_provider->CreateGpuTextureResource(
       gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kDefault, format,
       gfx::ColorSpace());
 
@@ -3420,7 +3474,7 @@
 }
 
 TEST_P(ResourceProviderTest, ScopedWriteLockGL_Overlay) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
       new StrictMock<AllocationTrackingContext3D>);
@@ -3440,7 +3494,7 @@
       gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
       CreateResourceSettings()));
 
-  viz::ResourceId id = resource_provider->CreateResource(
+  viz::ResourceId id = resource_provider->CreateGpuTextureResource(
       gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kOverlay, format,
       gfx::ColorSpace());
 
@@ -3471,7 +3525,7 @@
 }
 
 TEST_P(ResourceProviderTest, ScopedWriteLockRaster_Mailbox) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
       new StrictMock<AllocationTrackingContext3D>);
@@ -3490,7 +3544,7 @@
       gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
       CreateResourceSettings()));
 
-  viz::ResourceId id = resource_provider->CreateResource(
+  viz::ResourceId id = resource_provider->CreateGpuTextureResource(
       gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kDefault, format,
       gfx::ColorSpace());
 
@@ -3553,7 +3607,7 @@
 }
 
 TEST_P(ResourceProviderTest, ScopedWriteLockRaster_Mailbox_Overlay) {
-  if (GetParam() != viz::ResourceType::kTexture)
+  if (!use_gpu())
     return;
 
   std::unique_ptr<AllocationTrackingContext3D> context_owned(
@@ -3575,7 +3629,7 @@
       gpu_memory_buffer_manager_.get(), kDelegatedSyncPointsRequired,
       CreateResourceSettings()));
 
-  viz::ResourceId id = resource_provider->CreateResource(
+  viz::ResourceId id = resource_provider->CreateGpuTextureResource(
       gfx::Size(kWidth, kHeight), viz::ResourceTextureHint::kOverlay, format,
       gfx::ColorSpace());
 
diff --git a/cc/resources/scoped_resource.cc b/cc/resources/scoped_resource.cc
index 15751cb..1f6b9da 100644
--- a/cc/resources/scoped_resource.cc
+++ b/cc/resources/scoped_resource.cc
@@ -15,15 +15,31 @@
   Free();
 }
 
-void ScopedResource::Allocate(const gfx::Size& size,
-                              viz::ResourceTextureHint hint,
-                              viz::ResourceFormat format,
-                              const gfx::ColorSpace& color_space) {
+void ScopedResource::AllocateSoftware(const gfx::Size& size,
+                                      const gfx::ColorSpace& color_space) {
+  DCHECK(!id());
+  DCHECK(!size.IsEmpty());
+
+  set_dimensions(size, viz::RGBA_8888);
+  set_id(resource_provider_->CreateBitmapResource(size, color_space));
+  set_color_space(color_space);
+  hint_ = viz::ResourceTextureHint::kDefault;
+
+#if DCHECK_IS_ON()
+  allocate_thread_id_ = base::PlatformThread::CurrentId();
+#endif
+}
+
+void ScopedResource::AllocateGpuTexture(const gfx::Size& size,
+                                        viz::ResourceTextureHint hint,
+                                        viz::ResourceFormat format,
+                                        const gfx::ColorSpace& color_space) {
   DCHECK(!id());
   DCHECK(!size.IsEmpty());
 
   set_dimensions(size, format);
-  set_id(resource_provider_->CreateResource(size, hint, format, color_space));
+  set_id(resource_provider_->CreateGpuTextureResource(size, hint, format,
+                                                      color_space));
   set_color_space(color_space);
   hint_ = hint;
 
@@ -32,7 +48,7 @@
 #endif
 }
 
-void ScopedResource::AllocateWithGpuMemoryBuffer(
+void ScopedResource::AllocateGpuMemoryBuffer(
     const gfx::Size& size,
     viz::ResourceFormat format,
     gfx::BufferUsage usage,
diff --git a/cc/resources/scoped_resource.h b/cc/resources/scoped_resource.h
index 47da4cd..68b8c10a 100644
--- a/cc/resources/scoped_resource.h
+++ b/cc/resources/scoped_resource.h
@@ -24,14 +24,16 @@
   explicit ScopedResource(ResourceProvider* provider);
   virtual ~ScopedResource();
 
-  void Allocate(const gfx::Size& size,
-                viz::ResourceTextureHint hint,
-                viz::ResourceFormat format,
-                const gfx::ColorSpace& color_space);
-  void AllocateWithGpuMemoryBuffer(const gfx::Size& size,
-                                   viz::ResourceFormat format,
-                                   gfx::BufferUsage usage,
-                                   const gfx::ColorSpace& color_space);
+  void AllocateSoftware(const gfx::Size& size,
+                        const gfx::ColorSpace& color_space);
+  void AllocateGpuTexture(const gfx::Size& size,
+                          viz::ResourceTextureHint hint,
+                          viz::ResourceFormat format,
+                          const gfx::ColorSpace& color_space);
+  void AllocateGpuMemoryBuffer(const gfx::Size& size,
+                               viz::ResourceFormat format,
+                               gfx::BufferUsage usage,
+                               const gfx::ColorSpace& color_space);
   void Free();
 
   viz::ResourceTextureHint hint() const { return hint_; }
diff --git a/cc/resources/scoped_resource_unittest.cc b/cc/resources/scoped_resource_unittest.cc
index 2b7ad01..62fed59 100644
--- a/cc/resources/scoped_resource_unittest.cc
+++ b/cc/resources/scoped_resource_unittest.cc
@@ -48,8 +48,9 @@
       FakeResourceProvider::Create(context_provider.get(),
                                    shared_bitmap_manager.get());
   auto texture = std::make_unique<ScopedResource>(resource_provider.get());
-  texture->Allocate(gfx::Size(30, 30), viz::ResourceTextureHint::kDefault,
-                    viz::RGBA_8888, gfx::ColorSpace());
+  texture->AllocateGpuTexture(gfx::Size(30, 30),
+                              viz::ResourceTextureHint::kDefault,
+                              viz::RGBA_8888, gfx::ColorSpace());
 
   // The texture has an allocated byte-size now.
   size_t expected_bytes = 30 * 30 * 4;
@@ -77,8 +78,9 @@
     auto texture = std::make_unique<ScopedResource>(resource_provider.get());
 
     EXPECT_EQ(0u, resource_provider->num_resources());
-    texture->Allocate(gfx::Size(30, 30), viz::ResourceTextureHint::kDefault,
-                      viz::RGBA_8888, gfx::ColorSpace());
+    texture->AllocateGpuTexture(gfx::Size(30, 30),
+                                viz::ResourceTextureHint::kDefault,
+                                viz::RGBA_8888, gfx::ColorSpace());
     EXPECT_LT(0u, texture->id());
     EXPECT_EQ(1u, resource_provider->num_resources());
   }
@@ -87,8 +89,9 @@
   {
     auto texture = std::make_unique<ScopedResource>(resource_provider.get());
     EXPECT_EQ(0u, resource_provider->num_resources());
-    texture->Allocate(gfx::Size(30, 30), viz::ResourceTextureHint::kDefault,
-                      viz::RGBA_8888, gfx::ColorSpace());
+    texture->AllocateGpuTexture(gfx::Size(30, 30),
+                                viz::ResourceTextureHint::kDefault,
+                                viz::RGBA_8888, gfx::ColorSpace());
     EXPECT_LT(0u, texture->id());
     EXPECT_EQ(1u, resource_provider->num_resources());
     texture->Free();
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
index 79b555e..dac835d 100644
--- a/cc/resources/video_resource_updater.cc
+++ b/cc/resources/video_resource_updater.cc
@@ -36,8 +36,6 @@
 
 namespace {
 
-const viz::ResourceFormat kRGBResourceFormat = viz::RGBA_8888;
-
 VideoFrameExternalResources::ResourceType ExternalResourceTypeForHardwarePlanes(
     media::VideoPixelFormat format,
     GLuint target,
@@ -237,24 +235,29 @@
 
   // There was nothing available to reuse or recycle. Allocate a new resource.
   return AllocateResource(resource_size, resource_format, color_space,
-                          !software_resource);
+                          software_resource);
 }
 
 VideoResourceUpdater::ResourceList::iterator
 VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size,
                                        viz::ResourceFormat format,
                                        const gfx::ColorSpace& color_space,
-                                       bool has_mailbox) {
+                                       bool software_resource) {
+  viz::ResourceId resource_id;
+  gpu::Mailbox mailbox;
+
   // TODO(danakj): Abstract out hw/sw resource create/delete from
   // ResourceProvider and stop using ResourceProvider in this class.
-  const viz::ResourceId resource_id = resource_provider_->CreateResource(
-      plane_size, viz::ResourceTextureHint::kDefault, format, color_space);
-  DCHECK_NE(resource_id, 0u);
-
-  gpu::Mailbox mailbox;
-  if (has_mailbox) {
+  if (software_resource) {
+    DCHECK_EQ(format, viz::RGBA_8888);
+    resource_id =
+        resource_provider_->CreateBitmapResource(plane_size, color_space);
+  } else {
     DCHECK(context_provider_);
 
+    resource_id = resource_provider_->CreateGpuTextureResource(
+        plane_size, viz::ResourceTextureHint::kDefault, format, color_space);
+
     gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
 
     gl->GenMailboxCHROMIUM(mailbox.name);
@@ -342,7 +345,7 @@
   // Obviously, this is suboptimal and should be addressed once ubercompositor
   // starts shaping up.
   if (software_compositor || texture_needs_rgb_conversion) {
-    output_resource_format = kRGBResourceFormat;
+    output_resource_format = viz::RGBA_8888;
     output_plane_count = 1;
     bits_per_channel = 8;
   }
@@ -385,7 +388,7 @@
   if (software_compositor || texture_needs_rgb_conversion) {
     DCHECK_EQ(plane_resources.size(), 1u);
     PlaneResource& plane_resource = *plane_resources[0];
-    DCHECK_EQ(plane_resource.resource_format(), kRGBResourceFormat);
+    DCHECK_EQ(plane_resource.resource_format(), viz::RGBA_8888);
     DCHECK(!software_compositor ||
            plane_resource.resource_id() > viz::kInvalidResourceId);
     DCHECK_EQ(software_compositor, plane_resource.mailbox().IsZero());
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h
index 8e1f6b4..c422902 100644
--- a/cc/resources/video_resource_updater.h
+++ b/cc/resources/video_resource_updater.h
@@ -176,7 +176,7 @@
   ResourceList::iterator AllocateResource(const gfx::Size& plane_size,
                                           viz::ResourceFormat format,
                                           const gfx::ColorSpace& color_space,
-                                          bool has_mailbox);
+                                          bool software_resource);
   void DeleteResource(ResourceList::iterator resource_it);
   void CopyHardwarePlane(media::VideoFrame* video_frame,
                          const gfx::ColorSpace& resource_color_space,
diff --git a/cc/test/DEPS b/cc/test/DEPS
index 5e9cc03..953d17f 100644
--- a/cc/test/DEPS
+++ b/cc/test/DEPS
@@ -8,7 +8,7 @@
   "+gpu/command_buffer/client/gles2_lib.h",
   "+gpu/command_buffer/client/raster_implementation_gles.h",
   "+gpu/command_buffer/client/shared_memory_limits.h",
-  "+gpu/command_buffer/common/gles2_cmd_utils.h",
+  "+gpu/command_buffer/common/context_creation_attribs.h",
   "+gpu/command_buffer/service/image_factory.h",
   "+gpu/ipc",
   "+gpu/skia_bindings/grcontext_for_gles2_interface.h",
diff --git a/cc/test/fake_picture_layer_tiling_client.cc b/cc/test/fake_picture_layer_tiling_client.cc
index 33c236a..d556e43 100644
--- a/cc/test/fake_picture_layer_tiling_client.cc
+++ b/cc/test/fake_picture_layer_tiling_client.cc
@@ -25,6 +25,7 @@
     ResourceProvider* resource_provider)
     : resource_pool_(
           ResourcePool::Create(resource_provider,
+                               true,
                                base::ThreadTaskRunnerHandle::Get().get(),
                                viz::ResourceTextureHint::kDefault,
                                ResourcePool::kDefaultExpirationDelay,
diff --git a/cc/test/fake_ui_resource_layer_tree_host_impl.cc b/cc/test/fake_ui_resource_layer_tree_host_impl.cc
index c24049be..f1b602ed 100644
--- a/cc/test/fake_ui_resource_layer_tree_host_impl.cc
+++ b/cc/test/fake_ui_resource_layer_tree_host_impl.cc
@@ -23,7 +23,7 @@
     DeleteUIResource(uid);
 
   UIResourceData data;
-  data.resource_id = resource_provider()->CreateResource(
+  data.resource_id = resource_provider()->CreateGpuTextureResource(
       bitmap.GetSize(), viz::ResourceTextureHint::kDefault, viz::RGBA_8888,
       gfx::ColorSpace());
 
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index 8ddce1e..1cd7223 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -60,9 +60,10 @@
 
       *raster_buffer_provider =
           BitmapRasterBufferProvider::Create(resource_provider);
-      *resource_pool = ResourcePool::Create(
-          resource_provider, task_runner, viz::ResourceTextureHint::kDefault,
-          ResourcePool::kDefaultExpirationDelay, false);
+      *resource_pool =
+          ResourcePool::Create(resource_provider, false, task_runner,
+                               viz::ResourceTextureHint::kDefault,
+                               ResourcePool::kDefaultExpirationDelay, false);
       break;
     case GPU:
       EXPECT_TRUE(compositor_context_provider);
@@ -74,7 +75,7 @@
           resource_provider, false, 0, viz::PlatformColor::BestTextureFormat(),
           false);
       *resource_pool =
-          ResourcePool::Create(resource_provider, task_runner,
+          ResourcePool::Create(resource_provider, true, task_runner,
                                viz::ResourceTextureHint::kFramebuffer,
                                ResourcePool::kDefaultExpirationDelay, false);
       break;
@@ -99,9 +100,10 @@
           resource_provider, max_bytes_per_copy_operation, false,
           max_staging_buffer_usage_in_bytes,
           viz::PlatformColor::BestTextureFormat());
-      *resource_pool = ResourcePool::Create(
-          resource_provider, task_runner, viz::ResourceTextureHint::kDefault,
-          ResourcePool::kDefaultExpirationDelay, false);
+      *resource_pool =
+          ResourcePool::Create(resource_provider, true, task_runner,
+                               viz::ResourceTextureHint::kDefault,
+                               ResourcePool::kDefaultExpirationDelay, false);
       break;
   }
 }
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h
index 04cc88c..9ad595d 100644
--- a/cc/test/pixel_test.h
+++ b/cc/test/pixel_test.h
@@ -96,6 +96,8 @@
     return static_cast<RendererType*>(renderer_.get());
   }
 
+  bool use_gpu() { return !!child_context_provider_; }
+
  protected:
   void SetUp() override;
 };
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc
index 12110bd..ded74602 100644
--- a/cc/test/render_pass_test_utils.cc
+++ b/cc/test/render_pass_test_utils.cc
@@ -133,32 +133,32 @@
       gpu::CommandBufferId::FromUnsafeValue(0x123), 30);
   *sync_token_for_mailbox_tebxture = kSyncTokenForMailboxTextureQuad;
 
-  viz::ResourceId resource1 = resource_provider->CreateResource(
+  viz::ResourceId resource1 = resource_provider->CreateGpuTextureResource(
       gfx::Size(45, 5), viz::ResourceTextureHint::kDefault,
       resource_provider->best_texture_format(), gfx::ColorSpace::CreateSRGB());
   resource_provider->AllocateForTesting(resource1);
-  viz::ResourceId resource2 = resource_provider->CreateResource(
+  viz::ResourceId resource2 = resource_provider->CreateGpuTextureResource(
       gfx::Size(346, 61), viz::ResourceTextureHint::kDefault,
       resource_provider->best_texture_format(), gfx::ColorSpace::CreateSRGB());
   resource_provider->AllocateForTesting(resource2);
-  viz::ResourceId resource3 = resource_provider->CreateResource(
+  viz::ResourceId resource3 = resource_provider->CreateGpuTextureResource(
       gfx::Size(12, 134), viz::ResourceTextureHint::kDefault,
       resource_provider->best_texture_format(), gfx::ColorSpace::CreateSRGB());
   resource_provider->AllocateForTesting(resource3);
-  viz::ResourceId resource4 = resource_provider->CreateResource(
+  viz::ResourceId resource4 = resource_provider->CreateGpuTextureResource(
       gfx::Size(56, 12), viz::ResourceTextureHint::kDefault,
       resource_provider->best_texture_format(), gfx::ColorSpace::CreateSRGB());
   resource_provider->AllocateForTesting(resource4);
   gfx::Size resource5_size(73, 26);
-  viz::ResourceId resource5 = resource_provider->CreateResource(
+  viz::ResourceId resource5 = resource_provider->CreateGpuTextureResource(
       resource5_size, viz::ResourceTextureHint::kDefault,
       resource_provider->best_texture_format(), gfx::ColorSpace::CreateSRGB());
   resource_provider->AllocateForTesting(resource5);
-  viz::ResourceId resource6 = resource_provider->CreateResource(
+  viz::ResourceId resource6 = resource_provider->CreateGpuTextureResource(
       gfx::Size(64, 92), viz::ResourceTextureHint::kDefault,
       resource_provider->best_texture_format(), gfx::ColorSpace::CreateSRGB());
   resource_provider->AllocateForTesting(resource6);
-  viz::ResourceId resource7 = resource_provider->CreateResource(
+  viz::ResourceId resource7 = resource_provider->CreateGpuTextureResource(
       gfx::Size(9, 14), viz::ResourceTextureHint::kDefault,
       resource_provider->best_texture_format(), gfx::ColorSpace::CreateSRGB());
   resource_provider->AllocateForTesting(resource7);
@@ -245,7 +245,7 @@
 
   viz::ResourceId plane_resources[4];
   for (int i = 0; i < 4; ++i) {
-    plane_resources[i] = resource_provider->CreateResource(
+    plane_resources[i] = resource_provider->CreateGpuTextureResource(
         gfx::Size(20, 12), viz::ResourceTextureHint::kDefault,
         resource_provider->best_texture_format(),
         gfx::ColorSpace::CreateREC601());
@@ -281,38 +281,38 @@
       gpu::CommandBufferId::FromUnsafeValue(0x123), 30);
   *sync_token_for_mailbox_tebxture = kSyncTokenForMailboxTextureQuad;
 
-  viz::ResourceId resource1 = child_resource_provider->CreateResource(
+  viz::ResourceId resource1 = child_resource_provider->CreateGpuTextureResource(
       gfx::Size(45, 5), viz::ResourceTextureHint::kDefault,
       child_resource_provider->best_texture_format(),
       gfx::ColorSpace::CreateSRGB());
   child_resource_provider->AllocateForTesting(resource1);
-  viz::ResourceId resource2 = child_resource_provider->CreateResource(
+  viz::ResourceId resource2 = child_resource_provider->CreateGpuTextureResource(
       gfx::Size(346, 61), viz::ResourceTextureHint::kDefault,
       child_resource_provider->best_texture_format(),
       gfx::ColorSpace::CreateSRGB());
   child_resource_provider->AllocateForTesting(resource2);
-  viz::ResourceId resource3 = child_resource_provider->CreateResource(
+  viz::ResourceId resource3 = child_resource_provider->CreateGpuTextureResource(
       gfx::Size(12, 134), viz::ResourceTextureHint::kDefault,
       child_resource_provider->best_texture_format(),
       gfx::ColorSpace::CreateSRGB());
   child_resource_provider->AllocateForTesting(resource3);
-  viz::ResourceId resource4 = child_resource_provider->CreateResource(
+  viz::ResourceId resource4 = child_resource_provider->CreateGpuTextureResource(
       gfx::Size(56, 12), viz::ResourceTextureHint::kDefault,
       child_resource_provider->best_texture_format(),
       gfx::ColorSpace::CreateSRGB());
   child_resource_provider->AllocateForTesting(resource4);
   gfx::Size resource5_size(73, 26);
-  viz::ResourceId resource5 = child_resource_provider->CreateResource(
+  viz::ResourceId resource5 = child_resource_provider->CreateGpuTextureResource(
       resource5_size, viz::ResourceTextureHint::kDefault,
       child_resource_provider->best_texture_format(),
       gfx::ColorSpace::CreateSRGB());
   child_resource_provider->AllocateForTesting(resource5);
-  viz::ResourceId resource6 = child_resource_provider->CreateResource(
+  viz::ResourceId resource6 = child_resource_provider->CreateGpuTextureResource(
       gfx::Size(64, 92), viz::ResourceTextureHint::kDefault,
       child_resource_provider->best_texture_format(),
       gfx::ColorSpace::CreateSRGB());
   child_resource_provider->AllocateForTesting(resource6);
-  viz::ResourceId resource7 = child_resource_provider->CreateResource(
+  viz::ResourceId resource7 = child_resource_provider->CreateGpuTextureResource(
       gfx::Size(9, 14), viz::ResourceTextureHint::kDefault,
       child_resource_provider->best_texture_format(),
       gfx::ColorSpace::CreateSRGB());
@@ -341,7 +341,7 @@
 
   viz::ResourceId plane_resources[4];
   for (int i = 0; i < 4; ++i) {
-    plane_resources[i] = child_resource_provider->CreateResource(
+    plane_resources[i] = child_resource_provider->CreateGpuTextureResource(
         gfx::Size(20, 12), viz::ResourceTextureHint::kDefault,
         child_resource_provider->best_texture_format(),
         gfx::ColorSpace::CreateREC601());
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc
index 1a997eb..746f32cd 100644
--- a/cc/test/test_in_process_context_provider.cc
+++ b/cc/test/test_in_process_context_provider.cc
@@ -17,7 +17,7 @@
 #include "gpu/command_buffer/client/gles2_lib.h"
 #include "gpu/command_buffer/client/raster_implementation_gles.h"
 #include "gpu/command_buffer/client/shared_memory_limits.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/ipc/gl_in_process_context.h"
 #include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
 #include "third_party/khronos/GLES2/gl2.h"
@@ -35,7 +35,7 @@
     gpu::GLInProcessContext* shared_context,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   const bool is_offscreen = true;
-  gpu::gles2::ContextCreationAttribHelper attribs;
+  gpu::ContextCreationAttribs attribs;
   attribs.alpha_size = -1;
   attribs.depth_size = 24;
   attribs.stencil_size = 8;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index ba0c010..5d186491 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2530,7 +2530,7 @@
       layer_tree_frame_sink_->context_provider();
   if (!compositor_context_provider) {
     *resource_pool =
-        ResourcePool::Create(resource_provider_.get(), GetTaskRunner(),
+        ResourcePool::Create(resource_provider_.get(), false, GetTaskRunner(),
                              viz::ResourceTextureHint::kDefault,
                              ResourcePool::kDefaultExpirationDelay,
                              settings_.disallow_non_exact_resource_reuse);
@@ -2546,7 +2546,7 @@
     DCHECK(worker_context_provider);
 
     *resource_pool =
-        ResourcePool::Create(resource_provider_.get(), GetTaskRunner(),
+        ResourcePool::Create(resource_provider_.get(), true, GetTaskRunner(),
                              viz::ResourceTextureHint::kFramebuffer,
                              ResourcePool::kDefaultExpirationDelay,
                              settings_.disallow_non_exact_resource_reuse);
@@ -2591,7 +2591,7 @@
   }
 
   *resource_pool = ResourcePool::Create(
-      resource_provider_.get(), GetTaskRunner(),
+      resource_provider_.get(), true, GetTaskRunner(),
       viz::ResourceTextureHint::kDefault, ResourcePool::kDefaultExpirationDelay,
       settings_.disallow_non_exact_resource_reuse);
 
@@ -3841,6 +3841,11 @@
 }
 
 void LayerTreeHostImpl::MouseMoveAt(const gfx::Point& viewport_point) {
+  // Early out if there are no animation controllers and avoid the hit test.
+  // This happens on platforms without animated scrollbars.
+  if (scrollbar_animation_controllers_.empty())
+    return;
+
   gfx::PointF device_viewport_point = gfx::ScalePoint(
       gfx::PointF(viewport_point), active_tree_->device_scale_factor());
   LayerImpl* layer_impl =
@@ -4326,9 +4331,15 @@
     upload_size = gfx::ScaleToCeiledSize(source_size, scale, scale);
   }
 
-  id = resource_provider_->CreateResource(
-      upload_size, viz::ResourceTextureHint::kDefault, format,
-      gfx::ColorSpace::CreateSRGB());
+  if (layer_tree_frame_sink_->context_provider()) {
+    id = resource_provider_->CreateGpuTextureResource(
+        upload_size, viz::ResourceTextureHint::kDefault, format,
+        gfx::ColorSpace::CreateSRGB());
+  } else {
+    DCHECK_EQ(format, viz::RGBA_8888);
+    id = resource_provider_->CreateBitmapResource(
+        upload_size, gfx::ColorSpace::CreateSRGB());
+  }
 
   if (!scaled) {
     resource_provider_->CopyToResource(id, bitmap.GetPixels(), source_size);
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 7fa7327..7bf3a45 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -7940,12 +7940,27 @@
 
 class BlendStateCheckLayer : public LayerImpl {
  public:
-  static std::unique_ptr<LayerImpl> Create(
-      LayerTreeImpl* tree_impl,
-      int id,
-      ResourceProvider* resource_provider) {
-    return base::WrapUnique(
-        new BlendStateCheckLayer(tree_impl, id, resource_provider));
+  BlendStateCheckLayer(LayerTreeImpl* tree_impl,
+                       int id,
+                       ResourceProvider* resource_provider)
+      : LayerImpl(tree_impl, id),
+        blend_(false),
+        has_render_surface_(false),
+        comparison_layer_(nullptr),
+        quads_appended_(false),
+        quad_rect_(5, 5, 5, 5),
+        quad_visible_rect_(5, 5, 5, 5) {
+    if (tree_impl->context_provider()) {
+      resource_id_ = resource_provider->CreateGpuTextureResource(
+          gfx::Size(1, 1), viz::ResourceTextureHint::kDefault, viz::RGBA_8888,
+          gfx::ColorSpace());
+    } else {
+      resource_id_ = resource_provider->CreateBitmapResource(gfx::Size(1, 1),
+                                                             gfx::ColorSpace());
+    }
+    resource_provider->AllocateForTesting(resource_id_);
+    SetBounds(gfx::Size(10, 10));
+    SetDrawsContent(true);
   }
 
   void AppendQuads(viz::RenderPass* render_pass,
@@ -7994,26 +8009,6 @@
   }
 
  private:
-  BlendStateCheckLayer(LayerTreeImpl* tree_impl,
-                       int id,
-                       ResourceProvider* resource_provider)
-      : LayerImpl(tree_impl, id),
-        blend_(false),
-        has_render_surface_(false),
-        comparison_layer_(nullptr),
-        quads_appended_(false),
-        quad_rect_(5, 5, 5, 5),
-        quad_visible_rect_(5, 5, 5, 5),
-        resource_id_(resource_provider->CreateResource(
-            gfx::Size(1, 1),
-            viz::ResourceTextureHint::kDefault,
-            viz::RGBA_8888,
-            gfx::ColorSpace())) {
-    resource_provider->AllocateForTesting(resource_id_);
-    SetBounds(gfx::Size(10, 10));
-    SetDrawsContent(true);
-  }
-
   bool blend_;
   bool has_render_surface_;
   LayerImpl* comparison_layer_;
@@ -8035,7 +8030,7 @@
   }
   LayerImpl* root = host_impl_->active_tree()->root_layer_for_testing();
 
-  root->test_properties()->AddChild(BlendStateCheckLayer::Create(
+  root->test_properties()->AddChild(std::make_unique<BlendStateCheckLayer>(
       host_impl_->active_tree(), 2, host_impl_->resource_provider()));
   auto* layer1 =
       static_cast<BlendStateCheckLayer*>(root->test_properties()->children[0]);
@@ -8088,7 +8083,7 @@
   EXPECT_TRUE(layer1->quads_appended());
   host_impl_->DidDrawAllLayers(frame);
 
-  layer1->test_properties()->AddChild(BlendStateCheckLayer::Create(
+  layer1->test_properties()->AddChild(std::make_unique<BlendStateCheckLayer>(
       host_impl_->active_tree(), 3, host_impl_->resource_provider()));
   auto* layer2 = static_cast<BlendStateCheckLayer*>(
       layer1->test_properties()->children[0]);
@@ -8352,7 +8347,7 @@
     host_impl_->active_tree()
         ->root_layer_for_testing()
         ->test_properties()
-        ->AddChild(BlendStateCheckLayer::Create(
+        ->AddChild(std::make_unique<BlendStateCheckLayer>(
             host_impl_->active_tree(), 2, host_impl_->resource_provider()));
     child_ = static_cast<BlendStateCheckLayer*>(host_impl_->active_tree()
                                                     ->root_layer_for_testing()
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index 8cdfee3..97054e58 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -199,6 +199,7 @@
           "//chrome_elf",
           "//components/browser_watcher:browser_watcher_client",
           "//components/crash/content/app:run_as_crashpad_handler",
+          "//components/crash/core/common",
           "//components/flags_ui:switches",
           "//content:sandbox_helper_win",
           "//content/public/common:static_switches",
diff --git a/chrome/VERSION b/chrome/VERSION
index 0c4df07..e1dd217 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=65
 MINOR=0
-BUILD=3301
+BUILD=3302
 PATCH=0
diff --git a/chrome/android/java/res/drawable-hdpi/infobar_redirect_blocked.png b/chrome/android/java/res/drawable-hdpi/infobar_redirect_blocked.png
deleted file mode 100644
index eca1506..0000000
--- a/chrome/android/java/res/drawable-hdpi/infobar_redirect_blocked.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/infobar_redirect_blocked.png b/chrome/android/java/res/drawable-mdpi/infobar_redirect_blocked.png
deleted file mode 100644
index 67814ba5..0000000
--- a/chrome/android/java/res/drawable-mdpi/infobar_redirect_blocked.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/infobar_redirect_blocked.png b/chrome/android/java/res/drawable-xhdpi/infobar_redirect_blocked.png
deleted file mode 100644
index 9a224a27..0000000
--- a/chrome/android/java/res/drawable-xhdpi/infobar_redirect_blocked.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/infobar_redirect_blocked.png b/chrome/android/java/res/drawable-xxhdpi/infobar_redirect_blocked.png
deleted file mode 100644
index f9833d5a..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/infobar_redirect_blocked.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/infobar_redirect_blocked.png b/chrome/android/java/res/drawable-xxxhdpi/infobar_redirect_blocked.png
deleted file mode 100644
index 33e666f..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/infobar_redirect_blocked.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
index aac5fc1..7008962 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -384,6 +384,14 @@
         newIntent.setData(uri);
         newIntent.setClassName(context, CustomTabActivity.class.getName());
 
+        // If |uri| is a content:// URI, we want to propagate the URI permissions. This can't be
+        // achieved by simply adding the FLAG_GRANT_READ_URI_PERMISSION to the Intent, since the
+        // data URI on the Intent isn't |uri|, it just has |uri| as a query parameter.
+        if (uri != null && UrlConstants.CONTENT_SCHEME.equals(uri.getScheme())) {
+            context.grantUriPermission(
+                    context.getPackageName(), uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        }
+
         // If a CCT intent triggers First Run, then NEW_TASK will be automatically applied.  As
         // part of that, it will inherit the EXCLUDE_FROM_RECENTS bit from ChromeLauncherActivity,
         // so explicitly remove it to ensure the CCT does not get lost in recents.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index bde03300..20111de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -225,7 +225,7 @@
         mTabModelObserver = new EmptyTabModelObserver() {
             @Override
             public void didSelectTab(Tab tab, TabSelectionType type, int lastId) {
-                if (!mIsPromotingToTab && tab.getId() != lastId
+                if ((!mIsPromotingToTab && tab.getId() != lastId)
                         || mActivity.getTabModelSelector().isIncognitoSelected()) {
                     hideContextualSearch(StateChangeReason.UNKNOWN);
                     mSelectionController.onTabSelected();
@@ -352,6 +352,15 @@
         return mSearchPanel == null ? null : mSearchPanel.getContentViewCore();
     }
 
+    /**
+     * @return the {@link WebContents} of the {@code mSearchPanel} or {@code null}.
+     */
+    private @Nullable WebContents getSearchPanelWebContents() {
+        return getSearchPanelContentViewCore() == null
+                ? null
+                : getSearchPanelContentViewCore().getWebContents();
+    }
+
     /** @return The Base Page's {@link WebContents}. */
     @Nullable
     private WebContents getBaseWebContents() {
@@ -790,7 +799,9 @@
         assert mSearchPanel != null;
         mLoadedSearchUrlTimeMs = System.currentTimeMillis();
         mLastSearchRequestLoaded = mSearchRequest;
-        mSearchPanel.loadUrlInPanel(mSearchRequest.getSearchUrl());
+        String searchUrl = mSearchRequest.getSearchUrl();
+        nativeWhitelistContextualSearchJsApiUrl(mNativeContextualSearchManagerPtr, searchUrl);
+        mSearchPanel.loadUrlInPanel(searchUrl);
         mDidStartLoadingResolvedSearchRequest = true;
 
         // TODO(pedrosimonetti): If the user taps on a word and quickly after that taps on the
@@ -850,9 +861,9 @@
 
     @Override
     public void stopPanelContentsNavigation() {
-        if (getSearchPanelContentViewCore() == null) return;
+        if (getSearchPanelWebContents() == null) return;
 
-        getSearchPanelContentViewCore().getWebContents().stop();
+        getSearchPanelWebContents().stop();
     }
 
     // ============================================================================================
@@ -1007,13 +1018,10 @@
 
         @Override
         public void onContentViewCreated(ContentViewCore contentViewCore) {
-            // TODO(donnd): Consider moving to OverlayPanelContent.
-            // Enable the Contextual Search JavaScript API between our service and the new view.
-            nativeEnableContextualSearchJsApiForOverlay(
-                    mNativeContextualSearchManagerPtr, contentViewCore.getWebContents());
-
             // TODO(mdjones): Move SearchContentViewDelegate ownership to panel.
             mSearchContentViewDelegate.setOverlayPanelContentViewCore(contentViewCore);
+            nativeEnableContextualSearchJsApiForWebContents(
+                    mNativeContextualSearchManagerPtr, getSearchPanelWebContents());
         }
 
         @Override
@@ -1749,7 +1757,9 @@
             ContextualSearchContext contextualSearchContext, WebContents baseWebContents);
     protected native void nativeGatherSurroundingText(long nativeContextualSearchManager,
             ContextualSearchContext contextualSearchContext, WebContents baseWebContents);
-    private native void nativeEnableContextualSearchJsApiForOverlay(
+    private native void nativeWhitelistContextualSearchJsApiUrl(
+            long nativeContextualSearchManager, String url);
+    private native void nativeEnableContextualSearchJsApiForWebContents(
             long nativeContextualSearchManager, WebContents overlayWebContents);
     // Don't call these directly, instead call the private methods that cache the results.
     private native String nativeGetTargetLanguage(long nativeContextualSearchManager);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunFragment.java
index 2a3e596..597ec447 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/AccountFirstRunFragment.java
@@ -12,6 +12,7 @@
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ntp.cards.SignInPromo;
 import org.chromium.chrome.browser.signin.AccountSigninView;
 import org.chromium.chrome.browser.signin.SigninAccessPoint;
 import org.chromium.chrome.browser.signin.SigninManager;
@@ -44,6 +45,7 @@
         AccountSigninView.Listener listener = new AccountSigninView.Listener() {
             @Override
             public void onAccountSelectionCanceled() {
+                SignInPromo.temporarilySuppressPromos();
                 getPageDelegate().refuseSignIn();
                 advanceToNextPage();
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/FramebustBlockInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/FramebustBlockInfoBar.java
index 347708b..4bb4d0b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/FramebustBlockInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/FramebustBlockInfoBar.java
@@ -27,7 +27,7 @@
 
     @VisibleForTesting
     public FramebustBlockInfoBar(String blockedUrl) {
-        super(R.drawable.infobar_redirect_blocked, null, null);
+        super(R.drawable.infobar_chrome, null, null);
         mBlockedUrl = blockedUrl;
     }
 
@@ -61,7 +61,7 @@
         ellipsizerView.setOnClickListener(view -> onLinkClicked());
 
         control.addView(ellipsizerView);
-        layout.setButtons(getContext().getResources().getString(R.string.ok), null);
+        layout.setButtons(getContext().getResources().getString(R.string.got_it), null);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java
index 669a24e..28dbf93d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java
@@ -41,6 +41,7 @@
 import org.chromium.components.signin.AccountsChangeObserver;
 
 import java.util.Collections;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Shows a card prompting the user to sign in. This item is also an {@link OptionalLeaf}, and sign
@@ -48,6 +49,12 @@
  */
 public class SignInPromo extends OptionalLeaf {
     /**
+     * Period for which promos are suppressed if signin is refused in FRE.
+     */
+    @VisibleForTesting
+    static final long SUPPRESSION_PERIOD_MS = TimeUnit.DAYS.toMillis(1);
+
+    /**
      * Whether the promo had been previously dismissed, before creating an instance of the
      * {@link SignInPromo}.
      */
@@ -69,6 +76,11 @@
      */
     private boolean mCanShowPersonalizedSuggestions;
 
+    /**
+     * Whether signin promo was temporary suppressed.
+     */
+    private boolean mSuppressed;
+
     private final OneShotImpressionListener mOneShotImpressionTracker =
             new OneShotImpressionListener(this::onImpression);
 
@@ -96,16 +108,8 @@
             mWasDismissed = preferenceManager.getNewTabPageGenericSigninPromoDismissed();
         }
 
-        SuggestionsSource suggestionsSource = uiDelegate.getSuggestionsSource();
-        SigninManager signinManager = SigninManager.get(context);
-
-        mCanSignIn = signinManager.isSignInAllowed() && !signinManager.isSignedInOnNative();
-        mCanShowPersonalizedSuggestions = suggestionsSource.areRemoteSuggestionsEnabled();
-        mDismissed = mWasDismissed;
-
-        updateVisibility();
-
         if (mWasDismissed) {
+            setVisibilityInternal(false);
             mSigninObserver = null;
             mProfileDataCache = null;
             mSigninPromoController = null;
@@ -113,6 +117,15 @@
             return;
         }
 
+        SuggestionsSource suggestionsSource = uiDelegate.getSuggestionsSource();
+        SigninManager signinManager = SigninManager.get(context);
+
+        mCanSignIn = signinManager.isSignInAllowed() && !signinManager.isSignedInOnNative();
+        mCanShowPersonalizedSuggestions = suggestionsSource.areRemoteSuggestionsEnabled();
+        mSuppressed = getSuppressionStatus();
+
+        updateVisibility();
+
         if (mArePersonalizedPromosEnabled) {
             int imageSize = context.getResources().getDimensionPixelSize(R.dimen.user_picture_size);
             mProfileDataCache = new ProfileDataCache(context, imageSize);
@@ -129,6 +142,28 @@
         uiDelegate.addDestructionObserver(mSigninObserver);
     }
 
+    /**
+     * Suppress signin promos in New Tab Page for {@link SUPPRESSION_PERIOD_MS}. This will not
+     * affect promos that were created before this call.
+     */
+    public static void temporarilySuppressPromos() {
+        ChromePreferenceManager.getInstance().setNewTabPageSigninPromoSuppressionPeriodStart(
+                System.currentTimeMillis());
+    }
+
+    private boolean getSuppressionStatus() {
+        long suppressedFrom = ChromePreferenceManager.getInstance()
+                                      .getNewTabPageSigninPromoSuppressionPeriodStart();
+        if (suppressedFrom == 0) return false;
+        long currentTime = System.currentTimeMillis();
+        long suppressedTo = suppressedFrom + SUPPRESSION_PERIOD_MS;
+        if (suppressedFrom <= currentTime && currentTime < suppressedTo) {
+            return true;
+        }
+        ChromePreferenceManager.getInstance().clearNewTabPageSigninPromoSuppressionPeriodStart();
+        return false;
+    }
+
     @Override
     @ItemViewType
     protected int getItemViewType() {
@@ -180,7 +215,8 @@
     }
 
     private void updateVisibility() {
-        setVisibilityInternal(!mDismissed && mCanSignIn && mCanShowPersonalizedSuggestions);
+        setVisibilityInternal(
+                !mDismissed && mCanSignIn && mCanShowPersonalizedSuggestions && !mSuppressed);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePagesDownloadManagerBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePagesDownloadManagerBridge.java
new file mode 100644
index 0000000..f8929fb
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePagesDownloadManagerBridge.java
@@ -0,0 +1,99 @@
+// 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.offlinepages;
+
+import android.annotation.TargetApi;
+import android.app.DownloadManager;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Build;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+/**
+ * Since the {@link AndroidDownloadManager} can only be accessed from Java, this bridge will
+ * transfer all C++ calls over to Java land for making the call to ADM.  This is a one-way bridge,
+ * from C++ to Java only.  The Java side of this bridge is not called by other Java code.
+ */
+@JNINamespace("offline_pages::android")
+public class OfflinePagesDownloadManagerBridge {
+    /** Offline pages should not be scanned as for media content. */
+    public static final boolean IS_MEDIA_SCANNER_SCANNABLE = false;
+
+    /** We don't want another download notification, since we already made one. */
+    public static final boolean SHOW_NOTIFICATION = false;
+
+    /** Mime type to use for Offline Pages. */
+    public static final String MIME_TYPE = "multipart/related";
+
+    /** Returns true if DownloadManager is installed on the phone. */
+    @CalledByNative
+    private static boolean isAndroidDownloadManagerInstalled() {
+        DownloadManager downloadManager = getDownloadManager();
+        return (downloadManager != null);
+    }
+
+    /**
+     * This is a pass through to the {@link AndroidDownloadManager} function of the same name.
+     * @param title The display name for this download.
+     * @param description Long description for this download.
+     * @param path File system path for this download.
+     * @param length Length in bytes of this downloaded item.
+     * @param uri The origin of this download.  Used in API 24+ only.
+     * @param referer Where this download was refered from.  Used in API 24+ only.
+     * @return the download ID of this item as assigned by the download manager.
+     */
+    @CalledByNative
+    private static long addCompletedDownload(String title, String description, String path,
+            long length, String uri, String referer) {
+        // Call the proper version of the pass through based on the supported API level.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+            return callAddCompletedDownload(title, description, path, length);
+        }
+
+        return callAddCompletedDownload(title, description, path, length, uri, referer);
+    }
+
+    // Use this pass through before API level 24.
+    private static long callAddCompletedDownload(
+            String title, String description, String path, long length) {
+        DownloadManager downloadManager = getDownloadManager();
+        if (downloadManager == null) return 0;
+
+        return downloadManager.addCompletedDownload(title, description, IS_MEDIA_SCANNER_SCANNABLE,
+                MIME_TYPE, path, length, SHOW_NOTIFICATION);
+    }
+
+    // Use this pass through for API levels 24 and higher.
+    @TargetApi(Build.VERSION_CODES.N)
+    private static long callAddCompletedDownload(String title, String description, String path,
+            long length, String uri, String referer) {
+        DownloadManager downloadManager = getDownloadManager();
+        if (downloadManager == null) return 0;
+
+        return downloadManager.addCompletedDownload(title, description, IS_MEDIA_SCANNER_SCANNABLE,
+                MIME_TYPE, path, length, SHOW_NOTIFICATION, Uri.parse(uri), Uri.parse(referer));
+    }
+
+    /**
+     * This is a pass through to the {@link AndroidDownloadManager} function of the same name.
+     * @param ids An array of download IDs to be removed from the download manager.
+     * @return the number of IDs that were removed.
+     */
+    @CalledByNative
+    private static int remove(long[] ids) {
+        DownloadManager downloadManager = getDownloadManager();
+        if (downloadManager == null) return 0;
+
+        return downloadManager.remove(ids);
+    }
+
+    private static DownloadManager getDownloadManager() {
+        return (DownloadManager) ContextUtils.getApplicationContext().getSystemService(
+                Context.DOWNLOAD_SERVICE);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
index e2e2ecbd..095c66c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
@@ -61,10 +61,11 @@
     private static boolean shouldSkipReading() {
         SharedPreferences pref = ContextUtils.getAppSharedPreferences();
         long last = pref.getLong(PartnerBookmarksReader.LAST_EMPTY_READ_PREFS_NAME, 0);
-        long elapsed = System.currentTimeMillis() - last;
+        int elapsed = (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - last);
+
         if (last > 0) {
-            RecordHistogram.recordCustomTimesHistogram("PartnerBookmark.TimeSinceLastEmptyRead",
-                    elapsed, 1, TimeUnit.DAYS.toMillis(365), TimeUnit.MILLISECONDS, 50);
+            RecordHistogram.recordCustomCountHistogram("PartnerBookmark.TimeSinceLastEmptyRead2",
+                    elapsed, 1, (int) TimeUnit.DAYS.toSeconds(365), 50);
         }
         // Without checking elapsed >= 0, we might get stuck at an "always skip mode" if
         // |LAST_EMPTY_READ_PREFS_NAME| is a bogus future time.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
index 67df141..69d22a9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -59,6 +59,8 @@
     private static final String NTP_GENERIC_SIGNIN_PROMO_DISMISSED = "ntp.signin_promo_dismissed";
     private static final String NTP_PERSONALIZED_SIGNIN_PROMO_DISMISSED =
             "ntp.personalized_signin_promo_dismissed";
+    private static final String NTP_SIGNIN_PROMO_SUPPRESSION_PERIOD_START =
+            "ntp.signin_promo_suppression_period_start";
     private static final String NTP_ANIMATION_RUN_COUNT = "ntp_recycler_view_animation_run_count";
 
     private static final String SUCCESS_UPLOAD_SUFFIX = "_crash_success_upload";
@@ -368,6 +370,32 @@
         writeBoolean(NTP_PERSONALIZED_SIGNIN_PROMO_DISMISSED, isPromoDismissed);
     }
 
+    /**
+     * Returns timestamp of the suppression period start if signin promos in the New Tab Page are
+     * temporarily suppressed; zero otherwise.
+     * @return the epoch time in milliseconds (see {@link System#currentTimeMillis()}).
+     */
+    public long getNewTabPageSigninPromoSuppressionPeriodStart() {
+        return readLong(NTP_SIGNIN_PROMO_SUPPRESSION_PERIOD_START, 0);
+    }
+
+    /**
+     * Sets timestamp of the suppression period start if signin promos in the New Tab Page are
+     * temporarily suppressed.
+     * @param timeMillis the epoch time in milliseconds (see {@link System#currentTimeMillis()}).
+     */
+    public void setNewTabPageSigninPromoSuppressionPeriodStart(long timeMillis) {
+        writeLong(NTP_SIGNIN_PROMO_SUPPRESSION_PERIOD_START, timeMillis);
+    }
+
+    /**
+     * Removes the stored timestamp of the suppression period start when signin promos in the New
+     * Tab Page are no longer suppressed.
+     */
+    public void clearNewTabPageSigninPromoSuppressionPeriodStart() {
+        removeKey(NTP_SIGNIN_PROMO_SUPPRESSION_PERIOD_START);
+    }
+
     /** Gets the number of times the New Tab Page first card animation has been run. */
     public int getNewTabPageFirstCardAnimationRunCount() {
         return readInt(NTP_ANIMATION_RUN_COUNT);
@@ -431,7 +459,7 @@
      * Remove the Chrome Home user preference.
      */
     public void clearChromeHomeUserPreference() {
-        mSharedPreferences.edit().remove(CHROME_HOME_USER_ENABLED_KEY).apply();
+        removeKey(CHROME_HOME_USER_ENABLED_KEY);
     }
 
     /**
@@ -517,6 +545,29 @@
     }
 
     /**
+     * Writes the given long to the named shared preference.
+     *
+     * @param key The name of the preference to modify.
+     * @param value The new value for the preference.
+     */
+    private void writeLong(String key, long value) {
+        SharedPreferences.Editor ed = mSharedPreferences.edit();
+        ed.putLong(key, value);
+        ed.apply();
+    }
+
+    /**
+     * Reads the given long value from the named shared preference.
+     *
+     * @param key The name of the preference to return.
+     * @param defaultValue The default value to return if there's no value stored.
+     * @return The value of the preference if stored; defaultValue otherwise.
+     */
+    private long readLong(String key, long defaultValue) {
+        return mSharedPreferences.getLong(key, defaultValue);
+    }
+
+    /**
      * Writes the given String to the named shared preference.
      *
      * @param key The name of the preference to modify.
@@ -541,6 +592,17 @@
     }
 
     /**
+     * Removes the shared preference entry.
+     *
+     * @param key The key of the preference to remove.
+     */
+    private void removeKey(String key) {
+        SharedPreferences.Editor ed = mSharedPreferences.edit();
+        ed.remove(key);
+        ed.apply();
+    }
+
+    /**
      * Logs the most recent date that Chrome Home was enabled.
      * Removes the entry if Chrome Home is disabled.
      *
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 0abf3bec..1b132ba9 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
@@ -1307,6 +1307,10 @@
         mToolbar.startLoadProgress();
     }
 
+    public void setProgressBarEnabled(boolean enabled) {
+        mToolbar.getProgressBar().setVisibility(enabled ? View.VISIBLE : View.GONE);
+    }
+
     private boolean shouldShowCusrsorInLocationBar() {
         Tab tab = mToolbarModel.getTab();
         if (tab == null) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
index 00d161c..1cc44bb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
@@ -112,6 +112,8 @@
         mDelegate = delegate;
         mTabModelSelector = tabModelSelector;
 
+        mActivity.getToolbarManager().setProgressBarEnabled(false);
+
         mActivity.getFullscreenManager().addListener(this);
 
         // This overrides the default intent created by GVR to return to Chrome when the DON flow
@@ -602,6 +604,7 @@
             mTab.getWebContents().setSize(parent.getWidth(), parent.getHeight());
         }
         mTab.updateBrowserControlsState(BrowserControlsState.SHOWN, true);
+        mActivity.getToolbarManager().setProgressBarEnabled(true);
 
         mContentVirtualDisplay.destroy();
         super.shutdown();
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index c3842a9..13483e0d3 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -134,6 +134,9 @@
       <message name="IDS_OK_GOT_IT" desc="Label of a button by which the user confirms that they read and understood the information or instructions. Used in multiple contexts. [CHAR-LIMIT=20]">
         OK, got it
       </message>
+      <message name="IDS_GOT_IT" desc="Label of a button by which the user confirms that they read and understood the information or instructions. Used in multiple contexts. [CHAR-LIMIT=20]">
+        Got it
+      </message>
       <message name="IDS_CANCEL" desc="Label for a cancel button. Used in multiple contexts. [CHAR-LIMIT=20]">
         Cancel
       </message>
@@ -3294,7 +3297,7 @@
 
       <!-- Interventions -->
       <message name="IDS_REDIRECT_BLOCKED_MESSAGE" desc="The message stating that a redirect (noun) was blocked on this page. This will be followed on a separate line with the address the user was being redirected to.">
-         Chrome stopped this site from taking you to
+         Redirect blocked to site:
       </message>
       <message name="IDS_REDIRECT_BLOCKED_SHORT_MESSAGE" desc="The short message stating that a redirect (noun) was blocked on this page.">
          Redirect blocked.
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 8a2d6dc..b2373b7 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -747,6 +747,7 @@
   "java/src/org/chromium/chrome/browser/offlinepages/OfflinePageOrigin.java",
   "java/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserver.java",
   "java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java",
+  "java/src/org/chromium/chrome/browser/offlinepages/OfflinePagesDownloadManagerBridge.java",
   "java/src/org/chromium/chrome/browser/offlinepages/SavePageRequest.java",
   "java/src/org/chromium/chrome/browser/offlinepages/TaskExtrasPacker.java",
   "java/src/org/chromium/chrome/browser/offlinepages/TriggerConditions.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/AudioTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/AudioTest.java
index 6139041..9bdd6e3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/AudioTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/AudioTest.java
@@ -28,8 +28,7 @@
  * Simple HTML5 audio tests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AudioTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java
index 7068a86..5960eb9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/BindingManagerIntegrationTest.java
@@ -49,8 +49,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class BindingManagerIntegrationTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/BluetoothChooserDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/BluetoothChooserDialogTest.java
index 2603cc10..caa4e5d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/BluetoothChooserDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/BluetoothChooserDialogTest.java
@@ -43,8 +43,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class BluetoothChooserDialogTest {
     /**
      * Works like the BluetoothChooserDialog class, but records calls to native methods instead of
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeActivityTest.java
index 26d3130..426cd5c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeActivityTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.ChromeTabCreator;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -32,8 +31,7 @@
  * Instrumentation tests for ChromeActivity.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ChromeActivityTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java
index 9c5d1c6..5686bd3f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ContentViewFocusTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandler;
 import org.chromium.chrome.browser.compositor.layouts.eventfilter.ScrollDirection;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -45,10 +44,7 @@
  * Tab swiping, etc.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ContentViewFocusTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
index 443e295b..a3affc2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
@@ -27,7 +27,6 @@
 import org.chromium.blink.mojom.document_metadata.Values;
 import org.chromium.blink.mojom.document_metadata.WebPage;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -41,8 +40,8 @@
  * Tests Copyless Paste AppIndexing using instrumented tests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-features=CopylessPaste"})
+@CommandLineFlags.
+Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=CopylessPaste"})
 @Restriction(Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE)
 public class CopylessPasteTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java
index bb4a325..2fabd94 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java
@@ -32,8 +32,9 @@
  * Tests for zooming into & out of a selected & deselected editable text field.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({
+        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+})
 public class FocusedEditableTextFieldZoomTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java
index 675885f..190da31 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java
@@ -17,7 +17,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.blink_public.web.WebReferrerPolicy;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.net.test.EmbeddedTestServer;
@@ -27,10 +26,7 @@
  * Test the behavior of tabs when opening an HTTPS URL from an external app.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 
 public class HTTPSTabsOpenedFromExternalAppTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/InstalledAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/InstalledAppTest.java
index 917a4a3..ace69c2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/InstalledAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/InstalledAppTest.java
@@ -27,7 +27,6 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({
         ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         "enable-blink-features=InstalledApp",
 })
 public class InstalledAppTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ItemChooserDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ItemChooserDialogTest.java
index be3bb9d3..ceca038 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ItemChooserDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ItemChooserDialogTest.java
@@ -37,8 +37,7 @@
  * Tests for the ItemChooserDialog class.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class ItemChooserDialogTest implements ItemChooserDialog.ItemSelectedCallback {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java
index 5059760..e0734b5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java
@@ -18,7 +18,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -30,10 +29,7 @@
  * Tests for evaluation of JavaScript.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class JavaScriptEvalChromeTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java
index d0ce5eb..f010c57 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java
@@ -16,7 +16,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -26,10 +25,7 @@
  * Tests starting the activity with URLs.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class MainActivityWithURLTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java
index 5e81438..52a026b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ModalDialogTest.java
@@ -45,8 +45,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ModalDialogTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java
index 7414a53..8aa1dbe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java
@@ -34,7 +34,6 @@
 import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -60,10 +59,7 @@
  * Navigate in UrlBar tests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class NavigateTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigationPopupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigationPopupTest.java
index 038ee0d8..51bd992 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigationPopupTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigationPopupTest.java
@@ -36,8 +36,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class NavigationPopupTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/OSKOverscrollTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/OSKOverscrollTest.java
index 3019a98..9886d8b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/OSKOverscrollTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/OSKOverscrollTest.java
@@ -38,8 +38,7 @@
  */
 
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class OSKOverscrollTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/PopularUrlsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/PopularUrlsTest.java
index 7d12ceba..3383b311 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/PopularUrlsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/PopularUrlsTest.java
@@ -49,8 +49,7 @@
  * can continue opening the next URL when they are restarted.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PopularUrlsTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/PopupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/PopupTest.java
index c6e125c..be08b58 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/PopupTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/PopupTest.java
@@ -38,8 +38,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PopupTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/PowerBroadcastReceiverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/PowerBroadcastReceiverTest.java
index 09024a34..4ea8039 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/PowerBroadcastReceiverTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/PowerBroadcastReceiverTest.java
@@ -21,7 +21,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ApplicationTestUtils;
@@ -30,10 +29,7 @@
  * Tests for the PowerBroadcastReceiver.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class PowerBroadcastReceiverTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/PrerenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/PrerenderTest.java
index 9fbcb603..7d700f1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/PrerenderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/PrerenderTest.java
@@ -25,7 +25,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.prerender.ExternalPrerenderHandler;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.PrerenderTestHelper;
@@ -41,10 +40,7 @@
  * Tests are disabled on low-end devices. These only support one renderer for performance reasons.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PrerenderTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ProcessIsolationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ProcessIsolationTest.java
index 513f2cd..b29bf7e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ProcessIsolationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ProcessIsolationTest.java
@@ -31,8 +31,7 @@
  * Test to make sure browser and renderer are seperated process.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ProcessIsolationTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/RepostFormWarningTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/RepostFormWarningTest.java
index 24aa5425..d70a6d3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/RepostFormWarningTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/RepostFormWarningTest.java
@@ -36,8 +36,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class RepostFormWarningTest {
     // Active tab.
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/RestoreHistogramTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/RestoreHistogramTest.java
index 1e2fb2fc..2b5af698 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/RestoreHistogramTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/RestoreHistogramTest.java
@@ -20,7 +20,6 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.MetricsUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 
@@ -28,10 +27,7 @@
  * This test tests the logic for writing the restore histogram at two different levels
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class RestoreHistogramTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/SelectFileDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/SelectFileDialogTest.java
index c109651..b716364 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/SelectFileDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/SelectFileDialogTest.java
@@ -36,8 +36,7 @@
  * Integration test for select file dialog used for <input type="file" />
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SelectFileDialogTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java
index 34949935..8a49a67 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ShareIntentTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.share.ShareMenuActionHandler;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.ChromeFileProvider;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 
@@ -36,10 +35,7 @@
  * Instrumentation tests for Share intents.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ShareIntentTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/SmartClipProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/SmartClipProviderTest.java
index 4826260ee..25fc7bb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/SmartClipProviderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/SmartClipProviderTest.java
@@ -39,8 +39,7 @@
  * Tests for the SmartClipProvider.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SmartClipProviderTest implements Handler.Callback {
     // This is a key for meta-data in the package manifest. It should NOT
     // change, as OEMs will use it when they look for the SmartClipProvider
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabCountLabelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabCountLabelTest.java
index ec2a13c..69e28b6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabCountLabelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabCountLabelTest.java
@@ -20,7 +20,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.toolbar.TabSwitcherDrawable;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -31,10 +30,7 @@
  */
 
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TabCountLabelTest {
     /**
      * Check the tabCount string against an expected value.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabObserverTest.java
index 296f46190..c2034b1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabObserverTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabObserverTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -34,8 +33,7 @@
  * Tests for TabObserver.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TabObserverTest {
     /** A {@Link TabObserver} that has callback helpers for each event. */
     private static class TestTabObserver extends EmptyTabObserver {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabTest.java
index 8ac9923d..3882b34 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabTest.java
@@ -35,8 +35,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TabTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabThemeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabThemeTest.java
index 35abcff..0da6cfe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabThemeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabThemeTest.java
@@ -33,8 +33,7 @@
  * Tests related to the Tab's theme color.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TabThemeTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
index 7d4be44..e42a8b8d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
@@ -36,7 +36,6 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ApplicationTestUtils;
@@ -56,10 +55,7 @@
  * Test the behavior of tabs when opening a URL from an external app.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class TabsOpenedFromExternalAppTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
index 7388afcb..6bf109bd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -61,7 +61,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.browser.tabmodel.TabbedModeTabPersistencePolicy;
 import org.chromium.chrome.browser.toolbar.ToolbarPhone;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ApplicationTestUtils;
@@ -93,10 +92,7 @@
  * General Tab tests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TabsTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/UrlSchemeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/UrlSchemeTest.java
index fc7b7ec15..118b306 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/UrlSchemeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/UrlSchemeTest.java
@@ -37,8 +37,7 @@
 /** Test suite for different Android URL schemes. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class UrlSchemeTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/UsbChooserDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/UsbChooserDialogTest.java
index d7645c8..6ce2816 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/UsbChooserDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/UsbChooserDialogTest.java
@@ -33,8 +33,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class UsbChooserDialogTest {
     /**
      * Works like the UsbChooserDialog class, but records calls to native methods instead of
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/VideoFullscreenOrientationLockChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/VideoFullscreenOrientationLockChromeTest.java
index 6ddd1e9..fabed21f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/VideoFullscreenOrientationLockChromeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/VideoFullscreenOrientationLockChromeTest.java
@@ -22,7 +22,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.browser.media.MediaViewerUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content.browser.test.util.Criteria;
@@ -41,7 +40,6 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         MediaSwitches.AUTOPLAY_NO_GESTURE_REQUIRED_POLICY,
         "enable-features=VideoFullscreenOrientationLock",
         "disable-features=" + ChromeFeatureList.FULLSCREEN_ACTIVITY})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/WebShareTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/WebShareTest.java
index 5f9d399a..e1443a3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/WebShareTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/WebShareTest.java
@@ -31,8 +31,7 @@
 
 /** Test suite for Web Share (navigator.share) functionality. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class WebShareTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
index 92ff36f..e23edbc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
@@ -39,8 +39,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AppMenuTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java
index 5ed3844..fc24be3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/DataSaverAppMenuTest.java
@@ -30,8 +30,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class DataSaverAppMenuTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryTest.java
index 08afdb01..3b309c8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryTest.java
@@ -42,9 +42,8 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({"enable-features=AutofillKeyboardAccessory",
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.
+Add({"enable-features=AutofillKeyboardAccessory", ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AutofillKeyboardAccessoryTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java
index a41275d..47e8ca3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java
@@ -45,8 +45,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AutofillPopupTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java
index 32ac0b8..80db7ae 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupWithKeyboardTest.java
@@ -39,8 +39,7 @@
  * Integration tests for interaction of the AutofillPopup and a keyboard.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AutofillPopupWithKeyboardTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
index 7d8a2845..7385785 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTest.java
@@ -43,8 +43,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AutofillTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
index b9ef5bb..7a4e653 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -44,7 +44,6 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.webapps.WebappDataStorage;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.InfoBarUtil;
@@ -65,8 +64,7 @@
  * Tests the app banners.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AppBannerManagerTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
index 54d4802..c21a49a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
@@ -59,10 +59,7 @@
  * Tests for the bookmark manager.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class BookmarkTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
index c3ffbd4..de05c16f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
@@ -41,8 +41,7 @@
  * successful in its own unit tests. This test can do so.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class BrowsingDataRemoverIntegrationTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java
index 20ee2b0..76b74d2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/CompositorVisibilityTest.java
@@ -20,7 +20,6 @@
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.ui.resources.ResourceManager;
@@ -29,8 +28,7 @@
  * Integration tests for {@link org.chromium.chrome.browser.compositor.CompositorView}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP)
 public class CompositorVisibilityTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
index 46ec43e..e257b89 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
@@ -27,7 +27,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -47,10 +46,7 @@
  * Test suite for the TabStrip and making sure it properly represents the TabModel backend.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TabStripTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
index c1cbadb2..76cbc606d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -37,7 +37,6 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils;
 import org.chromium.content.browser.test.util.Criteria;
@@ -59,7 +58,6 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         ChromeSwitches.GOOGLE_BASE_URL + "=http://example.com/",
         ChromeSwitches.HERB_FLAVOR_DISABLED_SWITCH})
 public class ContextMenuTest implements CustomMainActivityStart {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUiTest.java
index e906776..548b6e7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUiTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/TabularContextMenuUiTest.java
@@ -40,8 +40,7 @@
  * groups.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TabularContextMenuUiTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
index e6d7443..5a29dc58 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -20,6 +20,7 @@
 import android.os.Build;
 import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
 import android.support.test.filters.SmallTest;
 import android.text.TextUtils;
 import android.view.KeyEvent;
@@ -113,7 +114,6 @@
 // NOTE: Disable online detection so we we'll default to online on test bots with no network.
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED,
         "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION,
         "disable-features=" + ChromeFeatureList.FULLSCREEN_ACTIVITY})
@@ -2854,6 +2854,36 @@
     }
 
     /**
+     * Tests the Translate Caption on a tap gesture.
+     * This test is disabled because it relies on the network and a live search result,
+     * which would be flaky for bots.
+     */
+    @DisabledTest(message = "Useful for manual testing when a network is connected.")
+    @Test
+    @LargeTest
+    @Feature({"ContextualSearch"})
+    public void testTranslateCaption() throws InterruptedException, TimeoutException {
+        // Tapping a German word should trigger translation.
+        simulateTapSearch("german");
+
+        // Make sure we tried to trigger translate.
+        Assert.assertTrue("Translation was not forced with the current request URL: "
+                        + mManager.getRequest().getSearchUrl(),
+                mManager.getRequest().isTranslationForced());
+
+        // Wait for the translate caption to be shown in the Bar.
+        int waitFactor = 5; // We need to wait an extra long time for the panel content to render.
+        CriteriaHelper.pollUiThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                ContextualSearchBarControl barControl = mPanel.getSearchBarControl();
+                return barControl != null && barControl.getCaptionVisible()
+                        && !TextUtils.isEmpty(barControl.getCaptionText());
+            }
+        }, 3000 * waitFactor, DEFAULT_POLLING_INTERVAL * waitFactor);
+    }
+
+    /**
      * Tests that Contextual Search works in fullscreen. Specifically, tests that tapping a word
      * peeks the panel, expanding the bar results in the bar ending at the correct spot in the page
      * and tapping the base page closes the panel.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicyTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicyTest.java
index c85dd5b2..b96d936 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicyTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicyTest.java
@@ -17,7 +17,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 
@@ -27,10 +26,7 @@
  * Tests for the ContextualSearchPolicy class.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ContextualSearchPolicyTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequestTest.java
index d2cd635..130a293c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequestTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequestTest.java
@@ -17,7 +17,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 
@@ -25,10 +24,7 @@
  * Class responsible for testing the ContextualSearchRequest.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ContextualSearchRequestTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java
index d263930..78cfe52 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java
@@ -39,10 +39,7 @@
  * Mock touch events with Contextual Search to test behavior of its panel and manager.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ContextualSearchTapEventTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
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 c5e6f82..9e63317f 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
@@ -96,7 +96,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.CustomTabToolbar;
 import org.chromium.chrome.browser.util.ColorUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil;
@@ -125,10 +124,7 @@
  * Instrumentation tests for app menu, context menu, and toolbar of a {@link CustomTabActivity}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class CustomTabActivityTest {
     @Rule
     public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
index 5967f03..1645ae3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.externalnav.ExternalNavigationParams;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.net.test.EmbeddedTestServer;
 
@@ -33,10 +32,7 @@
  * Instrumentation test for external navigation handling of a Custom Tab.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class CustomTabExternalNavigationTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java
index e17c84e..9f98608 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java
@@ -35,7 +35,6 @@
 import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
@@ -49,7 +48,6 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         ChromeSwitches.HERB_FLAVOR_ELDERBERRY_SWITCH})
 public class CustomTabFromChromeExternalNavigationTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java
index 08cf163b..4f663ab 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.TabState;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
@@ -29,10 +28,7 @@
  * Integration testing for the CustomTab Tab persistence logic.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class CustomTabTabPersistenceIntegrationTest {
     @Rule
     public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/document/LauncherActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/document/LauncherActivityTest.java
index 2107661..f02ef72 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/document/LauncherActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/document/LauncherActivityTest.java
@@ -44,10 +44,7 @@
  * Tests for launching Chrome.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class LauncherActivityTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistillabilityServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistillabilityServiceTest.java
index 5d0c4479..23cd640b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistillabilityServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/DistillabilityServiceTest.java
@@ -37,9 +37,10 @@
  * Tests for making sure the distillability service is communicating correctly.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({"enable-dom-distiller", "reader-mode-heuristics=alwaystrue",
+@CommandLineFlags.Add({
+        "enable-dom-distiller", "reader-mode-heuristics=alwaystrue",
         ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+})
 public class DistillabilityServiceTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ChromeDownloadDelegateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ChromeDownloadDelegateTest.java
index 15228a8f..ebb36d8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ChromeDownloadDelegateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ChromeDownloadDelegateTest.java
@@ -30,8 +30,7 @@
  * Tests for ChromeDownloadDelegate class.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ChromeDownloadDelegateTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ChromeHomeDownloadManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ChromeHomeDownloadManagerTest.java
index 88605a1d..a5f9f8b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ChromeHomeDownloadManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ChromeHomeDownloadManagerTest.java
@@ -27,7 +27,6 @@
 import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.test.BottomSheetTestRule;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
@@ -39,8 +38,9 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
-@CommandLineFlags.Add({"enable-features=ChromeHome", ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({
+        "enable-features=ChromeHome", ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+})
 public class ChromeHomeDownloadManagerTest {
     private static final String TEST_PAGE = "/chrome/test/data/android/google.html";
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
index 6c1a4fe..1c9bbb3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
@@ -34,7 +34,6 @@
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.InfoBarUtil;
 import org.chromium.content.browser.test.util.Criteria;
@@ -52,10 +51,7 @@
  * Tests Chrome download feature by attempting to download some files.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class DownloadTest implements CustomMainActivityStart {
     @Rule
     public DownloadTestRule mDownloadTestRule = new DownloadTestRule(this);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java
index e0d9a5b..6e900f0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java
@@ -24,8 +24,7 @@
  * Test for the Site Engagement Service Java binding.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SiteEngagementServiceTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
index eb51fff9..00a97bb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
@@ -30,8 +30,7 @@
  * Instrumentation tests for {@link ExternalNavigationHandler}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ExternalNavigationDelegateImplTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
index badab54a..a784d3f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
@@ -52,8 +52,7 @@
  * Test suite for verifying the behavior of various URL overriding actions.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class UrlOverridingTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
index f4d238a..98346e0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
@@ -39,7 +39,6 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.tab.TabWebContentsDelegateAndroid;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.FullscreenTestUtils;
@@ -65,7 +64,6 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({
         ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         "disable-features=" + ChromeFeatureList.FULLSCREEN_ACTIVITY,
 })
 @RetryOnFailure
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/ChromeTabbedActivityHWATest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/ChromeTabbedActivityHWATest.java
index 0fd2865..c2d326bc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/ChromeTabbedActivityHWATest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/ChromeTabbedActivityHWATest.java
@@ -14,7 +14,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 
@@ -22,10 +21,7 @@
  * Tests that ChromeTabbedActivity is hardware accelerated only high-end devices.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ChromeTabbedActivityHWATest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/CustomTabActivityHWATest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/CustomTabActivityHWATest.java
index 9d973773..0d2efcf0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/CustomTabActivityHWATest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/CustomTabActivityHWATest.java
@@ -16,17 +16,13 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 /**
  * Tests that CustomTabActivity is hardware accelerated only high-end devices.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class CustomTabActivityHWATest {
     @Rule
     public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/ToastHWATest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/ToastHWATest.java
index 2f6ab52..639414f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/ToastHWATest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/ToastHWATest.java
@@ -33,7 +33,6 @@
 import org.chromium.chrome.browser.download.DownloadTestRule.CustomMainActivityStart;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils;
 import org.chromium.net.test.EmbeddedTestServer;
@@ -45,10 +44,7 @@
  * Tests that toasts don't trigger HW acceleration.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP)
 public class ToastHWATest implements CustomMainActivityStart {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/WebappActivityHWATest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/WebappActivityHWATest.java
index b90a15a7..64b0573 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/WebappActivityHWATest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/hardware_acceleration/WebappActivityHWATest.java
@@ -15,15 +15,13 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.webapps.WebappActivity;
 import org.chromium.chrome.browser.webapps.WebappActivityTestRule;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 /**
  * Tests that WebappActivity is hardware accelerated only high-end devices.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class WebappActivityHWATest {
     @Rule
     public final WebappActivityTestRule mActivityTestRule = new WebappActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
index df1dba8..fb4c28a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -55,7 +55,6 @@
 import org.chromium.chrome.browser.widget.selection.SelectableItemView;
 import org.chromium.chrome.browser.widget.selection.SelectableItemViewHolder;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
@@ -72,10 +71,7 @@
  * Tests the {@link HistoryActivity}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
 public class HistoryActivityTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java
index 3cc6002..895e777d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java
@@ -28,7 +28,6 @@
 import org.chromium.chrome.browser.tabmodel.TabPersistentStore;
 import org.chromium.chrome.browser.tabmodel.TestTabModelDirectory;
 import org.chromium.chrome.browser.tabmodel.TestTabModelDirectory.TabStateInfo;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content.browser.test.util.Criteria;
@@ -42,10 +41,7 @@
  * Tests for the Incognito Notification service.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class IncognitoNotificationServiceTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarAppearanceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarAppearanceTest.java
index a480220..f2ea1f6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarAppearanceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarAppearanceTest.java
@@ -29,8 +29,7 @@
  */
 // clang-format off
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @ScreenShooter.Directory("InfoBars")
 public class InfoBarAppearanceTest {
     // clang-format on
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java
index 9aa78c6..efb34c8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java
@@ -46,8 +46,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class InfoBarContainerTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
index 911fb9ad..d75db9de 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
@@ -49,8 +49,7 @@
 
 /** Tests for the InfoBars. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class InfoBarTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfobarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfobarTest.java
index 155a619..49ca686 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfobarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfobarTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.preferences.website.ContentSetting;
 import org.chromium.chrome.browser.preferences.website.GeolocationInfo;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -46,10 +45,7 @@
  * Tests for the permission update infobar.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PermissionUpdateInfobarTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBarTest.java
index c333dad9..8e55fcb3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBarTest.java
@@ -33,8 +33,7 @@
 
 /** Tests for the SearchGeolocationDisclosureInfobar. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SearchGeolocationDisclosureInfoBarTest {
     private static final String SEARCH_PAGE = "/chrome/test/data/android/google.html";
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/input/SelectPopupOtherContentViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/input/SelectPopupOtherContentViewTest.java
index 56b4db9..ff61bb6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/input/SelectPopupOtherContentViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/input/SelectPopupOtherContentViewTest.java
@@ -36,8 +36,7 @@
  * Test the select popup and how it interacts with another ContentViewCore.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SelectPopupOtherContentViewTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
index 1d63ce5..d4f609f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
@@ -37,8 +37,7 @@
  * Unit tests for {@link InstantAppsHandler}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class InstantAppsHandlerTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterTest.java
index ae90b47..d73a2b97 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/ChromeBrowserSyncAdapterTest.java
@@ -41,8 +41,7 @@
  * Tests for ChromeBrowserSyncAdapter.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ChromeBrowserSyncAdapterTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastNotificationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastNotificationTest.java
index 212441b8..ccfe8c84 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastNotificationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastNotificationTest.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.media.remote.RemoteVideoInfo.PlayerState;
 import org.chromium.chrome.browser.media.ui.MediaNotificationListener;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.TimeoutException;
@@ -32,10 +31,7 @@
  * Tests of the notification.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class CastNotificationTest {
     @Rule
     public CastTestRule mCastTestRule = new CastTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastPositionTransferTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastPositionTransferTest.java
index 43f1b04..86413d4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastPositionTransferTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastPositionTransferTest.java
@@ -24,7 +24,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.test.util.JavaScriptUtils;
 
@@ -37,10 +36,7 @@
  * the remote player.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class CastPositionTransferTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastStartStopTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastStartStopTest.java
index cdb10c2..4fb1490 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastStartStopTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastStartStopTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.media.ui.MediaNotificationListener;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.TimeoutException;
@@ -35,10 +34,7 @@
  * video.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class CastStartStopTest {
     @Rule
     public CastTestRule mCastTestRule = new CastTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastSwitchVideoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastSwitchVideoTest.java
index 576850c4..867456b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastSwitchVideoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastSwitchVideoTest.java
@@ -24,7 +24,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.test.util.DOMUtils;
 import org.chromium.content_public.browser.WebContents;
@@ -35,10 +34,7 @@
  * Test that other videos are played locally when casting
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class CastSwitchVideoTest {
     @Rule
     public CastTestRule mCastTestRule = new CastTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastVideoControlsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastVideoControlsTest.java
index bd8d08d..2095085 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastVideoControlsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/remote/CastVideoControlsTest.java
@@ -22,7 +22,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.TimeoutException;
@@ -31,10 +30,7 @@
  * Instrumentation tests for the fullscreen cast controls.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class CastVideoControlsTest {
     @Rule
     public CastTestRule mCastTestRule = new CastTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java
index 8140f0a..16394b2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java
@@ -49,8 +49,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ContentSwitches.DISABLE_GESTURE_REQUIREMENT_FOR_PRESENTATION,
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class MediaRouterIntegrationTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/AutoplayMutedNotificationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/AutoplayMutedNotificationTest.java
index 30cebeee..71fcef13 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/AutoplayMutedNotificationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/AutoplayMutedNotificationTest.java
@@ -36,8 +36,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AutoplayMutedNotificationTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java
index 0f18cca..4eace725 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PauseOnHeadsetUnplugTest.java
@@ -36,9 +36,8 @@
  * Tests for checking whether the media are paused when unplugging the headset
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.
-Add({MediaSwitches.AUTOPLAY_NO_GESTURE_REQUIRED_POLICY, ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({MediaSwitches.AUTOPLAY_NO_GESTURE_REQUIRED_POLICY,
+        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PauseOnHeadsetUnplugTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetricsIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetricsIntegrationTest.java
index 0f7d11e..7863acc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetricsIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetricsIntegrationTest.java
@@ -32,9 +32,11 @@
 
 import java.util.concurrent.Callable;
 
+/**
+ * Tests the metrics recording for main intent behaviours.
+ */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class MainIntentBehaviorMetricsIntegrationTest {
     @Rule
     public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/PageLoadMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/PageLoadMetricsTest.java
index 2f2316ee..90e4d3e7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/PageLoadMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/PageLoadMetricsTest.java
@@ -32,8 +32,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PageLoadMetricsTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UkmIncognitoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UkmIncognitoTest.java
index 0a2789c5..a7909bf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UkmIncognitoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UkmIncognitoTest.java
@@ -16,7 +16,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content.browser.test.util.JavaScriptUtils;
@@ -26,10 +25,8 @@
  * Tests for UKM monitoring of incognito activity.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-        "force-enable-metrics-reporting"})
+@CommandLineFlags.
+Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "force-enable-metrics-reporting"})
 public class UkmIncognitoTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java
index 97af7a1..d2c7bb12 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowIntegrationTest.java
@@ -31,7 +31,6 @@
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabWindowManager;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.MenuUtils;
@@ -45,10 +44,7 @@
  * Integration testing for Android's N+ MultiWindow.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @MinAndroidSdkLevel(Build.VERSION_CODES.N)
 public class MultiWindowIntegrationTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java
index c243e3bb..b17e2363 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsTest.java
@@ -27,7 +27,6 @@
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.ChromeTabbedActivity2;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content.browser.test.util.Criteria;
@@ -39,10 +38,7 @@
  * Class for testing MultiWindowUtils.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @MinAndroidSdkLevel(Build.VERSION_CODES.N)
 public class MultiWindowUtilsTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java
index d8f07e43..c99a1804 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.preferences.Preferences;
 import org.chromium.chrome.browser.preferences.website.SingleCategoryPreferences;
 import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ActivityUtils;
 import org.chromium.content.browser.test.util.Criteria;
@@ -39,8 +38,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class NotificationPlatformBridgeIntentTest {
     /**
      * Name of the Intent extra holding the notification id. This is set by the framework when a
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
index 38d9f7b6..339782e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
@@ -47,7 +47,6 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.InfoBarUtil;
 import org.chromium.chrome.test.util.browser.TabTitleObserver;
@@ -70,11 +69,7 @@
  * Web Notifications are only supported on Android JellyBean and beyond.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        // Preconnect causes issues with the single-threaded Java test server.
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class NotificationPlatformBridgeTest {
     @Rule
     public NotificationTestRule mNotificationTestRule = new NotificationTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java
index f1abddff..099daa9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java
@@ -27,7 +27,6 @@
 import org.chromium.chrome.browser.suggestions.Tile;
 import org.chromium.chrome.browser.suggestions.TileVisualType;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.NewTabPageTestUtils;
@@ -41,10 +40,7 @@
  * Tests for events around the loading of a New Tab Page.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class NewTabPageLoadTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java
index ed3a5b43..6154c9ef 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.net.test.EmbeddedTestServer;
@@ -30,10 +29,7 @@
  * Tests loading the NTP and navigating between it and other pages.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class NewTabPageNavigationTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java
index 5cec2dd..e062c1f9c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content.browser.test.util.Criteria;
@@ -37,10 +36,7 @@
  * Instrumentation tests for {@link RecentTabsPage}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class RecentTabsPageTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/AllDismissedItemTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/AllDismissedItemTest.java
index 66e4115..3286632 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/AllDismissedItemTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/AllDismissedItemTest.java
@@ -31,10 +31,7 @@
  * Tests for the appearance and behaviour of AllDismissedItem.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AllDismissedItemTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
index b14f9659..3a263ef 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
@@ -89,8 +89,7 @@
  */
 @RunWith(ParameterizedRunner.class)
 @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ArticleSnippetsTest {
     @Rule
     public SuggestionsDependenciesRule mSuggestionsDeps = new SuggestionsDependenciesRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/MHTMLPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/MHTMLPageTest.java
index 121046e..e990412 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/MHTMLPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/MHTMLPageTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.download.DownloadTestRule;
 import org.chromium.chrome.browser.download.DownloadTestRule.CustomMainActivityStart;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.net.test.EmbeddedTestServer;
@@ -35,8 +34,7 @@
 
 /** Unit tests for offline page request handling. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class MHTMLPageTest implements CustomMainActivityStart {
     @Rule
     public DownloadTestRule mDownloadTestRule = new DownloadTestRule(this);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
index 4a4a19a..d8723ff 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
@@ -43,8 +43,7 @@
 
 /** Unit tests for {@link OfflinePageBridge}. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class OfflinePageBridgeTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java
index e5e6780..0b23dbe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java
@@ -33,8 +33,7 @@
 
 /** Unit tests for offline page request handling. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class OfflinePageRequestTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
index 434344d..ed0c917c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageSavePageLaterEvaluationTest.java
@@ -59,8 +59,7 @@
  * storage.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class OfflinePageSavePageLaterEvaluationTest {
     /**
      * Class which is used to calculate time difference.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
index 0e2a98e..565bcfdf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
@@ -38,9 +38,8 @@
 
 /** Instrumentation tests for {@link OfflinePageUtils}. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({"enable-features=OfflinePagesSharing",
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.
+Add({"enable-features=OfflinePagesSharing", ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class OfflinePageUtilsTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java
index 3e300a0..61cf5ffb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.net.NetworkChangeNotifier;
@@ -38,8 +37,7 @@
 
 /** Integration tests for the Last 1 feature of Offline Pages. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class RecentTabsTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
index 6cab24d1..b2b163c8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
@@ -20,7 +20,6 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.components.background_task_scheduler.BackgroundTask.TaskFinishedCallback;
@@ -38,7 +37,6 @@
 /** Unit tests for {@link PrefetchBackgroundTask}. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         "enable-features=OfflinePagesPrefetching"})
 public class PrefetchBackgroundTaskTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java
index 5013a10..12cb49d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.UrlConstants;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher;
@@ -35,8 +34,7 @@
  * Tests for the UpdateMenuItemHelper.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable_update_menu_item"})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable_update_menu_item"})
 public class UpdateMenuItemHelperTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/BottomSheetLocationBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/BottomSheetLocationBarTest.java
index ce8d44bc..e9435a9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/BottomSheetLocationBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/BottomSheetLocationBarTest.java
@@ -33,7 +33,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.test.BottomSheetTestRule;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.net.test.EmbeddedTestServer;
 import org.chromium.net.test.ServerCertificate;
@@ -46,8 +45,7 @@
  * Tests for {@link LocationBarLayout} UI component in the home sheet.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @CommandLineParameter({"", "disable-features=" + ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE})
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
 @SuppressLint("SetTextI18n")
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
index a05ac3c..10ca321 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
@@ -79,8 +79,7 @@
  * framework once it supports Test Rule Parameterization
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @CommandLineParameter({"", "disable-features=" + ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE})
 @SuppressLint("SetTextI18n")
 public class OmniboxTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
index 8b300d8c..e24f1099 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
@@ -59,8 +59,7 @@
  * framework once it supports Test Rule Parameterization
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @CommandLineParameter({"", "disable-features=" + ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE})
 public class UrlBarTest {
     // 9000+ chars of goodness
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 11b1b4c..b0042e55 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
@@ -34,12 +34,8 @@
  * Tests for GeolocationHeader and GeolocationTracker.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class GeolocationHeaderTest {
-
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
             new ChromeActivityTestRule<>(ChromeActivity.class);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeIntegrationTest.java
index 35aedcc..8bc2b9f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeIntegrationTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsProvider;
 import org.chromium.content.browser.test.util.Criteria;
@@ -39,10 +38,7 @@
  * Integration tests for the partner disabling incognito mode feature.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PartnerDisableIncognitoModeIntegrationTest {
     @Rule
     public BasePartnerBrowserCustomizationIntegrationTestRule mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java
index ce2e4a3..15a44ba 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java
@@ -37,7 +37,6 @@
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabList;
 import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsProvider;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -54,10 +53,7 @@
  * Integration test suite for partner homepage.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PartnerHomepageIntegrationTest {
     @Rule
     public BasePartnerBrowserCustomizationIntegrationTestRule mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java
index 6839026..92f7b13 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java
@@ -36,10 +36,7 @@
 
 /** An integration test for the Android payment app finder. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @MediumTest
 public class AndroidPaymentAppFinderTest implements PaymentAppCreatedCallback {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java
index e7027f8..3749bef1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestDownloaderTest.java
@@ -30,10 +30,7 @@
 
 /** An integration test for the payment manifest downloader. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @MediumTest
 public class PaymentManifestDownloaderTest implements ManifestDownloadCallback {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestParserTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestParserTest.java
index 48ab2ad..27b28ee 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestParserTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentManifestParserTest.java
@@ -29,10 +29,7 @@
 
 /** An integration test for the payment manifest parser. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentManifestParserTest implements ManifestParseCallback {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
index 452d4fc..089bcf55 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -30,10 +29,7 @@
  * A payment integration test for a merchant that aborts their payment request.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestAbortTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
index ee71e459..d4555ba 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -34,10 +33,7 @@
  * A payment integration test for biling addresses.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestBillingAddressTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
index c7626906..1ec6386 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBillingAddressWithoutPhoneTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -34,12 +33,8 @@
  * A payment integration test for biling addresses without a phone.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestBillingAddressWithoutPhoneTest implements MainActivityStartCallback {
-
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
             new PaymentRequestTestRule("payment_request_free_shipping_test.html", this);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBlobUrlTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBlobUrlTest.java
index 3d4c030..7398a9af 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBlobUrlTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestBlobUrlTest.java
@@ -13,7 +13,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -21,10 +20,7 @@
 
 /** Web payments test for blob URL.  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestBlobUrlTest {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
index c935a67..517b0bb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentMetricsTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -34,10 +33,7 @@
  * A payment integration test for the correct log of the CanMakePayment metrics.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestCanMakePaymentMetricsTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
index a2501ec..1d3c0a5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryNoCardTest.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -34,10 +33,7 @@
  * app or a credit card. This user does not have a complete credit card on file.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestCanMakePaymentQueryNoCardTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
index e56f8490..982bbee 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCanMakePaymentQueryTest.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -34,10 +33,7 @@
  * a credit card. This user has a valid credit card without a billing address on file.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestCanMakePaymentQueryTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
index 1c138d5..5a30550 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCardEditorAutoAdvanceTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -35,10 +34,7 @@
  * https://developers.braintreepayments.com/guides/unionpay/testing/javascript/v3
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestCardEditorAutoAdvanceTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
index 472e3a3..7c1949fe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryNoCardTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -29,10 +28,7 @@
  * This user does not have a complete credit card on file.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestCcCanMakePaymentQueryNoCardTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
index 33495bf..e4a1896 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestCcCanMakePaymentQueryTest.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -30,10 +29,7 @@
  * user has a valid  credit card without a billing address on file.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestCcCanMakePaymentQueryTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
index 7fe0ee5..48171c0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsAndFreeShippingTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * a phone number and provides free shipping regardless of address.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestContactDetailsAndFreeShippingTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule = new PaymentRequestTestRule(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
index a088dd5..c1e62cac 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * A payment integration test for a merchant that requests contact details.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestContactDetailsTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDataUrlTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDataUrlTest.java
index 78e19b61..1312e18e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDataUrlTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDataUrlTest.java
@@ -14,7 +14,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -22,10 +21,7 @@
 
 /** Web payments test for data URL.  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestDataUrlTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule = new PaymentRequestTestRule(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDebitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDebitTest.java
index e750d92..459dc2dd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDebitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDebitTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -31,10 +30,7 @@
  * card on file.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestDebitTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDontHaveDebitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDontHaveDebitTest.java
index 4c860723..26265bb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDontHaveDebitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDontHaveDebitTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -32,10 +31,7 @@
  * pre-selected, but should be available for the user to select.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestDontHaveDebitTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
index 2282c9d..c9793ef 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.ArrayList;
@@ -30,10 +29,7 @@
  * and user that has 5 addresses stored in autofill settings.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestDynamicShippingMultipleAddressesTest
         implements MainActivityStartCallback {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
index 3a60612..bf03a2b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -35,10 +34,7 @@
  * and user that has a single address stored in autofill settings.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestDynamicShippingSingleAddressTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
index d356eaa..a1dfef37 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndFreeShippingTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * shipping regardless of address.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestEmailAndFreeShippingTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
index 9d991b6..34ec278 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailAndPhoneTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -32,10 +31,7 @@
  * A payment integration test for a merchant that requests email address and a phone number.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestEmailAndPhoneTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
index b00dff90..f1e09d3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -32,10 +31,7 @@
  * A payment integration test for a merchant that requests email address.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestEmailTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmptyUpdateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmptyUpdateTest.java
index a65f2c4..0054b34 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmptyUpdateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmptyUpdateTest.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -30,10 +29,7 @@
  * shipping addresses via updateWith({}), which is an "empty update."
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestEmptyUpdateTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
index cda6b1c..ac0dc223 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExpiredLocalCardTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.Calendar;
@@ -32,10 +31,7 @@
  * A payment integration test for a user that pays with an expired local credit card.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestExpiredLocalCardTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
index d84ac5db..05e6a86 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestExtraShippingOptionsTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -31,10 +30,7 @@
  * shipping address.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestExtraShippingOptionsTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
index 72fafb8..97b9b78f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -30,10 +29,7 @@
  * A payment integration test for a merchant that always fails to complete the transaction.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestFailCompleteTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFieldTrialTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFieldTrialTest.java
index 1ec47e1..e34e0f18 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFieldTrialTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFieldTrialTest.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -29,10 +28,7 @@
  * A payment integration test for the different fields trials affecting payment requests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestFieldTrialTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
index 2677700..4c10f26 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.RenderTestRule;
 
@@ -35,10 +34,7 @@
  * A payment integration test for a merchant that provides free shipping regardless of address.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestFreeShippingTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
index a48656ef..549ac4470 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIdTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -31,10 +30,7 @@
  * free-form identifier specified in PaymentDetailsInit.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestIdTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsAndFreeShippingTest.java
index 4778eed9..4ac87348 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsAndFreeShippingTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * incomplete information.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestIncompleteContactDetailsAndFreeShippingTest
         implements MainActivityStartCallback {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java
index 957cad6..8226733 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * incomplete contact details stored on disk.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestIncompleteContactDetailsTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteEmailTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteEmailTest.java
index afc378e..883e3e5a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteEmailTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteEmailTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * incomplete email address stored on disk.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestIncompleteEmailTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java
index dc0921b..1034f8b50 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompletePhoneTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * incomplete phone number stored on disk.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestIncompletePhoneTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
index 39599e07..51d4868 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteServerCardTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -30,10 +29,7 @@
  * A test for paying with an incomplete server card.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestIncompleteServerCardTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
index d8df15c7..b44b827 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestJourneyLoggerTest.java
@@ -28,7 +28,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -38,10 +37,7 @@
  * A payment integration test to validate the logging of Payment Request metrics.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestJourneyLoggerTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestLongIdTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestLongIdTest.java
index 5a79ac3a..e2119bba 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestLongIdTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestLongIdTest.java
@@ -14,7 +14,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -22,10 +21,7 @@
 
 /** A test to verify that PaymentRequest does not crash with very long request identifiers. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestLongIdTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
index 4588c37..80ab855 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMetricsTest.java
@@ -32,7 +32,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 
@@ -43,10 +42,7 @@
  * A payment integration test to validate the logging of Payment Request metrics.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestMetricsTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestModifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestModifierTest.java
index 6cd3a05c..c943f4a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestModifierTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestModifierTest.java
@@ -14,7 +14,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -22,10 +21,7 @@
 
 /** A payment request integration test for a merchant that uses a modifier. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestModifierTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java
index 9315d684..890fb49 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.ArrayList;
@@ -33,10 +32,7 @@
  * multiple contact detail options.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestMultipleContactDetailsTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
index bfe8611..2f4bb91 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameAndFreeShippingTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * regardless of address.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestNameAndFreeShippingTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
index 53ed289d..114497c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNameTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -32,10 +31,7 @@
  * A payment integration test for a merchant that requests payer name.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestNameTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
index 4c5e7463bd..abfb8a3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
@@ -29,7 +29,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -39,10 +38,7 @@
  * A payment integration test for a merchant that does not require shipping address.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestNoShippingTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoUpdateWithTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoUpdateWithTest.java
index 7279b65..922fd75 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoUpdateWithTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoUpdateWithTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * timeouts.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestNoUpdateWithTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndBasicCardWithModifiersTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndBasicCardWithModifiersTest.java
index 41bd227..91fbde6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndBasicCardWithModifiersTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndBasicCardWithModifiersTest.java
@@ -30,7 +30,6 @@
 import org.chromium.chrome.browser.autofill.CardType;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.payments.mojom.BasicCardNetwork;
 import org.chromium.payments.mojom.BasicCardType;
@@ -43,11 +42,8 @@
  * modifiers.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-        ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES, ENABLE_WEB_PAYMENTS_MODIFIERS,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+        ENABLE_EXPERIMENTAL_WEB_PLATFORM_FEATURES, ENABLE_WEB_PAYMENTS_MODIFIERS})
 public class PaymentRequestPaymentAppAndBasicCardWithModifiersTest {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule = new PaymentRequestTestRule(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
index 98cf15c..958702d9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppAndCardsTest.java
@@ -26,7 +26,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -36,10 +35,7 @@
  * A payment integration test for a merchant that requests payment via Bob Pay or cards.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestPaymentAppAndCardsTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppCanMakePaymentQueryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppCanMakePaymentQueryTest.java
index 2f72722..676f9b4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppCanMakePaymentQueryTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppCanMakePaymentQueryTest.java
@@ -20,7 +20,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -30,10 +29,7 @@
  * A payment integration test for checking whether user can make a payment using a payment app.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestPaymentAppCanMakePaymentQueryTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule = new PaymentRequestTestRule(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
index 9c1dab02..c10e26b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.payments.PaymentRequestTestCommon.TestPay;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -32,10 +31,7 @@
  * A payment integration test for a merchant that requests payment via Bob Pay.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestPaymentAppTest {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java
index d0cc255e..8efd04c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipPreloadTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -38,7 +37,6 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({
         ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         // Speed up the test by not looking up actual apps installed on the device.
         "disable-features=" + ChromeFeatureList.ANDROID_PAYMENT_APPS,
         "disable-features=" + ChromeFeatureList.SERVICE_WORKER_PAYMENT_APPS,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipTest.java
index 7725a34..ca7afbd1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppUiSkipTest.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -34,13 +33,10 @@
  * single payment app UI skip optimization.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         // Speed up the test by not looking up actual apps installed on the device.
         "disable-features=" + ChromeFeatureList.ANDROID_PAYMENT_APPS,
-        "disable-features=" + ChromeFeatureList.SERVICE_WORKER_PAYMENT_APPS,
-})
+        "disable-features=" + ChromeFeatureList.SERVICE_WORKER_PAYMENT_APPS})
 public class PaymentRequestPaymentAppUiSkipTest {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
index 61e2038..c793b693 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentAppsSortingTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestCommon.TestPay;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -32,10 +31,7 @@
 
 /** A payment integration test that sorting payment apps and instruments by frecency. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestPaymentAppsSortingTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule = new PaymentRequestTestRule(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentMethodIdentifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentMethodIdentifierTest.java
index c0d1a88..c66cd89 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentMethodIdentifierTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPaymentMethodIdentifierTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -35,10 +34,7 @@
  * A payment integration test for supported payment methods.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestPaymentMethodIdentifierTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
index 6898270..80b4419c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneAndFreeShippingTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -33,10 +32,7 @@
  * regardless of address.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestPhoneAndFreeShippingTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
index cee5599..bc93758 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestPhoneTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -32,10 +31,7 @@
  * A payment integration test for a merchant that requests phone number.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestPhoneTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
index 92aaa94..2cfae2fb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestRemoveBillingAddressTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -34,10 +33,7 @@
  * A payment integration test for removing a billing address that is associated with a credit card.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestRemoveBillingAddressTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
index b264337..3121a61 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServerCardTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -30,10 +29,7 @@
  * A test for using a server card in payments UI.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestServerCardTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
index be135be..37740482 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.payments.mojom.BasicCardNetwork;
 import org.chromium.payments.mojom.BasicCardType;
@@ -31,13 +30,10 @@
  * A payment integration test for service worker based payment apps.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         // For all the tests in this file, we expect abort exception when there is no supported
         // payment instruments instead of showing payment request UI.
-        "enable-features=" + ChromeFeatureList.NO_CREDIT_CARD_ABORT,
-})
+        "enable-features=" + ChromeFeatureList.NO_CREDIT_CARD_ABORT})
 public class PaymentRequestServiceWorkerPaymentAppTest {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule = new PaymentRequestTestRule(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressAndOptionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressAndOptionTest.java
index 45045e47..de63ba5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressAndOptionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressAndOptionTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -30,10 +29,7 @@
  * A payment integration test for shipping address labels.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestShippingAddressAndOptionTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
index 70288d17..dfa9581 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -29,10 +28,7 @@
  * A payment integration test for a merchant that requires shipping address to calculate shipping.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestShippingAddressChangeTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
index 5f4d632..0de357e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -31,10 +30,7 @@
  * A payment integration test for a merchant that calls show() twice.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestShowTwiceTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
index 3dae6f24..812c4a8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.LoadUrlParams;
 
@@ -37,10 +36,7 @@
  * elsewhere.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestTabTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
index fa3db8b..b858ae6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
 import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.ExecutionException;
@@ -32,10 +31,7 @@
  * updated when they are used to complete a Payment Request transaction.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PaymentRequestUseStatsTest implements MainActivityStartCallback {
     @Rule
     public PaymentRequestTestRule mPaymentRequestTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java
index 48d550e..5623fa10 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.permissions.PermissionTestRule.PermissionUpdateWaiter;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil;
 import org.chromium.device.geolocation.LocationProviderFactory;
@@ -31,10 +30,7 @@
  * - Google location is enabled.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class GeolocationTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java
index 4fc2e6d..02e2507d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.permissions.PermissionTestRule.PermissionUpdateWaiter;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.common.ContentSwitches;
 
@@ -24,10 +23,7 @@
  * Test suite for media permissions requests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class MediaTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java
index 2cbe130..fcfe0b93 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java
@@ -16,7 +16,6 @@
 import org.chromium.chrome.browser.permissions.PermissionTestRule.DialogShownCriteria;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.test.util.CriteriaHelper;
 
@@ -24,10 +23,7 @@
  * Test suite for interaction between permissions requests and navigation.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class PermissionNavigationTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/QuotaTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/QuotaTest.java
index f9e0302..bc8cccf6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/QuotaTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/QuotaTest.java
@@ -16,17 +16,13 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.permissions.PermissionTestRule.PermissionUpdateWaiter;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 /**
  * Test suite for quota permissions requests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class QuotaTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialogTest.java
index 8953560..c33f785 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialogTest.java
@@ -42,12 +42,9 @@
  * Tests for the PhotoPickerDialog class.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
-public class PhotoPickerDialogTest implements PhotoPickerListener,
-        SelectionObserver<PickerBitmap>, DecoderServiceHost.ServiceReadyCallback {
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+public class PhotoPickerDialogTest implements PhotoPickerListener, SelectionObserver<PickerBitmap>,
+                                              DecoderServiceHost.ServiceReadyCallback {
     // The timeout (in seconds) to wait for the decoder service to be ready.
     private static final long WAIT_TIMEOUT_SECONDS = scaleTimeout(30);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java
index 7b15db7..c1fcc65 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java
@@ -26,8 +26,7 @@
 
 /** Instrumentation tests for {@link CombinedPolicyProvider} */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class CombinedPolicyProviderTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
index 5db4963..9615fd8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
@@ -30,6 +30,7 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.PasswordManagerHandler;
@@ -355,6 +356,7 @@
     @SmallTest
     @Feature({"Preferences"})
     @EnableFeatures("password-export")
+    @DisabledTest(message = "crbug.com/796939")
     public void testExportMenuItem() throws Exception {
         setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password"));
 
@@ -385,6 +387,7 @@
     @SmallTest
     @Feature({"Preferences"})
     @EnableFeatures("password-export")
+    @DisabledTest(message = "crbug.com/796939")
     public void testExportMenuItemNoLock() throws Exception {
         setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password"));
 
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 8e5cbd3..c8fbc52 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
@@ -35,8 +35,7 @@
  * Integration tests for ClearBrowsingDataPreferences.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class BrowsingDataBridgeTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasicTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasicTest.java
index f454521a..ac165e55 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasicTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasicTest.java
@@ -41,8 +41,7 @@
  * Integration tests for ClearBrowsingDataPreferencesBasic.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ClearBrowsingDataPreferencesBasicTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
index 833d965..c7ce8a5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
@@ -56,10 +56,7 @@
  * Integration tests for ClearBrowsingDataPreferences.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class ClearBrowsingDataPreferencesTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/ManageSpaceActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/ManageSpaceActivityTest.java
index e224084..2e56fd7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/ManageSpaceActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/ManageSpaceActivityTest.java
@@ -39,8 +39,7 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @TargetApi(Build.VERSION_CODES.KITKAT)
 @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT)
-@CommandLineFlags.Add({"enable-site-engagement", ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({"enable-site-engagement", ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ManageSpaceActivityTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java
index 6375738..2669508 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/PermissionInfoTest.java
@@ -27,8 +27,7 @@
 
 /** Tests for the PermissionInfoTest. */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PermissionInfoTest {
     private static final String DSE_ORIGIN = "https://www.google.com";
     private static final String OTHER_ORIGIN = "https://www.other.com";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java
index 98deea6..90959e61 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferencesTest.java
@@ -44,8 +44,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SiteSettingsPreferencesTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/printing/PrintingControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/printing/PrintingControllerTest.java
index 72f9ba5..86a03e6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/printing/PrintingControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/printing/PrintingControllerTest.java
@@ -58,8 +58,7 @@
 @RetryOnFailure
 @SuppressLint("NewApi")
 @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PrintingControllerTest {
     @Rule
     public final ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java
index 99a54e9..6b168a2b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java
@@ -22,8 +22,7 @@
  * Test suite for out of process heap profiling.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ProfilingProcessHostAndroidTest {
     private static final String TAG = "ProfilingProcessHostAndroidTest";
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/provider/ProviderBookmarksUriTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/provider/ProviderBookmarksUriTest.java
index 5bbd1637..6f9f7fc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/provider/ProviderBookmarksUriTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/provider/ProviderBookmarksUriTest.java
@@ -20,7 +20,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.Arrays;
@@ -30,10 +29,7 @@
  * Tests the use of the Bookmark URI as part of the Android provider public API.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ProviderBookmarksUriTest {
     @Rule
     public ProviderTestRule mProviderTestRule = new ProviderTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/provider/ProviderSearchesUriTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/provider/ProviderSearchesUriTest.java
index 47daa43..c08e3746 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/provider/ProviderSearchesUriTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/provider/ProviderSearchesUriTest.java
@@ -20,7 +20,6 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.Date;
@@ -29,10 +28,7 @@
  * Tests the use of the Searches URI as part of the Android provider public API.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ProviderSearchesUriTest {
     @Rule
     public ProviderTestRule mProviderTestRule = new ProviderTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/push_messaging/PushMessagingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/push_messaging/PushMessagingTest.java
index b18fcab..68be8bc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/push_messaging/PushMessagingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/push_messaging/PushMessagingTest.java
@@ -36,7 +36,6 @@
 import org.chromium.chrome.browser.notifications.NotificationTestRule;
 import org.chromium.chrome.browser.preferences.website.ContentSetting;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.InfoBarUtil;
 import org.chromium.chrome.test.util.browser.TabTitleObserver;
@@ -56,10 +55,7 @@
  */
 // TODO(mvanouwerkerk): remove @SuppressLint once crbug.com/501900 is fixed.
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @SuppressLint("NewApi")
 public class PushMessagingTest implements PushMessagingServiceObserver.Listener {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/services/GoogleServicesManagerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/services/GoogleServicesManagerIntegrationTest.java
index 9ebae05..7c8452df 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/services/GoogleServicesManagerIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/services/GoogleServicesManagerIntegrationTest.java
@@ -22,8 +22,7 @@
  * Google Services Manager tests
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class GoogleServicesManagerIntegrationTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/shape_detection/ShapeDetectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/shape_detection/ShapeDetectionTest.java
index a2906ef9..3d3d565 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/shape_detection/ShapeDetectionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/shape_detection/ShapeDetectionTest.java
@@ -37,8 +37,7 @@
  *  hence is tested via content_browsertests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ShapeDetectionTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareMenuActionHandlerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareMenuActionHandlerIntegrationTest.java
index cba7e83b..ad169d1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareMenuActionHandlerIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareMenuActionHandlerIntegrationTest.java
@@ -31,8 +31,7 @@
  * Integration tests for the Share Menu handling.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ShareMenuActionHandlerIntegrationTest {
     private static final String PAGE_WITH_HTTPS_CANONICAL_URL =
             "/chrome/test/data/android/share/link_share_https_canonical.html";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
index 6e2dcfac..e75f6154 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
@@ -35,7 +35,6 @@
 import org.chromium.chrome.browser.preferences.SignInPreference;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ActivityUtils;
@@ -54,10 +53,7 @@
  * The accounts used to sign in are mocked by a FakeAccountManagerDelegate.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SigninTest {
     /**
      * Helper class that observes when signing in becomes allowed.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/DataReductionPromoSnackbarControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/DataReductionPromoSnackbarControllerTest.java
index ed4b073..1cbc2558 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/DataReductionPromoSnackbarControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/DataReductionPromoSnackbarControllerTest.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.preferences.datareduction.DataReductionPromoUtils;
 import org.chromium.chrome.browser.preferences.datareduction.DataReductionProxyUma;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 
@@ -28,10 +27,7 @@
  * from a field trial param and that the correct uma is recorded.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class DataReductionPromoSnackbarControllerTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/SnackbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/SnackbarTest.java
index 0a80025..3c2f67b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/SnackbarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/snackbar/SnackbarTest.java
@@ -18,7 +18,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content.browser.test.util.Criteria;
@@ -28,10 +27,7 @@
  * Tests for {@link SnackbarManager}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SnackbarTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
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 d855abc..c4b51c27 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
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.snackbar.Snackbar;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -34,10 +33,7 @@
  * Tests for the UndoBarController.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class UndoBarControllerTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
index 2559c9b..ff2df33 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ssl/CaptivePortalTest.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -42,10 +41,7 @@
 /** Tests for the Captive portal interstitial. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @MediumTest
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @CommandLineParameter({"", "enable-features=" + ChromeFeatureList.CAPTIVE_PORTAL_CERTIFICATE_LIST})
 public class CaptivePortalTest {
     private static final String CAPTIVE_PORTAL_INTERSTITIAL_TITLE_PREFIX = "Connect to";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java
index b8846e413..dfb1dbd8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java
@@ -33,10 +33,7 @@
  * Misc. Content Suggestions instrumentation tests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ContentSuggestionsTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsTest.java
index 50186c1c..4aee2f1a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsTest.java
@@ -20,7 +20,6 @@
 import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
-import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
@@ -30,7 +29,6 @@
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.RenderTestRule;
 import org.chromium.chrome.test.util.browser.ChromeHome;
@@ -49,7 +47,6 @@
  * Integration tests for Contextual suggestions.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add(ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG)
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
 public class ContextualSuggestionsTest {
     private static final String TEST_PAGE = "/chrome/test/data/android/test.html";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java
index 4917f43..1fb54d0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.BottomSheetTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -37,8 +36,7 @@
  * Instrumentation tests for {@link NavigationRecorder}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        BottomSheetTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class NavigationRecorderTest {
     @Rule
     public ChromeTabbedActivityTestRule mTestSetupRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java
index 4f9d884..6da3a22 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/TileGroupTest.java
@@ -31,7 +31,6 @@
 import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.NewTabPageTestUtils;
@@ -50,10 +49,7 @@
  * Instrumentation tests for {@link TileGroup} on the New Tab Page.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class TileGroupTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderTest.java
index a880fe8..1a8a473 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderTest.java
@@ -40,8 +40,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SupervisedUserContentProviderTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
index 3dd0ec18..599e1320 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
@@ -40,8 +40,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class InterceptNavigationDelegateTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/SadTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/SadTabTest.java
index 285b77d..02490b1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/SadTabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/SadTabTest.java
@@ -28,8 +28,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class SadTabTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java
index 9e1fd56..c83d2c3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabUmaTest.java
@@ -36,8 +36,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TabUmaTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/UndoIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/UndoIntegrationTest.java
index 35aaec03..8dc367de 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/UndoIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/UndoIntegrationTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content.browser.test.util.Criteria;
@@ -37,10 +36,7 @@
  * Tests undo and it's interactions with the UI.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class UndoIntegrationTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java
index 19bc73c4..0c99b64 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreatorTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -39,10 +38,7 @@
  * Tests for ChromeTabCreator.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ChromeTabCreatorTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ContextMenuLoadUrlParamsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ContextMenuLoadUrlParamsTest.java
index d3650fc..0a0f44fc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ContextMenuLoadUrlParamsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ContextMenuLoadUrlParamsTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabWindowManager.TabModelSelectorFactory;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils;
@@ -39,10 +38,7 @@
  * Verifies URL load parameters set when triggering navigations from the context menu.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure
 public class ContextMenuLoadUrlParamsTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java
index 3069669..2eb347d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -28,10 +27,7 @@
  * Tests for IncognitoTabModel.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class IncognitoTabModelTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java
index 1ead798..b6063a6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java
@@ -36,7 +36,6 @@
 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabPersistentStoreTest.MockTabPersistentStoreObserver;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -50,10 +49,7 @@
  * Tests merging tab models for Android N+ multi-instance.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
 @MinAndroidSdkLevel(24)
 public class TabModelMergingTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
index 281520a..290e532 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
@@ -31,7 +31,6 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -47,10 +46,7 @@
  * Tests undo and restoring of tabs in a {@link TabModel}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class UndoTabModelTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java
index 768703bb..6435c86 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java
@@ -46,8 +46,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class BrandColorTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java
index 8efc282..7b3cad8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -29,10 +28,7 @@
  * Tests for ToolbarModel.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ToolbarModelTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java
index 11236e2..a8a7ff3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java
@@ -38,8 +38,7 @@
  * Tests for toolbar manager behavior.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ToolbarTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java
index be4fe87..13c5b49c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java
@@ -37,8 +37,7 @@
  * preferences set to English.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TranslateCompactInfoBarTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateInfoBarTest.java
index 2859c34..518b64d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateInfoBarTest.java
@@ -40,8 +40,7 @@
  * Services than is installed on the test devices. See http://crbug.com/514449
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TranslateInfoBarTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/video/FullscreenVideoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/video/FullscreenVideoTest.java
index 1f23e14..eba6da0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/video/FullscreenVideoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/video/FullscreenVideoTest.java
@@ -39,9 +39,8 @@
  * Test suite for fullscreen video implementation.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.
-Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, MediaSwitches.AUTOPLAY_NO_GESTURE_REQUIRED_POLICY,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+        MediaSwitches.AUTOPLAY_NO_GESTURE_REQUIRED_POLICY})
 public class FullscreenVideoTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/video/VideoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/video/VideoTest.java
index d947ecf..d713db5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/video/VideoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/video/VideoTest.java
@@ -32,8 +32,7 @@
  *  Simple tests of html5 video.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class VideoTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrFeedbackInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrFeedbackInfoBarTest.java
index 97ab3a5..f40b510 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrFeedbackInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrFeedbackInfoBarTest.java
@@ -26,7 +26,6 @@
 import org.chromium.chrome.browser.vr_shell.util.VrInfoBarUtils;
 import org.chromium.chrome.browser.vr_shell.util.VrShellDelegateUtils;
 import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 
@@ -36,8 +35,7 @@
  * Tests for the infobar that prompts the user to enter feedback on their VR browsing experience.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-webvr"})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM)
 @RetryOnFailure(message = "These tests have a habit of hitting a race condition, preventing "
                 + "VR entry. See crbug.com/762724")
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrInstallUpdateInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrInstallUpdateInfoBarTest.java
index bf8a0e08..3a47016 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrInstallUpdateInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrInstallUpdateInfoBarTest.java
@@ -16,7 +16,6 @@
 import org.junit.rules.RuleChain;
 import org.junit.runner.RunWith;
 
-import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
 import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
 import org.chromium.base.test.params.ParameterSet;
@@ -25,7 +24,6 @@
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.vr_shell.mock.MockVrCoreVersionCheckerImpl;
 import org.chromium.chrome.browser.vr_shell.rules.VrActivityRestriction;
 import org.chromium.chrome.browser.vr_shell.util.VrInfoBarUtils;
 import org.chromium.chrome.browser.vr_shell.util.VrShellDelegateUtils;
@@ -43,8 +41,7 @@
  */
 @RunWith(ParameterizedRunner.class)
 @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT) // WebVR is only supported on K+
 public class VrInstallUpdateInfoBarTest {
     @ClassParameter
@@ -73,17 +70,7 @@
      * @param checkerReturnCompatibility The compatibility to have the VrCoreVersionChecker return
      */
     private void infoBarTestHelper(final int checkerReturnCompatibility) {
-        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
-            @Override
-            public void run() {
-                MockVrCoreVersionCheckerImpl mockChecker = new MockVrCoreVersionCheckerImpl();
-                mockChecker.setMockReturnValue(new VrCoreInfo(null, checkerReturnCompatibility));
-                VrShellDelegateUtils.getDelegateInstance().overrideVrCoreVersionCheckerForTesting(
-                        mockChecker);
-                Assert.assertEquals(
-                        checkerReturnCompatibility, mockChecker.getLastReturnValue().compatibility);
-            }
-        });
+        VrShellDelegateUtils.setVrCoreCompatibility(checkerReturnCompatibility);
         View decorView = mVrTestRule.getActivity().getWindow().getDecorView();
         if (checkerReturnCompatibility == VrCoreCompatibility.VR_READY) {
             VrInfoBarUtils.expectInfoBarPresent(mVrTestFramework, false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellCompositorViewHolderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellCompositorViewHolderTest.java
index 6398360..fdccd0f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellCompositorViewHolderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellCompositorViewHolderTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.vr_shell.rules.ChromeTabbedActivityVrTestRule;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.test.util.Criteria;
@@ -34,8 +33,7 @@
  * End-to-end tests for the CompositorViewHolder's behavior while in VR.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class VrShellCompositorViewHolderTest {
     // We explicitly instantiate a rule here instead of using parameterization since this class
     // only ever runs in ChromeTabbedActivity.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
index 369d743..ca665bf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.vr_shell.rules.ChromeTabbedActivityVrTestRule;
 import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.ContentViewCore;
 import org.chromium.content.browser.test.util.Coordinates;
@@ -39,8 +38,7 @@
  * End-to-end tests for Daydream controller input while in the VR browser.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Restriction({RESTRICTION_TYPE_DEVICE_DAYDREAM, RESTRICTION_TYPE_VIEWER_DAYDREAM})
 public class VrShellControllerInputTest {
     // We explicitly instantiate a rule here instead of using parameterization since this class
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNativeUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNativeUiTest.java
index 592b473..1fac6a9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNativeUiTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNativeUiTest.java
@@ -28,7 +28,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.vr_shell.rules.ChromeTabbedActivityVrTestRule;
 import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 import java.util.concurrent.TimeoutException;
@@ -37,8 +36,7 @@
  * End-to-end tests for native UI presentation in VR Browser mode.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-webvr"})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM)
 public class VrShellNativeUiTest {
     // We explicitly instantiate a rule here instead of using parameterization since this class
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java
index 0eb8295..99115d68 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java
@@ -47,8 +47,7 @@
  * "VR Shell".
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-webvr"})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM)
 public class VrShellNavigationTest {
     // We explicitly instantiate a rule here instead of using parameterization since this class
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java
index 005310c0..015eb9b4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java
@@ -33,7 +33,6 @@
 import org.chromium.chrome.browser.vr_shell.util.NfcSimUtils;
 import org.chromium.chrome.browser.vr_shell.util.VrShellDelegateUtils;
 import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
@@ -49,8 +48,7 @@
  * into the VR browser.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class VrShellTransitionTest {
     // We explicitly instantiate a rule here instead of using parameterization since this class
     // only ever runs in ChromeTabbedActivity.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrDeviceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrDeviceTest.java
index 7e014b5..a2c2e57 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrDeviceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrDeviceTest.java
@@ -9,6 +9,7 @@
 import android.os.Build;
 import android.support.test.filters.MediumTest;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -23,6 +24,7 @@
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.vr_shell.rules.VrActivityRestriction;
+import org.chromium.chrome.browser.vr_shell.util.VrShellDelegateUtils;
 import org.chromium.chrome.browser.vr_shell.util.VrTestRuleUtils;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
@@ -36,8 +38,7 @@
  */
 @RunWith(ParameterizedRunner.class)
 @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-webvr"})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
 @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT) // WebVR is only supported on K+
 public class WebVrDeviceTest {
     @ClassParameter
@@ -74,4 +75,25 @@
                 mVrTestFramework.getFirstTabWebContents());
         VrTestFramework.endTest(mVrTestFramework.getFirstTabWebContents());
     }
+
+    /**
+     * Tests that the magic-window-only GVR-less implementation causes a VRDisplay to be present
+     * when GVR isn't present and has expected capabilities.
+     */
+    @Test
+    @MediumTest
+    @VrActivityRestriction({VrActivityRestriction.SupportedActivity.ALL})
+    public void testGvrlessMagicWindowCapabilities() throws InterruptedException {
+        // Make Chrome think that VrCore is not installed
+        VrShellDelegateUtils.setVrCoreCompatibility(VrCoreCompatibility.VR_NOT_AVAILABLE);
+
+        mVrTestFramework.loadUrlAndAwaitInitialization(
+                VrTestFramework.getHtmlTestFile("test_device_capabilities_match_expectations"),
+                PAGE_LOAD_TIMEOUT_S);
+        Assert.assertTrue(
+                VrTestFramework.vrDisplayFound(mVrTestFramework.getFirstTabWebContents()));
+        VrTestFramework.executeStepAndWait("stepCheckDeviceCapabilities('VR Orientation Device')",
+                mVrTestFramework.getFirstTabWebContents());
+        VrTestFramework.endTest(mVrTestFramework.getFirstTabWebContents());
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java
index 4585bdd..91a767a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java
@@ -57,9 +57,8 @@
  */
 @RunWith(ParameterizedRunner.class)
 @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-webvr",
-        "enable-gamepad-extensions"})
+@CommandLineFlags.
+Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr", "enable-gamepad-extensions"})
 @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT) // WebVR is only supported on K+
 public class WebVrInputTest {
     @ClassParameter
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTabTest.java
index a9355ad8..001a2a6b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTabTest.java
@@ -34,8 +34,7 @@
  */
 @RunWith(ParameterizedRunner.class)
 @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-webvr"})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
 @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT) // WebVR is only supported on K+
 public class WebVrTabTest {
     @ClassParameter
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 eca1e43..c01d9bb3 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
@@ -57,8 +57,7 @@
  */
 @RunWith(ParameterizedRunner.class)
 @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-webvr"})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
 @MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT) // WebVR is only supported on K+
 public class WebVrTransitionTest {
     @ClassParameter
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/util/VrShellDelegateUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/util/VrShellDelegateUtils.java
index 14b3b53..beb6ede0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/util/VrShellDelegateUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/util/VrShellDelegateUtils.java
@@ -4,8 +4,12 @@
 
 package org.chromium.chrome.browser.vr_shell.util;
 
+import org.junit.Assert;
+
 import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.browser.vr_shell.TestVrShellDelegate;
+import org.chromium.chrome.browser.vr_shell.VrCoreInfo;
+import org.chromium.chrome.browser.vr_shell.mock.MockVrCoreVersionCheckerImpl;
 
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -30,4 +34,26 @@
         });
         return delegate.get();
     }
+
+    /**
+     * Creates and sets a MockVrCoreVersionCheckerImpl as the VrShellDelegate's
+     * VrCoreVersionChecker instance.
+     * @param compatibility An int corresponding to a VrCoreCompatibility value that the mock
+     *     version checker will return.
+     * @return The MockVrCoreVersionCheckerImpl that was set as VrShellDelegate's
+     *     VrCoreVersionChecker instance.
+     */
+    public static MockVrCoreVersionCheckerImpl setVrCoreCompatibility(int compatibility) {
+        final MockVrCoreVersionCheckerImpl mockChecker = new MockVrCoreVersionCheckerImpl();
+        mockChecker.setMockReturnValue(new VrCoreInfo(null, compatibility));
+        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+            @Override
+            public void run() {
+                VrShellDelegateUtils.getDelegateInstance().overrideVrCoreVersionCheckerForTesting(
+                        mockChecker);
+            }
+        });
+        Assert.assertEquals(compatibility, mockChecker.getLastReturnValue().compatibility);
+        return mockChecker;
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java
index b673c1134..520084f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java
@@ -44,8 +44,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @RetryOnFailure
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class AddToHomescreenManagerTest {
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java
index 6d37bc2..ee99046 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java
@@ -39,7 +39,6 @@
 /** Integration tests for WebAPK feature. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1"})
 public class WebApkIntegrationTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java
index 0b2d1cd..6d117243 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java
@@ -19,7 +19,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.WebappTestPage;
@@ -31,10 +30,7 @@
  * Tests the WebApkUpdateDataFetcher.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class WebApkUpdateDataFetcherTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
index da0cfbf..6371946 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
@@ -22,7 +22,6 @@
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.WebappTestPage;
@@ -38,7 +37,6 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
         ChromeSwitches.CHECK_FOR_WEB_MANIFEST_UPDATE_ON_STARTUP})
 public class WebApkUpdateManagerTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappDeferredStartupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappDeferredStartupTest.java
index dcc5288..cd806b0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappDeferredStartupTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappDeferredStartupTest.java
@@ -20,15 +20,13 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorBase;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 /**
  * Tests that when WebappActivity#onDeferredStartup() is run, the activity tab has finished loading.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class WebappDeferredStartupTest {
     static class PageLoadFinishedTabObserver extends EmptyTabObserver {
         private boolean mIsPageLoadFinished;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenBackgroundColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenBackgroundColorTest.java
index 54c5e05a..a9ea450 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenBackgroundColorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenBackgroundColorTest.java
@@ -20,15 +20,13 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.metrics.WebappUma;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 /**
  * Tests for splash screens with EXTRA_BACKGROND_COLOR specified in the Intent.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class WebappSplashScreenBackgroundColorTest {
     @Rule
     public final WebappActivityTestRule mActivityTestRule = new WebappActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenHomescreenIconTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenHomescreenIconTest.java
index d8e2b58..4c57428 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenHomescreenIconTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenHomescreenIconTest.java
@@ -23,15 +23,13 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.metrics.WebappUma;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 /**
  * Tests for splash screens with EXTRA_ICON specified in the Intent.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class WebappSplashScreenHomescreenIconTest {
     @Rule
     public final WebappActivityTestRule mActivityTestRule = new WebappActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java
index a8fc4b5..d401e77 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java
@@ -23,15 +23,13 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.metrics.WebappUma;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 /**
  * Tests for splash screens with an icon registered in WebappRegistry.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class WebappSplashScreenIconTest {
     @Rule
     public final WebappActivityTestRule mActivityTestRule = new WebappActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
index 78d936c..d8fe2c7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
@@ -34,15 +34,13 @@
 import org.chromium.chrome.browser.metrics.WebappUma;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabTestUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 
 /**
  * Tests for splash screens.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class WebappSplashScreenTest {
     @Rule
     public final WebappActivityTestRule mActivityTestRule = new WebappActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java
index 6336c05..a6fdb29 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenThemeColorTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.metrics.WebappUma;
 import org.chromium.chrome.browser.tab.TabTestUtils;
 import org.chromium.chrome.browser.util.ColorUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
@@ -35,8 +34,7 @@
  * Tests for splash screens with EXTRA_THEME_COLOR specified in the Intent.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class WebappSplashScreenThemeColorTest {
     @Rule
     public final WebappActivityTestRule mActivityTestRule = new WebappActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java
index c7fd90e..0b94a72 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java
@@ -32,7 +32,6 @@
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.widget.accessibility.AccessibilityTabModelListItem;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -52,10 +51,7 @@
  * Tests accessibility UI.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class OverviewListLayoutTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java
index 4871303..ad2cb8b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/PromoDialogTest.java
@@ -26,7 +26,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.widget.PromoDialog.DialogParams;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 
@@ -36,10 +35,7 @@
  * Tests for the PromoDialog and PromoDialogLayout.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class PromoDialogTest {
     // TODO(tedchoc): Find a way to introduce a lightweight activity that doesn't spin up the world.
     //                crbug.com/728297
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java
index 64e6f825..cf320d8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ThumbnailProviderImplTest.java
@@ -24,7 +24,6 @@
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.widget.ThumbnailProvider.ThumbnailRequest;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 
@@ -32,10 +31,7 @@
  * Instrumentation test for {@link ThumbnailProviderImpl}.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class ThumbnailProviderImplTest {
     private static final String TEST_DIRECTORY = "chrome/test/data/android/thumbnail_provider/";
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ToolbarProgressBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ToolbarProgressBarTest.java
index ea402657..5cea92e5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ToolbarProgressBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ToolbarProgressBarTest.java
@@ -44,8 +44,7 @@
  * Tests related to the ToolbarProgressBar.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
 public class ToolbarProgressBarTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java
index 9f2c4f0..8f717cc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetBackBehaviorTest.java
@@ -44,8 +44,7 @@
  * Tests the behavior of the bottom sheet when used with the back button.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        BottomSheetTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
 public class BottomSheetBackBehaviorTest {
     private static final String TEST_PAGE = "/chrome/test/data/android/simple.html";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNavigateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNavigateTest.java
index f9c1ec2..69e3f8d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNavigateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNavigateTest.java
@@ -26,7 +26,6 @@
 import org.chromium.chrome.browser.omnibox.LocationBarLayout;
 import org.chromium.chrome.browser.omnibox.UrlBar;
 import org.chromium.chrome.test.BottomSheetTestRule;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.OmniboxTestUtils;
 import org.chromium.chrome.test.util.browser.TabLoadObserver;
@@ -40,10 +39,7 @@
  * Navigate in UrlBar for BottomSheet tests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
 public class BottomSheetNavigateTest {
     @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java
index cae07ebe..174436b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetNewTabControllerTest.java
@@ -45,8 +45,7 @@
  * Tests for the NTP UI displayed when Chrome Home is enabled.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        BottomSheetTestRule.DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) // ChromeHome is only enabled on phones
 public class BottomSheetNewTabControllerTest {
     private FadingBackgroundView mFadingBackgroundView;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/findinpage/FindTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/findinpage/FindTest.java
index 2af8657..de47ec80 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/findinpage/FindTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/findinpage/FindTest.java
@@ -39,7 +39,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.FullscreenTestUtils;
@@ -57,10 +56,7 @@
  * Find in page tests.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class FindTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
index 4c63b60..573cc4e 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -317,6 +317,7 @@
         CardsVariationParameters.setTestVariationParams(null);
         SigninManager.setInstanceForTesting(null);
         ChromePreferenceManager.getInstance().setNewTabPagePersonalizedSigninPromoDismissed(false);
+        ChromePreferenceManager.getInstance().clearNewTabPageSigninPromoSuppressionPeriodStart();
     }
 
     /**
@@ -986,6 +987,40 @@
 
     @Test
     @Feature({"Ntp"})
+    public void testSigninPromoSuppressionActive() {
+        when(mMockSigninManager.isSignInAllowed()).thenReturn(true);
+        when(mMockSigninManager.isSignedInOnNative()).thenReturn(false);
+
+        // Suppress promo.
+        ChromePreferenceManager.getInstance().setNewTabPageSigninPromoSuppressionPeriodStart(
+                System.currentTimeMillis());
+
+        resetUiDelegate();
+        reloadNtp();
+        assertFalse(isSignInPromoVisible());
+    }
+
+    @Test
+    @Feature({"Ntp"})
+    public void testSigninPromoSuppressionExpired() {
+        when(mMockSigninManager.isSignInAllowed()).thenReturn(true);
+        when(mMockSigninManager.isSignedInOnNative()).thenReturn(false);
+
+        // Suppress promo.
+        ChromePreferenceManager preferenceManager = ChromePreferenceManager.getInstance();
+        preferenceManager.setNewTabPageSigninPromoSuppressionPeriodStart(
+                System.currentTimeMillis() - SignInPromo.SUPPRESSION_PERIOD_MS);
+
+        resetUiDelegate();
+        reloadNtp();
+        assertTrue(isSignInPromoVisible());
+
+        // SignInPromo should clear shared preference when suppression period ends.
+        assertEquals(0, preferenceManager.getNewTabPageSigninPromoSuppressionPeriodStart());
+    }
+
+    @Test
+    @Feature({"Ntp"})
     @EnableFeatures(ChromeFeatureList.CHROME_HOME)
     public void testSigninPromoModern() {
         when(mMockSigninManager.isSignInAllowed()).thenReturn(true);
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java
index 1fe3e8ea..afd94ff 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/AutofillTest.java
@@ -20,7 +20,6 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.sync.SyncTestRule.DataCriteria;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
 import org.chromium.components.sync.ModelType;
@@ -37,10 +36,7 @@
  * Test suite for the autofill profile sync data type.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure // crbug.com/637448
 public class AutofillTest {
     @Rule
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java
index 5187982e..2b96a15e 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/BookmarksTest.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.sync.SyncTestRule.DataCriteria;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
 import org.chromium.components.bookmarks.BookmarkId;
@@ -40,10 +39,7 @@
  * Test suite for the bookmarks sync data type.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure // crbug.com/637448
 public class BookmarksTest {
     @Rule
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
index 5c7d5ae3..fed8dfa 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
@@ -33,7 +33,6 @@
 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
 import org.chromium.chrome.browser.preferences.Preferences;
 import org.chromium.chrome.browser.signin.AccountManagementFragment;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ActivityUtils;
 import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
@@ -47,7 +46,6 @@
  * Tests for the first run experience.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add(ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG)
 @CommandLineFlags.Remove(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
 @RetryOnFailure // crbug.com/637448
 public class FirstRunTest {
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/GmsCoreSyncListenerTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/GmsCoreSyncListenerTest.java
index 81c4e81..d1dc460 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/GmsCoreSyncListenerTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/GmsCoreSyncListenerTest.java
@@ -19,7 +19,6 @@
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
 import org.chromium.content.browser.test.util.Criteria;
@@ -31,10 +30,7 @@
  * Test suite for the GmsCoreSyncListener.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @DisabledTest // crbug.com/789947
 public class GmsCoreSyncListenerTest {
     @Rule
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java
index 19115a1..228668d8 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/OpenTabsTest.java
@@ -26,7 +26,6 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
 import org.chromium.components.sync.SyncConstants;
@@ -50,10 +49,7 @@
  * Test suite for the open tabs (sessions) sync data type.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure // crbug.com/637448
 public class OpenTabsTest {
     @Rule
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
index 229724cf..10561274 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncCustomizationFragmentTest.java
@@ -38,7 +38,6 @@
 import org.chromium.chrome.browser.sync.ui.PassphraseDialogFragment;
 import org.chromium.chrome.browser.sync.ui.PassphraseTypeDialogFragment;
 import org.chromium.chrome.browser.sync.ui.SyncCustomizationFragment;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ActivityUtils;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
@@ -59,10 +58,7 @@
  * Tests for SyncCustomizationFragment.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @SuppressLint("UseSparseArrays")
 @RetryOnFailure // crbug.com/637448
 public class SyncCustomizationFragmentTest {
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java
index 8068d012..6e76934 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java
@@ -27,7 +27,6 @@
 import org.chromium.chrome.browser.signin.AccountTrackerService;
 import org.chromium.chrome.browser.signin.SigninHelper;
 import org.chromium.chrome.browser.signin.SigninManager;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.signin.MockChangeEventChecker;
 import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
@@ -42,12 +41,9 @@
  * Test suite for Sync.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         // TODO(crbug.com/781368) remove once feature enabled.
-        "enable-features=SyncUSSTypedURL"
-})
+        "enable-features=SyncUSSTypedURL"})
 @RetryOnFailure // crbug.com/637448
 public class SyncTest {
     @Rule
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java
index a05dbaa..68fd1bac 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java
@@ -21,7 +21,6 @@
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
 import org.chromium.components.sync.ModelType;
@@ -41,10 +40,7 @@
  * Test suite for the typed URLs sync data type.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure // crbug.com/637448
 public class TypedUrlsTest {
     @Rule
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java
index 0c641b52..c1cac9d 100644
--- a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.sync.SyncTestRule;
-import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.components.sync.PassphraseType;
 
@@ -29,10 +28,7 @@
  * Tests to make sure that PassphraseTypeDialogFragment presents the correct options.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({
-        ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG,
-})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @RetryOnFailure // crbug.com/637448
 public class PassphraseTypeDialogFragmentTest {
     @Rule
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index d9f303e..c62ffd9 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -1137,15 +1137,11 @@
       </if>
 
       <!-- Framebust / Blocked Redirection intervention message -->
-      <message name="IDS_REDIRECT_BLOCKED_MESSAGE" desc="The message stating that a redirect (noun) was blocked on this page. This will be followed on a separate line with the address the user was being redirected to.">
-         Chromium stopped this site from taking you to
-      </message>
-      <if expr="is_android">
-        <message name="IDS_REDIRECT_BLOCKED_SHORT_MESSAGE" desc="The short message stating that a redirect (noun) was blocked on this page.">
-           Redirect blocked.
-        </message>
-      </if>
       <if expr="not is_android">
+        <!-- Android strings are not product specific and declared in android_chrome_strings.grd. -->
+        <message name="IDS_REDIRECT_BLOCKED_MESSAGE" desc="The message stating that a redirect (noun) was blocked on this page. This will be followed on a separate line with the address the user was being redirected to.">
+          Chromium stopped this site from taking you to
+        </message>
         <message name="IDS_REDIRECT_BLOCKED_TITLE" desc="The short message stating that a redirect (noun) was blocked on this page. Same as IDS_REDIRECT_BLOCKED_SHORT_MESSAGE but without the period.">
            Redirect blocked
         </message>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 145de8c9..84f1845 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -1154,15 +1154,11 @@
       </if>
 
       <!-- Framebust / Blocked Redirection intervention message -->
-      <message name="IDS_REDIRECT_BLOCKED_MESSAGE" desc="The message stating that a redirect (noun) was blocked on this page. This will be followed on a separate line with the address the user was being redirected to.">
-         Chrome stopped this site from taking you to
-      </message>
-      <if expr="is_android">
-        <message name="IDS_REDIRECT_BLOCKED_SHORT_MESSAGE" desc="The short message stating that a redirect (noun) was blocked on this page.">
-           Redirect blocked.
-        </message>
-      </if>
       <if expr="not is_android">
+        <!-- Android strings are not product specific and declared in android_chrome_strings.grd. -->
+        <message name="IDS_REDIRECT_BLOCKED_MESSAGE" desc="The message stating that a redirect (noun) was blocked on this page. This will be followed on a separate line with the address the user was being redirected to.">
+          Chrome stopped this site from taking you to
+        </message>
         <message name="IDS_REDIRECT_BLOCKED_TITLE" desc="The short message stating that a redirect (noun) was blocked on this page. Same as IDS_REDIRECT_BLOCKED_SHORT_MESSAGE but without the period.">
            Redirect blocked
         </message>
diff --git a/chrome/app/md_extensions_strings.grdp b/chrome/app/md_extensions_strings.grdp
index 6f7030f..f5612d5 100644
--- a/chrome/app/md_extensions_strings.grdp
+++ b/chrome/app/md_extensions_strings.grdp
@@ -91,6 +91,12 @@
   <message name="IDS_MD_EXTENSIONS_ITEM_ON" desc="The label to indicate that a specific extension is currently enabled.">
     On
   </message>
+  <message name="IDS_MD_EXTENSIONS_ITEM_EXTENSION_WEBSITE" desc="Label for button to go to the website the extension developer specified.">
+    Open extension website
+  </message>
+  <message name="IDS_MD_EXTENSIONS_ITEM_CHROME_WEB_STORE" desc="Label for button to visit the Chrome web store.">
+    View in Chrome Web Store
+  </message>
   <message name="IDS_MD_EXTENSIONS_ITEM_OPTIONS" desc="The label on the button to open an extension options page.">
     Extension options
   </message>
@@ -143,7 +149,7 @@
     Retry
   </message>
   <message name="IDS_MD_EXTENSIONS_NO_INSTALLED_ITEMS" desc="The message shown to the user on the Extensions settings page when there are no extensions or apps installed.">
-    Find extensions and apps in the <ph name="BEGIN_LINK">&lt;a target="_blank" href="https://chrome.google.com/webstore/category/extensions"&gt;</ph>Chrome Web Store<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
+    Find extensions and themes in the <ph name="BEGIN_LINK">&lt;a target="_blank" href="https://chrome.google.com/webstore/category/extensions"&gt;</ph>Chrome Web Store<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
   </message>
   <message name="IDS_MD_EXTENSIONS_NO_DESCRIPTION" desc="The message shown to the user when an extension does not have any description.">
     No description provided
@@ -219,7 +225,7 @@
   </message>
 <if expr="is_macosx">
   <message name="IDS_MD_EXTENSIONS_INCLUDE_START_MODIFIER" desc="Error message explaining that shortcuts must start with either the Control, Alt, or Command key.">
-    Include Ctrl, Alt, or Command
+    Include Ctrl, Alt, or ⌘
   </message>
 </if>
 <if expr="chromeos">
@@ -237,11 +243,11 @@
     Include either Ctrl or Alt
   </message>
   <message name="IDS_MD_EXTENSIONS_TOO_MANY_MODIFIERS" desc="Error message explaining not to use both Ctrl and Alt in a shortcut.">
-    Either, not both Ctrl and Alt
+    Use either Ctrl or Alt
   </message>
 </if>
 <message name="IDS_MD_EXTENSIONS_NEED_CHARACTER" desc="Error message explaining that a shortcut needs a character. This is only shown if a valid modifier is already entered.">
-  Need a character
+  Type a letter
 </message>
 <if expr="chromeos">
   <!-- Extensions Kiosk apps -->
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index dd6ce9ee..45cae25 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3723,6 +3723,8 @@
         "offline_pages/android/offline_page_model_factory.cc",
         "offline_pages/android/offline_page_origin_utils_android.cc",
         "offline_pages/android/offline_page_utils_android.cc",
+        "offline_pages/android/offline_pages_download_manager_bridge.cc",
+        "offline_pages/android/offline_pages_download_manager_bridge.h",
         "offline_pages/android/prefetch_background_task_android.cc",
         "offline_pages/android/prefetch_background_task_android.h",
         "offline_pages/android/prefetch_background_task_scheduler_android.cc",
@@ -4293,6 +4295,7 @@
       "../android/java/src/org/chromium/chrome/browser/offlinepages/CCTRequestStatus.java",
       "../android/java/src/org/chromium/chrome/browser/offlinepages/CctOfflinePageModelObserver.java",
       "../android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java",
+      "../android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePagesDownloadManagerBridge.java",
       "../android/java/src/org/chromium/chrome/browser/offlinepages/SavePageRequest.java",
       "../android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java",
       "../android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageNotificationBridge.java",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index f0f3a85..fdf77fd 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1447,6 +1447,10 @@
      ENABLE_DISABLE_VALUE_TYPE(
          chromeos::switches::kEnableNetworkPortalNotification,
          chromeos::switches::kDisableNetworkPortalNotification)},
+    {"enable-captive-portal-random-url",
+     flag_descriptions::kEnableCaptivePortalRandomUrl,
+     flag_descriptions::kEnableCaptivePortalRandomUrlDescription, kOsCrOS,
+     SINGLE_VALUE_TYPE(chromeos::switches::kEnableCaptivePortalRandomUrl)},
     {"disable-network-settings-config",
      flag_descriptions::kDisableNetworkSettingsConfigName,
      flag_descriptions::kDisableNetworkSettingsConfigDescription, kOsCrOS,
@@ -3492,9 +3496,9 @@
      SINGLE_DISABLE_VALUE_TYPE(
          ash::switches::kAshDisableTabletAutohideTitlebars)},
 
-    {"enable-tablet-splitview", flag_descriptions::kEnableTabletSplitViewName,
-     flag_descriptions::kEnableTabletSplitViewDescription, kOsCrOS,
-     SINGLE_VALUE_TYPE(ash::switches::kAshEnableTabletSplitView)},
+    {"disable-tablet-splitview", flag_descriptions::kDisableTabletSplitViewName,
+     flag_descriptions::kDisableTabletSplitViewDescription, kOsCrOS,
+     SINGLE_VALUE_TYPE(ash::switches::kAshDisableTabletSplitView)},
 #endif  // defined(OS_CHROMEOS)
 
     {"enable-parallel-downloading", flag_descriptions::kParallelDownloadingName,
diff --git a/chrome/browser/android/contextualsearch/contextual_search_manager.cc b/chrome/browser/android/contextualsearch/contextual_search_manager.cc
index 9531bd43..8b4974db 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_manager.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_manager.cc
@@ -17,7 +17,6 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "components/contextual_search/browser/contextual_search_js_api_service_impl.h"
-#include "components/contextual_search/common/overlay_page_notifier_service.mojom.h"
 #include "components/navigation_interception/intercept_navigation_delegate.h"
 #include "components/variations/variations_associated_data.h"
 #include "content/public/browser/render_frame_host.h"
@@ -204,30 +203,31 @@
       end_offset);
 }
 
-void ContextualSearchManager::EnableContextualSearchJsApiForOverlay(
+void ContextualSearchManager::EnableContextualSearchJsApiForWebContents(
     JNIEnv* env,
     jobject obj,
     const JavaParamRef<jobject>& j_overlay_web_contents) {
+  DCHECK(j_overlay_web_contents);
   WebContents* overlay_web_contents =
       WebContents::FromJavaWebContents(j_overlay_web_contents);
   DCHECK(overlay_web_contents);
-  // Tell our Overlay Notifier Service that this is currently a CS page.
-  content::RenderFrameHost* render_frame_host =
-      overlay_web_contents->GetRenderViewHost()->GetMainFrame();
-  DCHECK(render_frame_host);
-  contextual_search::mojom::OverlayPageNotifierServicePtr page_notifier_service;
-  render_frame_host->GetRemoteInterfaces()->GetInterface(
-      &page_notifier_service);
-  DCHECK(page_notifier_service);
-  page_notifier_service->NotifyIsContextualSearchOverlay();
-
   ContextualSearchObserver::EnsureForWebContents(overlay_web_contents, this);
 }
 
-jlong JNI_ContextualSearchManager_Init(JNIEnv* env,
-                                       const JavaParamRef<jobject>& obj) {
-  ContextualSearchManager* manager = new ContextualSearchManager(env, obj);
-  return reinterpret_cast<intptr_t>(manager);
+void ContextualSearchManager::WhitelistContextualSearchJsApiUrl(
+    JNIEnv* env,
+    jobject obj,
+    const base::android::JavaParamRef<jstring>& j_url) {
+  DCHECK(j_url);
+  overlay_gurl_ = GURL(base::android::ConvertJavaStringToUTF8(env, j_url));
+}
+
+void ContextualSearchManager::ShouldEnableJsApi(
+    const GURL& gurl,
+    contextual_search::mojom::ContextualSearchJsApiService::
+        ShouldEnableJsApiCallback callback) {
+  bool should_enable = (gurl == overlay_gurl_);
+  std::move(callback).Run(should_enable);
 }
 
 void ContextualSearchManager::SetCaption(std::string caption,
@@ -238,3 +238,9 @@
   Java_ContextualSearchManager_onSetCaption(env, java_manager_, j_caption,
                                             does_answer);
 }
+
+jlong JNI_ContextualSearchManager_Init(JNIEnv* env,
+                                       const JavaParamRef<jobject>& obj) {
+  ContextualSearchManager* manager = new ContextualSearchManager(env, obj);
+  return reinterpret_cast<intptr_t>(manager);
+}
diff --git a/chrome/browser/android/contextualsearch/contextual_search_manager.h b/chrome/browser/android/contextualsearch/contextual_search_manager.h
index 869d445..488fc4ed 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_manager.h
+++ b/chrome/browser/android/contextualsearch/contextual_search_manager.h
@@ -57,8 +57,26 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
 
-  // Enables the Contextual Search JS API for the given |WebContents|.
-  void EnableContextualSearchJsApiForOverlay(
+  // Whitelists the given |j_url| for injection of the Contextual Search
+  // JavaScript API.  EnableContextualSearchJsApiForWebContents must also be
+  // called with the WebContents that will host the page in the Overlay.
+  // This method should be called when the URL navigation starts so the
+  // JavaScript API can be established before the page executes.
+  // The given URL is stored for future reference when ShouldEnableJsApi is
+  // called by a Renderer through mojo.
+  void WhitelistContextualSearchJsApiUrl(
+      JNIEnv* env,
+      jobject obj,
+      const base::android::JavaParamRef<jstring>& j_url);
+
+  // Enables the Contextual Search JS API for the given |j_web_contents|.
+  // This method should be called at least once for this Overlay Panel, and
+  // before any page loads in the Overlay so that the Contextual Search
+  // JavaScript API can be injected into the Overlay Panel.
+  // WhitelistContextualSearchJsApiUrl must also be called for every URL
+  // that will be loaded, in order for the JavaScript API to be enabled for that
+  // URL.
+  void EnableContextualSearchJsApiForWebContents(
       JNIEnv* env,
       jobject obj,
       const base::android::JavaParamRef<jobject>& j_web_contents);
@@ -66,6 +84,15 @@
   // ContextualSearchJsApiHandler overrides:
   void SetCaption(std::string caption, bool does_answer) override;
 
+  // Determines whether the JS API should be enabled for the given URL.
+  // Calls the given |callback| with the answer: whether the API should be
+  // enabled.  The callback is responsible for injecting the JS API into the
+  // renderer.
+  void ShouldEnableJsApi(
+      const GURL& gurl,
+      contextual_search::mojom::ContextualSearchJsApiService::
+          ShouldEnableJsApiCallback callback) override;
+
  private:
   void OnSearchTermResolutionResponse(
       const ResolvedSearchTerm& resolved_search_term);
@@ -81,6 +108,10 @@
   // Our global reference to the Java ContextualSearchManager.
   base::android::ScopedJavaGlobalRef<jobject> java_manager_;
 
+  // The url of the overlay, used to determine if the JS API should be enabled.
+  // See ShouldEnableJsApi.
+  GURL overlay_gurl_;
+
   // The delegate we're using the do the real work.
   std::unique_ptr<ContextualSearchDelegate> delegate_;
 
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h
index ae1e7979..c1e4bd3 100644
--- a/chrome/browser/android/resource_id.h
+++ b/chrome/browser/android/resource_id.h
@@ -50,8 +50,6 @@
 DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_SUBRESOURCE_FILTERING,
                     R.drawable.infobar_chrome)
 DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_WARNING, R.drawable.infobar_warning)
-DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_FRAMEBUST,
-                    R.drawable.infobar_redirect_blocked)
 
 // PageInfoUI images, used in ConnectionInfoPopup
 // Good:
diff --git a/chrome/browser/android/vr_shell/gl_browser_interface.h b/chrome/browser/android/vr_shell/gl_browser_interface.h
index a0f331c..64a35c88 100644
--- a/chrome/browser/android/vr_shell/gl_browser_interface.h
+++ b/chrome/browser/android/vr_shell/gl_browser_interface.h
@@ -14,10 +14,6 @@
 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h"
 #include "ui/gfx/transform.h"
 
-namespace base {
-class Version;
-}  // namespace base
-
 namespace vr_shell {
 
 // VrShellGl talks to VrShell through this interface. This could be split up if
@@ -32,8 +28,6 @@
   virtual void ForceExitVr() = 0;
   virtual void OnContentPaused(bool enabled) = 0;
   virtual void ToggleCardboardGamepad(bool enabled) = 0;
-  virtual void OnAssetsLoaded(vr::AssetsLoadStatus status,
-                              const base::Version& component_version) = 0;
 };
 
 }  // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/mailbox_to_surface_bridge.cc b/chrome/browser/android/vr_shell/mailbox_to_surface_bridge.cc
index 5cb7d97..7d00e6bc 100644
--- a/chrome/browser/android/vr_shell/mailbox_to_surface_bridge.cc
+++ b/chrome/browser/android/vr_shell/mailbox_to_surface_bridge.cc
@@ -211,7 +211,7 @@
             // See GetCompositorContextAttributes in
             // content/browser/renderer_host/compositor_impl_android.cc
             // and crbug.com/699330.
-            gpu::gles2::ContextCreationAttribHelper attributes;
+            gpu::ContextCreationAttribs attributes;
             attributes.alpha_size = -1;
             attributes.red_size = 8;
             attributes.green_size = 8;
diff --git a/chrome/browser/android/vr_shell/vr_gl_thread.cc b/chrome/browser/android/vr_shell/vr_gl_thread.cc
index 8195c83..61cbc66 100644
--- a/chrome/browser/android/vr_shell/vr_gl_thread.cc
+++ b/chrome/browser/android/vr_shell/vr_gl_thread.cc
@@ -10,6 +10,7 @@
 #include "base/version.h"
 #include "chrome/browser/android/vr_shell/vr_shell.h"
 #include "chrome/browser/android/vr_shell/vr_shell_gl.h"
+#include "chrome/browser/vr/assets.h"
 #include "chrome/browser/vr/browser_ui_interface.h"
 #include "chrome/browser/vr/model/omnibox_suggestions.h"
 #include "chrome/browser/vr/model/toolbar_state.h"
@@ -67,9 +68,14 @@
     }
   }
 
+  if (ui_initial_state_.assets_available) {
+    vr::Assets::GetInstance()->Load(
+        base::BindOnce(&VrGLThread::OnAssetsLoaded, base::Unretained(this)));
+  }
+
   vr_shell_gl_ = base::MakeUnique<VrShellGl>(
       this, std::move(ui), gvr_api_, reprojected_rendering_, daydream_support_,
-      ui_initial_state_.in_web_vr, ui_initial_state_.assets_available);
+      ui_initial_state_.in_web_vr);
 
   browser_ui_ = vr_shell_gl_->GetBrowserUiWeakPtr();
 
@@ -161,14 +167,6 @@
       base::Bind(&VrShell::ToggleCardboardGamepad, weak_vr_shell_, enabled));
 }
 
-void VrGLThread::OnAssetsLoaded(vr::AssetsLoadStatus status,
-                                const base::Version& component_version) {
-  DCHECK(OnGlThread());
-  main_thread_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&VrShell::OnAssetsLoaded, weak_vr_shell_, status,
-                            component_version));
-}
-
 void VrGLThread::OnUnsupportedMode(vr::UiUnsupportedMode mode) {
   DCHECK(OnGlThread());
   main_thread_task_runner_->PostTask(
@@ -349,4 +347,19 @@
   return task_runner()->BelongsToCurrentThread();
 }
 
+void VrGLThread::OnAssetsLoaded(vr::AssetsLoadStatus status,
+                                std::unique_ptr<SkBitmap> background_image,
+                                const base::Version& component_version) {
+  if (status == vr::AssetsLoadStatus::kSuccess) {
+    VLOG(1) << "Successfully loaded VR assets component";
+    vr_shell_gl_->OnAssetsLoaded(std::move(background_image),
+                                 component_version);
+  } else {
+    VLOG(1) << "Failed to load VR assets component";
+  }
+  main_thread_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&VrShell::OnAssetsLoaded, weak_vr_shell_,
+                                status, component_version));
+}
+
 }  // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/vr_gl_thread.h b/chrome/browser/android/vr_shell/vr_gl_thread.h
index 908280a..6fd7daa8 100644
--- a/chrome/browser/android/vr_shell/vr_gl_thread.h
+++ b/chrome/browser/android/vr_shell/vr_gl_thread.h
@@ -20,6 +20,10 @@
 #include "chrome/browser/vr/ui_browser_interface.h"
 #include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h"
 
+namespace base {
+class Version;
+}  // namespace base
+
 namespace vr_shell {
 
 class VrShell;
@@ -50,8 +54,6 @@
   void ForceExitVr() override;
   void OnContentPaused(bool enabled) override;
   void ToggleCardboardGamepad(bool enabled) override;
-  void OnAssetsLoaded(vr::AssetsLoadStatus status,
-                      const base::Version& component_version) override;
 
   // vr::ContentInputForwarder
   void ForwardEvent(std::unique_ptr<blink::WebInputEvent> event,
@@ -101,6 +103,10 @@
   bool OnMainThread() const;
   bool OnGlThread() const;
 
+  void OnAssetsLoaded(vr::AssetsLoadStatus status,
+                      std::unique_ptr<SkBitmap> background_image,
+                      const base::Version& component_version);
+
   // Created on GL thread.
   std::unique_ptr<VrShellGl> vr_shell_gl_;
   std::unique_ptr<GvrKeyboardDelegate> keyboard_delegate_;
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.cc b/chrome/browser/android/vr_shell/vr_shell_gl.cc
index 7cdb0b0..d9206b3 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.cc
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.cc
@@ -52,9 +52,7 @@
 
 namespace {
 static constexpr float kZNear = 0.1f;
-// This should be kept fairly small with current reticle rendering technique
-// which requires fairly high precision to draw on top of elements correctly.
-static constexpr float kZFar = 100.0f;
+static constexpr float kZFar = 10000.0f;
 
 // GVR buffer indices for use with viewport->SetSourceBufferIndex
 // or frame.BindBuffer. We use one for world content (with reprojection)
@@ -162,8 +160,7 @@
                      gvr_context* gvr_api,
                      bool reprojected_rendering,
                      bool daydream_support,
-                     bool start_in_web_vr_mode,
-                     bool assets_available)
+                     bool start_in_web_vr_mode)
     : ui_(std::move(ui)),
       web_vr_mode_(start_in_web_vr_mode),
       surfaceless_rendering_(reprojected_rendering),
@@ -177,7 +174,6 @@
       webvr_js_wait_time_(kWebVRSlidingAverageSize),
       webvr_acquire_time_(kWebVRSlidingAverageSize),
       webvr_submit_time_(kWebVRSlidingAverageSize),
-      assets_available_(assets_available),
       weak_ptr_factory_(this) {
   GvrInit(gvr_api);
 }
@@ -255,11 +251,6 @@
   ui_->OnGlInitialized(content_texture_id,
                        vr::UiElementRenderer::kTextureLocationExternal, true);
 
-  if (assets_available_) {
-    vr::Assets::GetInstance()->Load(base::BindOnce(
-        &VrShellGl::OnAssetsLoaded, weak_ptr_factory_.GetWeakPtr()));
-  }
-
   webvr_vsync_align_ = base::FeatureList::IsEnabled(features::kWebVrVsyncAlign);
 
   if (daydream_support_ && !reinitializing) {
@@ -395,6 +386,11 @@
   ui_->OnSwapContents(new_content_id);
 }
 
+void VrShellGl::OnAssetsLoaded(std::unique_ptr<SkBitmap> background_image,
+                               const base::Version& component_version) {
+  ui_->SetBackgroundImage(std::move(background_image));
+}
+
 void VrShellGl::OnContentFrameAvailable() {
   content_surface_texture_->UpdateTexImage();
   content_frame_available_ = true;
@@ -908,7 +904,7 @@
 
   std::vector<const vr::UiElement*> overlay_elements;
   if (ShouldDrawWebVr()) {
-    overlay_elements = ui_->scene()->GetVisibleWebVrOverlayForegroundElements();
+    overlay_elements = ui_->scene()->GetVisibleWebVrOverlayElementsToDraw();
   }
 
   if (!overlay_elements.empty() && ShouldDrawWebVr()) {
@@ -1300,16 +1296,4 @@
   binding_.Close();
 }
 
-void VrShellGl::OnAssetsLoaded(vr::AssetsLoadStatus status,
-                               std::unique_ptr<SkBitmap> background_image,
-                               const base::Version& component_version) {
-  // TODO(793407): Handle adding background image to UI.
-  if (status == vr::AssetsLoadStatus::kSuccess) {
-    VLOG(1) << "Successfully loaded VR assets component";
-  } else {
-    VLOG(1) << "Failed to load VR assets component";
-  }
-  browser_->OnAssetsLoaded(status, component_version);
-}
-
 }  // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/vr_shell_gl.h b/chrome/browser/android/vr_shell/vr_shell_gl.h
index b772e7f..441b0f0e 100644
--- a/chrome/browser/android/vr_shell/vr_shell_gl.h
+++ b/chrome/browser/android/vr_shell/vr_shell_gl.h
@@ -83,8 +83,7 @@
             gvr_context* gvr_api,
             bool reprojected_rendering,
             bool daydream_support,
-            bool start_in_web_vr_mode,
-            bool assets_available);
+            bool start_in_web_vr_mode);
   ~VrShellGl() override;
 
   void Initialize();
@@ -121,6 +120,9 @@
 
   void OnSwapContents(int new_content_id);
 
+  void OnAssetsLoaded(std::unique_ptr<SkBitmap> background_image,
+                      const base::Version& component_version);
+
  private:
   void GvrInit(gvr_context* gvr_api);
   void InitializeRenderer();
@@ -179,10 +181,6 @@
 
   void ClosePresentationBindings();
 
-  void OnAssetsLoaded(vr::AssetsLoadStatus status,
-                      std::unique_ptr<SkBitmap> background_image,
-                      const base::Version& component_version);
-
   // samplerExternalOES texture data for WebVR content image.
   int webvr_texture_id_ = 0;
 
@@ -293,8 +291,6 @@
 
   vr::ControllerModel controller_model_;
 
-  bool assets_available_;
-
   base::WeakPtrFactory<VrShellGl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(VrShellGl);
diff --git a/chrome/browser/browsing_data/history_counter_browsertest.cc b/chrome/browser/browsing_data/history_counter_browsertest.cc
index dfe8a5c1..4012b6aa 100644
--- a/chrome/browser/browsing_data/history_counter_browsertest.cc
+++ b/chrome/browser/browsing_data/history_counter_browsertest.cc
@@ -9,8 +9,6 @@
 #include "base/run_loop.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/web_history_service_factory.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -21,8 +19,6 @@
 #include "components/history/core/browser/web_history_service.h"
 #include "components/history/core/test/fake_web_history_service.h"
 #include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_manager.h"
 #include "net/http/http_status_code.h"
 #include "url/gurl.h"
 
@@ -41,8 +37,6 @@
     history_service_ = HistoryServiceFactory::GetForProfileWithoutCreating(
         browser()->profile());
     fake_web_history_service_.reset(new history::FakeWebHistoryService(
-        ProfileOAuth2TokenServiceFactory::GetForProfile(browser()->profile()),
-        SigninManagerFactory::GetForProfile(browser()->profile()),
         browser()->profile()->GetRequestContext()));
 
     SetHistoryDeletionPref(true);
diff --git a/chrome/browser/browsing_data/sync_aware_counter_browsertest.cc b/chrome/browser/browsing_data/sync_aware_counter_browsertest.cc
index 8bef2550..dce4f2a2 100644
--- a/chrome/browser/browsing_data/sync_aware_counter_browsertest.cc
+++ b/chrome/browser/browsing_data/sync_aware_counter_browsertest.cc
@@ -9,8 +9,6 @@
 #include "chrome/browser/history/web_history_service_factory.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/web_data_service_factory.h"
@@ -25,8 +23,6 @@
 #include "components/history/core/browser/web_history_service.h"
 #include "components/history/core/test/fake_web_history_service.h"
 #include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_manager.h"
 #include "content/public/browser/browser_thread.h"
 
 using browsing_data::BrowsingDataCounter;
@@ -41,8 +37,6 @@
 
   void SetUpOnMainThread() override {
     fake_web_history_service_.reset(new history::FakeWebHistoryService(
-        ProfileOAuth2TokenServiceFactory::GetForProfile(browser()->profile()),
-        SigninManagerFactory::GetForProfile(browser()->profile()),
         browser()->profile()->GetRequestContext()));
     run_loop_.reset(new base::RunLoop());
   }
diff --git a/chrome/browser/chrome_content_renderer_manifest_overlay.json b/chrome/browser/chrome_content_renderer_manifest_overlay.json
index a5ed336..2ef0ce1 100644
--- a/chrome/browser/chrome_content_renderer_manifest_overlay.json
+++ b/chrome/browser/chrome_content_renderer_manifest_overlay.json
@@ -23,8 +23,8 @@
           "blink::mojom::document_metadata::CopylessPaste",
           "chrome::mojom::InsecureContentRenderer",
           "chrome::mojom::ChromeRenderFrame",
-          "contextual_search::mojom::OverlayPageNotifierService",
           "dom_distiller::mojom::DistillerPageNotifierService",
+          "extensions::mojom::AppWindow",
           "spellcheck::mojom::SpellCheckPanel"
         ]
       }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 2f2c6c5..1f84895 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1989,6 +1989,7 @@
     "../ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc",
     "../ui/webui/settings/chromeos/device_power_handler_unittest.cc",
     "../ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc",
+    "../ui/webui/settings/chromeos/internet_handler_unittest.cc",
     "//components/drive/change_list_loader_unittest.cc",
     "//components/drive/change_list_processor_unittest.cc",
     "//components/drive/chromeos/file_cache_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 21c702e..2d0caa3 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -286,7 +286,8 @@
                               content::NotificationService::AllSources());
   notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
                               content::NotificationService::AllSources());
-
+  notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
+                              content::NotificationService::AllSources());
   input_method::InputMethodManager::Get()->AddObserver(this);
   session_manager::SessionManager::Get()->AddObserver(this);
 
@@ -1400,6 +1401,10 @@
         SetProfile(NULL);
       break;
     }
+    case chrome::NOTIFICATION_APP_TERMINATING: {
+      chromevox_panel_ = nullptr;
+      break;
+    }
   }
 }
 
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
index 41c09543..16e43c7 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/syslog_logging.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -25,7 +25,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "components/crx_file/id_util.h"
 #include "components/session_manager/core/session_manager.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/constants.h"
@@ -36,7 +35,6 @@
 #include "extensions/common/manifest_url_handlers.h"
 #include "net/base/load_flags.h"
 
-using content::BrowserThread;
 using extensions::Extension;
 
 namespace chromeos {
@@ -55,20 +53,15 @@
       app_id_(app_id),
       diagnostic_mode_(diagnostic_mode),
       delegate_(delegate),
+      kiosk_app_manager_observer_(this),
+      install_observer_(this),
       weak_ptr_factory_(this) {
   DCHECK(profile_);
   DCHECK(crx_file::id_util::IdIsValid(app_id_));
-  KioskAppManager::Get()->AddObserver(this);
+  kiosk_app_manager_observer_.Add(KioskAppManager::Get());
 }
 
-StartupAppLauncher::~StartupAppLauncher() {
-  KioskAppManager::Get()->RemoveObserver(this);
-
-  // StartupAppLauncher can be deleted at anytime during the launch process
-  // through a user bailout shortcut.
-  extensions::InstallTrackerFactory::GetForBrowserContext(profile_)
-      ->RemoveObserver(this);
-}
+StartupAppLauncher::~StartupAppLauncher() = default;
 
 void StartupAppLauncher::Initialize() {
   MaybeInitializeNetwork();
@@ -158,16 +151,15 @@
   // If the app is not offline enabled, make sure the network is ready before
   // launching.
   if (offline_enabled || delegate_->IsNetworkReady()) {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::BindOnce(&StartupAppLauncher::OnReadyToLaunch,
-                                           weak_ptr_factory_.GetWeakPtr()));
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(&StartupAppLauncher::OnReadyToLaunch,
+                                  weak_ptr_factory_.GetWeakPtr()));
   } else {
     ++launch_attempt_;
     if (launch_attempt_ < kMaxLaunchAttempt) {
-      BrowserThread::PostTask(
-          BrowserThread::UI, FROM_HERE,
-          base::BindOnce(&StartupAppLauncher::MaybeInitializeNetwork,
-                         weak_ptr_factory_.GetWeakPtr()));
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(&StartupAppLauncher::MaybeInitializeNetwork,
+                                    weak_ptr_factory_.GetWeakPtr()));
       return;
     }
     OnLaunchFailure(KioskAppLaunchError::UNABLE_TO_LAUNCH);
@@ -244,9 +236,7 @@
     return;
   }
 
-  extensions::InstallTracker* tracker =
-      extensions::InstallTrackerFactory::GetForBrowserContext(profile_);
-  tracker->RemoveObserver(this);
+  install_observer_.RemoveAll();
   if (delegate_->IsShowingNetworkConfigScreen()) {
     SYSLOG(WARNING) << "Showing network config screen";
     return;
@@ -424,9 +414,8 @@
           ->IsIdPending(app_id_)) {
     delegate_->OnInstallingApp();
     // Observe the crx installation events.
-    extensions::InstallTracker* tracker =
-        extensions::InstallTrackerFactory::GetForBrowserContext(profile_);
-    tracker->AddObserver(this);
+    install_observer_.Add(
+        extensions::InstallTrackerFactory::GetForBrowserContext(profile_));
     return;
   }
 
@@ -463,9 +452,8 @@
   if (IsAnySecondaryAppPending()) {
     delegate_->OnInstallingApp();
     // Observe the crx installation events.
-    extensions::InstallTracker* tracker =
-        extensions::InstallTrackerFactory::GetForBrowserContext(profile_);
-    tracker->AddObserver(this);
+    install_observer_.Add(
+        extensions::InstallTrackerFactory::GetForBrowserContext(profile_));
     return;
   }
 
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.h b/chrome/browser/chromeos/app_mode/startup_app_launcher.h
index 3f55a54..a01f1d3 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.h
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_launch_error.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
 #include "chrome/browser/extensions/install_observer.h"
@@ -18,8 +19,14 @@
 
 class Profile;
 
+namespace extensions {
+class InstallTracker;
+}
+
 namespace chromeos {
 
+class KioskAppManager;
+
 // Launches the app at startup. The flow roughly looks like this:
 // First call Initialize():
 // - Initialize network if app is not installed or not offline_enabled.
@@ -135,6 +142,12 @@
 
   content::NotificationRegistrar registrar_;
 
+  ScopedObserver<KioskAppManager, KioskAppManagerObserver>
+      kiosk_app_manager_observer_;
+
+  ScopedObserver<extensions::InstallTracker, extensions::InstallObserver>
+      install_observer_;
+
   base::WeakPtrFactory<StartupAppLauncher> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(StartupAppLauncher);
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
index 0a9b901..b6397db4 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
@@ -36,6 +36,8 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
+#include "chrome/browser/ui/ash/test_wallpaper_controller.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -178,11 +180,16 @@
 
     ASSERT_FALSE(arc_session_manager_->enable_requested());
     chromeos::WallpaperManager::Initialize();
+    wallpaper_controller_client_ =
+        std::make_unique<WallpaperControllerClient>();
+    wallpaper_controller_client_->InitForTesting(
+        test_wallpaper_controller_.CreateInterfacePtr());
   }
 
   void TearDown() override {
     chromeos::WallpaperManager::Shutdown();
     arc_session_manager_->Shutdown();
+    wallpaper_controller_client_.reset();
     profile_.reset();
     arc_session_manager_.reset();
     arc_service_manager_.reset();
@@ -229,6 +236,8 @@
   std::unique_ptr<ArcSessionManager> arc_session_manager_;
   user_manager::ScopedUserManager user_manager_enabler_;
   base::ScopedTempDir temp_dir_;
+  std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_;
+  TestWallpaperController test_wallpaper_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcSessionManagerTestBase);
 };
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc
index bc0086f..3431fd0 100644
--- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service_unittest.cc
@@ -177,8 +177,6 @@
   std::vector<uint8_t> bytes;
   service_->SetWallpaper(bytes, 10 /* ID */);
   content::RunAllTasksUntilIdle();
-  // Wait until wallpaper loading is done.
-  chromeos::wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   ASSERT_EQ(1u, wallpaper_instance_->changed_ids().size());
   EXPECT_EQ(10, wallpaper_instance_->changed_ids()[0]);
 
@@ -197,8 +195,6 @@
   std::vector<uint8_t> bytes;
   service_->SetWallpaper(bytes, 10 /* ID */);
   content::RunAllTasksUntilIdle();
-  // Wait until wallpaper loading is done.
-  chromeos::wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
 
   // For failure case, ArcWallpaperService reports that wallpaper is changed to
   // requested wallpaper (ID=10), then reports that the wallpaper is changed
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
index fe52d25b..3706db4 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -523,7 +523,7 @@
 }
 
 void FileManagerPrivateGetSizeStatsFunction::OnGetMtpAvailableSpace(
-    const MtpStorageInfo& mtp_storage_info,
+    const device::mojom::MtpStorageInfo& mtp_storage_info,
     const bool error) {
   if (error) {
     // If stats couldn't be gotten from MTP volume, result should be left
@@ -532,8 +532,8 @@
     return;
   }
 
-  const uint64_t max_capacity = mtp_storage_info.max_capacity();
-  const uint64_t free_space_in_bytes = mtp_storage_info.free_space_in_bytes();
+  const uint64_t max_capacity = mtp_storage_info.max_capacity;
+  const uint64_t free_space_in_bytes = mtp_storage_info.free_space_in_bytes;
   OnGetSizeStats(&max_capacity, &free_space_in_bytes);
 }
 
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
index 2401661..dbdfc25 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
@@ -22,7 +22,7 @@
 #include "chrome/browser/extensions/chrome_extension_function.h"
 #include "chrome/browser/extensions/chrome_extension_function_details.h"
 #include "components/drive/file_errors.h"
-#include "device/media_transfer_protocol/mtp_storage_info.pb.h"
+#include "device/media_transfer_protocol/public/interfaces/mtp_storage_info.mojom.h"
 #include "extensions/browser/extension_function.h"
 #include "storage/browser/fileapi/file_system_url.h"
 
@@ -185,8 +185,9 @@
                                 int64_t bytes_total,
                                 int64_t bytes_used);
 
-  void OnGetMtpAvailableSpace(const MtpStorageInfo& mtp_storage_info,
-                              const bool error);
+  void OnGetMtpAvailableSpace(
+      const device::mojom::MtpStorageInfo& mtp_storage_info,
+      const bool error);
 
   void OnGetSizeStats(const uint64_t* total_size,
                       const uint64_t* remaining_size);
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
index a2498dab..7c4d29e 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -289,7 +289,8 @@
   if (params->layout != wallpaper_base::WALLPAPER_LAYOUT_STRETCH &&
       resolution == ash::WallpaperController::WALLPAPER_RESOLUTION_SMALL) {
     file_name = base::FilePath(file_name)
-                    .InsertBeforeExtension(chromeos::kSmallWallpaperSuffix)
+                    .InsertBeforeExtension(
+                        ash::WallpaperController::kSmallWallpaperSuffix)
                     .value();
   }
   wallpaper_path = wallpaper_path.Append(file_name);
@@ -411,7 +412,7 @@
     CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir));
     base::FilePath file_path =
         wallpaper_dir.Append(file_name).InsertBeforeExtension(
-            chromeos::kSmallWallpaperSuffix);
+            ash::WallpaperController::kSmallWallpaperSuffix);
     if (base::PathExists(file_path))
       return;
     // Generates and saves small resolution wallpaper. Uses CENTER_CROPPED to
@@ -784,7 +785,8 @@
          current = files.Next()) {
       std::string file_name = current.BaseName().RemoveExtension().value();
       // Do not add file name of small resolution wallpaper to the list.
-      if (!base::EndsWith(file_name, chromeos::kSmallWallpaperSuffix,
+      if (!base::EndsWith(file_name,
+                          ash::WallpaperController::kSmallWallpaperSuffix,
                           base::CompareCase::SENSITIVE))
         file_list.push_back(current.BaseName().value());
     }
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
index b16ce42b..91db9dc 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
@@ -15,6 +15,8 @@
 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
+#include "chrome/browser/ui/ash/test_wallpaper_controller.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "extensions/browser/api_test_utils.h"
@@ -184,6 +186,8 @@
 
  private:
   MultiUserWindowManagerChromeOS* multi_user_window_manager_;
+  std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_;
+  TestWallpaperController test_wallpaper_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(WallpaperPrivateApiMultiUserUnittest);
 };
@@ -191,6 +195,9 @@
 void WallpaperPrivateApiMultiUserUnittest::SetUp() {
   AshTestBase::SetUp();
   WallpaperManager::Initialize();
+  wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>();
+  wallpaper_controller_client_->InitForTesting(
+      test_wallpaper_controller_.CreateInterfacePtr());
   fake_user_manager()->AddUser(test_account_id1_);
   fake_user_manager()->AddUser(test_account_id2_);
 }
@@ -199,6 +206,7 @@
   MultiUserWindowManager::DeleteInstance();
   AshTestBase::TearDown();
   WallpaperManager::Shutdown();
+  wallpaper_controller_client_.reset();
 }
 
 void WallpaperPrivateApiMultiUserUnittest::SetUpMultiUserWindowManager(
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc
index 6f0c1dc..d63f0e0b 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -866,7 +866,7 @@
   base::RemoveChars(info.location(), kRootPath, &storage_name);
   DCHECK(!storage_name.empty());
 
-  const MtpStorageInfo* mtp_storage_info;
+  const device::mojom::MtpStorageInfo* mtp_storage_info;
   if (get_mtp_storage_info_callback_.is_null()) {
     mtp_storage_info = storage_monitor::StorageMonitor::GetInstance()
                            ->media_transfer_protocol_manager()
@@ -889,8 +889,8 @@
   const bool read_only =
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           chromeos::switches::kDisableMtpWriteSupport) ||
-      mtp_storage_info->access_capability() != kAccessCapabilityReadWrite ||
-      mtp_storage_info->filesystem_type() !=
+      mtp_storage_info->access_capability != kAccessCapabilityReadWrite ||
+      mtp_storage_info->filesystem_type !=
           kFilesystemTypeGenericHierarchical ||
       GetExternalStorageAccessMode(profile_) ==
           chromeos::MOUNT_ACCESS_MODE_READ_ONLY;
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.h b/chrome/browser/chromeos/file_manager/volume_manager.h
index d99a2435d..a3204e9 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.h
+++ b/chrome/browser/chromeos/file_manager/volume_manager.h
@@ -26,7 +26,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/storage_monitor/removable_storage_observer.h"
-#include "device/media_transfer_protocol/mtp_storage_info.pb.h"
+#include "device/media_transfer_protocol/public/interfaces/mtp_storage_info.mojom.h"
 
 class Profile;
 
@@ -232,7 +232,8 @@
  public:
   // Returns MediaTransferProtocolManager. Used for injecting
   // FakeMediaTransferProtocolManager for testing.
-  typedef base::Callback<const MtpStorageInfo*(const std::string&)>
+  typedef base::Callback<const device::mojom::MtpStorageInfo*(
+      const std::string&)>
       GetMtpStorageInfoCallback;
 
   VolumeManager(
diff --git a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
index 8d05fb7..924e7e28 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
@@ -27,7 +27,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/storage_monitor/storage_info.h"
 #include "content/public/test/test_browser_thread_bundle.h"
-#include "device/media_transfer_protocol/mtp_storage_info.pb.h"
 #include "extensions/browser/extension_registry.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -189,7 +188,7 @@
     VolumeManager* volume_manager() const { return volume_manager_.get(); }
 
    private:
-    const MtpStorageInfo* GetFakeMtpStorageInfo(
+    const device::mojom::MtpStorageInfo* GetFakeMtpStorageInfo(
         const std::string& /*storage_name*/) {
       return &fake_mtp_storage_info_;
     }
@@ -199,7 +198,7 @@
     std::unique_ptr<chromeos::file_system_provider::Service>
         file_system_provider_service_;
     std::unique_ptr<VolumeManager> volume_manager_;
-    const MtpStorageInfo fake_mtp_storage_info_;
+    const device::mojom::MtpStorageInfo fake_mtp_storage_info_;
   };
 
   void SetUp() override {
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
index 3856f7a0..8e9c9a60 100644
--- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
@@ -79,23 +79,6 @@
 
 WallpaperManager* wallpaper_manager = nullptr;
 
-// The directory and file name to save the downloaded device policy controlled
-// wallpaper.
-const char kDeviceWallpaperDir[] = "device_wallpaper";
-const char kDeviceWallpaperFile[] = "device_wallpaper_image.jpg";
-
-// Maximum number of entries in WallpaperManager::last_load_times_ .
-const size_t kLastLoadsStatsMsMaxSize = 4;
-
-// Minimum delay between wallpaper loads, milliseconds.
-const unsigned kLoadMinDelayMs = 50;
-
-// Default wallpaper load delay, milliseconds.
-const unsigned kLoadDefaultDelayMs = 200;
-
-// Maximum wallpaper load delay, milliseconds.
-const unsigned kLoadMaxDelayMs = 2000;
-
 // The Wallpaper App that the user is using right now on Chrome OS. It's the
 // app that is used when the user right clicks on desktop and selects "Set
 // wallpaper" or when the user selects "Set wallpaper" from chrome://settings
@@ -207,161 +190,6 @@
 
 const char kWallpaperSequenceTokenName[] = "wallpaper-sequence";
 
-const char kSmallWallpaperSuffix[] = "_small";
-const char kLargeWallpaperSuffix[] = "_large";
-
-// This is "wallpaper either scheduled to load, or loading right now".
-//
-// While enqueued, it defines moment in the future, when it will be loaded.
-// Enqueued but not started request might be updated by subsequent load
-// request. Therefore it's created empty, and updated being enqueued.
-//
-// PendingWallpaper is owned by WallpaperManager.
-class WallpaperManager::PendingWallpaper {
- public:
-  explicit PendingWallpaper(const base::TimeDelta delay) : weak_factory_(this) {
-    timer.Start(FROM_HERE, delay,
-                base::Bind(&WallpaperManager::PendingWallpaper::ProcessRequest,
-                           weak_factory_.GetWeakPtr()));
-  }
-
-  ~PendingWallpaper() { weak_factory_.InvalidateWeakPtrs(); }
-
-  // There are four cases:
-  // 1) gfx::ImageSkia is found in cache.
-  void SetWallpaperFromImage(const AccountId& account_id,
-                             const gfx::ImageSkia& image,
-                             const wallpaper::WallpaperInfo& info) {
-    SetMode(account_id, image, info, base::FilePath(), false);
-  }
-
-  // 2) WallpaperInfo is found in cache.
-  void SetWallpaperFromInfo(const AccountId& account_id,
-                            const wallpaper::WallpaperInfo& info) {
-    SetMode(account_id, gfx::ImageSkia(), info, base::FilePath(), false);
-  }
-
-  // 3) Wallpaper path is not null.
-  void SetWallpaperFromPath(const AccountId& account_id,
-                            const wallpaper::WallpaperInfo& info,
-                            const base::FilePath& wallpaper_path) {
-    SetMode(account_id, gfx::ImageSkia(), info, wallpaper_path, false);
-  }
-
-  // 4) Set default wallpaper (either on some error, or when user is new).
-  void SetDefaultWallpaper(const AccountId& account_id) {
-    SetMode(account_id, gfx::ImageSkia(), WallpaperInfo(), base::FilePath(),
-            true);
-  }
-
- private:
-  // All methods use SetMode() to set object to new state.
-  void SetMode(const AccountId& account_id,
-               const gfx::ImageSkia& image,
-               const wallpaper::WallpaperInfo& info,
-               const base::FilePath& wallpaper_path,
-               const bool is_default) {
-    account_id_ = account_id;
-    user_wallpaper_ = image;
-    info_ = info;
-    wallpaper_path_ = wallpaper_path;
-    default_ = is_default;
-  }
-
-  // This method is usually triggered by timer to actually load request.
-  void ProcessRequest() {
-    // The only known case for this check to fail is global destruction during
-    // wallpaper load. It should never happen.
-    if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
-      return;
-
-    // Erase reference to self.
-    timer.Stop();
-
-    WallpaperManager* manager = WallpaperManager::Get();
-    if (manager->pending_inactive_ == this)
-      manager->pending_inactive_ = NULL;
-
-    // This is "on destroy" callback that will call OnWallpaperSet() when
-    // image is loaded.
-    MovableOnDestroyCallbackHolder on_finish =
-        std::make_unique<ash::WallpaperController::MovableOnDestroyCallback>(
-            base::Bind(&WallpaperManager::PendingWallpaper::OnWallpaperSet,
-                       weak_factory_.GetWeakPtr()));
-
-    started_load_at_ = base::Time::Now();
-
-    if (default_) {
-      // The most recent request is |SetDefaultWallpaper|.
-      manager->SetDefaultWallpaperImpl(account_id_, true /* update_wallpaper */,
-                                       std::move(on_finish));
-    } else if (!user_wallpaper_.isNull()) {
-      // The most recent request is |SetWallpaperFromImage|.
-      SetWallpaper(user_wallpaper_, info_);
-    } else if (!wallpaper_path_.empty()) {
-      // The most recent request is |SetWallpaperFromPath|.
-      manager->task_runner_->PostTask(
-          FROM_HERE,
-          base::BindOnce(&WallpaperManager::GetCustomWallpaperInternal,
-                         account_id_, info_, wallpaper_path_,
-                         true /* update wallpaper */,
-                         base::ThreadTaskRunnerHandle::Get(),
-                         base::Passed(std::move(on_finish)),
-                         manager->weak_factory_.GetWeakPtr()));
-    } else if (!info_.location.empty()) {
-      // The most recent request is |SetWallpaperFromInfo|.
-      manager->LoadWallpaper(account_id_, info_, true /* update_wallpaper */,
-                             std::move(on_finish));
-    } else {
-      // PendingWallpaper was created but none of the four methods was called.
-      // This should never happen. Do not record time in this case.
-      NOTREACHED();
-      started_load_at_ = base::Time();
-    }
-  }
-
-  // This method is called by callback, when load request is finished.
-  void OnWallpaperSet() {
-    // The only known case for this check to fail is global destruction during
-    // wallpaper load. It should never happen.
-    if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
-      return;
-
-    // Erase reference to self.
-    timer.Stop();
-
-    WallpaperManager* manager = WallpaperManager::Get();
-    if (!started_load_at_.is_null()) {
-      const base::TimeDelta elapsed = base::Time::Now() - started_load_at_;
-      manager->SaveLastLoadTime(elapsed);
-    }
-    if (manager->pending_inactive_ == this) {
-      // ProcessRequest() was never executed.
-      manager->pending_inactive_ = NULL;
-    }
-
-    // Destroy self.
-    manager->RemovePendingWallpaperFromList(this);
-  }
-
-  AccountId account_id_;
-  wallpaper::WallpaperInfo info_;
-  gfx::ImageSkia user_wallpaper_;
-  base::FilePath wallpaper_path_;
-
-  // Load default wallpaper instead of user image.
-  bool default_;
-
-  base::OneShotTimer timer;
-
-  // Load start time to calculate duration.
-  base::Time started_load_at_;
-
-  base::WeakPtrFactory<PendingWallpaper> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(PendingWallpaper);
-};
-
 // CustomizedWallpaperRescaledFiles:
 const base::FilePath&
 WallpaperManager::CustomizedWallpaperRescaledFiles::path_downloaded() const {
@@ -455,9 +283,6 @@
   show_user_name_on_signin_subscription_.reset();
   device_wallpaper_image_subscription_.reset();
   weak_factory_.InvalidateWeakPtrs();
-  // In case there's wallpaper load request being processed.
-  for (size_t i = 0; i < loading_.size(); ++i)
-    delete loading_[i];
 }
 
 // static
@@ -496,10 +321,12 @@
   std::unique_ptr<CustomizedWallpaperRescaledFiles> rescaled_files(
       new CustomizedWallpaperRescaledFiles(
           file_path,
-          resized_directory.Append(downloaded_file_name +
-                                   kSmallWallpaperSuffix),
-          resized_directory.Append(downloaded_file_name +
-                                   kLargeWallpaperSuffix)));
+          resized_directory.Append(
+              downloaded_file_name +
+              ash::WallpaperController::kSmallWallpaperSuffix),
+          resized_directory.Append(
+              downloaded_file_name +
+              ash::WallpaperController::kLargeWallpaperSuffix)));
 
   base::Closure check_file_exists = rescaled_files->CreateCheckerClosure();
   base::Closure on_checked_closure =
@@ -535,83 +362,10 @@
       SetDeviceWallpaperIfApplicable(account_id))
     return;
 
-  // Guest user or regular user in ephemeral mode.
-  if ((user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral(
-           account_id) &&
-       user->HasGaiaAccount()) ||
-      user->GetType() == user_manager::USER_TYPE_GUEST) {
-    InitializeUserWallpaperInfo(account_id);
-    GetPendingWallpaper()->SetDefaultWallpaper(account_id);
-    if (base::SysInfo::IsRunningOnChromeOS()) {
-      LOG(ERROR)
-          << "User is ephemeral or guest! Fallback to default wallpaper.";
-    }
-    return;
-  }
-
-  last_selected_user_ = account_id;
-
-  WallpaperInfo info;
-
-  if (!GetUserWallpaperInfo(account_id, &info)) {
-    InitializeUserWallpaperInfo(account_id);
-    GetUserWallpaperInfo(account_id, &info);
-  }
-
-  gfx::ImageSkia user_wallpaper;
-  if (GetWallpaperFromCache(account_id, &user_wallpaper)) {
-    GetPendingWallpaper()->SetWallpaperFromImage(account_id, user_wallpaper,
-                                                 info);
-  } else {
-    if (info.location.empty()) {
-      // Uses default built-in wallpaper when file is empty. Eventually, we
-      // will only ship one built-in wallpaper in ChromeOS image.
-      GetPendingWallpaper()->SetDefaultWallpaper(account_id);
-      return;
-    }
-
-    if (info.type == wallpaper::CUSTOMIZED || info.type == wallpaper::POLICY ||
-        info.type == wallpaper::DEVICE) {
-      base::FilePath wallpaper_path;
-      if (info.type != wallpaper::DEVICE) {
-        const char* sub_dir = GetCustomWallpaperSubdirForCurrentResolution();
-        // Wallpaper is not resized when layout is
-        // wallpaper::WALLPAPER_LAYOUT_CENTER.
-        // Original wallpaper should be used in this case.
-        // TODO(bshe): Generates cropped custom wallpaper for CENTER layout.
-        if (info.layout == wallpaper::WALLPAPER_LAYOUT_CENTER)
-          sub_dir = ash::WallpaperController::kOriginalWallpaperSubDir;
-        wallpaper_path =
-            ash::WallpaperController::GetCustomWallpaperDir(sub_dir);
-        wallpaper_path = wallpaper_path.Append(info.location);
-      } else {
-        wallpaper_path = GetDeviceWallpaperFilePath();
-      }
-
-      ash::CustomWallpaperMap* wallpaper_cache_map = GetWallpaperCacheMap();
-      ash::CustomWallpaperMap::iterator it =
-          wallpaper_cache_map->find(account_id);
-      // Do not try to load the wallpaper if the path is the same. Since loading
-      // could still be in progress, we ignore the existence of the image.
-      if (it != wallpaper_cache_map->end() &&
-          it->second.first == wallpaper_path)
-        return;
-
-      // Set the new path and reset the existing image - the image will be
-      // added once it becomes available.
-      (*wallpaper_cache_map)[account_id] =
-          ash::CustomWallpaperElement(wallpaper_path, gfx::ImageSkia());
-      loaded_wallpapers_for_test_++;
-
-      GetPendingWallpaper()->SetWallpaperFromPath(account_id, info,
-                                                  wallpaper_path);
-      return;
-    }
-
-    // Load downloaded online or converted default wallpapers according to the
-    // WallpaperInfo.
-    GetPendingWallpaper()->SetWallpaperFromInfo(account_id, info);
-  }
+  // TODO(crbug.com/776464): Move the above to
+  // |WallpaperController::ShowUserWallpaper| after
+  // |SetDeviceWallpaperIfApplicable| is migrated.
+  WallpaperControllerClient::Get()->ShowUserWallpaper(account_id);
 }
 
 void WallpaperManager::ShowSigninWallpaper() {
@@ -640,9 +394,11 @@
   // Apply device customization.
   if (ShouldUseCustomizedDefaultWallpaper()) {
     SetCustomizedDefaultWallpaperImpl(
-        GetCustomizedWallpaperDefaultRescaledFileName(kSmallWallpaperSuffix),
+        GetCustomizedWallpaperDefaultRescaledFileName(
+            ash::WallpaperController::kSmallWallpaperSuffix),
         std::unique_ptr<gfx::ImageSkia>(),
-        GetCustomizedWallpaperDefaultRescaledFileName(kLargeWallpaperSuffix),
+        GetCustomizedWallpaperDefaultRescaledFileName(
+            ash::WallpaperController::kLargeWallpaperSuffix),
         std::unique_ptr<gfx::ImageSkia>());
   }
 
@@ -681,14 +437,15 @@
   if (clear_cache)
     GetWallpaperCacheMap()->clear();
 
-  // For GAIA login flow, the last_selected_user_ may not be set before user
-  // login. If UpdateWallpaper is called at GAIA login screen, no wallpaper will
-  // be set. It could result a black screen on external monitors.
+  // For GAIA login flow, |current_user_| may not be set before user login. If
+  // UpdateWallpaper is called at GAIA login screen, no wallpaper will be set.
+  // It could result a black screen on external monitors.
   // See http://crbug.com/265689 for detail.
-  if (last_selected_user_.empty())
+  AccountId current_user_account_id = GetCurrentUserAccountId();
+  if (current_user_account_id.empty())
     ShowSigninWallpaper();
   else
-    ShowUserWallpaper(last_selected_user_);
+    ShowUserWallpaper(current_user_account_id);
 }
 
 bool WallpaperManager::GetLoggedInUserWallpaperInfo(WallpaperInfo* info) {
@@ -753,10 +510,6 @@
   }
 }
 
-size_t WallpaperManager::GetPendingListSizeForTesting() const {
-  return loading_.size();
-}
-
 bool WallpaperManager::IsPolicyControlled(const AccountId& account_id) const {
   if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) {
     // Some unit tests come here without a Shell instance.
@@ -776,7 +529,7 @@
   WallpaperInfo info;
   GetUserWallpaperInfo(account_id, &info);
   info.type = wallpaper::POLICY;
-  SetUserWallpaperInfo(account_id, info, true /* is_persistent */);
+  SetUserWallpaperInfo(account_id, info, true /*is_persistent=*/);
 }
 
 void WallpaperManager::OnPolicyCleared(const std::string& policy,
@@ -784,12 +537,13 @@
   WallpaperInfo info;
   GetUserWallpaperInfo(account_id, &info);
   info.type = wallpaper::DEFAULT;
-  SetUserWallpaperInfo(account_id, info, true /* is_persistent */);
+  SetUserWallpaperInfo(account_id, info, true /*is_persistent=*/);
 
   // If we're at the login screen, do not change the wallpaper but defer it
   // until the user logs in to the system.
-  if (user_manager::UserManager::Get()->IsUserLoggedIn())
-    GetPendingWallpaper()->SetDefaultWallpaper(account_id);
+  if (user_manager::UserManager::Get()->IsUserLoggedIn()) {
+    SetDefaultWallpaperImpl(account_id, true /*show_wallpaper=*/);
+  }
 }
 
 void WallpaperManager::AddObserver(WallpaperManager::Observer* observer) {
@@ -851,49 +605,6 @@
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
 }
 
-// static
-void WallpaperManager::GetCustomWallpaperInternal(
-    const AccountId& account_id,
-    const WallpaperInfo& info,
-    const base::FilePath& wallpaper_path,
-    bool update_wallpaper,
-    const scoped_refptr<base::SingleThreadTaskRunner>& reply_task_runner,
-    MovableOnDestroyCallbackHolder on_finish,
-    base::WeakPtr<WallpaperManager> weak_ptr) {
-  base::FilePath valid_path = wallpaper_path;
-  if (!base::PathExists(wallpaper_path)) {
-    // Falls back on original file if the correct resolution file does not
-    // exist. This may happen when the original custom wallpaper is small or
-    // browser shutdown before resized wallpaper saved.
-    valid_path = ash::WallpaperController::GetCustomWallpaperDir(
-        ash::WallpaperController::kOriginalWallpaperSubDir);
-    valid_path = valid_path.Append(info.location);
-  }
-
-  if (!base::PathExists(valid_path)) {
-    // Falls back to custom wallpaper that uses AccountId as part of its file
-    // path.
-    // Note that account id is used instead of wallpaper_files_id here.
-    const std::string& old_path = account_id.GetUserEmail();  // Migrated
-    valid_path = ash::WallpaperController::GetCustomWallpaperPath(
-        ash::WallpaperController::kOriginalWallpaperSubDir, old_path,
-        info.location);
-  }
-
-  if (!base::PathExists(valid_path)) {
-    reply_task_runner->PostTask(
-        FROM_HERE,
-        base::Bind(&WallpaperManager::OnCustomWallpaperFileNotFound, weak_ptr,
-                   account_id, wallpaper_path, update_wallpaper,
-                   base::Passed(std::move(on_finish))));
-  } else {
-    reply_task_runner->PostTask(
-        FROM_HERE, base::Bind(&WallpaperManager::StartLoad, weak_ptr,
-                              account_id, info, update_wallpaper, valid_path,
-                              base::Passed(std::move(on_finish))));
-  }
-}
-
 void WallpaperManager::ResizeCustomizedDefaultWallpaper(
     std::unique_ptr<gfx::ImageSkia> image,
     const CustomizedWallpaperRescaledFiles* rescaled_files,
@@ -941,7 +652,8 @@
     // directly. Otherwise download it first.
     base::PostTaskWithTraitsAndReplyWithResult(
         FROM_HERE, {base::MayBlock()},
-        base::Bind(&base::PathExists, GetDeviceWallpaperFilePath()),
+        base::Bind(&base::PathExists,
+                   ash::WallpaperController::GetDeviceWallpaperFilePath()),
         base::Bind(&WallpaperManager::OnDeviceWallpaperExists,
                    weak_factory_.GetWeakPtr(), account_id, url, hash));
     return true;
@@ -1016,78 +728,6 @@
   }
 }
 
-void WallpaperManager::LoadWallpaper(const AccountId& account_id,
-                                     const WallpaperInfo& info,
-                                     bool update_wallpaper,
-                                     MovableOnDestroyCallbackHolder on_finish) {
-  base::FilePath wallpaper_path;
-
-  // Do a sanity check that file path information is not empty.
-  if (info.type == wallpaper::ONLINE || info.type == wallpaper::DEFAULT) {
-    if (info.location.empty()) {
-      if (base::SysInfo::IsRunningOnChromeOS()) {
-        NOTREACHED() << "User wallpaper info appears to be broken: "
-                     << account_id.Serialize();
-      } else {
-        // Filename might be empty on debug configurations when stub users
-        // were created directly in Local State (for testing). Ignore such
-        // errors i.e. allowsuch type of debug configurations on the desktop.
-        LOG(WARNING) << "User wallpaper info is empty: "
-                     << account_id.Serialize();
-
-        // |on_finish| callback will get called on destruction.
-        return;
-      }
-    }
-  }
-
-  if (info.type == wallpaper::ONLINE) {
-    std::string file_name = GURL(info.location).ExtractFileName();
-    ash::WallpaperController::WallpaperResolution resolution =
-        ash::WallpaperController::GetAppropriateResolution();
-    // Only solid color wallpapers have stretch layout and they have only one
-    // resolution.
-    if (info.layout != wallpaper::WALLPAPER_LAYOUT_STRETCH &&
-        resolution == ash::WallpaperController::WALLPAPER_RESOLUTION_SMALL) {
-      file_name = base::FilePath(file_name)
-                      .InsertBeforeExtension(kSmallWallpaperSuffix)
-                      .value();
-    }
-    DCHECK(!ash::WallpaperController::dir_chrome_os_wallpapers_path_.empty());
-    wallpaper_path =
-        ash::WallpaperController::dir_chrome_os_wallpapers_path_.Append(
-            file_name);
-
-    // If the wallpaper exists and it contains already the correct image we can
-    // return immediately.
-    ash::CustomWallpaperMap* wallpaper_cache_map = GetWallpaperCacheMap();
-    ash::CustomWallpaperMap::iterator it =
-        wallpaper_cache_map->find(account_id);
-    if (it != wallpaper_cache_map->end() &&
-        it->second.first == wallpaper_path && !it->second.second.isNull())
-      return;
-
-    loaded_wallpapers_for_test_++;
-    StartLoad(account_id, info, update_wallpaper, wallpaper_path,
-              std::move(on_finish));
-  } else if (info.type == wallpaper::DEFAULT) {
-    // Default wallpapers are migrated from M21 user profiles. A code refactor
-    // overlooked that case and caused these wallpapers not being loaded at all.
-    // On some slow devices, it caused login webui not visible after upgrade to
-    // M26 from M21. See crosbug.com/38429 for details.
-    DCHECK(!ash::WallpaperController::dir_user_data_path_.empty());
-    wallpaper_path =
-        ash::WallpaperController::dir_user_data_path_.Append(info.location);
-    StartLoad(account_id, info, update_wallpaper, wallpaper_path,
-              std::move(on_finish));
-  } else {
-    // In unexpected cases, revert to default wallpaper to fail safely. See
-    // crosbug.com/38429.
-    LOG(ERROR) << "Wallpaper reverts to default unexpected.";
-    SetDefaultWallpaperImpl(account_id, update_wallpaper, std::move(on_finish));
-  }
-}
-
 bool WallpaperManager::GetUserWallpaperInfo(const AccountId& account_id,
                                             WallpaperInfo* info) const {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -1128,48 +768,8 @@
   return true;
 }
 
-base::FilePath WallpaperManager::GetDeviceWallpaperDir() {
-  DCHECK(!ash::WallpaperController::dir_chrome_os_wallpapers_path_.empty());
-  return ash::WallpaperController::dir_chrome_os_wallpapers_path_.Append(
-      kDeviceWallpaperDir);
-}
-
-base::FilePath WallpaperManager::GetDeviceWallpaperFilePath() {
-  return GetDeviceWallpaperDir().Append(kDeviceWallpaperFile);
-}
-
-void WallpaperManager::OnWallpaperDecoded(
-    const AccountId& account_id,
-    const wallpaper::WallpaperInfo& info,
-    bool update_wallpaper,
-    MovableOnDestroyCallbackHolder on_finish,
-    std::unique_ptr<user_manager::UserImage> user_image) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  TRACE_EVENT_ASYNC_END0("ui", "LoadAndDecodeWallpaper", this);
-
-  // If decoded wallpaper is empty, we have probably failed to decode the file.
-  // Use default wallpaper in this case.
-  if (user_image->image().isNull()) {
-    // Updates user pref to default wallpaper.
-    wallpaper::WallpaperInfo default_info(
-        "", wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::DEFAULT,
-        base::Time::Now().LocalMidnight());
-    SetUserWallpaperInfo(account_id, default_info, true);
-    SetDefaultWallpaperImpl(account_id, update_wallpaper, std::move(on_finish));
-    return;
-  }
-
-  // Update the image, but keep the path which was set earlier.
-  (*GetWallpaperCacheMap())[account_id].second = user_image->image();
-
-  if (update_wallpaper)
-    SetWallpaper(user_image->image(), info);
-}
-
-void WallpaperManager::SetDefaultWallpaperImpl(
-    const AccountId& account_id,
-    bool show_wallpaper,
-    MovableOnDestroyCallbackHolder on_finish) {
+void WallpaperManager::SetDefaultWallpaperImpl(const AccountId& account_id,
+                                               bool show_wallpaper) {
   if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) {
     // Some unit tests come here without a Shell instance.
     // TODO(crbug.com/776464): This is intended not to work under mash. Make it
@@ -1188,79 +788,12 @@
     return;
   }
   ash::Shell::Get()->wallpaper_controller()->SetDefaultWallpaperImpl(
-      account_id, user->GetType(), show_wallpaper, std::move(on_finish));
-}
-
-void WallpaperManager::StartLoad(const AccountId& account_id,
-                                 const WallpaperInfo& info,
-                                 bool update_wallpaper,
-                                 const base::FilePath& wallpaper_path,
-                                 MovableOnDestroyCallbackHolder on_finish) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  TRACE_EVENT_ASYNC_BEGIN0("ui", "LoadAndDecodeWallpaper", this);
-  if (update_wallpaper) {
-    // We are now about to change the wallpaper, so update the path and remove
-    // the existing image.
-    (*GetWallpaperCacheMap())[account_id] =
-        ash::CustomWallpaperElement(wallpaper_path, gfx::ImageSkia());
-  }
-
-  if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) {
-    user_image_loader::StartWithFilePath(
-        task_runner_, wallpaper_path, ImageDecoder::ROBUST_JPEG_CODEC,
-        0,  // Do not crop.
-        base::Bind(&WallpaperManager::OnWallpaperDecoded,
-                   weak_factory_.GetWeakPtr(), account_id, info,
-                   update_wallpaper, base::Passed(std::move(on_finish))));
-  } else {
-    ash::WallpaperController::ReadAndDecodeWallpaper(
-        base::Bind(&WallpaperManager::OnWallpaperDecoded,
-                   weak_factory_.GetWeakPtr(), account_id, info,
-                   update_wallpaper, base::Passed(std::move(on_finish))),
-        task_runner_, wallpaper_path);
-  }
-}
-
-void WallpaperManager::SaveLastLoadTime(const base::TimeDelta elapsed) {
-  while (last_load_times_.size() >= kLastLoadsStatsMsMaxSize)
-    last_load_times_.pop_front();
-
-  if (elapsed > base::TimeDelta::FromMicroseconds(0)) {
-    last_load_times_.push_back(elapsed);
-    last_load_finished_at_ = base::Time::Now();
-  }
+      account_id, user->GetType(), show_wallpaper);
 }
 
 void WallpaperManager::NotifyAnimationFinished() {
   for (auto& observer : observers_)
-    observer.OnWallpaperAnimationFinished(last_selected_user_);
-}
-
-base::TimeDelta WallpaperManager::GetWallpaperLoadDelay() const {
-  base::TimeDelta delay;
-
-  if (last_load_times_.size() == 0) {
-    delay = base::TimeDelta::FromMilliseconds(kLoadDefaultDelayMs);
-  } else {
-    // Calculate the average loading time.
-    delay = std::accumulate(last_load_times_.begin(), last_load_times_.end(),
-                            base::TimeDelta(), std::plus<base::TimeDelta>()) /
-            last_load_times_.size();
-
-    if (delay < base::TimeDelta::FromMilliseconds(kLoadMinDelayMs))
-      delay = base::TimeDelta::FromMilliseconds(kLoadMinDelayMs);
-    else if (delay > base::TimeDelta::FromMilliseconds(kLoadMaxDelayMs))
-      delay = base::TimeDelta::FromMilliseconds(kLoadMaxDelayMs);
-
-    // Reduce the delay by the time passed after the last wallpaper load.
-    DCHECK(!last_load_finished_at_.is_null());
-    const base::TimeDelta interval = base::Time::Now() - last_load_finished_at_;
-    if (interval > delay)
-      delay = base::TimeDelta::FromMilliseconds(0);
-    else
-      delay -= interval;
-  }
-  return delay;
+    observer.OnWallpaperAnimationFinished(GetCurrentUserAccountId());
 }
 
 void WallpaperManager::SetCustomizedDefaultWallpaperAfterCheck(
@@ -1284,7 +817,7 @@
                      weak_factory_.GetWeakPtr(), wallpaper_url,
                      base::Passed(std::move(rescaled_files))));
     } else {
-      ash::WallpaperController::ReadAndDecodeWallpaper(
+      ash::Shell::Get()->wallpaper_controller()->ReadAndDecodeWallpaper(
           base::Bind(&WallpaperManager::OnCustomizedDefaultWallpaperDecoded,
                      weak_factory_.GetWeakPtr(), wallpaper_url,
                      base::Passed(std::move(rescaled_files))),
@@ -1380,56 +913,6 @@
              : ash::WallpaperController::kLargeWallpaperSubDir;
 }
 
-void WallpaperManager::OnCustomWallpaperFileNotFound(
-    const AccountId& account_id,
-    const base::FilePath& expected_path,
-    bool update_wallpaper,
-    MovableOnDestroyCallbackHolder on_finish) {
-  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
-  const user_manager::User* user = user_manager->FindUser(account_id);
-  LOG(ERROR) << "Failed to load previously selected custom wallpaper. "
-             << "Fallback to default wallpaper. Expected wallpaper path: "
-             << expected_path.value() << ". Number of users on the device: "
-             << user_manager->GetUsers().size()
-             << ", Number of logged in users on the device: "
-             << user_manager->GetLoggedInUsers().size()
-             << ". Current user type: " << user->GetType()
-             << ", IsActiveUser=" << (user_manager->GetActiveUser() == user)
-             << ", IsPrimaryUser=" << (user_manager->GetPrimaryUser() == user)
-             << ".";
-
-  SetDefaultWallpaperImpl(account_id, update_wallpaper, std::move(on_finish));
-}
-
-WallpaperManager::PendingWallpaper* WallpaperManager::GetPendingWallpaper() {
-  // If |pending_inactive_| already exists, return it directly. This allows the
-  // pending request (whose timer is still running) to be overriden by a
-  // subsequent request.
-  if (!pending_inactive_) {
-    loading_.push_back(
-        new WallpaperManager::PendingWallpaper(GetWallpaperLoadDelay()));
-    pending_inactive_ = loading_.back();
-  }
-  return pending_inactive_;
-}
-
-void WallpaperManager::RemovePendingWallpaperFromList(
-    PendingWallpaper* finished_loading_request) {
-  DCHECK(loading_.size() > 0);
-  for (size_t i = 0; i < loading_.size(); ++i) {
-    if (loading_[i] == finished_loading_request) {
-      delete loading_[i];
-      loading_.erase(loading_.begin() + i);
-      break;
-    }
-  }
-
-  if (loading_.empty()) {
-    for (auto& observer : observers_)
-      observer.OnPendingListEmptyForTesting();
-  }
-}
-
 void WallpaperManager::SetPolicyControlledWallpaper(
     const AccountId& account_id,
     std::unique_ptr<user_manager::UserImage> user_image) {
@@ -1472,7 +955,8 @@
   if (exist) {
     base::PostTaskWithTraitsAndReplyWithResult(
         FROM_HERE, {base::MayBlock()},
-        base::Bind(&CheckDeviceWallpaperMatchHash, GetDeviceWallpaperFilePath(),
+        base::Bind(&CheckDeviceWallpaperMatchHash,
+                   ash::WallpaperController::GetDeviceWallpaperFilePath(),
                    hash),
         base::Bind(&WallpaperManager::OnCheckDeviceWallpaperMatchHash,
                    weak_factory_.GetWeakPtr(), account_id, url, hash));
@@ -1480,7 +964,8 @@
     GURL device_wallpaper_url(url);
     device_wallpaper_downloader_.reset(new CustomizationWallpaperDownloader(
         g_browser_process->system_request_context(), device_wallpaper_url,
-        GetDeviceWallpaperDir(), GetDeviceWallpaperFilePath(),
+        ash::WallpaperController::GetDeviceWallpaperDir(),
+        ash::WallpaperController::GetDeviceWallpaperFilePath(),
         base::Bind(&WallpaperManager::OnDeviceWallpaperDownloaded,
                    weak_factory_.GetWeakPtr(), account_id, hash)));
     device_wallpaper_downloader_->Start();
@@ -1494,14 +979,14 @@
   if (!success) {
     LOG(ERROR) << "Failed to download the device wallpaper. Fallback to "
                   "default wallpaper.";
-    GetPendingWallpaper()->SetDefaultWallpaper(account_id);
+    SetDefaultWallpaperImpl(account_id, true /*show_wallpaper=*/);
     return;
   }
 
   base::PostTaskWithTraitsAndReplyWithResult(
       FROM_HERE, {base::MayBlock()},
-      base::Bind(&CheckDeviceWallpaperMatchHash, GetDeviceWallpaperFilePath(),
-                 hash),
+      base::Bind(&CheckDeviceWallpaperMatchHash,
+                 ash::WallpaperController::GetDeviceWallpaperFilePath(), hash),
       base::Bind(&WallpaperManager::OnCheckDeviceWallpaperMatchHash,
                  weak_factory_.GetWeakPtr(), account_id, url.spec(), hash));
 }
@@ -1519,14 +1004,15 @@
       GURL device_wallpaper_url(url);
       device_wallpaper_downloader_.reset(new CustomizationWallpaperDownloader(
           g_browser_process->system_request_context(), device_wallpaper_url,
-          GetDeviceWallpaperDir(), GetDeviceWallpaperFilePath(),
+          ash::WallpaperController::GetDeviceWallpaperDir(),
+          ash::WallpaperController::GetDeviceWallpaperFilePath(),
           base::Bind(&WallpaperManager::OnDeviceWallpaperDownloaded,
                      weak_factory_.GetWeakPtr(), account_id, hash)));
       device_wallpaper_downloader_->Start();
     } else {
       LOG(ERROR) << "The device wallpaper hash doesn't match with provided "
                     "hash value. Fallback to default wallpaper! ";
-      GetPendingWallpaper()->SetDefaultWallpaper(account_id);
+      SetDefaultWallpaperImpl(account_id, true /*show_wallpaper=*/);
 
       // Reset the boolean variable so that it can retry to download when the
       // next device wallpaper request comes in.
@@ -1535,16 +1021,17 @@
     return;
   }
 
-  const base::FilePath file_path = GetDeviceWallpaperFilePath();
+  const base::FilePath file_path =
+      ash::WallpaperController::GetDeviceWallpaperFilePath();
   if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash()) {
     user_image_loader::StartWithFilePath(
-        task_runner_, GetDeviceWallpaperFilePath(),
+        task_runner_, ash::WallpaperController::GetDeviceWallpaperFilePath(),
         ImageDecoder::ROBUST_JPEG_CODEC,
         0,  // Do not crop.
         base::Bind(&WallpaperManager::OnDeviceWallpaperDecoded,
                    weak_factory_.GetWeakPtr(), account_id));
   } else {
-    ash::WallpaperController::ReadAndDecodeWallpaper(
+    ash::Shell::Get()->wallpaper_controller()->ReadAndDecodeWallpaper(
         base::Bind(&WallpaperManager::OnDeviceWallpaperDecoded,
                    weak_factory_.GetWeakPtr(), account_id),
         task_runner_, file_path);
@@ -1557,12 +1044,13 @@
   // It might be possible that the device policy controlled wallpaper finishes
   // decoding after the user logs in. In this case do nothing.
   if (!user_manager::UserManager::Get()->IsUserLoggedIn()) {
-    WallpaperInfo wallpaper_info = {GetDeviceWallpaperFilePath().value(),
-                                    wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
-                                    wallpaper::DEVICE,
-                                    base::Time::Now().LocalMidnight()};
-    GetPendingWallpaper()->SetWallpaperFromImage(
-        account_id, user_image->image(), wallpaper_info);
+    WallpaperInfo wallpaper_info = {
+        ash::WallpaperController::GetDeviceWallpaperFilePath().value(),
+        wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::DEVICE,
+        base::Time::Now().LocalMidnight()};
+    // TODO(crbug.com/776464): This should go through PendingWallpaper after
+    // moving to WallpaperController.
+    SetWallpaper(user_image->image(), wallpaper_info);
   }
 }
 
@@ -1592,4 +1080,10 @@
   return ash::Shell::Get()->wallpaper_controller()->GetWallpaperCacheMap();
 }
 
+AccountId WallpaperManager::GetCurrentUserAccountId() {
+  if (!ash::Shell::HasInstance() || ash_util::IsRunningInMash())
+    return EmptyAccountId();
+  return ash::Shell::Get()->wallpaper_controller()->GetCurrentUserAccountId();
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h
index 1f4ee73..fb1252e3 100644
--- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h
+++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h
@@ -57,20 +57,9 @@
 // Name of wallpaper sequence token.
 extern const char kWallpaperSequenceTokenName[];
 
-// File path suffices of resized small or large wallpaper.
-// TODO(bshe): Use the same sub folder system as custom wallpapers use.
-// crbug.com/174928
-extern const char kSmallWallpaperSuffix[];
-extern const char kLargeWallpaperSuffix[];
-
 class WallpaperManager : public wm::ActivationChangeObserver,
                          public aura::WindowObserver {
  public:
-  class PendingWallpaper;
-
-  using MovableOnDestroyCallbackHolder =
-      ash::WallpaperController::MovableOnDestroyCallbackHolder;
-
   class CustomizedWallpaperRescaledFiles {
    public:
     CustomizedWallpaperRescaledFiles(const base::FilePath& path_downloaded,
@@ -202,9 +191,6 @@
                        const AccountId& account_id,
                        std::unique_ptr<std::string> data);
 
-  // Returns queue size.
-  size_t GetPendingListSizeForTesting() const;
-
   // A wrapper of |WallpaperController::IsPolicyControlled|.
   bool IsPolicyControlled(const AccountId& account_id) const;
 
@@ -239,18 +225,6 @@
 
   WallpaperManager();
 
-  // Gets |account_id|'s custom wallpaper at |wallpaper_path|. Falls back on
-  // original custom wallpaper. When |update_wallpaper| is true, sets wallpaper
-  // to the loaded wallpaper. Must run on wallpaper sequenced worker thread.
-  static void GetCustomWallpaperInternal(
-      const AccountId& account_id,
-      const wallpaper::WallpaperInfo& info,
-      const base::FilePath& wallpaper_path,
-      bool update_wallpaper,
-      const scoped_refptr<base::SingleThreadTaskRunner>& reply_task_runner,
-      MovableOnDestroyCallbackHolder on_finish,
-      base::WeakPtr<WallpaperManager> weak_ptr);
-
   // Resize and save customized default wallpaper.
   static void ResizeCustomizedDefaultWallpaper(
       std::unique_ptr<gfx::ImageSkia> image,
@@ -283,13 +257,6 @@
   // Note that before device is enrolled, it proceeds with untrusted setting.
   void InitializeRegisteredDeviceWallpaper();
 
-  // Loads |account_id|'s wallpaper. When |update_wallpaper| is true, sets
-  // wallpaper to the loaded wallpaper.
-  void LoadWallpaper(const AccountId& account_id,
-                     const wallpaper::WallpaperInfo& info,
-                     bool update_wallpaper,
-                     MovableOnDestroyCallbackHolder on_finish);
-
   // A wrapper of |WallpaperController::GetUserWallpaperInfo|.
   bool GetUserWallpaperInfo(const AccountId& account_id,
                             wallpaper::WallpaperInfo* info) const;
@@ -299,45 +266,13 @@
                                 std::string* url,
                                 std::string* hash);
 
-  // Returns the file directory where the downloaded device wallpaper is saved.
-  base::FilePath GetDeviceWallpaperDir();
-
-  // Returns the full path for the downloaded device wallpaper.
-  base::FilePath GetDeviceWallpaperFilePath();
-
-  // Sets wallpaper to the decoded wallpaper if |update_wallpaper| is true.
-  // Otherwise, cache wallpaper to memory if not logged in.  (Takes a UserImage
-  // because that's the callback interface provided by UserImageLoader.)
-  void OnWallpaperDecoded(const AccountId& account_id,
-                          const wallpaper::WallpaperInfo& info,
-                          bool update_wallpaper,
-                          MovableOnDestroyCallbackHolder on_finish,
-                          std::unique_ptr<user_manager::UserImage> user_image);
-
   // A wrapper of |WallpaperController::SetDefaultWallpaperImpl|.
   void SetDefaultWallpaperImpl(const AccountId& account_id,
-                               bool show_wallpaper,
-                               MovableOnDestroyCallbackHolder on_finish);
-
-  // Starts to load wallpaper at |wallpaper_path|. If |wallpaper_path| is
-  // already loaded for that user, do nothing. Must be called on UI thread.
-  void StartLoad(const AccountId& account_id,
-                 const wallpaper::WallpaperInfo& info,
-                 bool update_wallpaper,
-                 const base::FilePath& wallpaper_path,
-                 MovableOnDestroyCallbackHolder on_finish);
-
-  // After completed load operation, update average load time.
-  void SaveLastLoadTime(const base::TimeDelta elapsed);
+                               bool show_wallpaper);
 
   // Notify all registered observers.
   void NotifyAnimationFinished();
 
-  // Calculates delay for the next wallpaper load. In most cases it is zero. It
-  // starts with the average wallpaper load time, and is reduced by the time
-  // passed after the last wallpaper load.
-  base::TimeDelta GetWallpaperLoadDelay() const;
-
   // This is called after we check that supplied default wallpaper files exist.
   void SetCustomizedDefaultWallpaperAfterCheck(
       const GURL& wallpaper_url,
@@ -365,20 +300,6 @@
   // Returns wallpaper subdirectory name for current resolution.
   const char* GetCustomWallpaperSubdirForCurrentResolution();
 
-  // Callback function for GetCustomWallpaperInternal().
-  void OnCustomWallpaperFileNotFound(const AccountId& account_id,
-                                     const base::FilePath& expected_path,
-                                     bool update_wallpaper,
-                                     MovableOnDestroyCallbackHolder on_finish);
-
-  // Returns modifiable PendingWallpaper. (Either |pending_inactive_| or a new
-  // |PendingWallpaper| object.)
-  PendingWallpaper* GetPendingWallpaper();
-
-  // This is called by PendingWallpaper when load is finished.
-  void RemovePendingWallpaperFromList(
-      PendingWallpaper* finished_loading_request);
-
   // Set wallpaper to |user_image| controlled by policy.  (Takes a UserImage
   // because that's the callback interface provided by UserImageLoader.)
   void SetPolicyControlledWallpaper(
@@ -423,6 +344,9 @@
   // Returns the wallpaper cache map, or a dummy value under mash.
   ash::CustomWallpaperMap* GetWallpaperCacheMap();
 
+  // Returns the account id of |current_user_|, or an empty value under mash.
+  AccountId GetCurrentUserAccountId();
+
   std::unique_ptr<CrosSettings::ObserverSubscription>
       show_user_name_on_signin_subscription_;
 
@@ -448,33 +372,12 @@
   // A placeholder for |wallpaper_cache_map_| under mash.
   ash::CustomWallpaperMap dummy_wallpaper_cache_map_;
 
-  // The last selected user on user pod row.
-  AccountId last_selected_user_ = EmptyAccountId();
-
   bool should_cache_wallpaper_ = false;
 
   base::ObserverList<Observer> observers_;
 
-  // These members are for the scheduler:
-
-  // When last load attempt finished.
-  base::Time last_load_finished_at_;
-
-  // last N wallpaper loads times.
-  base::circular_deque<base::TimeDelta> last_load_times_;
-
   bool retry_download_if_failed_ = true;
 
-  // Pointer to last inactive (waiting) entry of 'loading_' list.
-  // NULL when there is no inactive request.
-  PendingWallpaper* pending_inactive_ = nullptr;
-
-  // Owns PendingWallpaper.
-  // PendingWallpaper deletes itself from here on load complete.
-  // All pending will be finally deleted on destroy.
-  typedef std::vector<PendingWallpaper*> PendingList;
-  PendingList loading_;
-
   ScopedObserver<wm::ActivationClient, wm::ActivationChangeObserver>
       activation_client_observer_;
   ScopedObserver<aura::Window, aura::WindowObserver> window_observer_;
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc
index 4af0f4d..4c46689 100644
--- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_browsertest.cc
@@ -54,13 +54,6 @@
 
 namespace {
 
-constexpr int kLargeWallpaperWidth = 256;
-const int kLargeWallpaperHeight =
-    ash::WallpaperController::kLargeWallpaperMaxHeight;
-constexpr int kSmallWallpaperWidth = 256;
-const int kSmallWallpaperHeight =
-    ash::WallpaperController::kSmallWallpaperMaxHeight;
-
 constexpr char kTestUser1[] = "test1@domain.com";
 constexpr char kTestUser1GaiaId[] = "0000000001";
 constexpr char kTestUser1Hash[] = "test1@domain.com-hash";
@@ -68,17 +61,6 @@
 constexpr char kTestUser2GaiaId[] = "0000000002";
 constexpr char kTestUser2Hash[] = "test2@domain.com-hash";
 
-// Helper function to get wallpaper files id.
-wallpaper::WallpaperFilesId GetFilesId(const AccountId& account_id) {
-  return WallpaperControllerClient::Get()->GetFilesId(account_id);
-}
-
-// Helper function to remove user wallpaper.
-void RemoveUserWallpaper(const AccountId& account_id) {
-  WallpaperControllerClient::Get()->RemoveUserWallpaper(account_id);
-  WallpaperControllerClient::Get()->FlushForTesting();
-}
-
 }  // namespace
 
 class WallpaperManagerBrowserTest : public InProcessBrowserTest {
@@ -110,33 +92,6 @@
 
   void WaitAsyncWallpaperLoadStarted() { base::RunLoop().RunUntilIdle(); }
 
-  void WaitUntilCustomWallpapersDeleted(const AccountId& account_id) {
-    wallpaper::WallpaperFilesId wallpaper_file_id = GetFilesId(account_id);
-
-    base::FilePath small_wallpaper_dir =
-        ash::WallpaperController::GetCustomWallpaperDir(
-            ash::WallpaperController::kSmallWallpaperSubDir)
-            .Append(wallpaper_file_id.id());
-    base::FilePath large_wallpaper_dir =
-        ash::WallpaperController::GetCustomWallpaperDir(
-            ash::WallpaperController::kLargeWallpaperSubDir)
-            .Append(wallpaper_file_id.id());
-    base::FilePath original_wallpaper_dir =
-        ash::WallpaperController::GetCustomWallpaperDir(
-            ash::WallpaperController::kOriginalWallpaperSubDir)
-            .Append(wallpaper_file_id.id());
-    base::FilePath thumbnail_wallpaper_dir =
-        ash::WallpaperController::GetCustomWallpaperDir(
-            ash::WallpaperController::kThumbnailWallpaperSubDir)
-            .Append(wallpaper_file_id.id());
-
-    while (base::PathExists(small_wallpaper_dir) ||
-           base::PathExists(large_wallpaper_dir) ||
-           base::PathExists(original_wallpaper_dir) ||
-           base::PathExists(thumbnail_wallpaper_dir)) {
-    }
-  }
-
  protected:
   // Return custom wallpaper path. Create directory if not exist.
   base::FilePath GetCustomWallpaperPath(
@@ -179,13 +134,6 @@
     // wrong with how these tests simulate login.
   }
 
-  int LoadedWallpapers() {
-    return WallpaperManager::Get()->loaded_wallpapers_for_test() +
-           ash::Shell::Get()
-               ->wallpaper_controller()
-               ->num_decode_request_for_testing();
-  }
-
   ash::WallpaperController* controller_;
   PrefService* local_state_;
   std::unique_ptr<base::CommandLine> wallpaper_manager_command_line_;
@@ -208,182 +156,6 @@
   DISALLOW_COPY_AND_ASSIGN(WallpaperManagerBrowserTest);
 };
 
-// Tests that the appropriate custom wallpaper (large vs. small) is loaded
-// depending on the desktop resolution.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
-                       LoadCustomLargeWallpaperForLargeExternalScreen) {
-  WallpaperManager* wallpaper_manager = WallpaperManager::Get();
-  LogIn(test_account_id1_, kTestUser1Hash);
-  std::string id = base::Int64ToString(base::Time::Now().ToInternalValue());
-  base::FilePath small_wallpaper_path =
-      GetCustomWallpaperPath(ash::WallpaperController::kSmallWallpaperSubDir,
-                             test_account1_wallpaper_files_id_, id);
-  base::FilePath large_wallpaper_path =
-      GetCustomWallpaperPath(ash::WallpaperController::kLargeWallpaperSubDir,
-                             test_account1_wallpaper_files_id_, id);
-
-  // Saves the small/large resolution wallpapers to small/large custom
-  // wallpaper paths.
-  ASSERT_TRUE(ash::WallpaperController::WriteJPEGFileForTesting(
-      small_wallpaper_path, kSmallWallpaperWidth, kSmallWallpaperHeight,
-      wallpaper_manager_test_utils::kSmallCustomWallpaperColor));
-  ASSERT_TRUE(ash::WallpaperController::WriteJPEGFileForTesting(
-      large_wallpaper_path, kLargeWallpaperWidth, kLargeWallpaperHeight,
-      wallpaper_manager_test_utils::kLargeCustomWallpaperColor));
-
-  std::string relative_path =
-      base::FilePath(test_account1_wallpaper_files_id_.id()).Append(id).value();
-  // Saves wallpaper info to local state for user |test_account_id1_|.
-  WallpaperInfo info = {relative_path, WALLPAPER_LAYOUT_CENTER_CROPPED,
-                        wallpaper::CUSTOMIZED,
-                        base::Time::Now().LocalMidnight()};
-  wallpaper_manager->SetUserWallpaperInfo(test_account_id1_, info, true);
-
-  // Set the wallpaper for |test_account_id1_|.
-  wallpaper_manager->ShowUserWallpaper(test_account_id1_);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  gfx::ImageSkia wallpaper = controller_->GetWallpaper();
-
-  // Display is initialized to 800x600. The small resolution custom wallpaper is
-  // expected.
-  EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
-
-  // Hook up another 800x600 display. This shouldn't trigger a reload.
-  UpdateDisplay("800x600,800x600");
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  // The small resolution custom wallpaper is expected.
-  EXPECT_EQ(kSmallWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kSmallWallpaperHeight, wallpaper.height());
-
-  // Detach the secondary display.
-  UpdateDisplay("800x600");
-  // Hook up a 2000x2000 display. The large resolution custom wallpaper should
-  // be loaded.
-  UpdateDisplay("800x600,2000x2000");
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  wallpaper = controller_->GetWallpaper();
-
-  // The large resolution custom wallpaper is expected.
-  EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
-
-  // Detach the secondary display.
-  UpdateDisplay("800x600");
-  // Hook up the 2000x2000 display again. The large resolution default wallpaper
-  // should persist. Test for crbug/165788.
-  UpdateDisplay("800x600,2000x2000");
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  wallpaper = controller_->GetWallpaper();
-
-  // The large resolution custom wallpaper is expected.
-  EXPECT_EQ(kLargeWallpaperWidth, wallpaper.width());
-  EXPECT_EQ(kLargeWallpaperHeight, wallpaper.height());
-}
-
-// If chrome tries to reload the same wallpaper twice, the latter request should
-// be prevented. Otherwise, there are some strange animation issues as
-// described in crbug.com/158383.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
-                       PreventReloadingSameWallpaper) {
-  WallpaperManager* wallpaper_manager = WallpaperManager::Get();
-  // New user log in, a default wallpaper is loaded.
-  LogIn(test_account_id1_, kTestUser1Hash);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_EQ(1, LoadedWallpapers());
-  // Loads the same wallpaper before the initial one finished. It should be
-  // prevented.
-  wallpaper_manager->ShowUserWallpaper(test_account_id1_);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_EQ(1, LoadedWallpapers());
-  // Loads the same wallpaper after the initial one finished. It should be
-  // prevented.
-  wallpaper_manager->ShowUserWallpaper(test_account_id1_);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_EQ(1, LoadedWallpapers());
-
-  // Change wallpaper to a custom wallpaper.
-  std::string id = base::Int64ToString(base::Time::Now().ToInternalValue());
-  base::FilePath small_wallpaper_path =
-      GetCustomWallpaperPath(ash::WallpaperController::kSmallWallpaperSubDir,
-                             test_account1_wallpaper_files_id_, id);
-  ASSERT_TRUE(ash::WallpaperController::WriteJPEGFileForTesting(
-      small_wallpaper_path, kSmallWallpaperWidth, kSmallWallpaperHeight,
-      wallpaper_manager_test_utils::kSmallCustomWallpaperColor));
-
-  std::string relative_path =
-      base::FilePath(test_account1_wallpaper_files_id_.id()).Append(id).value();
-  // Saves wallpaper info to local state for user |test_account_id1_|.
-  WallpaperInfo info = {relative_path, WALLPAPER_LAYOUT_CENTER_CROPPED,
-                        wallpaper::CUSTOMIZED,
-                        base::Time::Now().LocalMidnight()};
-  wallpaper_manager->SetUserWallpaperInfo(test_account_id1_, info, true);
-
-  wallpaper_manager->ShowUserWallpaper(test_account_id1_);
-  WaitAsyncWallpaperLoadStarted();
-  EXPECT_EQ(2, LoadedWallpapers());
-  // Loads the same wallpaper before the initial one finished. It should be
-  // prevented.
-  wallpaper_manager->ShowUserWallpaper(test_account_id1_);
-  WaitAsyncWallpaperLoadStarted();
-  EXPECT_EQ(2, LoadedWallpapers());
-  wallpaper_manager->ShowUserWallpaper(test_account_id1_);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_EQ(2, LoadedWallpapers());
-}
-
-// Some users have old user profiles which may have legacy wallpapers. And these
-// lagacy wallpapers should migrate to new wallpaper picker version seamlessly.
-// This tests make sure we compatible with migrated old wallpapers.
-// crosbug.com/38429
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
-                       PRE_UseMigratedWallpaperInfo) {
-  // New user log in, a default wallpaper is loaded.
-  LogIn(test_account_id1_, kTestUser1Hash);
-  // Old wallpaper migration code doesn't exist in codebase anymore. Modify user
-  // wallpaper info directly to simulate the wallpaper migration. See
-  // crosbug.com/38429 for details about why we modify wallpaper info this way.
-  WallpaperInfo info = {"123", WALLPAPER_LAYOUT_CENTER_CROPPED,
-                        wallpaper::DEFAULT, base::Time::Now().LocalMidnight()};
-  base::FilePath user_data_dir;
-  ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
-  ASSERT_TRUE(ash::WallpaperController::WriteJPEGFileForTesting(
-      user_data_dir.Append("123"), wallpaper_manager_test_utils::kWallpaperSize,
-      wallpaper_manager_test_utils::kWallpaperSize,
-      wallpaper_manager_test_utils::kLargeCustomWallpaperColor));
-  WallpaperManager::Get()->SetUserWallpaperInfo(test_account_id1_, info, true);
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, UseMigratedWallpaperInfo) {
-  LogIn(test_account_id1_, kTestUser1Hash);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  // This test should finish normally. If timeout, it is probably because
-  // migrated wallpaper is somehow not loaded. Bad things can happen if
-  // wallpaper is not loaded at login screen. One example is: crosbug.com/38429.
-}
-
-// TODO(crbug.com/776464): This test implicitly calls |InitializeWallpaper|.
-// Move it to |WallpaperControllerTest| after |InitializeWallpaper| is migrated.
-// Some users have old user profiles which may never get a chance to migrate.
-// This tests make sure we compatible with these profiles.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
-                       PRE_UsePreMigrationWallpaperInfo) {
-  // New user log in, a default wallpaper is loaded.
-  LogIn(test_account_id1_, kTestUser1Hash);
-  // Old wallpaper migration code doesn't exist in codebase anymore. So if
-  // user's profile is not migrated, it is the same as no wallpaper info. To
-  // simulate this, we remove user's wallpaper info here.
-  RemoveUserWallpaper(test_account_id1_);
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
-                       UsePreMigrationWallpaperInfo) {
-  LogIn(test_account_id1_, kTestUser1Hash);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  // This test should finish normally. If timeout, it is probably because chrome
-  // can not handle pre migrated user profile (M21 profile or older).
-}
-
 // Test for http://crbug.com/265689. When hooked up a large external monitor,
 // the default large resolution wallpaper should load.
 IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
@@ -391,119 +163,12 @@
   UpdateDisplay("800x600");
   // Set initial wallpaper to the default wallpaper.
   ash::Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
 
   // Hook up a 2000x2000 display. The large resolution custom wallpaper should
   // be loaded.
   UpdateDisplay("800x600,2000x2000");
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
 }
 
-class WallpaperManagerBrowserTestNoAnimation
-    : public WallpaperManagerBrowserTest {
- public:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(switches::kLoginManager);
-    command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
-    command_line->AppendSwitch(chromeos::switches::kDisableLoginAnimations);
-    command_line->AppendSwitch(chromeos::switches::kDisableBootAnimation);
-  }
-};
-
-// Same test as WallpaperManagerBrowserTest.UseMigratedWallpaperInfo. But
-// disabled boot and login animation.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
-                       PRE_UseMigratedWallpaperInfo) {
-  // New user log in, a default wallpaper is loaded.
-  LogIn(test_account_id1_, kTestUser1Hash);
-  // Old wallpaper migration code doesn't exist in codebase anymore. Modify user
-  // wallpaper info directly to simulate the wallpaper migration. See
-  // crosbug.com/38429 for details about why we modify wallpaper info this way.
-  WallpaperInfo info = {"123", WALLPAPER_LAYOUT_CENTER_CROPPED,
-                        wallpaper::DEFAULT, base::Time::Now().LocalMidnight()};
-  base::FilePath user_data_dir;
-  ASSERT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
-  ASSERT_TRUE(ash::WallpaperController::WriteJPEGFileForTesting(
-      user_data_dir.Append("123"), wallpaper_manager_test_utils::kWallpaperSize,
-      wallpaper_manager_test_utils::kWallpaperSize,
-      wallpaper_manager_test_utils::kLargeCustomWallpaperColor));
-  WallpaperManager::Get()->SetUserWallpaperInfo(test_account_id1_, info, true);
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
-                       UseMigratedWallpaperInfo) {
-  LogIn(test_account_id1_, kTestUser1Hash);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  // This test should finish normally. If timeout, it is probably because
-  // migrated wallpaper is somehow not loaded. Bad things can happen if
-  // wallpaper is not loaded at login screen. One example is: crosbug.com/38429.
-}
-
-// Same test as WallpaperManagerBrowserTest.UsePreMigrationWallpaperInfo. But
-// disabled boot and login animation.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
-                       PRE_UsePreMigrationWallpaperInfo) {
-  // New user log in, a default wallpaper is loaded.
-  LogIn(test_account_id1_, kTestUser1Hash);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  // Old wallpaper migration code doesn't exist in codebase anymore. So if
-  // user's profile is not migrated, it is the same as no wallpaper info. To
-  // simulate this, we remove user's wallpaper info here.
-  RemoveUserWallpaper(test_account_id1_);
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestNoAnimation,
-                       UsePreMigrationWallpaperInfo) {
-  LogIn(test_account_id1_, kTestUser1Hash);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  // This test should finish normally. If timeout, it is probably because chrome
-  // can not handle pre migrated user profile (M21 profile or older).
-}
-
-class WallpaperManagerBrowserTestCrashRestore
-    : public WallpaperManagerBrowserTest {
- public:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(chromeos::switches::kDisableLoginAnimations);
-    command_line->AppendSwitch(chromeos::switches::kDisableBootAnimation);
-    command_line->AppendSwitchASCII(switches::kLoginUser,
-                                    test_account_id1_.GetUserEmail());
-    command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,
-                       PRE_RestoreWallpaper) {
-  // No need to explicitly login for crash-n-restore.
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-}
-
-// Test for crbug.com/270278. It simulates a browser crash and verifies if user
-// wallpaper is loaded.
-// Fails on the MSAN bots. See http://crbug.com/444477
-#if defined(MEMORY_SANITIZER)
-#define MAYBE_RestoreWallpaper DISABLED_RestoreWallpaper
-#else
-#define MAYBE_RestoreWallpaper RestoreWallpaper
-#endif
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTestCrashRestore,
-                       MAYBE_RestoreWallpaper) {
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_EQ(1, LoadedWallpapers());
-}
-
-class WallpaperManagerBrowserTestCacheUpdate
-    : public WallpaperManagerBrowserTest {
- protected:
-  // Creates a test image of size 1x1.
-  gfx::ImageSkia CreateTestImage(SkColor color) {
-    return wallpaper_manager_test_utils::CreateTestImage(1, 1, color);
-  }
-};
-
-// ----------------------------------------------------------------------
-// Test default wallpapers.
-
 class TestObserver : public WallpaperManager::Observer {
  public:
   explicit TestObserver(WallpaperManager* wallpaper_manager)
@@ -546,21 +211,18 @@
   // multiple displays are connected.
   UpdateDisplay("800x600");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(ash::WallpaperController::WALLPAPER_RESOLUTION_SMALL,
             ash::WallpaperController::GetAppropriateResolution());
   EXPECT_EQ(0, observer.GetUpdateWallpaperCountAndReset());
 
   UpdateDisplay("800x600,800x600");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(ash::WallpaperController::WALLPAPER_RESOLUTION_SMALL,
             ash::WallpaperController::GetAppropriateResolution());
   EXPECT_EQ(0, observer.GetUpdateWallpaperCountAndReset());
 
   UpdateDisplay("1366x800");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(ash::WallpaperController::WALLPAPER_RESOLUTION_SMALL,
             ash::WallpaperController::GetAppropriateResolution());
   EXPECT_EQ(1, observer.GetUpdateWallpaperCountAndReset());
@@ -568,21 +230,18 @@
   // At larger sizes, large wallpapers should be used.
   UpdateDisplay("1367x800");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(ash::WallpaperController::WALLPAPER_RESOLUTION_LARGE,
             ash::WallpaperController::GetAppropriateResolution());
   EXPECT_EQ(1, observer.GetUpdateWallpaperCountAndReset());
 
   UpdateDisplay("1367x801");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(ash::WallpaperController::WALLPAPER_RESOLUTION_LARGE,
             ash::WallpaperController::GetAppropriateResolution());
   EXPECT_EQ(1, observer.GetUpdateWallpaperCountAndReset());
 
   UpdateDisplay("2560x1700");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(ash::WallpaperController::WALLPAPER_RESOLUTION_LARGE,
             ash::WallpaperController::GetAppropriateResolution());
   EXPECT_EQ(1, observer.GetUpdateWallpaperCountAndReset());
@@ -590,20 +249,17 @@
   // Rotated smaller screen may use larger image.
   UpdateDisplay("800x600/r");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(ash::WallpaperController::WALLPAPER_RESOLUTION_SMALL,
             ash::WallpaperController::GetAppropriateResolution());
   EXPECT_EQ(1, observer.GetUpdateWallpaperCountAndReset());
 
   UpdateDisplay("800x600/r,800x600");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(ash::WallpaperController::WALLPAPER_RESOLUTION_SMALL,
             ash::WallpaperController::GetAppropriateResolution());
   EXPECT_EQ(1, observer.GetUpdateWallpaperCountAndReset());
   UpdateDisplay("1366x800/r");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(ash::WallpaperController::WALLPAPER_RESOLUTION_LARGE,
             ash::WallpaperController::GetAppropriateResolution());
   EXPECT_EQ(1, observer.GetUpdateWallpaperCountAndReset());
@@ -611,170 +267,7 @@
   // Max display size didn't change.
   UpdateDisplay("900x800/r,400x1366");
   base::RunLoop().RunUntilIdle();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
   EXPECT_EQ(0, observer.GetUpdateWallpaperCountAndReset());
 }
 
-// Tests that if there are multiple users on the device and if one user lost his
-// wallpaper somehow, the wallpapers should still show correctly on lock/login
-// screen.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest, CustomWallpaperLostTest) {
-  UpdateDisplay("640x480");
-  WallpaperManager* wallpaper_manager = WallpaperManager::Get();
-
-  LogIn(test_account_id1_, kTestUser1Hash);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-
-  // Now log in |test_account_id2_| to make it the current active user.
-  LogIn(test_account_id2_, kTestUser2Hash);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_EQ(user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(),
-            test_account_id2_);
-
-  // Set a different wallpaper for |test_account_id2_|.
-  std::string id = std::to_string(
-      std::abs((base::Time::Now() - base::Time::Now().LocalMidnight())
-                   .InMilliseconds()));
-  base::FilePath small_wallpaper_path =
-      GetCustomWallpaperPath(ash::WallpaperController::kSmallWallpaperSubDir,
-                             test_account2_wallpaper_files_id_, id);
-  ASSERT_TRUE(ash::WallpaperController::WriteJPEGFileForTesting(
-      small_wallpaper_path, kSmallWallpaperWidth, kSmallWallpaperHeight,
-      wallpaper_manager_test_utils::kSmallCustomWallpaperColor));
-  std::string relative_path2 =
-      base::FilePath(test_account2_wallpaper_files_id_.id()).Append(id).value();
-  WallpaperInfo info2 = {relative_path2, WALLPAPER_LAYOUT_CENTER_CROPPED,
-                         wallpaper::CUSTOMIZED,
-                         base::Time::Now().LocalMidnight()};
-  wallpaper_manager->SetUserWallpaperInfo(test_account_id2_, info2, true);
-  wallpaper_manager->ShowUserWallpaper(test_account_id2_);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_TRUE(wallpaper_manager_test_utils::ImageIsNearColor(
-      controller_->GetWallpaper(),
-      wallpaper_manager_test_utils::kSmallCustomWallpaperColor));
-
-  // Now simulate the lost of |test_account_id1_|'s wallpaper by only updating
-  // its WallpaperInfo but not providing its wallpaper. In this case we just
-  // fallback to the default wallpaper.
-  std::string relative_path =
-      base::FilePath(test_account1_wallpaper_files_id_.id()).Append(id).value();
-  // Saves wallpaper info to local state for user |test_account_id1_|.
-  WallpaperInfo info = {relative_path, WALLPAPER_LAYOUT_CENTER_CROPPED,
-                        wallpaper::CUSTOMIZED,
-                        base::Time::Now().LocalMidnight()};
-  wallpaper_manager->SetUserWallpaperInfo(test_account_id1_, info, true);
-}
-
-// TODO(crbug.com/776464): Move this test to |WallpaperControllerTest| after
-// |ShowUserWallpaper| is migrated.
-// Tests that if a user who has a custom wallpaper is removed from the device,
-// only the directory that contains the user's custom wallpapers gets removed.
-// The other user's custom wallpaper is not affected.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
-                       RemoveUserWithCustomWallpaperTest) {
-  UpdateDisplay("640x480");
-  WallpaperManager* wallpaper_manager = WallpaperManager::Get();
-
-  // Set a custom wallpaper for |test_account_id1_| and verify the wallpaper
-  // exists.
-  LogIn(test_account_id1_, kTestUser1Hash);
-  wallpaper::WallpaperFilesId wallpaper_file_id1 =
-      GetFilesId(test_account_id1_);
-  const std::string id = std::to_string(
-      std::abs((base::Time::Now() - base::Time::Now().LocalMidnight())
-                   .InMilliseconds()));
-  base::FilePath small_wallpaper_path = GetCustomWallpaperPath(
-      ash::WallpaperController::kSmallWallpaperSubDir, wallpaper_file_id1, id);
-  ASSERT_TRUE(ash::WallpaperController::WriteJPEGFileForTesting(
-      small_wallpaper_path, kSmallWallpaperWidth, kSmallWallpaperHeight,
-      wallpaper_manager_test_utils::kSmallCustomWallpaperColor));
-  std::string relative_path =
-      base::FilePath(wallpaper_file_id1.id()).Append(id).value();
-  // Saves wallpaper info to local state for user |test_account_id1_|.
-  WallpaperInfo info = {relative_path, WALLPAPER_LAYOUT_CENTER_CROPPED,
-                        wallpaper::CUSTOMIZED,
-                        base::Time::Now().LocalMidnight()};
-  wallpaper_manager->SetUserWallpaperInfo(test_account_id1_, info, true);
-  wallpaper_manager->ShowUserWallpaper(test_account_id1_);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_TRUE(base::PathExists(small_wallpaper_path));
-
-  // Now login another user and set a custom wallpaper for it.
-  LogIn(test_account_id2_, kTestUser2Hash);
-  wallpaper::WallpaperFilesId wallpaper_file_id2 =
-      GetFilesId(test_account_id2_);
-  base::FilePath small_wallpaper_path2 = GetCustomWallpaperPath(
-      ash::WallpaperController::kSmallWallpaperSubDir, wallpaper_file_id2, id);
-  ASSERT_TRUE(ash::WallpaperController::WriteJPEGFileForTesting(
-      small_wallpaper_path2, kSmallWallpaperWidth, kSmallWallpaperHeight,
-      wallpaper_manager_test_utils::kSmallCustomWallpaperColor));
-  std::string relative_path2 =
-      base::FilePath(wallpaper_file_id2.id()).Append(id).value();
-  // Saves wallpaper info to local state for user |test_account_id2_|.
-  WallpaperInfo info2 = {relative_path2, WALLPAPER_LAYOUT_CENTER_CROPPED,
-                         wallpaper::CUSTOMIZED,
-                         base::Time::Now().LocalMidnight()};
-  wallpaper_manager->SetUserWallpaperInfo(test_account_id2_, info2, true);
-  wallpaper_manager->ShowUserWallpaper(test_account_id2_);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_TRUE(base::PathExists(small_wallpaper_path2));
-
-  // Simulate the removal of |test_account_id2_|.
-  RemoveUserWallpaper(test_account_id2_);
-  // Wait until all files under the user's custom_wallpapers directory are
-  // removed.
-  WaitUntilCustomWallpapersDeleted(test_account_id2_);
-
-  // Test that the other user's wallpaper is not affected.
-  EXPECT_TRUE(base::PathExists(small_wallpaper_path));
-}
-
-// TODO(crbug.com/776464): Move this test to |WallpaperControllerTest| after
-// |ShowUserWallpaper| is migrated.
-// Tests that if a user who has a default wallpaper is removed from the device,
-// the other user's custom wallpaper is not affected.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerBrowserTest,
-                       RemoveUserWithDefaultWallpaperTest) {
-  UpdateDisplay("640x480");
-  WallpaperManager* wallpaper_manager = WallpaperManager::Get();
-
-  // Set a custom wallpaper for |test_account_id1_| and verify the custom
-  // wallpaper exists.
-  LogIn(test_account_id1_, kTestUser1Hash);
-  wallpaper::WallpaperFilesId wallpaper_file_id1 =
-      GetFilesId(test_account_id1_);
-  std::string id = std::to_string(
-      std::abs((base::Time::Now() - base::Time::Now().LocalMidnight())
-                   .InMilliseconds()));
-  base::FilePath small_wallpaper_path = GetCustomWallpaperPath(
-      ash::WallpaperController::kSmallWallpaperSubDir, wallpaper_file_id1, id);
-  ASSERT_TRUE(ash::WallpaperController::WriteJPEGFileForTesting(
-      small_wallpaper_path, kSmallWallpaperWidth, kSmallWallpaperHeight,
-      wallpaper_manager_test_utils::kSmallCustomWallpaperColor));
-  std::string relative_path =
-      base::FilePath(wallpaper_file_id1.id()).Append(id).value();
-  // Saves wallpaper info to local state for user |test_account_id1_|.
-  WallpaperInfo info = {relative_path, WALLPAPER_LAYOUT_CENTER_CROPPED,
-                        wallpaper::CUSTOMIZED,
-                        base::Time::Now().LocalMidnight()};
-  wallpaper_manager->SetUserWallpaperInfo(test_account_id1_, info, true);
-  wallpaper_manager->ShowUserWallpaper(test_account_id1_);
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-  EXPECT_TRUE(base::PathExists(small_wallpaper_path));
-
-  // Now login another user and set a default wallpaper.
-  LogIn(test_account_id2_, kTestUser2Hash);
-  WallpaperControllerClient::Get()->SetDefaultWallpaper(
-      test_account_id2_, true /* show_wallpaper */);
-  WallpaperControllerClient::Get()->FlushForTesting();
-  wallpaper_manager_test_utils::WaitAsyncWallpaperLoadFinished();
-
-  // Simulate the removal of |test_account_id2_|.
-  RemoveUserWallpaper(test_account_id2_);
-  WaitUntilCustomWallpapersDeleted(test_account_id2_);
-
-  // Test that the other user's wallpaper is not affected.
-  EXPECT_TRUE(base::PathExists(small_wallpaper_path));
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc
index 48b8ecf..fd6e853 100644
--- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc
@@ -344,11 +344,9 @@
   SetSystemSalt();
   wallpaper::WallpaperInfo info;
   LoginUser(testUsers_[0]);
-  base::RunLoop().RunUntilIdle();
 
-  // First user: Wait until default wallpaper has been loaded (happens
-  // automatically) and store color to recognize it later.
-  RunUntilWallpaperChangeCount(1);
+  // First user: Stores the average color of the default wallpaper (set
+  // automatically) to be compared against later.
   const SkColor original_wallpaper_color = GetAverageWallpaperColor();
 
   // Second user: Set wallpaper policy to blue image.  This should not result in
@@ -357,14 +355,14 @@
 
   // First user: Set wallpaper policy to red image and verify average color.
   InjectPolicy(0, kRedImageFileName);
-  RunUntilWallpaperChangeCount(2);
+  RunUntilWallpaperChangeCount(1);
   GetUserWallpaperInfo(0, &info);
   ASSERT_EQ(wallpaper::POLICY, info.type);
   ASSERT_EQ(kRedImageColor, GetAverageWallpaperColor());
 
   // First user: Set wallpaper policy to green image and verify average color.
   InjectPolicy(0, kGreenImageFileName);
-  RunUntilWallpaperChangeCount(3);
+  RunUntilWallpaperChangeCount(2);
   GetUserWallpaperInfo(0, &info);
   ASSERT_EQ(wallpaper::POLICY, info.type);
   ASSERT_EQ(kGreenImageColor, GetAverageWallpaperColor());
@@ -372,66 +370,14 @@
   // First user: Clear wallpaper policy and verify that the default wallpaper is
   // set again.
   InjectPolicy(0, "");
-  RunUntilWallpaperChangeCount(4);
+  RunUntilWallpaperChangeCount(3);
   GetUserWallpaperInfo(0, &info);
   ASSERT_EQ(wallpaper::DEFAULT, info.type);
   ASSERT_EQ(original_wallpaper_color, GetAverageWallpaperColor());
 
   // Check wallpaper change count to ensure that setting the second user's
   // wallpaper didn't have any effect.
-  ASSERT_EQ(4, wallpaper_change_count_);
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest,
-                       DISABLED_PRE_PRE_PRE_WallpaperOnLoginScreen) {
-  RegisterUser(testUsers_[0]);
-  RegisterUser(testUsers_[1]);
-  StartupUtils::MarkOobeCompleted();
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest,
-                       DISABLED_PRE_PRE_WallpaperOnLoginScreen) {
-  LoginUser(testUsers_[0]);
-
-  // Wait until default wallpaper has been loaded.
-  RunUntilWallpaperChangeCount(1);
-
-  // Set wallpaper policy to red image.
-  InjectPolicy(0, kRedImageFileName);
-
-  // Run until wallpaper has changed.
-  RunUntilWallpaperChangeCount(2);
-  ASSERT_EQ(kRedImageColor, GetAverageWallpaperColor());
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest,
-                       DISABLED_PRE_WallpaperOnLoginScreen) {
-  LoginUser(testUsers_[1]);
-
-  // Wait until default wallpaper has been loaded.
-  RunUntilWallpaperChangeCount(1);
-
-  // Set wallpaper policy to green image.
-  InjectPolicy(1, kGreenImageFileName);
-
-  // Run until wallpaper has changed.
-  RunUntilWallpaperChangeCount(2);
-  ASSERT_EQ(kGreenImageColor, GetAverageWallpaperColor());
-}
-
-// Disabled due to flakiness: http://crbug.com/385648.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest,
-                       DISABLED_WallpaperOnLoginScreen) {
-  // Wait for active pod's wallpaper to be loaded.
-  RunUntilWallpaperChangeCount(1);
-  ASSERT_EQ(kGreenImageColor, GetAverageWallpaperColor());
-
-  // Select the second pod (belonging to user 1).
-  ASSERT_TRUE(content::ExecuteScript(
-      LoginDisplayHost::default_host()->GetOobeUI()->web_ui()->GetWebContents(),
-      "document.getElementsByClassName('pod')[1].focus();"));
-  RunUntilWallpaperChangeCount(2);
-  ASSERT_EQ(kRedImageColor, GetAverageWallpaperColor());
+  ASSERT_EQ(3, wallpaper_change_count_);
 }
 
 IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, PRE_PRE_PersistOverLogout) {
@@ -444,14 +390,11 @@
   SetSystemSalt();
   LoginUser(testUsers_[0]);
 
-  // Wait until default wallpaper has been loaded.
-  RunUntilWallpaperChangeCount(1);
-
   // Set wallpaper policy to red image.
   InjectPolicy(0, kRedImageFileName);
 
   // Run until wallpaper has changed.
-  RunUntilWallpaperChangeCount(2);
+  RunUntilWallpaperChangeCount(1);
   ASSERT_EQ(kRedImageColor, GetAverageWallpaperColor());
   StartupUtils::MarkOobeCompleted();
 }
@@ -459,8 +402,6 @@
 IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, PersistOverLogout) {
   LoginUser(testUsers_[0]);
 
-  // Wait until wallpaper has been loaded.
-  RunUntilWallpaperChangeCount(1);
   ASSERT_EQ(kRedImageColor, GetAverageWallpaperColor());
 }
 
@@ -476,23 +417,20 @@
 IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, DevicePolicyTest) {
   SetSystemSalt();
 
-  // Wait until default wallpaper has been loaded in the login screen.
-  RunUntilWallpaperChangeCount(1);
-
   // Set the device wallpaper policy. Test that the device policy controlled
   // wallpaper shows up in the login screen.
   InjectDevicePolicy(kRedImageFileName);
-  RunUntilWallpaperChangeCount(2);
+  RunUntilWallpaperChangeCount(1);
   EXPECT_TRUE(ShouldSetDeviceWallpaper(user_manager::SignInAccountId()));
   EXPECT_EQ(kRedImageColor, GetAverageWallpaperColor());
 
   // Log in a test user and set the user wallpaper policy. The user policy
   // controlled wallpaper shows up in the user session.
   LoginUser(testUsers_[0]);
-  RunUntilWallpaperChangeCount(3);
+  RunUntilWallpaperChangeCount(2);
 
   InjectPolicy(0, kGreenImageFileName);
-  RunUntilWallpaperChangeCount(4);
+  RunUntilWallpaperChangeCount(3);
   EXPECT_EQ(kGreenImageColor, GetAverageWallpaperColor());
 
   // Set the device wallpaper policy inside the user session. That that the
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 c9970a1..86c87f40 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
@@ -10,7 +10,6 @@
 #include "ash/wallpaper/wallpaper_controller.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/run_loop.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
@@ -19,46 +18,6 @@
 #include "ui/gfx/geometry/rect.h"
 
 namespace chromeos {
-
-namespace {
-
-class TestWallpaperObserverPendingListEmpty
-    : public WallpaperManager::Observer {
- public:
-  explicit TestWallpaperObserverPendingListEmpty(
-      WallpaperManager* wallpaper_manager)
-      : empty_(false), wallpaper_manager_(wallpaper_manager) {
-    DCHECK(wallpaper_manager_);
-    wallpaper_manager_->AddObserver(this);
-  }
-
-  ~TestWallpaperObserverPendingListEmpty() override {
-    wallpaper_manager_->RemoveObserver(this);
-  }
-
-  void OnPendingListEmptyForTesting() override {
-    empty_ = true;
-    base::RunLoop::QuitCurrentWhenIdleDeprecated();
-  }
-
-  void WaitForPendingListEmpty() {
-    if (wallpaper_manager_->GetPendingListSizeForTesting() == 0) {
-      empty_ = true;
-      return;
-    }
-    while (!empty_)
-      base::RunLoop().Run();
-  }
-
- private:
-  bool empty_;
-  WallpaperManager* wallpaper_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestWallpaperObserverPendingListEmpty);
-};
-
-}  // namespace
-
 namespace wallpaper_manager_test_utils {
 
 const SkColor kLargeCustomWallpaperColor = SK_ColorDKGRAY;
@@ -105,11 +64,6 @@
   return true;
 }
 
-void WaitAsyncWallpaperLoadFinished() {
-  TestWallpaperObserverPendingListEmpty observer(WallpaperManager::Get());
-  observer.WaitForPendingListEmpty();
-}
-
 }  // namespace wallpaper_manager_test_utils
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.h b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.h
index fd68ab7..ac28c1b4 100644
--- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.h
+++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.h
@@ -30,10 +30,6 @@
 // used.)
 bool ImageIsNearColor(gfx::ImageSkia image, SkColor expected_color);
 
-// Wait until all wallpaper loading is done, and WallpaperManager comes into
-// a stable state.
-void WaitAsyncWallpaperLoadFinished();
-
 }  // namespace wallpaper_manager_test_utils
 }  // namespace chromeos
 
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
index 72447f3f..8202b083 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
@@ -17,6 +17,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/net/network_portal_notification_controller.h"
+#include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill_profile_client.h"
 #include "chromeos/login/login_state.h"
@@ -24,7 +25,6 @@
 #include "chromeos/network/network_state_handler.h"
 #include "components/device_event_log/device_event_log.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/common/content_switches.h"
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
@@ -220,6 +220,14 @@
   NET_LOG(EVENT) << "NetworkPortalDetectorImpl::NetworkPortalDetectorImpl()";
   captive_portal_detector_.reset(new CaptivePortalDetector(request_context));
 
+  // Captive portal randomization can cause problems in some environemnts.
+  // Disable randomization by default by setting portal_test_url_.
+  // http://crbug.com/776409.
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          chromeos::switches::kEnableCaptivePortalRandomUrl)) {
+    portal_test_url_ = GURL(CaptivePortalDetector::kDefaultURL);
+  }
+
   if (create_notification_controller) {
     notification_controller_.reset(
         new NetworkPortalNotificationController(this));
@@ -465,6 +473,7 @@
   const GURL test_url =
       !portal_test_url_.is_empty() ? portal_test_url_ : GetRandomizedTestURL();
   DCHECK(test_url.is_valid());
+  NET_LOG(EVENT) << "Starting captive portal detection with URL: " << test_url;
   captive_portal_detector_->DetectCaptivePortal(
       test_url,
       base::Bind(&NetworkPortalDetectorImpl::OnAttemptCompleted,
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.cc b/chrome/browser/chromeos/smb_client/smb_file_system.cc
index 0caaf24..575688a 100644
--- a/chrome/browser/chromeos/smb_client/smb_file_system.cc
+++ b/chrome/browser/chromeos/smb_client/smb_file_system.cc
@@ -4,11 +4,53 @@
 
 #include "chrome/browser/chromeos/smb_client/smb_file_system.h"
 
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/smb_provider_client.h"
 
 namespace chromeos {
+
+namespace {
+
+// This is a bogus data URI.
+// The Files app will attempt to download a whole image to create a thumbnail
+// any time you visit a folder. A bug (crbug.com/548050) tracks not doing that
+// for NETWORK providers. This work around is to supply an icon but make it
+// bogus so it falls back to the generic icon.
+constexpr char kUnknownImageDataUri[] = "data:image/png;base64,X";
+
+using file_system_provider::ProvidedFileSystemInterface;
+
+bool RequestedIsDirectory(
+    ProvidedFileSystemInterface::MetadataFieldMask fields) {
+  return fields & ProvidedFileSystemInterface::MetadataField::
+                      METADATA_FIELD_IS_DIRECTORY;
+}
+
+bool RequestedName(ProvidedFileSystemInterface::MetadataFieldMask fields) {
+  return fields &
+         ProvidedFileSystemInterface::MetadataField::METADATA_FIELD_NAME;
+}
+
+bool RequestedSize(ProvidedFileSystemInterface::MetadataFieldMask fields) {
+  return fields &
+         ProvidedFileSystemInterface::MetadataField::METADATA_FIELD_SIZE;
+}
+
+bool RequestedModificationTime(
+    ProvidedFileSystemInterface::MetadataFieldMask fields) {
+  return fields & ProvidedFileSystemInterface::MetadataField::
+                      METADATA_FIELD_MODIFICATION_TIME;
+}
+
+bool RequestedThumbnail(ProvidedFileSystemInterface::MetadataFieldMask fields) {
+  return fields &
+         ProvidedFileSystemInterface::MetadataField::METADATA_FIELD_THUMBNAIL;
+}
+
+}  // namespace
+
 namespace smb_client {
 
 namespace {
@@ -109,14 +151,19 @@
     const base::FilePath& entry_path,
     ProvidedFileSystemInterface::MetadataFieldMask fields,
     const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
-  NOTIMPLEMENTED();
+  GetSmbProviderClient()->GetMetadataEntry(
+      GetMountId(), entry_path,
+      base::BindOnce(&SmbFileSystem::HandleRequestGetMetadataEntryCallback,
+                     weak_ptr_factory_.GetWeakPtr(), fields, callback));
   return AbortCallback();
 }
 
 AbortCallback SmbFileSystem::GetActions(
     const std::vector<base::FilePath>& entry_paths,
     const GetActionsCallback& callback) {
-  NOTIMPLEMENTED();
+  const std::vector<file_system_provider::Action> actions;
+  // No actions are currently supported.
+  callback.Run(actions, base::File::FILE_OK);
   return AbortCallback();
 }
 
@@ -227,7 +274,10 @@
     const storage::AsyncFileUtil::StatusCallback& callback,
     const storage::WatcherManager::NotificationCallback&
         notification_callback) {
-  NOTIMPLEMENTED();
+  // Watchers are not supported.
+  // This method should not be getting called since watchable is set to false.
+  // crbug.com/796334.
+  callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
   return AbortCallback();
 }
 
@@ -236,7 +286,10 @@
     const base::FilePath& entry_path,
     bool recursive,
     const storage::AsyncFileUtil::StatusCallback& callback) {
-  NOTIMPLEMENTED();
+  // Watchers are not supported.
+  // This method should not be getting called since watchable is set to false.
+  // http://www.crbug.com/796334.
+  callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
 }
 
 const file_system_provider::ProvidedFileSystemInfo&
@@ -250,7 +303,9 @@
 }
 
 file_system_provider::Watchers* SmbFileSystem::GetWatchers() {
-  NOTIMPLEMENTED();
+  // Watchers are not supported.
+  // This method should not be getting called since watchable is set to false.
+  // http://www.crbug.com/796334.
   return &watchers_;
 }
 
@@ -293,10 +348,42 @@
   for (const smbprovider::DirectoryEntry& entry : entries.entries()) {
     entry_list.emplace_back(entry.name(), MapEntryType(entry.is_directory()));
   }
-  // TODO(allenvic): Implement has_more (https://crbug.com/796246).
+  // TODO(allenvic): Implement has_more (crbug.com/796246).
   callback.Run(TranslateError(error), entry_list, false /* has_more */);
 }
 
+void SmbFileSystem::HandleRequestGetMetadataEntryCallback(
+    ProvidedFileSystemInterface::MetadataFieldMask fields,
+    const ProvidedFileSystemInterface::GetMetadataCallback& callback,
+    smbprovider::ErrorType error,
+    const smbprovider::DirectoryEntry& entry) const {
+  if (error != smbprovider::ERROR_OK) {
+    callback.Run(std::unique_ptr<file_system_provider::EntryMetadata>(),
+                 TranslateError(error));
+    return;
+  }
+  std::unique_ptr<file_system_provider::EntryMetadata> metadata =
+      std::make_unique<file_system_provider::EntryMetadata>();
+  if (RequestedIsDirectory(fields)) {
+    metadata->is_directory = std::make_unique<bool>(entry.is_directory());
+  }
+  if (RequestedName(fields)) {
+    metadata->name = std::make_unique<std::string>(entry.name());
+  }
+  if (RequestedSize(fields)) {
+    metadata->size = std::make_unique<int64_t>(entry.size());
+  }
+  if (RequestedModificationTime(fields)) {
+    metadata->modification_time = std::make_unique<base::Time>(
+        base::Time::FromTimeT(entry.last_modified_time()));
+  }
+  if (RequestedThumbnail(fields)) {
+    metadata->thumbnail = std::make_unique<std::string>(kUnknownImageDataUri);
+  }
+  // Mime types are not supported.
+  callback.Run(std::move(metadata), base::File::FILE_OK);
+}
+
 base::WeakPtr<file_system_provider::ProvidedFileSystemInterface>
 SmbFileSystem::GetWeakPtr() {
   return weak_ptr_factory_.GetWeakPtr();
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.h b/chrome/browser/chromeos/smb_client/smb_file_system.h
index 7b56b84..2513fc67 100644
--- a/chrome/browser/chromeos/smb_client/smb_file_system.h
+++ b/chrome/browser/chromeos/smb_client/smb_file_system.h
@@ -176,6 +176,12 @@
       smbprovider::ErrorType error,
       const smbprovider::DirectoryEntryList& entries) const;
 
+  void HandleRequestGetMetadataEntryCallback(
+      ProvidedFileSystemInterface::MetadataFieldMask fields,
+      const ProvidedFileSystemInterface::GetMetadataCallback& callback,
+      smbprovider::ErrorType error,
+      const smbprovider::DirectoryEntry& entry) const;
+
   int32_t GetMountId() const;
 
   SmbProviderClient* GetSmbProviderClient() const;
diff --git a/chrome/browser/chromeos/tether/tether_service.cc b/chrome/browser/chromeos/tether/tether_service.cc
index 729ba2d..521d6dbb 100644
--- a/chrome/browser/chromeos/tether/tether_service.cc
+++ b/chrome/browser/chromeos/tether/tether_service.cc
@@ -188,6 +188,11 @@
           adapter_);
 }
 
+chromeos::tether::GmsCoreNotificationsStateTracker*
+TetherService::GetGmsCoreNotificationsStateTracker() {
+  return gms_core_notifications_state_tracker_.get();
+}
+
 void TetherService::StopTetherIfNecessary() {
   if (!tether_component_ ||
       tether_component_->status() !=
diff --git a/chrome/browser/chromeos/tether/tether_service.h b/chrome/browser/chromeos/tether/tether_service.h
index ecb029e..f4e2b0c 100644
--- a/chrome/browser/chromeos/tether/tether_service.h
+++ b/chrome/browser/chromeos/tether/tether_service.h
@@ -26,6 +26,7 @@
 namespace chromeos {
 class NetworkStateHandler;
 namespace tether {
+class GmsCoreNotificationsStateTracker;
 class GmsCoreNotificationsStateTrackerImpl;
 class NotificationPresenter;
 }  // namespace tether
@@ -40,6 +41,12 @@
 class PrefRegistrySyncable;
 }  // namespace user_prefs
 
+// Service providing access to the Instant Tethering component. Provides an
+// interface to start up the component as well as to retrieve metadata about
+// ongoing Tether connections.
+//
+// This service starts up when the user logs in (or recovers from a crash) and
+// is shut down when the user logs out.
 class TetherService : public KeyedService,
                       public chromeos::PowerManagerClient::Observer,
                       public chromeos::tether::TetherHostFetcher::Observer,
@@ -67,6 +74,9 @@
   // Should only be called once a user is logged in.
   virtual void StartTetherIfPossible();
 
+  virtual chromeos::tether::GmsCoreNotificationsStateTracker*
+  GetGmsCoreNotificationsStateTracker();
+
  protected:
   // KeyedService:
   void Shutdown() override;
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win.cc b/chrome/browser/component_updater/sw_reporter_installer_win.cc
index 376c6ce5..77c1212 100644
--- a/chrome/browser/component_updater/sw_reporter_installer_win.cc
+++ b/chrome/browser/component_updater/sw_reporter_installer_win.cc
@@ -35,6 +35,7 @@
 #include "base/win/registry.h"
 #include "base/win/windows_version.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
 #include "components/chrome_cleaner/public/constants/constants.h"
@@ -428,6 +429,30 @@
   return std::vector<std::string>();
 }
 
+SwReporterOnDemandFetcher::SwReporterOnDemandFetcher(
+    ComponentUpdateService* cus,
+    base::OnceClosure on_error_callback)
+    : cus_(cus), on_error_callback_(std::move(on_error_callback)) {
+  cus_->AddObserver(this);
+  cus_->GetOnDemandUpdater().OnDemandUpdate(kSwReporterComponentId, Callback());
+}
+
+SwReporterOnDemandFetcher::~SwReporterOnDemandFetcher() {
+  cus_->RemoveObserver(this);
+}
+
+void SwReporterOnDemandFetcher::OnEvent(Events event, const std::string& id) {
+  if (id != kSwReporterComponentId)
+    return;
+
+  if (event == Events::COMPONENT_NOT_UPDATED) {
+    std::move(on_error_callback_).Run();
+    cus_->RemoveObserver(this);
+  } else if (event == Events::COMPONENT_UPDATED) {
+    cus_->RemoveObserver(this);
+  }
+}
+
 void RegisterSwReporterComponent(ComponentUpdateService* cus) {
   ReportUMAForLastCleanerRun();
 
@@ -438,8 +463,11 @@
         FROM_HERE,
         content::BrowserThread::GetTaskRunnerForThread(
             content::BrowserThread::UI),
-        base::Bind(&safe_browsing::OnSwReporterReady,
-                   base::Passed(&invocations)));
+        base::BindOnce(
+            &safe_browsing::ChromeCleanerController::OnSwReporterReady,
+            base::Unretained(
+                safe_browsing::ChromeCleanerController::GetInstance()),
+            base::Passed(&invocations)));
   };
 
   // Install the component.
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win.h b/chrome/browser/component_updater/sw_reporter_installer_win.h
index e2614d0..fc181e8 100644
--- a/chrome/browser/component_updater/sw_reporter_installer_win.h
+++ b/chrome/browser/component_updater/sw_reporter_installer_win.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h"
 #include "components/component_updater/component_installer.h"
+#include "components/component_updater/component_updater_service.h"
 
 class PrefRegistrySimple;
 
@@ -83,6 +84,29 @@
   DISALLOW_COPY_AND_ASSIGN(SwReporterInstallerPolicy);
 };
 
+// Forces an update of the reporter component.
+// Note: this can have adverse effects on the component updater subsystem and
+// should only be created as a result of direct user action.
+// For example, if this is created repeatedly, it might result in too many
+// unexpected requests to the component updater service and cause system
+// instability.
+class SwReporterOnDemandFetcher : public ServiceObserver {
+ public:
+  SwReporterOnDemandFetcher(ComponentUpdateService* cus,
+                            base::OnceClosure on_error_callback);
+  ~SwReporterOnDemandFetcher() override;
+
+  // ServiceObserver implementation.
+  void OnEvent(Events event, const std::string& id) override;
+
+ private:
+  // Will outlive this object.
+  ComponentUpdateService* cus_;
+  base::OnceClosure on_error_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(SwReporterOnDemandFetcher);
+};
+
 // Call once during startup to make the component update service aware of the
 // SwReporter. Once ready, this may trigger a periodic run of the reporter.
 void RegisterSwReporterComponent(ComponentUpdateService* cus);
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc b/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc
index dca8b48..7ca7172c 100644
--- a/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc
+++ b/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc
@@ -25,6 +25,7 @@
 #include "base/version.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h"
 #include "components/chrome_cleaner/public/constants/constants.h"
+#include "components/component_updater/mock_component_updater_service.h"
 #include "components/variations/variations_params_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -39,6 +40,11 @@
 
 using safe_browsing::SwReporterInvocation;
 using safe_browsing::SwReporterInvocationSequence;
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::ReturnRef;
+
+using Events = update_client::UpdateClient::Observer::Events;
 
 }  // namespace
 
@@ -670,4 +676,89 @@
                                  SW_REPORTER_EXPERIMENT_ERROR_BAD_PARAMS, 1);
 }
 
+class SwReporterOnDemandFetcherTest : public ::testing::Test,
+                                      public OnDemandUpdater {
+ public:
+  SwReporterOnDemandFetcherTest() = default;
+
+  void SetUp() override {
+    EXPECT_CALL(mock_cus_, AddObserver(_)).Times(1);
+    EXPECT_CALL(mock_cus_, GetOnDemandUpdater()).WillOnce(ReturnRef(*this));
+    EXPECT_CALL(mock_cus_, RemoveObserver(_)).Times(AtLeast(1));
+  }
+
+  void CreateOnDemandFetcherAndVerifyExpecations(bool can_be_updated) {
+    component_can_be_updated_ = can_be_updated;
+
+    fetcher_ = base::MakeUnique<SwReporterOnDemandFetcher>(
+        &mock_cus_,
+        base::BindOnce(&SwReporterOnDemandFetcherTest::SetErrorCallbackCalled,
+                       base::Unretained(this)));
+  }
+
+  // OnDemandUpdater implementation:
+  void OnDemandUpdate(const std::string& crx_id, Callback callback) override {
+    ASSERT_EQ(kSwReporterComponentId, crx_id);
+    on_demand_update_called_ = true;
+
+    // |OnDemandUpdate| is called immediately on |SwReporterOnDemandFetcher|
+    // creation, before |fetcher_| has been assigned the newly created object.
+    // Post a task to guarantee that |fetcher_| is initialized.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            component_can_be_updated_
+                ? &SwReporterOnDemandFetcherTest::FireComponentUpdateEvents
+                : &SwReporterOnDemandFetcherTest::FireComponentNotUpdatedEvents,
+            base::Unretained(this)));
+  }
+
+ protected:
+  ::testing::StrictMock<MockComponentUpdateService> mock_cus_;
+  std::unique_ptr<SwReporterOnDemandFetcher> fetcher_;
+
+  bool on_demand_update_called_ = false;
+
+ private:
+  void FireComponentUpdateEvents() {
+    fetcher_->OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
+                      kSwReporterComponentId);
+    fetcher_->OnEvent(Events::COMPONENT_UPDATE_FOUND, kSwReporterComponentId);
+    fetcher_->OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING,
+                      kSwReporterComponentId);
+    fetcher_->OnEvent(Events::COMPONENT_UPDATE_READY, kSwReporterComponentId);
+    fetcher_->OnEvent(Events::COMPONENT_UPDATED, kSwReporterComponentId);
+
+    EXPECT_FALSE(error_callback_called_);
+  }
+
+  void FireComponentNotUpdatedEvents() {
+    fetcher_->OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
+                      kSwReporterComponentId);
+    fetcher_->OnEvent(Events::COMPONENT_NOT_UPDATED, kSwReporterComponentId);
+
+    EXPECT_TRUE(error_callback_called_);
+  }
+
+  void SetErrorCallbackCalled() { error_callback_called_ = true; }
+
+  bool component_can_be_updated_ = false;
+  bool error_callback_called_ = false;
+  content::TestBrowserThreadBundle threads_;
+
+  DISALLOW_COPY_AND_ASSIGN(SwReporterOnDemandFetcherTest);
+};
+
+TEST_F(SwReporterOnDemandFetcherTest, TestUpdateSuccess) {
+  CreateOnDemandFetcherAndVerifyExpecations(true);
+
+  EXPECT_TRUE(on_demand_update_called_);
+}
+
+TEST_F(SwReporterOnDemandFetcherTest, TestUpdateFailure) {
+  CreateOnDemandFetcherAndVerifyExpecations(false);
+
+  EXPECT_TRUE(on_demand_update_called_);
+}
+
 }  // namespace component_updater
diff --git a/chrome/browser/component_updater/widevine_cdm_component_installer.cc b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
index 2d27194..b9a08e2a 100644
--- a/chrome/browser/component_updater/widevine_cdm_component_installer.cc
+++ b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
@@ -39,6 +39,7 @@
 #include "content/public/browser/plugin_service.h"
 #include "content/public/common/cdm_info.h"
 #include "content/public/common/pepper_plugin_info.h"
+#include "media/base/video_codecs.h"
 #include "media/cdm/supported_cdm_versions.h"
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
 
@@ -223,6 +224,27 @@
   return codecs;
 }
 
+std::vector<media::VideoCodec> ConvertCodecsString(const std::string& codecs) {
+  std::vector<media::VideoCodec> supported_video_codecs;
+  const std::vector<base::StringPiece> supported_codecs =
+      base::SplitStringPiece(codecs,
+                             std::string(1, kCdmSupportedCodecsValueDelimiter),
+                             base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+  for (const auto& codec : supported_codecs) {
+    if (codec == kCdmSupportedCodecVp8)
+      supported_video_codecs.push_back(media::VideoCodec::kCodecVP8);
+    else if (codec == kCdmSupportedCodecVp9)
+      supported_video_codecs.push_back(media::VideoCodec::kCodecVP9);
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+    else if (codec == kCdmSupportedCodecAvc1)
+      supported_video_codecs.push_back(media::VideoCodec::kCodecH264);
+#endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
+  }
+
+  return supported_video_codecs;
+}
+
 bool GetPersistentLicenseSupport(const base::DictionaryValue& manifest) {
   std::string supported;
   const base::Value* value = manifest.FindKey(kCdmPersistentLicenseSupportName);
@@ -257,13 +279,13 @@
   const base::FilePath cdm_path =
       GetPlatformDirectory(cdm_install_dir)
           .AppendASCII(base::GetNativeLibraryName(kWidevineCdmLibraryName));
-  const std::vector<std::string> supported_codecs = base::SplitString(
-      codecs, std::string(1, kCdmSupportedCodecsValueDelimiter),
-      base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-  CdmRegistry::GetInstance()->RegisterCdm(
-      content::CdmInfo(kWidevineCdmDisplayName, kWidevineCdmGuid, cdm_version,
-                       cdm_path, kWidevineCdmFileSystemId, supported_codecs,
-                       supports_persistent_license, kWidevineKeySystem, false));
+  std::vector<media::VideoCodec> supported_video_codecs =
+      ConvertCodecsString(codecs);
+
+  CdmRegistry::GetInstance()->RegisterCdm(content::CdmInfo(
+      kWidevineCdmDisplayName, kWidevineCdmGuid, cdm_version, cdm_path,
+      kWidevineCdmFileSystemId, supported_video_codecs,
+      supports_persistent_license, kWidevineKeySystem, false));
 }
 
 }  // namespace
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 1857d94..c313b2ef 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -618,6 +618,34 @@
 #endif
 }
 
+bool ChromeDownloadManagerDelegate::IsMostRecentDownloadItemAtFilePath(
+    DownloadItem* download) {
+  Profile* profile = Profile::FromBrowserContext(download->GetBrowserContext());
+  std::vector<Profile*> profiles_to_check = {profile->GetOriginalProfile()};
+  if (profile->HasOffTheRecordProfile()) {
+    profiles_to_check.push_back(profile->GetOffTheRecordProfile());
+  }
+
+  std::vector<DownloadItem*> all_downloads;
+  for (auto* profile : profiles_to_check) {
+    content::DownloadManager* manager =
+        content::BrowserContext::GetDownloadManager(profile);
+    if (manager)
+      manager->GetAllDownloads(&all_downloads);
+  }
+
+  for (const auto* item : all_downloads) {
+    if (item->GetGuid() == download->GetGuid() ||
+        item->GetTargetFilePath() != download->GetTargetFilePath())
+      continue;
+
+    if (item->GetState() == DownloadItem::IN_PROGRESS)
+      return false;
+  }
+
+  return true;
+}
+
 void ChromeDownloadManagerDelegate::ShowDownloadInShell(
     DownloadItem* download) {
   if (!download->CanShowInFolder())
diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h
index 898690d..089756dc1 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.h
+++ b/chrome/browser/download/chrome_download_manager_delegate.h
@@ -85,6 +85,8 @@
   download::InProgressCache* GetInProgressCache() override;
   void SanitizeSavePackageResourceName(base::FilePath* filename) override;
   void OpenDownload(content::DownloadItem* download) override;
+  bool IsMostRecentDownloadItemAtFilePath(
+      content::DownloadItem* download) override;
   void ShowDownloadInShell(content::DownloadItem* download) override;
   void CheckForFileExistence(
       content::DownloadItem* download,
diff --git a/chrome/browser/extensions/active_tab_unittest.cc b/chrome/browser/extensions/active_tab_unittest.cc
index 3abd5bf..f043480a 100644
--- a/chrome/browser/extensions/active_tab_unittest.cc
+++ b/chrome/browser/extensions/active_tab_unittest.cc
@@ -40,6 +40,8 @@
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/ui/ash/test_wallpaper_controller.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/chromeos_switches.h"
@@ -461,6 +463,11 @@
       GetUserIdHashByUserIdForTesting(user_id);
   ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal());
   chromeos::WallpaperManager::Initialize();
+  std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_ =
+      std::make_unique<WallpaperControllerClient>();
+  TestWallpaperController test_wallpaper_controller_;
+  wallpaper_controller_client_->InitForTesting(
+      test_wallpaper_controller_.CreateInterfacePtr());
   g_browser_process->local_state()->SetString(
       "PublicAccountPendingDataRemoval", user_email);
   user_manager::UserManager::Get()->UserLoggedIn(account_id, user_id_hash,
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index deeb87e..8b66159f 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -316,6 +316,10 @@
 const char kEnableBrotliDescription[] =
     "Enable Brotli Content-Encoding support.";
 
+const char kEnableCaptivePortalRandomUrl[] = "Captive Portal url Randomization";
+const char kEnableCaptivePortalRandomUrlDescription[] =
+    "Enable Captive Portal URL randomization.";
+
 const char kEnableClientLoFiName[] = "Client-side Lo-Fi previews";
 
 const char kEnableClientLoFiDescription[] =
@@ -2454,6 +2458,10 @@
     "Disable tablet mode autohide titlebars functionality. The user will be "
     "able to see the titlebar in tablet mode.";
 
+const char kDisableTabletSplitViewName[] = "Disable split view in Tablet mode";
+const char kDisableTabletSplitViewDescription[] =
+    "Disable split view for Chrome OS tablet mode.";
+
 const char kEnablePerUserTimezoneName[] = "Per-user time zone preferences.";
 const char kEnablePerUserTimezoneDescription[] =
     "Chrome OS system timezone preference is stored and handled for each user "
@@ -2497,10 +2505,6 @@
 const char kEnableImeMenuDescription[] =
     "Enable access to the new IME menu in the Language Settings page.";
 
-const char kEnableTabletSplitViewName[] = "Split view in Tablet mode";
-const char kEnableTabletSplitViewDescription[] =
-    "Enable split view for Chrome OS tablet mode.";
-
 const char kEnableZipArchiverPackerName[] = "ZIP archiver - Packer";
 const char kEnableZipArchiverPackerDescription[] =
     "Enable the ability to archive files on Drive in the Files app";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 7d6bfbf8..713bb3e 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -219,6 +219,9 @@
 extern const char kEnableBrotliName[];
 extern const char kEnableBrotliDescription[];
 
+extern const char kEnableCaptivePortalRandomUrl[];
+extern const char kEnableCaptivePortalRandomUrlDescription[];
+
 extern const char kEnableClientLoFiName[];
 extern const char kEnableClientLoFiDescription[];
 
@@ -1517,6 +1520,9 @@
 extern const char kDisableTabletAutohideTitlebarsName[];
 extern const char kDisableTabletAutohideTitlebarsDescription[];
 
+extern const char kDisableTabletSplitViewName[];
+extern const char kDisableTabletSplitViewDescription[];
+
 extern const char kEnablePerUserTimezoneName[];
 extern const char kEnablePerUserTimezoneDescription[];
 
@@ -1544,9 +1550,6 @@
 extern const char kEnableImeMenuName[];
 extern const char kEnableImeMenuDescription[];
 
-extern const char kEnableTabletSplitViewName[];
-extern const char kEnableTabletSplitViewDescription[];
-
 extern const char kEnableZipArchiverPackerName[];
 extern const char kEnableZipArchiverPackerDescription[];
 
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index 22968fc..ce5d47c1 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -49,6 +49,7 @@
 // Variants of External Clear Key key system to test different scenarios.
 // To add a new variant, make sure you also update:
 // - media/test/data/eme_player_js/globals.js
+// - media/test/data/eme_player_js/player_utils.js
 // - AddExternalClearKey() in chrome_key_systems.cc
 // - CreateCdmInstance() in clear_key_cdm.cc
 const char kExternalClearKeyRenewalKeySystem[] =
@@ -69,6 +70,8 @@
 #endif
 const char kExternalClearKeyStorageIdTestKeySystem[] =
     "org.chromium.externalclearkey.storageidtest";
+const char kExternalClearKeyCdmProxyTestKeySystem[] =
+    "org.chromium.externalclearkey.cdmproxytest";
 #endif
 
 // Supported media types.
@@ -296,6 +299,7 @@
 
   void SetUpCommandLineForKeySystem(const std::string& key_system,
                                     CdmHostType cdm_host_type,
+                                    bool support_experimental_cdm_interface,
                                     base::CommandLine* command_line) {
     if (GetServerConfig(key_system))
       // Since the web and license servers listen on different ports, we need to
@@ -311,18 +315,27 @@
                         media::kClearKeyCdmAdapterFileName,
                         media::kClearKeyCdmDisplayName,
                         media::kClearKeyCdmPepperMimeType);
+
+      // TODO(xhwang): Update ScopedFeatureList::InitWithFeatures() to accept
+      // vectors so that we can simplify this block.
       if (cdm_host_type == CdmHostType::kMojo) {
         RegisterExternalClearKey(command_line);
-        scoped_feature_list_.InitWithFeatures(
-            {media::kExternalClearKeyForTesting, media::kMojoCdm}, {});
+        if (support_experimental_cdm_interface) {
+          scoped_feature_list_.InitWithFeatures(
+              {media::kExternalClearKeyForTesting,
+               media::kSupportExperimentalCdmInterface, media::kMojoCdm},
+              {});
+        } else {
+          scoped_feature_list_.InitWithFeatures(
+              {media::kExternalClearKeyForTesting, media::kMojoCdm}, {});
+        }
       } else {
-        // Pepper CDMs are conditionally compiled with or without support for
-        // experimental CDMs, so media::kSupportExperimentalCdmInterface is
-        // not needed as it isn't checked.
+        // Pepper CDM does not support any experimental CDM interface.
         scoped_feature_list_.InitWithFeatures(
             {media::kExternalClearKeyForTesting}, {});
       }
     } else {
+      // Experimental CDM interface is only supported with External Clear Key.
       if (cdm_host_type == CdmHostType::kMojo) {
         scoped_feature_list_.InitWithFeatures({media::kMojoCdm}, {});
       }
@@ -373,10 +386,37 @@
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override {
     EncryptedMediaTestBase::SetUpCommandLine(command_line);
-    SetUpCommandLineForKeySystem(kExternalClearKeyKeySystem, GetParam(),
+    SetUpCommandLineForKeySystem(kExternalClearKeyKeySystem, GetParam(), false,
                                  command_line);
   }
 };
+
+// Tests encrypted media playback using experimental CDM interface. Note that
+// experimental CDM interface is only supported by ExternalClearKey key system
+// using mojo CDM.
+class EncryptedMediaTestExperimentalCdmInterface
+    : public EncryptedMediaTestBase {
+ public:
+  // We use special |key_system| names to do non-playback related tests,
+  // e.g. kExternalClearKeyFileIOTestKeySystem is used to test file IO.
+  void TestNonPlaybackCases(const std::string& key_system,
+                            const std::string& expected_title) {
+    // Since we do not test playback, arbitrarily choose a test file and source
+    // type.
+    RunEncryptedMediaTest(kDefaultEmePlayer, "bear-a_enc-a.webm",
+                          kWebMVorbisAudioOnly, key_system, SrcType::SRC,
+                          kNoSessionToLoad, false, PlayCount::ONCE,
+                          expected_title);
+  }
+
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    EncryptedMediaTestBase::SetUpCommandLine(command_line);
+    SetUpCommandLineForKeySystem(kExternalClearKeyKeySystem, CdmHostType::kMojo,
+                                 true, command_line);
+  }
+};
+
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
 // Tests encrypted media playback with a combination of parameters:
@@ -502,7 +542,7 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     EncryptedMediaTestBase::SetUpCommandLine(command_line);
     SetUpCommandLineForKeySystem(CurrentKeySystem(), CurrentCdmHostType(),
-                                 command_line);
+                                 false, command_line);
   }
 };
 
@@ -831,4 +871,11 @@
                    true);
 }
 
+// Tests using experimental CDM interface.
+
+IN_PROC_BROWSER_TEST_F(EncryptedMediaTestExperimentalCdmInterface, CdmProxy) {
+  TestNonPlaybackCases(kExternalClearKeyCdmProxyTestKeySystem,
+                       kUnitTestSuccess);
+}
+
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest_base.cc b/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
index 3da2312..6f39913 100644
--- a/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
+++ b/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
@@ -12,19 +12,24 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "chrome/browser/extensions/chrome_test_extension_loader.h"
 #include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
 #include "chrome/browser/permissions/permission_request_manager.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/test/browser_test_utils.h"
+#include "extensions/browser/extension_registry.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
 #if defined(OS_WIN)
@@ -322,6 +327,20 @@
       embedded_test_server()->GetURL(test_page));
 }
 
+content::WebContents* WebRtcTestBase::OpenTestPageInNewTab(
+    const std::string& test_page) const {
+  chrome::AddTabAt(browser(), GURL(), -1, true);
+  GURL url = embedded_test_server()->GetURL(test_page);
+  ui_test_utils::NavigateToURL(browser(), url);
+  content::WebContents* new_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  // Accept if necessary, but don't expect a prompt (because auto-accept is also
+  // okay).
+  PermissionRequestManager::FromWebContents(new_tab)
+      ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+  return new_tab;
+}
+
 void WebRtcTestBase::CloseLastLocalStream(
     content::WebContents* tab_contents) const {
   EXPECT_EQ("ok-stopped",
@@ -721,3 +740,32 @@
 void WebRtcTestBase::CollectGarbage(content::WebContents* tab) const {
   EXPECT_EQ("ok-gc", ExecuteJavascript("collectGarbage()", tab));
 }
+
+std::string WebRtcTestBase::GetDesktopMediaStream(content::WebContents* tab) {
+  DCHECK(static_cast<bool>(LoadDesktopCaptureExtension()));
+
+  // Post a task to the extension, opening a desktop media stream.
+  return ExecuteJavascript("openDesktopMediaStream()", tab);
+}
+
+base::Optional<std::string> WebRtcTestBase::LoadDesktopCaptureExtension() {
+  base::Optional<std::string> extension_id;
+  if (!desktop_capture_extension_.get()) {
+    extensions::ChromeTestExtensionLoader loader(browser()->profile());
+    base::FilePath extension_path;
+    EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extension_path));
+    extension_path = extension_path.AppendASCII("extensions/desktop_capture");
+    desktop_capture_extension_ = loader.LoadExtension(extension_path);
+    LOG(INFO) << "Loaded desktop capture extension, id = "
+              << desktop_capture_extension_->id();
+
+    extensions::ExtensionRegistry* registry =
+        extensions::ExtensionRegistry::Get(browser()->profile());
+
+    EXPECT_TRUE(registry->enabled_extensions().GetByID(
+        desktop_capture_extension_->id()));
+  }
+  if (desktop_capture_extension_)
+    extension_id.emplace(desktop_capture_extension_->id());
+  return extension_id;
+}
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest_base.h b/chrome/browser/media/webrtc/webrtc_browsertest_base.h
index afee82d..0c12cbfd 100644
--- a/chrome/browser/media/webrtc/webrtc_browsertest_base.h
+++ b/chrome/browser/media/webrtc/webrtc_browsertest_base.h
@@ -22,6 +22,10 @@
 class WebContents;
 }
 
+namespace extensions {
+class Extension;
+}
+
 // Base class for WebRTC browser tests with useful primitives for interacting
 // getUserMedia. We use inheritance here because it makes the test code look
 // as clean as it can be.
@@ -107,9 +111,10 @@
   content::WebContents* OpenTestPageAndGetUserMediaInNewTab(
     const std::string& test_page) const;
 
-  // Opens the page at |url| where getUserMedia has been invoked through other
-  // means and accepts the user media request.
-  content::WebContents* OpenPageAndAcceptUserMedia(const GURL& url) const;
+  // Convenience method which gets the URL for |test_page|, but without calling
+  // GetUserMedia.
+  content::WebContents* OpenTestPageInNewTab(
+      const std::string& test_page) const;
 
   // Closes the last local stream acquired by the GetUserMedia* methods.
   void CloseLastLocalStream(content::WebContents* tab_contents) const;
@@ -238,6 +243,10 @@
   // Performs garbage collection with "gc()". Requires command line switch
   // |kJavaScriptFlags| with "--expose-gc".
   void CollectGarbage(content::WebContents* tab) const;
+  // Try to open a dekstop media stream, and return the stream id.
+  // On failure, will return empty string.
+  std::string GetDesktopMediaStream(content::WebContents* tab);
+  base::Optional<std::string> LoadDesktopCaptureExtension();
 
  private:
   void CloseInfoBarInTab(content::WebContents* tab_contents,
@@ -260,6 +269,7 @@
       const std::string& constraints) const;
 
   bool detect_errors_in_javascript_;
+  scoped_refptr<const extensions::Extension> desktop_capture_extension_;
 
   DISALLOW_COPY_AND_ASSIGN(WebRtcTestBase);
 };
diff --git a/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc b/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
new file mode 100644
index 0000000..ed531ca
--- /dev/null
+++ b/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
@@ -0,0 +1,98 @@
+// 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/command_line.h"
+#include "build/build_config.h"
+#include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
+#include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
+#include "content/public/common/features.h"
+#include "content/public/test/browser_test_utils.h"
+#include "media/base/media_switches.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace {
+static const char kMainWebrtcTestHtmlPage[] = "/webrtc/webrtc_jsep01_test.html";
+}  // namespace
+
+// Top-level integration test for WebRTC. Uses an actual desktop capture
+// extension to capture whole screen.
+class WebRtcDesktopCaptureBrowserTest : public WebRtcTestBase {
+ public:
+  WebRtcDesktopCaptureBrowserTest() : left_tab_(nullptr), right_tab_(nullptr) {}
+
+  void SetUpInProcessBrowserTestFixture() override {
+    DetectErrorsInJavaScript();  // Look for errors in our rather complex js.
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // Ensure the infobar is enabled, since we expect that in this test.
+    EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
+
+    // Always use fake devices.
+    command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
+
+    // Flags use to automatically select the right dekstop source and get
+    // around security restrictions.
+    command_line->AppendSwitchASCII(switches::kAutoSelectDesktopCaptureSource,
+                                    "Entire screen");
+    command_line->AppendSwitch(switches::kEnableUserMediaScreenCapturing);
+  }
+
+ protected:
+  void DetectVideoAndHangUp() {
+    StartDetectingVideo(left_tab_, "remote-view");
+    StartDetectingVideo(right_tab_, "remote-view");
+#if !defined(OS_MACOSX)
+    // Video is choppy on Mac OS X. http://crbug.com/443542.
+    WaitForVideoToPlay(left_tab_);
+    WaitForVideoToPlay(right_tab_);
+#endif
+    HangUp(left_tab_);
+    HangUp(right_tab_);
+  }
+
+  content::WebContents* left_tab_;
+  content::WebContents* right_tab_;
+};
+
+// TODO(crbug.com/796889): Enable on Mac when thread check crash is fixed.
+// TODO(sprang): Figure out why test times out on Win 10 and ChromeOS.
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#define MAYBE_RunsScreenshareFromOneTabToAnother \
+  RunsScreenshareFromOneTabToAnother
+#else
+#define MAYBE_RunsScreenshareFromOneTabToAnother \
+  DISABLED_RunsScreenshareFromOneTabToAnother
+#endif
+IN_PROC_BROWSER_TEST_F(WebRtcDesktopCaptureBrowserTest,
+                       MAYBE_RunsScreenshareFromOneTabToAnother) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  LoadDesktopCaptureExtension();
+  left_tab_ = OpenTestPageInNewTab(kMainWebrtcTestHtmlPage);
+  std::string stream_id = GetDesktopMediaStream(left_tab_);
+  EXPECT_NE(stream_id, "");
+
+  LOG(INFO) << "Opened desktop media stream, got id " << stream_id;
+
+  const std::string constraints =
+      "{audio: false, video: {mandatory: {chromeMediaSource: 'desktop',"
+      "chromeMediaSourceId: '" +
+      stream_id + "'}}}";
+  EXPECT_TRUE(GetUserMediaWithSpecificConstraintsAndAcceptIfPrompted(
+      left_tab_, constraints));
+  right_tab_ = OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
+  SetupPeerconnectionWithLocalStream(left_tab_);
+  SetupPeerconnectionWithLocalStream(right_tab_);
+  NegotiateCall(left_tab_, right_tab_);
+  VerifyStatsGeneratedCallback(right_tab_);
+  DetectVideoAndHangUp();
+}
diff --git a/chrome/browser/memory_details_android.cc b/chrome/browser/memory_details_android.cc
index fdd1cf2..d8954be8 100644
--- a/chrome/browser/memory_details_android.cc
+++ b/chrome/browser/memory_details_android.cc
@@ -55,7 +55,8 @@
     pmi.pid = *i;
     pmi.num_processes = 1;
 
-    if (pmi.pid == base::GetCurrentProcId())
+    base::ProcessId current_pid = base::GetCurrentProcId();
+    if (pmi.pid == current_pid)
       pmi.process_type = content::PROCESS_TYPE_BROWSER;
     else
       pmi.process_type = content::PROCESS_TYPE_UNKNOWN;
@@ -63,8 +64,13 @@
     std::unique_ptr<base::ProcessMetrics> metrics(
         base::ProcessMetrics::CreateProcessMetrics(*i));
     metrics->GetWorkingSetKBytes(&pmi.working_set);
-    // TODO(dcastagna): Compute number of open fds (pmi.num_open_fds) and soft
-    // limits (pmi.open_fds_soft_limit) on android.
+
+    // TODO(ssid): Reading "/proc/fd" only works for current process. For child
+    // processes, the values need to be computed by the process itself.
+    if (pmi.pid == current_pid) {
+      pmi.num_open_fds = metrics->GetOpenFdCount();
+      pmi.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();
+    }
 
     out->processes.push_back(pmi);
   }
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc
index e0889e9..9980613 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc
@@ -290,7 +290,7 @@
   return base::flat_map<const char*, int64_t>();
 }
 
-ProcessInfoVector GetProcessInfo(ukm::UkmRecorder& ukm_recorder) {
+ProcessInfoVector GetProcessInfo(ukm::TestUkmRecorder& ukm_recorder) {
   ProcessInfoVector process_infos;
 
   // Process 200 always has no URLs.
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index 3340b5a..117d4a83 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -21,6 +21,7 @@
 #include "content/public/browser/browsing_data_remover.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browsing_data_remover_test_util.h"
+#include "content/public/test/test_utils.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
 
 #if defined(OS_CHROMEOS)
@@ -42,6 +43,8 @@
       ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY,
       content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, &observer);
   observer.BlockUntilCompletion();
+  // Make sure HistoryServiceObservers have a chance to be notified.
+  content::RunAllPendingInMessageLoop();
 }
 
 }  // namespace
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc
index 3ea38b8..831719b 100644
--- a/chrome/browser/net/system_network_context_manager.cc
+++ b/chrome/browser/net/system_network_context_manager.cc
@@ -23,6 +23,7 @@
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/service_names.mojom.h"
+#include "content/public/network/network_service.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
 #include "net/net_features.h"
 
@@ -36,6 +37,8 @@
     safe_browsing::SafeBrowsingService* safe_browsing_service) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
+  if (!base::FeatureList::IsEnabled(features::kNetworkService))
+    content::GetNetworkServiceImpl()->DisableQuic();
   io_thread->DisableQuic();
 
   // Safebrowsing isn't yet using the IOThread's NetworkService, so must be
@@ -111,7 +114,8 @@
   // Profiles will also have QUIC disabled (because both IOThread's
   // NetworkService and the network service, if enabled will disable QUIC).
 
-  content::GetNetworkService()->DisableQuic();
+  if (base::FeatureList::IsEnabled(features::kNetworkService))
+    content::GetNetworkService()->DisableQuic();
 
   IOThread* io_thread = g_browser_process->io_thread();
   // Nothing more to do if IOThread has already been shut down.
diff --git a/chrome/browser/offline_pages/android/offline_pages_download_manager_bridge.cc b/chrome/browser/offline_pages/android/offline_pages_download_manager_bridge.cc
new file mode 100644
index 0000000..faab823
--- /dev/null
+++ b/chrome/browser/offline_pages/android/offline_pages_download_manager_bridge.cc
@@ -0,0 +1,67 @@
+// 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/offline_pages/android/offline_pages_download_manager_bridge.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "jni/OfflinePagesDownloadManagerBridge_jni.h"
+
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace offline_pages {
+namespace android {
+
+// Returns true if ADM is available on this phone.
+bool OfflinePagesDownloadManagerBridge::IsAndroidDownloadManagerInstalled() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  jboolean is_installed =
+      Java_OfflinePagesDownloadManagerBridge_isAndroidDownloadManagerInstalled(
+          env);
+  return is_installed;
+}
+
+// Returns the ADM ID of the download, which we will place in the offline
+// pages database as part of the offline page item.
+long OfflinePagesDownloadManagerBridge::addCompletedDownload(
+    const std::string& title,
+    const std::string& description,
+    const std::string& path,
+    int64_t length,
+    const std::string& uri,
+    const std::string& referer) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  // Convert strings to jstring references.
+  ScopedJavaLocalRef<jstring> j_title =
+      base::android::ConvertUTF8ToJavaString(env, title);
+  ScopedJavaLocalRef<jstring> j_description =
+      base::android::ConvertUTF8ToJavaString(env, description);
+  ScopedJavaLocalRef<jstring> j_path =
+      base::android::ConvertUTF8ToJavaString(env, path);
+  ScopedJavaLocalRef<jstring> j_uri =
+      base::android::ConvertUTF8ToJavaString(env, uri);
+  ScopedJavaLocalRef<jstring> j_referer =
+      base::android::ConvertUTF8ToJavaString(env, referer);
+
+  long count = Java_OfflinePagesDownloadManagerBridge_addCompletedDownload(
+      env, j_title, j_description, j_path, length, j_uri, j_referer);
+  return count;
+}
+
+// Returns the number of pages removed.
+int OfflinePagesDownloadManagerBridge::remove(
+    const std::vector<int64_t>& android_download_manager_ids) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  // Build a JNI array with our ID data.
+  ScopedJavaLocalRef<jlongArray> j_ids =
+      base::android::ToJavaLongArray(env, android_download_manager_ids);
+
+  return Java_OfflinePagesDownloadManagerBridge_remove(env, j_ids);
+}
+
+}  // namespace android
+}  // namespace offline_pages
diff --git a/chrome/browser/offline_pages/android/offline_pages_download_manager_bridge.h b/chrome/browser/offline_pages/android/offline_pages_download_manager_bridge.h
new file mode 100644
index 0000000..b2fd2aa
--- /dev/null
+++ b/chrome/browser/offline_pages/android/offline_pages_download_manager_bridge.h
@@ -0,0 +1,38 @@
+// 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_OFFLINE_PAGES_ANDROID_OFFLINE_PAGES_DOWNLOAD_MANAGER_BRIDGE_H_
+#define CHROME_BROWSER_OFFLINE_PAGES_ANDROID_OFFLINE_PAGES_DOWNLOAD_MANAGER_BRIDGE_H_
+
+#include <vector>
+
+namespace offline_pages {
+namespace android {
+
+// Bridge between C++ and Java for communicating with the AndroidDownloadManager
+// on Android.
+class OfflinePagesDownloadManagerBridge {
+ public:
+  // Returns true if ADM is available on this phone.
+  static bool IsAndroidDownloadManagerInstalled();
+
+  // Adds the download to the list managed by the AndroidDownloadManager.
+  // Returns the ADM ID of the download, which we will place in the offline
+  // pages database as part of the offline page item.
+  static long addCompletedDownload(const std::string& title,
+                                   const std::string& description,
+                                   const std::string& path,
+                                   int64_t length,
+                                   const std::string& uri,
+                                   const std::string& referer);
+
+  // Removes the pages with the given download IDs, and returns the number of
+  // pages removed.
+  static int remove(const std::vector<int64_t>& android_download_manager_ids);
+};
+
+}  // namespace android
+}  // namespace offline_pages
+
+#endif  // CHROME_BROWSER_OFFLINE_PAGES_ANDROID_OFFLINE_PAGES_DOWNLOAD_MANAGER_BRIDGE_H_
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc
index 5f268557..d3ce003 100644
--- a/chrome/browser/printing/print_job.cc
+++ b/chrome/browser/printing/print_job.cc
@@ -173,9 +173,6 @@
     return;
   is_canceling_ = true;
 
-  // Be sure to live long enough.
-  scoped_refptr<PrintJob> handle(this);
-
   DCHECK(RunsTasksInCurrentSequence());
   if (worker_ && worker_->IsRunning()) {
     // Call this right now so it renders the context invalid. Do not use
@@ -280,6 +277,8 @@
 
 void PrintJob::OnPdfConversionStarted(int page_count) {
   if (page_count <= 0) {
+    // Be sure to live long enough.
+    scoped_refptr<PrintJob> handle(this);
     pdf_conversion_state_.reset();
     Cancel();
     return;
@@ -295,6 +294,8 @@
   DCHECK(pdf_conversion_state_);
   if (!document_.get() || !metafile || page_number < 0 ||
       static_cast<size_t>(page_number) >= pdf_page_mapping_.size()) {
+    // Be sure to live long enough.
+    scoped_refptr<PrintJob> handle(this);
     pdf_conversion_state_.reset();
     Cancel();
     return;
diff --git a/chrome/browser/printing/print_job.h b/chrome/browser/printing/print_job.h
index df73274..2d5c8fb8 100644
--- a/chrome/browser/printing/print_job.h
+++ b/chrome/browser/printing/print_job.h
@@ -67,13 +67,15 @@
   void StartPrinting();
 
   // Asks for the worker thread to finish its queued tasks and disconnects the
-  // delegate object. The PrintJobManager will remove its reference. This may
-  // have the side-effect of destroying the object if the caller doesn't have a
-  // handle to the object. Use PrintJob::is_stopped() to check whether the
-  // worker thread has actually stopped.
+  // delegate object. The PrintJobManager will remove its reference.
+  // WARNING: This may have the side-effect of destroying the object if the
+  // caller doesn't have a handle to the object. Use PrintJob::is_stopped() to
+  // check whether the worker thread has actually stopped.
   void Stop();
 
   // Cancels printing job and stops the worker thread. Takes effect immediately.
+  // The caller must have a reference to the PrintJob before calling Cancel(),
+  // since Cancel() calls Stop(). See WARNING above for Stop().
   void Cancel();
 
   // Synchronously wait for the job to finish. It is mainly useful when the
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc
index b5e36da..4684c250 100644
--- a/chrome/browser/profiles/profile_manager_unittest.cc
+++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -56,6 +56,8 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
+#include "chrome/browser/ui/ash/test_wallpaper_controller.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chromeos/chromeos_switches.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/user_manager.h"
@@ -142,6 +144,10 @@
     base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
     cl->AppendSwitch(switches::kTestType);
     chromeos::WallpaperManager::Initialize();
+    wallpaper_controller_client_ =
+        std::make_unique<WallpaperControllerClient>();
+    wallpaper_controller_client_->InitForTesting(
+        test_wallpaper_controller_.CreateInterfacePtr());
 
     // Have to manually reset the session type in between test runs because
     // some tests log in users.
@@ -157,6 +163,7 @@
     content::RunAllTasksUntilIdle();
 #if defined(OS_CHROMEOS)
     session_type_.reset();
+    wallpaper_controller_client_.reset();
     chromeos::WallpaperManager::Shutdown();
 #endif
   }
@@ -234,6 +241,8 @@
   chromeos::ScopedTestUserManager test_user_manager_;
   std::unique_ptr<base::AutoReset<extensions::FeatureSessionType>>
       session_type_;
+  std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_;
+  TestWallpaperController test_wallpaper_controller_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(ProfileManagerTest);
@@ -607,6 +616,11 @@
     cl->AppendSwitch(::switches::kIncognito);
 
     chromeos::WallpaperManager::Initialize();
+    wallpaper_controller_client_ =
+        std::make_unique<WallpaperControllerClient>();
+    wallpaper_controller_client_->InitForTesting(
+        test_wallpaper_controller_.CreateInterfacePtr());
+
     // Have to manually reset the session type in between test runs because
     // RegisterUser() changes it.
     ASSERT_EQ(extensions::FeatureSessionType::INITIAL,
diff --git a/chrome/browser/profiling_host/profiling_process_host.cc b/chrome/browser/profiling_host/profiling_process_host.cc
index a50f462..a142363 100644
--- a/chrome/browser/profiling_host/profiling_process_host.cc
+++ b/chrome/browser/profiling_host/profiling_process_host.cc
@@ -22,6 +22,7 @@
 #include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
+#include "base/trace_event/trace_log.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
@@ -69,14 +70,15 @@
   std::string json_;
 };
 
-base::trace_event::TraceConfig GetBackgroundTracingConfig() {
+base::trace_event::TraceConfig GetBackgroundTracingConfig(bool anonymize) {
   // Disable all categories other than memory-infra.
   base::trace_event::TraceConfig trace_config(
       "-*,disabled-by-default-memory-infra",
       base::trace_event::RECORD_UNTIL_FULL);
 
   // This flag is set by background tracing to filter out undesired events.
-  trace_config.EnableArgumentFilter();
+  if (anonymize)
+    trace_config.EnableArgumentFilter();
 
   // Trigger a background memory dump exactly once by setting a time-delta
   // between dumps of 2**29.
@@ -269,8 +271,11 @@
   bool keep_small_allocations =
       !force_prune && cmdline->HasSwitch(switches::kMemlogKeepSmallAllocations);
 
+  bool strip_path_from_mapped_files = base::trace_event::TraceLog::GetInstance()
+                                          ->GetCurrentTraceConfig()
+                                          .IsArgumentFilterEnabled();
   profiling_service_->DumpProcessesForTracing(
-      keep_small_allocations,
+      keep_small_allocations, strip_path_from_mapped_files,
       base::BindOnce(&ProfilingProcessHost::OnDumpProcessesForTracingCallback,
                      base::Unretained(this), dump_guid));
 }
@@ -474,7 +479,8 @@
       },
       std::move(dest), std::move(done));
   RequestTraceWithHeapDump(std::move(finish_trace_callback),
-                           stop_immediately_after_heap_dump_for_tests);
+                           stop_immediately_after_heap_dump_for_tests,
+                           false /* anonymize */);
 }
 
 void ProfilingProcessHost::RequestProcessReport(std::string trigger_name) {
@@ -504,12 +510,15 @@
         }
       },
       base::Unretained(this), std::move(trigger_name));
-  RequestTraceWithHeapDump(std::move(finish_report_callback), false);
+  RequestTraceWithHeapDump(std::move(finish_report_callback),
+                           false /* keep_small_allocations */,
+                           true /* anonymize */);
 }
 
 void ProfilingProcessHost::RequestTraceWithHeapDump(
     TraceFinishedCallback callback,
-    bool stop_immediately_after_heap_dump_for_tests) {
+    bool stop_immediately_after_heap_dump_for_tests,
+    bool anonymize) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
   if (!connector_) {
@@ -521,7 +530,7 @@
   }
 
   bool result = content::TracingController::GetInstance()->StartTracing(
-      GetBackgroundTracingConfig(), base::Closure());
+      GetBackgroundTracingConfig(anonymize), base::Closure());
   if (!result) {
     DLOG(ERROR) << "Requesting heap dump when tracing has already started.";
     base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/profiling_host/profiling_process_host.h b/chrome/browser/profiling_host/profiling_process_host.h
index 5d792df..4d0231e 100644
--- a/chrome/browser/profiling_host/profiling_process_host.h
+++ b/chrome/browser/profiling_host/profiling_process_host.h
@@ -143,9 +143,9 @@
   // finished signal, in case there's a problem with the profiling process and
   // the heap-dump is never added to the trace.
   // Public for testing.
-  void RequestTraceWithHeapDump(
-      TraceFinishedCallback callback,
-      bool stop_immediately_after_heap_dump_for_tests);
+  void RequestTraceWithHeapDump(TraceFinishedCallback callback,
+                                bool stop_immediately_after_heap_dump_for_tests,
+                                bool anonymize);
 
   // Returns the pids of all profiled processes. The callback is posted on the
   // UI thread.
diff --git a/chrome/browser/profiling_host/profiling_test_driver.cc b/chrome/browser/profiling_host/profiling_test_driver.cc
index 452eeb52..64325f6 100644
--- a/chrome/browser/profiling_host/profiling_test_driver.cc
+++ b/chrome/browser/profiling_host/profiling_test_driver.cc
@@ -350,7 +350,8 @@
   profiling::ProfilingProcessHost::GetInstance()->RequestTraceWithHeapDump(
       base::Bind(&ProfilingTestDriver::TraceFinished, base::Unretained(this),
                  std::move(finish_tracing_closure)),
-      true);
+      true /* keep_small_allocations */,
+      false /* strip_path_from_mapped_files */);
 
   if (synchronous)
     run_loop->Run();
diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
index 85a565d1..75a9cf1 100644
--- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
+++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
@@ -1111,7 +1111,7 @@
   EXPECT_FALSE(send_and_check_show_ime());
 
   // Setting an irrelevant field. Expect no IME.
-  sender.SetMode(ui::TEXT_INPUT_MODE_LATIN);
+  sender.SetMode(ui::TEXT_INPUT_MODE_TEXT);
   EXPECT_FALSE(send_and_check_show_ime());
 
   // Set |TextInputState.show_ime_if_needed|. Expect IME.
diff --git a/chrome/browser/resources/bookmark_manager/js/compiled_resources2.gyp b/chrome/browser/resources/bookmark_manager/js/compiled_resources2.gyp
index 30dce813..388e1d1b 100644
--- a/chrome/browser/resources/bookmark_manager/js/compiled_resources2.gyp
+++ b/chrome/browser/resources/bookmark_manager/js/compiled_resources2.gyp
@@ -35,6 +35,7 @@
           '<(DEPTH)/ui/webui/resources/js/event_tracker.js',
           '<(DEPTH)/ui/webui/resources/js/i18n_template_no_process.js',
           '<(DEPTH)/ui/webui/resources/js/load_time_data.js',
+          '<(DEPTH)/ui/webui/resources/js/parse_html_subset.js',
           '<(DEPTH)/ui/webui/resources/js/promise_resolver.js',
           '<(DEPTH)/ui/webui/resources/js/util.js',
           '<(DEPTH)/ui/webui/resources/js/icon.js',
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/background.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/background.js
index 0bae33d..381a28d 100644
--- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/background.js
+++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/background.js
@@ -10,6 +10,7 @@
 
 goog.require('ChromeVoxState');
 goog.require('Msgs');
+goog.require('constants');
 goog.require('cvox.AbstractEarcons');
 goog.require('cvox.BrailleBackground');
 goog.require('cvox.BrailleCaptionsBackground');
@@ -87,7 +88,7 @@
     cvox.BrailleCaptionsBackground.setActive(!!value);
   } else if (pref == 'position') {
     cvox.ChromeVox.position =
-        /** @type {Object<string, cvox.Point>} */ (JSON.parse(
+        /** @type {Object<string, constants.Point>} */ (JSON.parse(
             /** @type {string} */ (value)));
   }
   window['prefs'].setPref(pref, value);
diff --git a/chrome/browser/resources/chromeos/chromevox/common/chromevox.js b/chrome/browser/resources/chromeos/chromevox/common/chromevox.js
index 1dcb41b..37cb604f 100644
--- a/chrome/browser/resources/chromeos/chromevox/common/chromevox.js
+++ b/chrome/browser/resources/chromeos/chromevox/common/chromevox.js
@@ -9,6 +9,7 @@
  */
 
 goog.provide('cvox.ChromeVox');
+goog.require('constants');
 
 // Forward declarations.
 // TODO (stoarca): Put these in a separate file and pass that
@@ -132,11 +133,7 @@
  */
 cvox.ChromeVox.keyEcho = {};
 /**
- * @typedef {{x: number, y: number}}
- */
-cvox.Point;
-/**
- * @type {Object<string, cvox.Point>}
+ * @type {Object<string, constants.Point>}
  */
 cvox.ChromeVox.position = {};
 /**
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js
index e05adba..5be61ec 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js
@@ -144,7 +144,7 @@
  * @return {boolean}
  */
 AutomationPredicate.visitedLink = function(node) {
-  return node.state.visited;
+  return node.state[State.VISITED];
 };
 
 /**
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_util.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_util.js
index 903c414..7f439ca1 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_util.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_util.js
@@ -259,7 +259,7 @@
  * with respect to their parents, the hit test considers all children before
  * their parents when looking for a matching node.
  * @param {AutomationNode} node Subtree to search.
- * @param {cvox.Point} point
+ * @param {constants.Point} point
  * @return {AutomationNode}
  */
 AutomationUtil.hitTest = function(node, point) {
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/constants.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/constants.js
index 762ca88e..6d44861 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/constants.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/constants.js
@@ -21,6 +21,12 @@
 };
 
 /**
+ * Represents a point.
+ * @typedef {{x: (number), y: (number)}}
+ */
+constants.Point;
+
+/**
  * If a node contains more characters than this, it should not be visited during
  * object navigation.
  *
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js
index 58ec5483e..519ae8c 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/cursors.js
@@ -538,9 +538,30 @@
       if (!endpoint)
         return this;
 
+      // Finds any explicitly provided focus.
+      var getDirectedFocus = function(node) {
+        return dir == Dir.FORWARD ? node.nextFocus : node.previousFocus;
+      };
+
       // Case 1: forwards (find the root-like node).
-      while (!AutomationPredicate.root(endpoint) && endpoint.parent)
+      var directedFocus;
+      while (!AutomationPredicate.root(endpoint) && endpoint.parent) {
+        if (directedFocus = getDirectedFocus(endpoint)) {
+          window.last = directedFocus;
+          break;
+        }
         endpoint = endpoint.parent;
+      }
+
+      if (directedFocus) {
+        directedFocus =
+            (dir == Dir.FORWARD ?
+                 AutomationUtil.findNodePre(
+                     directedFocus, dir, AutomationPredicate.object) :
+                 AutomationUtil.findLastNode(directedFocus, pred)) ||
+            directedFocus;
+        return new cursors.WrappingCursor(directedFocus, cursors.NODE_INDEX);
+      }
 
       // Always play a wrap earcon when moving forward.
       var playEarcon = dir == Dir.FORWARD;
diff --git a/chrome/browser/resources/chromeos/emulator/audio_settings.html b/chrome/browser/resources/chromeos/emulator/audio_settings.html
index d633a93..688da48 100644
--- a/chrome/browser/resources/chromeos/emulator/audio_settings.html
+++ b/chrome/browser/resources/chromeos/emulator/audio_settings.html
@@ -14,8 +14,9 @@
 
 <dom-module id="audio-settings">
   <template>
-    <style include="device-emulator-shared-styles cr-shared-style iron-flex
-        iron-flex-alignment iron-positioning">
+    <!-- TODO(michaelpg): Wrap the line below to fit within the 80-char limit.
+         See https://github.com/Polymer/polymer/pull/3668. -->
+    <style include="device-emulator-shared-styles cr-shared-style iron-flex iron-flex-alignment iron-positioning">
     </style>
     <dialog is="cr-dialog" id="editDialog">
       <div slot="title">[[currentEditableObject.deviceName]]</div>
diff --git a/chrome/browser/resources/chromeos/emulator/battery_settings.html b/chrome/browser/resources/chromeos/emulator/battery_settings.html
index 1889b1c5..8454f6b 100644
--- a/chrome/browser/resources/chromeos/emulator/battery_settings.html
+++ b/chrome/browser/resources/chromeos/emulator/battery_settings.html
@@ -13,6 +13,8 @@
 
 <dom-module id="battery-settings">
   <template>
+    <!-- TODO(michaelpg): Wrap the line below to fit within the 80-char limit.
+         See https://github.com/Polymer/polymer/pull/3668. -->
     <style include="device-emulator-shared-styles iron-flex iron-flex-alignment
         iron-positioning md-select">
     </style>
diff --git a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html
index 9bc4a1d..5389e24 100644
--- a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html
+++ b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html
@@ -14,8 +14,9 @@
 
 <dom-module id="bluetooth-settings">
   <template>
-    <style include="device-emulator-shared-styles cr-shared-style iron-flex
-        iron-flex-alignment iron-positioning">
+    <!-- TODO(michaelpg): Wrap the line below to fit within the 80-char limit.
+         See https://github.com/Polymer/polymer/pull/3668. -->
+    <style include="device-emulator-shared-styles cr-shared-style iron-flex iron-flex-alignment iron-positioning">
     </style>
     <dialog is="cr-dialog" id="editDialog">
       <div slot="title">[[currentEditableObject.alias]]</div>
diff --git a/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html b/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html
index e2abe2d5..9d876d3 100644
--- a/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html
+++ b/chrome/browser/resources/chromeos/emulator/device_emulator_pages.html
@@ -21,8 +21,9 @@
 
 <dom-module id="device-emulator-pages">
   <template>
-    <style include="device-emulator-shared-styles iron-flex iron-flex-alignment
-        iron-positioning">
+    <!-- TODO(michaelpg): Wrap the line below to fit within the 80-char limit.
+         See https://github.com/Polymer/polymer/pull/3668. -->
+    <style include="device-emulator-shared-styles iron-flex iron-flex-alignment iron-positioning">
       :host {
         display: flex;
         flex-direction: column;
diff --git a/chrome/browser/resources/chromeos/emulator/input_device_settings.html b/chrome/browser/resources/chromeos/emulator/input_device_settings.html
index 8726551..871e31e 100644
--- a/chrome/browser/resources/chromeos/emulator/input_device_settings.html
+++ b/chrome/browser/resources/chromeos/emulator/input_device_settings.html
@@ -7,8 +7,9 @@
 
 <dom-module id="input-device-settings">
   <template>
-    <style include="device-emulator-shared-styles iron-flex iron-flex-alignment
-         iron-positioning">
+    <!-- TODO(michaelpg): Wrap the line below to fit within the 80-char limit.
+         See https://github.com/Polymer/polymer/pull/3668. -->
+    <style include="device-emulator-shared-styles iron-flex iron-flex-alignment iron-positioning">
       .content > *:not(:first-child) {
         margin-top: 10px;
       }
diff --git a/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn b/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn
index a30ce42d..e0a5937fc 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn
+++ b/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn
@@ -26,6 +26,10 @@
   mode = "copy"
   dest_dir = select_to_speak_out_dir
   sources = [
+    "../chromevox/cvox2/background/automation_predicate.js",
+    "../chromevox/cvox2/background/automation_util.js",
+    "../chromevox/cvox2/background/constants.js",
+    "../chromevox/cvox2/background/tree_walker.js",
     "checked.png",
     "options.css",
     "options.html",
diff --git a/chrome/browser/resources/chromeos/select_to_speak/closure_shim.js b/chrome/browser/resources/chromeos/select_to_speak/closure_shim.js
new file mode 100644
index 0000000..e04ffc8
--- /dev/null
+++ b/chrome/browser/resources/chromeos/select_to_speak/closure_shim.js
@@ -0,0 +1,19 @@
+// 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.
+
+/**
+ * Provides a shim to allow select-to-speak to use closure files.
+ */
+
+var goog = {};
+
+goog.provide = function(n) {
+  window[n] = {};
+};
+
+goog.require = function() {};
+
+goog.scope = function(c) {
+  c();
+};
diff --git a/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp b/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp
index a581105..4284ec0 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp
+++ b/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp
@@ -6,6 +6,8 @@
     {
       'target_name': 'select_to_speak',
       'dependencies': [
+        '../chromevox/cvox2/background/constants',
+        '../chromevox/cvox2/background/automation_util',
 	'externs',
 	'paragraph_utils',
 	'<(EXTERNS_GYP):accessibility_private',
@@ -40,5 +42,43 @@
        ],
        'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
+    {
+      'target_name': '../chromevox/cvox2/background/automation_util',
+      'dependencies': [
+	'../chromevox/cvox2/background/automation_predicate',
+	'../chromevox/cvox2/background/tree_walker',
+	'../chromevox/cvox2/background/constants',
+	'<(EXTERNS_GYP):automation',
+	'<(EXTERNS_GYP):chrome_extensions',
+      ],
+      'includes':  ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
+      'target_name': '../chromevox/cvox2/background/tree_walker',
+      'dependencies': [
+	'../chromevox/cvox2/background/automation_predicate',
+	'../chromevox/cvox2/background/constants',
+	'<(EXTERNS_GYP):automation',
+	'<(EXTERNS_GYP):chrome_extensions',
+      ],
+      'includes':  ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
+      'target_name': '../chromevox/cvox2/background/automation_predicate',
+      'dependencies': [
+	'../chromevox/cvox2/background/constants',
+	'<(EXTERNS_GYP):automation',
+	'<(EXTERNS_GYP):chrome_extensions',
+      ],
+      'includes':  ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
+      'target_name': '../chromevox/cvox2/background/constants',
+      'includes':  ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
+      'target_name': 'closure_shim',
+      'includes':  ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
   ],
 }
diff --git a/chrome/browser/resources/chromeos/select_to_speak/manifest.json.jinja2 b/chrome/browser/resources/chromeos/select_to_speak/manifest.json.jinja2
index e0b3ef43..3461a8fc 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/manifest.json.jinja2
+++ b/chrome/browser/resources/chromeos/select_to_speak/manifest.json.jinja2
@@ -11,6 +11,11 @@
 {% endif %}
   "background": {
     "scripts": [
+      "closure_shim.js",
+      "constants.js",
+      "automation_predicate.js",
+      "tree_walker.js",
+      "automation_util.js",
       "paragraph_utils.js",
       "select_to_speak.js",
       "select_to_speak_main.js"
diff --git a/chrome/browser/resources/chromeos/select_to_speak/options.css b/chrome/browser/resources/chromeos/select_to_speak/options.css
index eb89feb0..5fc5037d 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/options.css
+++ b/chrome/browser/resources/chromeos/select_to_speak/options.css
@@ -51,6 +51,24 @@
     width: 646px;
 }
 
+.sub-option {
+    font-size: 13px;
+    max-height: 60px;
+    opacity: 1;
+    overflow: hidden;
+    padding: 0 24px;
+    transition: max-height 150ms ease-in;
+    vertical-align: middle;
+    width: 622px;
+}
+
+.sub-option.hidden {
+    max-height: 0;
+    opacity: 0;
+    overflow: hidden;
+    transition: max-height 150ms ease-out;
+}
+
 .option input[type='checkbox'] {
     -webkit-appearance: none;
     background-color: #fff;
diff --git a/chrome/browser/resources/chromeos/select_to_speak/options.html b/chrome/browser/resources/chromeos/select_to_speak/options.html
index 500b225..e218099 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/options.html
+++ b/chrome/browser/resources/chromeos/select_to_speak/options.html
@@ -51,40 +51,39 @@
         <label id="wordHighlightLabel" class="i18n"
                msgid="options_highlight_description">
         </label>
-      </div>
-      <div class="option">
-        <span class="i18n" msgid="options_highlight_color_description"
-              id="highlight_color_description"></span>
-        <select id="highlightColor"
-                aria-labeledby="options_highlight_color_description">
-          <option value="#5e9bff" class="i18n"
-                  msgid="options_highlight_color_blue">
-          </option>
-          <option value="#ffa13d" class="i18n"
-                  msgid="options_highlight_color_orange">
-          </option>
-          <option value="#eeff41" class="i18n"
-                  msgid="options_highlight_color_yellow">
-          </option>
-          <option value="#64dd17" class="i18n"
-                  msgid="options_highlight_color_green">
-          </option>
-          <option value="#ff4081" class="i18n"
-                  msgid="options_highlight_color_pink">
-          </option>
-        </select>
-        <div class="example dark">
-          <span class="i18n" msgid="options_highlight_dark"></span>
-          <div class="highlight">
+        <div class="sub-option hidden" id="highlightSubOption">
+          <span class="i18n" msgid="options_highlight_color_description"
+                id="highlight_color_description"></span>
+          <select id="highlightColor"
+                  aria-labeledby="options_highlight_color_description">
+            <option value="#5e9bff" class="i18n"
+                    msgid="options_highlight_color_blue">
+            </option>
+            <option value="#ffa13d" class="i18n"
+                    msgid="options_highlight_color_orange">
+            </option>
+            <option value="#eeff41" class="i18n"
+                    msgid="options_highlight_color_yellow">
+            </option>
+            <option value="#64dd17" class="i18n"
+                    msgid="options_highlight_color_green">
+            </option>
+            <option value="#ff4081" class="i18n"
+                    msgid="options_highlight_color_pink">
+            </option>
+          </select>
+          <div class="example dark">
+            <span class="i18n" msgid="options_highlight_dark"></span>
+            <div class="highlight">
+            </div>
           </div>
-        </div>
-        <div class="example light">
-          <span class="i18n" msgid="options_highlight_light"></span>
-          <div class="highlight">
+          <div class="example light">
+            <span class="i18n" msgid="options_highlight_light"></span>
+            <div class="highlight">
+            </div>
           </div>
         </div>
       </div>
-
     </div>
 
     <script src="select_to_speak_options.js"></script>
diff --git a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak_options.js b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak_options.js
index 806cbff7..a3cea7ea 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak_options.js
+++ b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak_options.js
@@ -22,7 +22,20 @@
     }.bind(this));
     this.syncSelectControlToPref_('voice', 'voice');
     this.syncSelectControlToPref_('rate', 'rate');
-    this.syncCheckboxControlToPref_('wordHighlight', 'wordHighlight');
+    this.syncCheckboxControlToPref_(
+        'wordHighlight', 'wordHighlight', function(checked) {
+          let elem = document.getElementById('highlightSubOption');
+          let select = document.getElementById('highlightColor');
+          if (checked) {
+            elem.classList.remove('hidden');
+            elem.setAttribute('aria-hidden', false);
+            select.disabled = false;
+          } else {
+            elem.classList.add('hidden');
+            elem.setAttribute('aria-hidden', true);
+            select.disabled = true;
+          }
+        });
     this.setUpHighlightListener_();
     chrome.metricsPrivate.recordUserAction(
         'Accessibility.CrosSelectToSpeak.LoadSettings');
@@ -89,9 +102,12 @@
   /**
    * Populate a checkbox with its current setting.
    * @param {string} checkboxId The id of the checkbox element.
+   * @param {string} pref The name for a chrome.storage pref.
+   * @param {?function(boolean): undefined=} opt_onChange A function
+   * to be called every time the checkbox state is changed.
    * @private
    */
-  syncCheckboxControlToPref_: function(checkboxId, pref) {
+  syncCheckboxControlToPref_: function(checkboxId, pref, opt_onChange) {
     let checkbox = document.getElementById(checkboxId);
 
     function updateFromPref() {
@@ -99,6 +115,9 @@
         let value = items[pref];
         if (value != null) {
           checkbox.checked = value;
+          if (opt_onChange) {
+            opt_onChange(checkbox.checked);
+          }
         }
       });
     }
diff --git a/chrome/browser/resources/extensions/compiled_resources2.gyp b/chrome/browser/resources/extensions/compiled_resources2.gyp
index c2f64619..060505c 100644
--- a/chrome/browser/resources/extensions/compiled_resources2.gyp
+++ b/chrome/browser/resources/extensions/compiled_resources2.gyp
@@ -13,6 +13,7 @@
         'source_files': [
           '<(DEPTH)/ui/webui/resources/js/promise_resolver.js',
           '<(DEPTH)/ui/webui/resources/js/load_time_data.js',
+          '<(DEPTH)/ui/webui/resources/js/parse_html_subset.js',
           '<(DEPTH)/ui/webui/resources/js/cr.js',
           '<(DEPTH)/ui/webui/resources/js/cr/ui/array_data_model.js',
           '<(DEPTH)/ui/webui/resources/js/cr/ui/list.js',
diff --git a/chrome/browser/resources/md_extensions/detail_view.html b/chrome/browser/resources/md_extensions/detail_view.html
index 06733dc..365e7f4 100644
--- a/chrome/browser/resources/md_extensions/detail_view.html
+++ b/chrome/browser/resources/md_extensions/detail_view.html
@@ -25,8 +25,7 @@
 
 <dom-module id="extensions-detail-view">
   <template>
-    <style include="iron-flex cr-shared-style cr-icons action-link
-        paper-button-style">
+    <style include="iron-flex cr-shared-style cr-icons action-link paper-button-style">
       :host {
         --iron-icon-fill-color: var(--paper-grey-600);
         display: block;
@@ -60,6 +59,7 @@
         background-color: white;
         margin: auto;
         min-height: 100%;
+        padding-bottom: 64px;
         width: var(--cr-toolbar-field-width);
       }
 
@@ -182,8 +182,8 @@
       }
 
       #size {
-        align-items: center;
         display: flex;
+        align-items: center;
       }
 
       paper-spinner-lite {
@@ -383,8 +383,8 @@
             on-tap="onExtensionOptionsTap_">
         </button>
         <button class="hr" hidden="[[!data.manifestHomePageUrl.length]]"
-            is="cr-link-row" icon-class="icon-external" id="developerWebsite"
-            label="$i18n{developerWebsite}" on-tap="onDeveloperWebSiteTap_">
+            is="cr-link-row" icon-class="icon-external" id="extensionWebsite"
+            label="$i18n{extensionWebsite}" on-tap="onExtensionWebSiteTap_">
         </button>
         <button class="hr" hidden="[[!data.webStoreUrl.length]]"
             is="cr-link-row" icon-class="icon-external" id="viewInStore"
diff --git a/chrome/browser/resources/md_extensions/detail_view.js b/chrome/browser/resources/md_extensions/detail_view.js
index 424f445..ce6eaa8 100644
--- a/chrome/browser/resources/md_extensions/detail_view.js
+++ b/chrome/browser/resources/md_extensions/detail_view.js
@@ -207,7 +207,7 @@
     },
 
     /** @private */
-    onDeveloperWebSiteTap_: function() {
+    onExtensionWebSiteTap_: function() {
       this.delegate.openUrl(this.data.manifestHomePageUrl);
     },
 
diff --git a/chrome/browser/resources/print_preview/data/print_ticket_store.js b/chrome/browser/resources/print_preview/data/print_ticket_store.js
index 6ae5c7fd..eb26e94 100644
--- a/chrome/browser/resources/print_preview/data/print_ticket_store.js
+++ b/chrome/browser/resources/print_preview/data/print_ticket_store.js
@@ -47,6 +47,12 @@
       this.documentInfo_ = documentInfo;
 
       /**
+       * The destination that capabilities were last received for.
+       * @private {?print_preview.Destination}
+       */
+      this.destination_ = null;
+
+      /**
        * Printing capabilities of Chromium and the currently selected
        * destination.
        * @type {!print_preview.CapabilitiesHolder}
@@ -531,7 +537,11 @@
      * @private
      */
     onSelectedDestinationCapabilitiesReady_() {
-      if (this.capabilitiesHolder_.get() != null) {
+      const selectedDestination = this.destinationStore_.selectedDestination;
+      const isFirstUpdate = this.capabilitiesHolder_.get() == null;
+      // Only clear the ticket items if the user selected a new destination
+      // and this is not the first update.
+      if (!isFirstUpdate && this.destination_ != selectedDestination) {
         this.customMargins_.updateValue(null);
         if (this.marginsType_.getValue() ==
             print_preview.ticket_items.MarginsTypeValue.CUSTOM) {
@@ -540,10 +550,9 @@
         }
         this.vendorItems_.updateValue({});
       }
-      const caps =
-          assert(this.destinationStore_.selectedDestination.capabilities);
-      const isFirstUpdate = this.capabilitiesHolder_.get() == null;
+      const caps = assert(selectedDestination.capabilities);
       this.capabilitiesHolder_.set(caps);
+      this.destination_ = selectedDestination;
       if (isFirstUpdate) {
         this.isInitialized_ = true;
         cr.dispatchSimpleEvent(this, PrintTicketStore.EventType.INITIALIZE);
diff --git a/chrome/browser/resources/print_preview/new/compiled_resources2.gyp b/chrome/browser/resources/print_preview/new/compiled_resources2.gyp
index cc4e4cc..eb765bd 100644
--- a/chrome/browser/resources/print_preview/new/compiled_resources2.gyp
+++ b/chrome/browser/resources/print_preview/new/compiled_resources2.gyp
@@ -85,6 +85,7 @@
     {
       'target_name': 'media_size_settings',
       'dependencies': [
+        'settings_behavior',
         'settings_select',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
@@ -92,13 +93,16 @@
     {
       'target_name': 'margins_settings',
       'dependencies': [
+        'settings_behavior',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
       'target_name': 'dpi_settings',
       'dependencies': [
+        'settings_behavior',
         'settings_select',
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
@@ -134,6 +138,7 @@
     {
       'target_name': 'settings_select',
       'dependencies': [
+        'settings_behavior',
         '../compiled_resources2.gyp:print_preview_utils',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
       ],
diff --git a/chrome/browser/resources/print_preview/new/dpi_settings.html b/chrome/browser/resources/print_preview/new/dpi_settings.html
index 9e8ae49..2e44806 100644
--- a/chrome/browser/resources/print_preview/new/dpi_settings.html
+++ b/chrome/browser/resources/print_preview/new/dpi_settings.html
@@ -1,6 +1,8 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="print_preview_shared_css.html">
+<link rel="import" href="settings_behavior.html">
 <link rel="import" href="settings_section.html">
 <link rel="import" href="settings_select.html">
 
@@ -12,7 +14,8 @@
       <span id="dpi-label" slot="title">$i18n{dpiLabel}</span>
       <div slot="controls">
         <print-preview-settings-select aria-labelled-by="dpi-label"
-            capability="[[capabilityWithLabels_]]">
+            capability="[[capabilityWithLabels_]]" setting-name="dpi"
+            settings="{{settings}}">
         </print-preview-settings-select>
       </div>
     </print-preview-settings-section>
diff --git a/chrome/browser/resources/print_preview/new/dpi_settings.js b/chrome/browser/resources/print_preview/new/dpi_settings.js
index 9bc4207..c5d1c8d 100644
--- a/chrome/browser/resources/print_preview/new/dpi_settings.js
+++ b/chrome/browser/resources/print_preview/new/dpi_settings.js
@@ -2,9 +2,30 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+cr.exportPath('print_preview_new');
+
+/**
+ * @typedef {{
+ *   horizontal_dpi: (number | undefined),
+ *   vertical_dpi: (number | undefined),
+ *   vendor_id: (number | undefined)}}
+ */
+print_preview_new.DpiOption;
+
+/**
+ * @typedef {{
+ *   horizontal_dpi: (number | undefined),
+ *   name: string,
+ *   vertical_dpi: (number | undefined),
+ *   vendor_id: (number | undefined)}}
+ */
+print_preview_new.LabelledDpiOption;
+
 Polymer({
   is: 'print-preview-dpi-settings',
 
+  behaviors: [SettingsBehavior],
+
   properties: {
     /** @type {{ option: Array<!print_preview_new.SelectOption> }} */
     capability: Object,
@@ -16,6 +37,10 @@
     },
   },
 
+  observers: [
+    'onDpiSettingChange_(settings.dpi.value, capabilityWithLabels_.option)',
+  ],
+
   /**
    * Adds default labels for each option.
    * @return {{option: Array<!print_preview_new.SelectOption>}}
@@ -28,8 +53,9 @@
         /** @type {{option: Array<!print_preview_new.SelectOption>}} */ (
             JSON.parse(JSON.stringify(this.capability)));
     this.capability.option.forEach((option, index) => {
-      const hDpi = option.horizontal_dpi || 0;
-      const vDpi = option.vertical_dpi || 0;
+      const dpiOption = /** @type {print_preview_new.DpiOption} */ (option);
+      const hDpi = dpiOption.horizontal_dpi || 0;
+      const vDpi = dpiOption.vertical_dpi || 0;
       if (hDpi > 0 && vDpi > 0 && hDpi != vDpi) {
         result.option[index].name = loadTimeData.getStringF(
             'nonIsotropicDpiItemLabel', hDpi.toLocaleString(),
@@ -40,5 +66,25 @@
       }
     });
     return result;
-  }
+  },
+
+  /**
+   * @param {!print_preview_new.SelectOption} value The new value of the dpi
+   *     setting.
+   * @private
+   */
+  onDpiSettingChange_: function(value) {
+    const dpiValue = /** @type {print_preview_new.DpiOption} */ (value);
+    for (const option of assert(this.capabilityWithLabels_.option)) {
+      const dpiOption =
+          /** @type {print_preview_new.LabelledDpiOption} */ (option);
+      if (dpiValue.horizontal_dpi == dpiOption.horizontal_dpi &&
+          dpiValue.vertical_dpi == dpiOption.vertical_dpi &&
+          dpiValue.vendor_id == dpiOption.vendor_id) {
+        this.$$('print-preview-settings-select')
+            .selectValue(JSON.stringify(option));
+        return;
+      }
+    }
+  },
 });
diff --git a/chrome/browser/resources/print_preview/new/margins_settings.html b/chrome/browser/resources/print_preview/new/margins_settings.html
index bffdaac..dbc9ac6 100644
--- a/chrome/browser/resources/print_preview/new/margins_settings.html
+++ b/chrome/browser/resources/print_preview/new/margins_settings.html
@@ -2,6 +2,7 @@
 
 <link rel="import" href="print_preview_shared_css.html">
 <link rel="import" href="select_css.html">
+<link rel="import" href="settings_behavior.html">
 <link rel="import" href="settings_section.html">
 
 <dom-module id="print-preview-margins-settings">
@@ -11,7 +12,7 @@
     <print-preview-settings-section>
       <span id="margins-label" slot="title">$i18n{marginsLabel}</span>
       <div slot="controls">
-        <select aria-labelledby="margins-label">
+        <select aria-labelledby="margins-label" on-change="onChange_">
           <!-- The order of these options must match the natural order of their
           values, which come from
           print_preview.ticket_items.MarginsTypeValue. -->
diff --git a/chrome/browser/resources/print_preview/new/margins_settings.js b/chrome/browser/resources/print_preview/new/margins_settings.js
index d0e9423..65ec5a1 100644
--- a/chrome/browser/resources/print_preview/new/margins_settings.js
+++ b/chrome/browser/resources/print_preview/new/margins_settings.js
@@ -4,4 +4,21 @@
 
 Polymer({
   is: 'print-preview-margins-settings',
+
+  behaviors: [SettingsBehavior],
+
+  observers: ['onMarginsSettingChange_(settings.margins.value)'],
+
+  /**
+   * @param {*} value The new value of the margins setting.
+   * @private
+   */
+  onMarginsSettingChange_: function(value) {
+    this.$$('select').value = /** @type {string} */ (value).toString();
+  },
+
+  /** @private */
+  onChange_: function() {
+    this.setSetting('margins', parseInt(this.$$('select').value, 10));
+  },
 });
diff --git a/chrome/browser/resources/print_preview/new/media_size_settings.html b/chrome/browser/resources/print_preview/new/media_size_settings.html
index 9bbaea84..540f8f0 100644
--- a/chrome/browser/resources/print_preview/new/media_size_settings.html
+++ b/chrome/browser/resources/print_preview/new/media_size_settings.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="print_preview_shared_css.html">
+<link rel="import" href="settings_behavior.html">
 <link rel="import" href="settings_section.html">
 <link rel="import" href="settings_select.html">
 
@@ -12,7 +13,8 @@
       <span id="media-size-label" slot="title">$i18n{mediaSizeLabel}</span>
       <div slot="controls">
         <print-preview-settings-select aria-labelledby="media-size-label"
-          capability="[[capability]]">
+            capability="[[capability]]" setting-name="mediaSize"
+            settings="{{settings}}">
         </print-preview-settings-select>
       </div>
     </print-preview-settings-section>
diff --git a/chrome/browser/resources/print_preview/new/media_size_settings.js b/chrome/browser/resources/print_preview/new/media_size_settings.js
index dcb65b2..55dc7ebc 100644
--- a/chrome/browser/resources/print_preview/new/media_size_settings.js
+++ b/chrome/browser/resources/print_preview/new/media_size_settings.js
@@ -5,7 +5,27 @@
 Polymer({
   is: 'print-preview-media-size-settings',
 
+  behaviors: [SettingsBehavior],
+
   properties: {
     capability: Object,
   },
+
+  observers:
+      ['onMediaSizeSettingChange_(settings.mediaSize.value, ' +
+       'capability.option)'],
+
+  /**
+   * @param {*} value The new value of the media size setting.
+   * @private
+   */
+  onMediaSizeSettingChange_: function(value) {
+    const valueToSet = JSON.stringify(value);
+    for (const option of this.capability.option) {
+      if (JSON.stringify(option) == valueToSet) {
+        this.$$('print-preview-settings-select').selectValue(valueToSet);
+        return;
+      }
+    }
+  },
 });
diff --git a/chrome/browser/resources/print_preview/new/model.js b/chrome/browser/resources/print_preview/new/model.js
index 43cad0e..2698161 100644
--- a/chrome/browser/resources/print_preview/new/model.js
+++ b/chrome/browser/resources/print_preview/new/model.js
@@ -171,19 +171,29 @@
   },
 
   observers:
-      ['updateSettingsAvailable_(' +
+      ['updateSettings_(' +
        'destination.id, destination.capabilities, ' +
        'documentInfo.isModifiable, documentInfo.hasCssMediaStyles,' +
        'documentInfo.hasSelection)'],
 
   /**
-   * Updates the availability of the settings sections.
+   * Updates the availability of the settings sections and values of dpi and
+   *     media size settings.
    * @private
    */
-  updateSettingsAvailable_: function() {
+  updateSettings_: function() {
     const caps = (!!this.destination && !!this.destination.capabilities) ?
         this.destination.capabilities.printer :
         null;
+    this.updateSettingsAvailability_(caps);
+    this.updateSettingsValues_(caps);
+  },
+
+  /**
+   * @param {?print_preview.CddCapabilities} caps The printer capabilities.
+   * @private
+   */
+  updateSettingsAvailability_: function(caps) {
     const isSaveToPdf = this.destination.id ==
         print_preview.Destination.GooglePromotedId.SAVE_AS_PDF;
     const knownSizeToSaveAsPdf = isSaveToPdf &&
@@ -225,7 +235,10 @@
             this.settings.rasterize.available);
   },
 
-  /** @param {?print_preview.CddCapabilities} caps The printer capabilities. */
+  /**
+   * @param {?print_preview.CddCapabilities} caps The printer capabilities.
+   * @private
+   */
   isLayoutAvailable_: function(caps) {
     if (!caps || !caps.page_orientation || !caps.page_orientation.option ||
         !this.documentInfo.isModifiable ||
@@ -241,4 +254,31 @@
     });
     return hasLandscapeOption && hasAutoOrPortraitOption;
   },
+
+  /**
+   * @param {?print_preview.CddCapabilities} caps The printer capabilities.
+   * @private
+   */
+  updateSettingsValues_: function(caps) {
+    if (this.settings.mediaSize.available) {
+      for (const option of caps.media_size.option) {
+        if (option.is_default) {
+          this.set('settings.mediaSize.value', option);
+          break;
+        }
+      }
+    }
+
+    if (this.settings.dpi.available) {
+      for (const option of caps.dpi.option) {
+        if (option.is_default) {
+          this.set('settings.dpi.value', option);
+          break;
+        }
+      }
+    } else if (
+        caps && caps.dpi && caps.dpi.option && caps.dpi.option.length > 0) {
+      this.set('settings.dpi.value', caps.dpi.option[0]);
+    }
+  }
 });
diff --git a/chrome/browser/resources/print_preview/new/settings_select.html b/chrome/browser/resources/print_preview/new/settings_select.html
index eee1f99f..0525c00 100644
--- a/chrome/browser/resources/print_preview/new/settings_select.html
+++ b/chrome/browser/resources/print_preview/new/settings_select.html
@@ -3,12 +3,13 @@
 <link rel="import" href="../print_preview_utils.html">
 <link rel="import" href="print_preview_shared_css.html">
 <link rel="import" href="select_css.html">
+<link rel="import" href="settings_behavior.html">
 
 <dom-module id="print-preview-settings-select">
   <template>
     <style include="print-preview-shared select">
     </style>
-    <select>
+    <select on-change="onChange_">
       <template is="dom-repeat" items="[[capability.option]]">
         <option selected="[[item.is_default]]" value="[[getValue_(item)]]">
           [[getDisplayName_(item)]]
diff --git a/chrome/browser/resources/print_preview/new/settings_select.js b/chrome/browser/resources/print_preview/new/settings_select.js
index 319dbc7..aba06807 100644
--- a/chrome/browser/resources/print_preview/new/settings_select.js
+++ b/chrome/browser/resources/print_preview/new/settings_select.js
@@ -17,16 +17,19 @@
 Polymer({
   is: 'print-preview-settings-select',
 
+  behaviors: [SettingsBehavior],
+
   properties: {
     /** @type {{ option: Array<!print_preview_new.SelectOption> }} */
     capability: Object,
 
     /** @type {string} */
-    selectedValue: {
-      type: String,
-      notify: true,
-      value: '',
-    },
+    settingName: String,
+  },
+
+  /** @param {string} value The value to select. */
+  selectValue: function(value) {
+    this.$$('select').value = value;
   },
 
   /**
@@ -53,4 +56,16 @@
     }
     return displayName || option.name || '';
   },
+
+  /** @private */
+  onChange_: function() {
+    let value = null;
+    try {
+      value = JSON.parse(this.$$('select').value);
+    } catch (e) {
+      assertNotReached();
+      return;
+    }
+    this.setSetting(this.settingName, /** @type {Object} */ (value));
+  },
 });
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
index 3572a12c..adb7eb4 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
@@ -14,6 +14,7 @@
 <link rel="import" href="../controls/settings_toggle_button.html">
 <link rel="import" href="../settings_shared_css.html">
 <link rel="import" href="chrome_cleanup_proxy.html">
+<link rel="import" href="items_to_remove_list.html">
 
 <dom-module id="settings-chrome-cleanup-page">
   <template>
@@ -22,20 +23,6 @@
         height: 20px;
         width: 20px;
       }
-
-      #files-to-remove-container {
-        padding: 0 var(--settings-box-row-padding);
-        /* Use the full available width for file paths to avoid inconsistent
-         *  line breaks when zooming in or out */
-        width: calc(var(--settings-card-max-width) -
-            2 * var(--settings-box-row-padding));
-      }
-
-      #files-to-remove-list {
-        margin: 0;
-        word-break: break-all;
-      }
-
       #learn-more {
         -webkit-margin-start: 0;
       }
@@ -101,7 +88,8 @@
         <div hidden="[[!showExplanation_]]">
           <span class="secondary">[[explanation_]]</span>
           <a id="learn-more" href="$i18n{chromeCleanupLearnMoreUrl}"
-              on-tap="learnMore_" target="_blank" hidden="[[!showLearnMore_]]">
+              on-tap="learnMore_" target="_blank"
+              hidden="[[!showLearnMore_]]">
             $i18n{learnMore}
           </a>
         </div>
@@ -123,22 +111,33 @@
              userInitiatedCleanupsEnabled_)]]"
         on-settings-boolean-control-change="changeLogsPermission_">
     </settings-toggle-button>
-    <div id="show-files-button" class="settings-box" actionable
+    <div id="show-items-button" class="settings-box" actionable
         on-tap="toggleExpandButton_" hidden="[[!showItemsToRemove_]]">
-      <div class="start">
-        $i18n{chromeCleanupLinkShowFiles}
-      </div>
-      <cr-expand-button expanded="{{filesToRemoveListExpanded_}}"
-          alt="$i18n{chromeCleanupLinkShowFiles}">
+      <div class="start">[[showItemsLinkLabel_]]</div>
+      <cr-expand-button expanded="{{itemsToRemoveSectionExpanded_}}"
+          alt="[[showItemsLinkLabel_]]">
       </cr-expand-button>
     </div>
-    <iron-collapse opened="[[filesToRemoveListExpanded_]]">
-      <div id="files-to-remove-container">
-        <ul id="files-to-remove-list" class="secondary">
-          <template is="dom-repeat" items="[[filesToRemove_]]" as="fileName">
-            <li>[[fileName]]</li>
-          </template>
-        </ul>
+    <iron-collapse id="iron-collapse-items"
+        opened="[[itemsToRemoveSectionExpanded_]]">
+      <items-to-remove-list
+          id="files-to-remove-list"
+          hidden="[[!hasFilesToShow_]]"
+          title-visible="[[userInitiatedCleanupsEnabled_]]"
+          title="$i18n{chromeCleanupDetailsFilesAndPrograms}"
+          initially-expanded="[[!userInitiatedCleanupsEnabled_]]"
+          items-to-show="[[scannerResults_.files]]">
+      </items-to-remove-list>
+      <items-to-remove-list
+          id="registry-keys-list"
+          hidden="[[!hasRegistryKeysToShow_]]"
+          title="$i18n{chromeCleanupDetailsRegistryEntries}"
+          items-to-show="[[scannerResults_.registryKeys]]">
+      </items-to-remove-list>
+      <div class="settings-box continuation">
+        <div class="secondary">
+          $i18nRaw{chromeCleanupDetailsExplanation}
+        </div>
       </div>
       <div id="powered-by-settings-box" class="settings-box continuation">
         <div id="powered-by-container" class="secondary"
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
index 82a4851..09f5631 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
@@ -99,6 +99,14 @@
 settings.ChromeCleanupCardComponents;
 
 /**
+ * @typedef {{
+ *   files: Array<string>,
+ *   registryKeys: Array<string>,
+ * }}
+ */
+settings.ChromeCleanerScannerResults;
+
+/**
  * @fileoverview
  * 'settings-chrome-cleanup-page' is the settings page containing Chrome
  * Cleanup settings.
@@ -117,6 +125,12 @@
 
   properties: {
     /** @private */
+    userInitiatedCleanupsEnabled_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /** @private */
     title_: {
       type: String,
       value: '',
@@ -175,16 +189,43 @@
     },
 
     /** @private */
-    filesToRemoveListExpanded_: {
+    itemsToRemoveSectionExpanded_: {
       type: Boolean,
       value: false,
-      observer: 'filesToRemoveListExpandedChanged_',
+      observer: 'itemsToRemoveSectionExpandedChanged_',
     },
 
     /** @private */
-    filesToRemove_: {
+    showItemsLinkLabel_: {
+      type: String,
+      value: '',
+    },
+
+    /** @private */
+    showingAllFiles_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /** @private {!settings.ChromeCleanerScannerResults} */
+    scannerResults_: {
       type: Array,
-      value: [],
+      value: function() {
+        return {'files': [], 'registryKeys': []};
+      },
+    },
+
+    /** @private */
+    hasFilesToShow_: {
+      type: Boolean,
+      computed: 'computeHasFilesToShow_(scannerResults_)',
+    },
+
+    /** @private */
+    hasRegistryKeysToShow_: {
+      type: Boolean,
+      computed: 'computeHasRegistryKeysToShow_(' +
+          'userInitiatedCleanupsEnabled_, scannerResults_)',
     },
 
     /** @private */
@@ -217,6 +258,9 @@
     },
   },
 
+  /** @private {!settings.ChromeCleanerScannerResults} */
+  emptyChromeCleanerScannerResults_: {'files': [], 'registryKeys': []},
+
   /** @private {?settings.ChromeCleanupProxy} */
   browserProxy_: null,
 
@@ -230,9 +274,6 @@
   /** @private {settings.ChromeCleanupOngoingAction} */
   ongoingAction_: settings.ChromeCleanupOngoingAction.NONE,
 
-  /** @private {boolean} */
-  userInitiatedCleanupsEnabled_: false,
-
   /**
    * If true, the scan offered view is rendered on state idle, regardless of
    * the idle reason received from the cleaner controller. The goal is to
@@ -312,16 +353,16 @@
   },
 
   /**
-   * Notify Chrome that the details section was opened or closed.
+   * Notifies Chrome that the details section was opened or closed.
    * @private
    */
-  filesToRemoveListExpandedChanged_: function() {
-    if (this.browserProxy_)
-      this.browserProxy_.notifyShowDetails(this.filesToRemoveListExpanded_);
+  itemsToRemoveSectionExpandedChanged_: function(newVal, oldVal) {
+    if (!oldVal && newVal)
+      this.browserProxy_.notifyShowDetails(this.itemsToRemoveSectionExpanded_);
   },
 
   /**
-   * Notfies Chrome that the "learn more" link was clicked.
+   * Notifies Chrome that the "learn more" link was clicked.
    * @private
    */
   learnMore_: function() {
@@ -333,7 +374,7 @@
    * @private
    */
   showPoweredBy_: function() {
-    return this.filesToRemoveListExpanded_ && this.isPartnerPowered_;
+    return this.itemsToRemoveSectionExpanded_ && this.isPartnerPowered_;
   },
 
   /**
@@ -346,12 +387,37 @@
   },
 
   /**
+   * Returns true if there are files to show to the user.
+   * @param {!settings.ChromeCleanerScannerResults} scannerResults The cleanup
+   *     items to be presented to the user.
+   * @return {boolean}
+   * @private
+   */
+  computeHasFilesToShow_(scannerResults) {
+    return scannerResults.files.length > 0;
+  },
+
+  /**
+   * Returns true if user-initiated cleanups are enabled and there are registry
+   * keys to show to the user.
+   * @param {!settings.ChromeCleanerScannerResults} scannerResults The cleanup
+   *     items to be presented to the user.
+   * @return {boolean}
+   * @private
+   */
+  computeHasRegistryKeysToShow_(userInitiatedCleanupsEnabled, scannerResults) {
+    return userInitiatedCleanupsEnabled &&
+        scannerResults.registryKeys.length > 0;
+  },
+
+  /**
    * Listener of event 'chrome-cleanup-on-idle'.
    * @param {string} idleReason
    * @private
    */
   onIdle_: function(idleReason) {
     this.ongoingAction_ = settings.ChromeCleanupOngoingAction.NONE;
+    this.scannerResults_ = this.emptyChromeCleanerScannerResults_;
 
     // If user-initiated cleanups are disabled, then the card will be shown at
     // the top of the settings page.
@@ -433,6 +499,7 @@
    */
   onScanning_: function() {
     this.ongoingAction_ = settings.ChromeCleanupOngoingAction.SCANNING;
+    this.scannerResults_ = this.emptyChromeCleanerScannerResults_;
     this.renderScanOfferedByDefault_ = false;
     this.renderCleanupCard_(
         this.userInitiatedCleanupsEnabled_ ?
@@ -443,27 +510,32 @@
   /**
    * Listener of event 'chrome-cleanup-on-infected'.
    * Offers a cleanup to the user and enables presenting files to be removed.
-   * @param {!Array<string>} files The list of files to present to the user.
+   * @param {!settings.ChromeCleanerScannerResults} scannerResults The cleanup
+   *     items to be presented to the user.
    * @private
    */
-  onInfected_: function(files) {
+  onInfected_: function(scannerResults) {
     this.ongoingAction_ = settings.ChromeCleanupOngoingAction.NONE;
     this.renderScanOfferedByDefault_ = false;
-    this.renderCleanupCard_(
-        settings.ChromeCleanerCardState.CLEANUP_OFFERED, files);
+    this.scannerResults_ = scannerResults;
+    this.updateShowItemsLinklabel_();
+    this.renderCleanupCard_(settings.ChromeCleanerCardState.CLEANUP_OFFERED);
   },
 
   /**
    * Listener of event 'chrome-cleanup-on-cleaning'.
    * Shows a spinner indicating that an on-going action and enables presenting
    * files to be removed.
-   * @param {!Array<string>} files The list of files to present to the user.
+   * @param {!settings.ChromeCleanerScannerResults} scannerResults The cleanup
+   *     items to be presented to the user.
    * @private
    */
-  onCleaning_: function(files) {
+  onCleaning_: function(scannerResults) {
     this.ongoingAction_ = settings.ChromeCleanupOngoingAction.CLEANING;
     this.renderScanOfferedByDefault_ = false;
-    this.renderCleanupCard_(settings.ChromeCleanerCardState.CLEANING, files);
+    this.scannerResults_ = scannerResults;
+    this.updateShowItemsLinklabel_();
+    this.renderCleanupCard_(settings.ChromeCleanerCardState.CLEANING);
   },
 
   /**
@@ -474,6 +546,7 @@
    */
   onRebootRequired_: function() {
     this.ongoingAction_ = settings.ChromeCleanupOngoingAction.NONE;
+    this.scannerResults_ = this.emptyChromeCleanerScannerResults_;
     this.renderScanOfferedByDefault_ = false;
     this.renderCleanupCard_(settings.ChromeCleanerCardState.REBOOT_REQUIRED);
   },
@@ -482,14 +555,12 @@
    * Renders the cleanup card given the state and list of files.
    * @param {!settings.ChromeCleanerCardState} state The card state to be
    *     rendered.
-   * @param {Array<string>=} opt_files The list of files to present to the user.
    * @private
    */
-  renderCleanupCard_: function(state, opt_files) {
+  renderCleanupCard_: function(state) {
     var components = this.cardStateToComponentsMap_.get(state);
     assert(components);
 
-    this.filesToRemove_ = opt_files || [];
     this.title_ = components.title || '';
     this.explanation_ = components.explanation || '';
     this.updateIcon_(components.icon);
@@ -550,8 +621,8 @@
 
     // Files to remove list should only be expandable if details are being
     // shown, otherwise it will add extra padding at the bottom of the card.
-    if (!this.showExplanation_)
-      this.filesToRemoveListExpanded_ = false;
+    if (!this.showExplanation_ || !this.showItemsToRemove_)
+      this.itemsToRemoveSectionExpanded_ = false;
   },
 
   /**
@@ -627,6 +698,25 @@
   },
 
   /**
+   * Updates the label for the collapsed detailed view. If user-initiated
+   * cleanups are enabled, the string is obtained from the browser proxy, since
+   * it may require a plural version. Otherwise, use the default value for
+   * |chromeCleanupLinkShowItems|.
+   */
+  updateShowItemsLinklabel_: function() {
+    var setShowItemsLabel = text => this.showItemsLinkLabel_ = text;
+    if (this.userInitiatedCleanupsEnabled_) {
+      this.browserProxy_
+          .getItemsToRemovePluralString(
+              this.scannerResults_.files.length +
+              this.scannerResults_.registryKeys.length)
+          .then(setShowItemsLabel);
+    } else {
+      setShowItemsLabel(this.i18n('chromeCleanupLinkShowItems'));
+    }
+  },
+
+  /**
    * Returns the map of card states to components to be rendered.
    * @return {!Map<settings.ChromeCleanerCardState,
    *               !settings.ChromeCleanupCardComponents>}
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js
index 76b3158..c92b662 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.js
@@ -50,6 +50,22 @@
      * Notifies Chrome that the "learn more" link was clicked.
      */
     notifyLearnMoreClicked() {}
+
+    /**
+     * Requests the plural string for the "show more" link in the detailed
+     * view for either files to delete or registry keys.
+     * @param {number} numHiddenItems
+     * @return {!Promise<string>}
+     */
+    getMoreItemsPluralString(numHiddenItems) {}
+
+    /**
+     * Requests the plural string for the "items to remove" link in the detailed
+     * view.
+     * @param {number} numItems
+     * @return {!Promise<string>}
+     */
+    getItemsToRemovePluralString(numItems) {}
   }
 
   /**
@@ -95,6 +111,16 @@
     notifyLearnMoreClicked() {
       chrome.send('notifyChromeCleanupLearnMoreClicked');
     }
+
+    /** @override */
+    getMoreItemsPluralString(numHiddenItems) {
+      return cr.sendWithPromise('getMoreItemsPluralString', numHiddenItems);
+    }
+
+    /** @override */
+    getItemsToRemovePluralString(numItems) {
+      return cr.sendWithPromise('getItemsToRemovePluralString', numItems);
+    }
   }
 
   cr.addSingletonGetter(ChromeCleanupProxyImpl);
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/compiled_resources2.gyp b/chrome/browser/resources/settings/chrome_cleanup_page/compiled_resources2.gyp
index 34c9d87..b9927717 100644
--- a/chrome/browser/resources/settings/chrome_cleanup_page/compiled_resources2.gyp
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/compiled_resources2.gyp
@@ -25,5 +25,13 @@
       ],
       'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
+    {
+      'target_name': 'items_to_remove_list',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+        'chrome_cleanup_proxy',
+      ],
+      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
   ],
 }
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.html b/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.html
new file mode 100644
index 0000000..6f8b7eb
--- /dev/null
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.html
@@ -0,0 +1,37 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/util.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="chrome_cleanup_proxy.html">
+
+<dom-module id="items-to-remove-list">
+  <template>
+    <style include="settings-shared">
+      :host {
+        display: block;
+        margin: 0;
+        padding: 0 var(--settings-box-row-padding);
+        word-break: break-all;
+      }
+
+      #more-items-link {
+        color: var(--google-blue-500);
+        cursor: pointer;
+      }
+    </style>
+    <div id="title" class="secondary" hidden="[[!titleVisible]]">
+      [[title]]
+    </div>
+    <ul id="list" class="secondary">
+      <template is="dom-repeat" items="[[visibleItems_]]">
+        <li class="visible-item">[[item]]</li>
+      </template>
+      <li id="more-items-link" hidden="[[expanded_]]" on-tap="expandList_">
+        [[moreItemsLinkText_]]
+      </li>
+    </ul>
+  </template>
+  <script src="items_to_remove_list.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.js b/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.js
new file mode 100644
index 0000000..e628437c5
--- /dev/null
+++ b/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.js
@@ -0,0 +1,142 @@
+// 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.
+
+cr.exportPath('settings');
+
+/**
+ * The default number of items to show for files and registry keys on the
+ * detailed view when user-initiated cleanups are enabled.
+ */
+settings.CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW = 4;
+
+/**
+ * @fileoverview
+ * 'items-to-remove-list' represents a list of items to
+ * be removed or changed to be shown on the Chrome Cleanup page.
+ * TODO(crbug.com/776538): Update the strings to say that some items are only
+ *                         changed and not removed.
+ *
+ * Examples:
+ *
+ *    <!-- Items list initially expanded. -->
+ *    <items-to-remove-list
+ *        title="Files and programs:"
+ *        initially-expanded="true"
+ *        items-to-show="[[filesToShow]]">
+ *    </items-to-remove-list>
+ *
+ *    <!-- Items list initially shows |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW|
+ *         items. If there are more than |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW|
+ *         items on the list, then a "show more" link is shown; tapping on it
+ *         expands the list. -->
+ *    <items-to-remove-list
+ *        title="Files and programs:"
+ *        items-to-show="[[filesToShow]]">
+ *    </items-to-remove-list>
+ */
+Polymer({
+  is: 'items-to-remove-list',
+
+  properties: {
+    titleVisible: {
+      type: Boolean,
+      value: true,
+    },
+
+    title: {
+      type: String,
+      value: '',
+    },
+
+    /** @type {!Array<string>} */
+    itemsToShow: Array,
+
+    /**
+     * If true, all items from |itemsToShow| will be presented on the card
+     * by default, and the "show more" link will be omitted.
+     */
+    initiallyExpanded: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
+     * If true, all items from |itemsToShow| will be presented on the card,
+     * and the "show more" link will be omitted.
+     */
+    expanded_: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
+     * The list of items to actually present on the card. If |expanded_|, then
+     * it's the same as |itemsToShow|.
+     * @private {?Array<string>}
+     */
+    visibleItems_: Array,
+
+    /**
+     * The text for the "show more" link available if not all files are visible
+     * in the card.
+     * @private
+     */
+    moreItemsLinkText_: {
+      type: String,
+      value: '',
+    },
+  },
+
+  observers: ['updateVisibleState_(itemsToShow, initiallyExpanded)'],
+
+  /** @private */
+  expandList_: function() {
+    this.expanded_ = true;
+    this.visibleItems_ = this.itemsToShow;
+    this.moreItemsLinkText_ = '';
+  },
+
+  /**
+   * Decides which elements will be visible in the card and if the "show more"
+   * link will be rendered.
+   *
+   * Cases handled:
+   *  1. If |initiallyExpanded|, then all items will be visible.
+   *  2. Otherwise:
+   *     (A) If size(itemsToShow) < CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW, then
+   *         all items will be visible.
+   *     (B) Otherwise, exactly |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW - 1| will
+   *         be visible and the "show more" link will be rendered. The list
+   *         presented to the user will contain exactly
+   *         |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW| elements, and the last one
+   *         will be the "show more" link.
+   *
+   * @param {!Array<string>} itemsToShow
+   * @param {boolean} initiallyExpanded
+   */
+  updateVisibleState_: function(itemsToShow, initiallyExpanded) {
+    // Start expanded if there are less than
+    // |settings.CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW| items to show.
+    this.expanded_ = this.initiallyExpanded ||
+        this.itemsToShow.length <=
+            settings.CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW;
+
+    if (this.expanded_) {
+      this.visibleItems_ = this.itemsToShow;
+      this.moreItemsLinkText_ = '';
+      return;
+    }
+
+    this.visibleItems_ = this.itemsToShow.slice(
+        0, settings.CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW - 1);
+
+    const browserProxy = settings.ChromeCleanupProxyImpl.getInstance();
+    browserProxy
+        .getMoreItemsPluralString(
+            this.itemsToShow.length - this.visibleItems_.length)
+        .then(linkText => {
+          this.moreItemsLinkText_ = linkText;
+        });
+  },
+});
diff --git a/chrome/browser/resources/settings/internet_page/network_proxy_section.html b/chrome/browser/resources/settings/internet_page/network_proxy_section.html
index 4d4ee9d..f5d88e8 100644
--- a/chrome/browser/resources/settings/internet_page/network_proxy_section.html
+++ b/chrome/browser/resources/settings/internet_page/network_proxy_section.html
@@ -20,8 +20,7 @@
 
 <dom-module id="network-proxy-section">
   <template>
-    <style include="internet-shared cr-hidden-style iron-flex
-       iron-flex-alignment">
+    <style include="internet-shared cr-hidden-style iron-flex iron-flex-alignment">
       cr-policy-network-indicator {
         -webkit-margin-end: 10px;
       }
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index f5cc696..2a5b9f2 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -318,6 +318,12 @@
                    file="chrome_cleanup_page/chrome_cleanup_page.js"
                    type="chrome_html"
                    preprocess="true" />
+        <structure name="IDR_SETTINGS_CHROME_CLEANUP_ITEMS_TO_REMOVE_LIST_HTML"
+                   file="chrome_cleanup_page/items_to_remove_list.html"
+                   type="chrome_html"/>
+        <structure name="IDR_SETTINGS_CHROME_CLEANUP_ITEMS_TO_REMOVE_LIST_JS"
+                   file="chrome_cleanup_page/items_to_remove_list.js"
+                   type="chrome_html"/>
       </if>
       <structure name="IDR_SETTINGS_CLEAR_BROWSING_DATA_BROWSER_PROXY_HTML"
                  file="clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html"
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html
index 024f5f2e2..36f4372 100644
--- a/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -11,8 +11,7 @@
 <!-- Common styles for Material Design settings. -->
 <dom-module id="settings-shared">
   <template>
-    <style include="settings-icons paper-button-style paper-checkbox-style
-        paper-input-style paper-toggle-style cr-shared-style">
+    <style include="settings-icons paper-button-style paper-checkbox-style paper-input-style paper-toggle-style cr-shared-style">
       /* Prevent action-links from being selected to avoid accidental
        * selection when trying to click it. */
       a[is=action-link] {
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc
index 59e3a1c5..56287e4 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc
@@ -24,6 +24,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/component_updater/sw_reporter_installer_win.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -37,6 +38,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/installer/util/scoped_token_privilege.h"
 #include "components/chrome_cleaner/public/constants/constants.h"
+#include "components/component_updater/component_updater_service.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/http/http_status_code.h"
@@ -352,6 +354,7 @@
       return;
 
     case SwReporterInvocationResult::kTimedOut:
+    case SwReporterInvocationResult::kComponentNotAvailable:
     case SwReporterInvocationResult::kProcessFailedToLaunch:
     case SwReporterInvocationResult::kGeneralFailure:
       idle_reason_ = IdleReason::kReporterFailed;
@@ -377,6 +380,62 @@
   SetStateAndNotifyObservers(State::kIdle);
 }
 
+void ChromeCleanerControllerImpl::OnSwReporterReady(
+    SwReporterInvocationSequence&& invocations) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(!invocations.container().empty());
+
+  SwReporterInvocationType invocation_type =
+      SwReporterInvocationType::kPeriodicRun;
+  {
+    base::AutoLock autolock(lock_);
+    // Cache a copy of the invocations.
+    cached_reporter_invocations_ =
+        std::make_unique<SwReporterInvocationSequence>(invocations);
+    std::swap(pending_invocation_type_, invocation_type);
+  }
+  safe_browsing::MaybeStartSwReporter(invocation_type, std::move(invocations));
+}
+
+void ChromeCleanerControllerImpl::RequestUserInitiatedScan() {
+  base::AutoLock autolock(lock_);
+  DCHECK(pending_invocation_type_ !=
+             SwReporterInvocationType::kUserInitiatedWithLogsAllowed &&
+         pending_invocation_type_ !=
+             SwReporterInvocationType::kUserInitiatedWithLogsDisallowed);
+
+  SwReporterInvocationType invocation_type =
+      logs_enabled_
+          ? SwReporterInvocationType::kUserInitiatedWithLogsAllowed
+          : SwReporterInvocationType::kUserInitiatedWithLogsDisallowed;
+
+  if (cached_reporter_invocations_) {
+    SwReporterInvocationSequence copied_sequence(*cached_reporter_invocations_);
+
+    content::BrowserThread::PostTask(
+        content::BrowserThread::UI, FROM_HERE,
+        base::BindOnce(
+            &safe_browsing::MaybeStartSwReporter, invocation_type,
+            // The invocations will be modified by the |ReporterRunner|.
+            // Give it a copy to keep the cached invocations pristine.
+            base::Passed(&copied_sequence)));
+  } else {
+    pending_invocation_type_ = invocation_type;
+    OnReporterSequenceStarted();
+
+    // Creation of the |SwReporterOnDemandFetcher| automatically starts fetching
+    // the SwReporter component. |OnSwReporterReady| will be called if the
+    // component is successfully installed. Otherwise, |OnReporterSequenceDone|
+    // will be called.
+    on_demand_sw_reporter_fetcher_ =
+        std::make_unique<component_updater::SwReporterOnDemandFetcher>(
+            g_browser_process->component_updater(),
+            base::BindOnce(&ChromeCleanerController::OnReporterSequenceDone,
+                           base::Unretained(this),
+                           SwReporterInvocationResult::kComponentNotAvailable));
+  }
+}
+
 void ChromeCleanerControllerImpl::Scan(
     const SwReporterInvocation& reporter_invocation) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h
index e8f1f4c..2968fa7 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h
@@ -16,6 +16,7 @@
 #include "base/threading/thread_checker.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_runner_win.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_scanner_results.h"
+#include "components/component_updater/component_updater_service.h"
 
 namespace safe_browsing {
 
@@ -65,6 +66,8 @@
   void RemoveObserver(Observer* observer) override;
   void OnReporterSequenceStarted() override;
   void OnReporterSequenceDone(SwReporterInvocationResult result) override;
+  void RequestUserInitiatedScan() override;
+  void OnSwReporterReady(SwReporterInvocationSequence&& invocations) override;
   void Scan(const SwReporterInvocation& reporter_invocation) override;
   void ReplyWithUserResponse(Profile* profile,
                              UserResponse user_response) override;
@@ -138,6 +141,18 @@
 
   base::ObserverList<Observer> observer_list_;
 
+  // Mutex that guards |pending_invocation_type_|,
+  // |on_demand_sw_reporter_fetcher_| and |cached_reporter_invocations_|.
+  mutable base::Lock lock_;
+  SwReporterInvocationType pending_invocation_type_ =
+      SwReporterInvocationType::kPeriodicRun;
+  std::unique_ptr<component_updater::SwReporterOnDemandFetcher>
+      on_demand_sw_reporter_fetcher_;
+  // Note: SwReporterInvocationSequence is mutable and should not be used more
+  // than once. Special care must be taken that the invocations are not sent
+  // to a |ReporterRunner| more than once.
+  std::unique_ptr<SwReporterInvocationSequence> cached_reporter_invocations_;
+
   THREAD_CHECKER(thread_checker_);
 
   base::WeakPtrFactory<ChromeCleanerControllerImpl> weak_factory_;
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
index d9510a8c..0bab622 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
@@ -149,6 +149,24 @@
   // kIdle otherwise.
   virtual void OnReporterSequenceDone(SwReporterInvocationResult result) = 0;
 
+  // Attempts to start the reporter runner to scan the system for unwanted
+  // software. Once the reporter runner has started (which may involve
+  // downloading the SwReporter component), |OnReporterSequenceStarted| and
+  // |OnReporterSequenceDone| will be called with the result.
+  //
+  // This can have adverse effects on the component updater subsystem and
+  // should only be called from direct user action.
+  virtual void RequestUserInitiatedScan() = 0;
+
+  // Calls |MaybeStartSwReporter| with the |invocation_type| of the next
+  // scheduled run, which will be |SwReporterInvocationType::kPeriodicRun|
+  // unless the user has manually requested a reporter run, in which case the
+  // |SwReporterInvocationType::kUserInitiatedWithLogsAllowed| or
+  // |SwReporterInvocationType::kUserInitiatedWithLogsDisallowed| types will be
+  // passed.
+  virtual void OnSwReporterReady(
+      SwReporterInvocationSequence&& invocations) = 0;
+
   // Downloads the Chrome Cleaner binary, executes it and waits for the Cleaner
   // to communicate with Chrome about harmful software found on the
   // system. During this time, the controller will be in the kScanning state. If
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 c0d6f63..717ed4a 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
@@ -92,7 +92,7 @@
       logs_enabled
           ? ChromeCleanerController::UserResponse::kAcceptedWithLogs
           : ChromeCleanerController::UserResponse::kAcceptedWithoutLogs);
-  chrome_cleaner_util::OpenSettingsPage(
+  chrome_cleaner_util::OpenCleanupPage(
       browser_, WindowOpenDisposition::NEW_FOREGROUND_TAB);
   OnInteractionDone();
 }
@@ -148,7 +148,7 @@
       "SoftwareReporter.PromptDialog_DetailsButtonClicked"));
 
   cleaner_controller_->SetLogsEnabled(logs_enabled);
-  chrome_cleaner_util::OpenSettingsPage(
+  chrome_cleaner_util::OpenCleanupPage(
       browser_, WindowOpenDisposition::NEW_FOREGROUND_TAB);
   OnInteractionDone();
 }
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_navigation_util_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_navigation_util_win.cc
index 6278823..e49a624 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_navigation_util_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_navigation_util_win.cc
@@ -4,8 +4,10 @@
 
 #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_list.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/url_constants.h"
 #include "ui/base/page_transition_types.h"
@@ -14,6 +16,15 @@
 
 namespace chrome_cleaner_util {
 
+namespace {
+GURL GetCleanupPageURL() {
+  if (safe_browsing::UserInitiatedCleanupsEnabled())
+    return chrome::GetSettingsUrl(chrome::kCleanupSubPage);
+  else
+    return chrome::GetSettingsUrl("");
+}
+}  // namespace
+
 Browser* FindBrowser() {
   BrowserList* browser_list = BrowserList::GetInstance();
   for (BrowserList::const_reverse_iterator browser_iterator =
@@ -30,20 +41,20 @@
   return nullptr;
 }
 
-bool SettingsPageIsActiveTab(Browser* browser) {
+bool CleanupPageIsActiveTab(Browser* browser) {
   DCHECK(browser);
 
   content::WebContents* web_contents =
       browser->tab_strip_model()->GetActiveWebContents();
   return web_contents &&
-         web_contents->GetLastCommittedURL() == chrome::kChromeUISettingsURL;
+         web_contents->GetLastCommittedURL() == GetCleanupPageURL();
 }
 
-void OpenSettingsPage(Browser* browser, WindowOpenDisposition disposition) {
+void OpenCleanupPage(Browser* browser, WindowOpenDisposition disposition) {
   DCHECK(browser);
 
   browser->OpenURL(content::OpenURLParams(
-      GURL(chrome::kChromeUISettingsURL), content::Referrer(), disposition,
+      GetCleanupPageURL(), content::Referrer(), disposition,
       ui::PAGE_TRANSITION_AUTO_TOPLEVEL, /*is_renderer_initiated=*/false));
 }
 
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_navigation_util_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_navigation_util_win.h
index 9828962..df562314 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_navigation_util_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_navigation_util_win.h
@@ -13,11 +13,11 @@
 // exists.
 Browser* FindBrowser();
 
-// Returns true if the settings page is the currently active tab.
-bool SettingsPageIsActiveTab(Browser* browser);
+// Returns true if the page with Cleaner UI is the currently active tab.
+bool CleanupPageIsActiveTab(Browser* browser);
 
-// Opens a new settings tab in |browser| with the given |disposition|.
-void OpenSettingsPage(Browser* browser, WindowOpenDisposition disposition);
+// Opens a new settings tab containing Cleaner UI card.
+void OpenCleanupPage(Browser* browser, WindowOpenDisposition disposition);
 
 }  // namespace chrome_cleaner_util
 
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_browsertest_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_browsertest_win.cc
index 0a39ad4..45f5746 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_browsertest_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_browsertest_win.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -45,18 +46,33 @@
   MOCK_METHOD0(OnSettingsPageIsActiveTab, void());
 };
 
-// Parameters for this test:
+// Parameters:
 //  - bool reboot_dialog_enabled_: if kRebootPromptDialogFeature is enabled.
-class ChromeCleanerRebootFlowTest : public InProcessBrowserTest,
-                                    public ::testing::WithParamInterface<bool> {
+//  - bool user_initiated_cleanups_enabled_:
+//        if kUserInitiatedChromeCleanupsFeature is enabled.
+using ChromeCleanerRebootFlowTestParams = std::tuple<bool, bool>;
+
+class ChromeCleanerRebootFlowTest
+    : public InProcessBrowserTest,
+      public ::testing::WithParamInterface<ChromeCleanerRebootFlowTestParams> {
  public:
-  ChromeCleanerRebootFlowTest() { reboot_dialog_enabled_ = GetParam(); }
+  ChromeCleanerRebootFlowTest() {
+    reboot_dialog_enabled_ = std::get<0>(GetParam());
+    user_initiated_cleanups_enabled_ = std::get<1>(GetParam());
+  }
 
   void SetUpInProcessBrowserTestFixture() override {
+    std::vector<base::Feature> enabled_features;
+    std::vector<base::Feature> disabled_features;
     if (reboot_dialog_enabled_)
-      scoped_feature_list_.InitAndEnableFeature(kRebootPromptDialogFeature);
+      enabled_features.push_back(kRebootPromptDialogFeature);
     else
-      scoped_feature_list_.InitAndDisableFeature(kRebootPromptDialogFeature);
+      disabled_features.push_back(kRebootPromptDialogFeature);
+    if (user_initiated_cleanups_enabled_)
+      enabled_features.push_back(kUserInitiatedChromeCleanupsFeature);
+    else
+      disabled_features.push_back(kUserInitiatedChromeCleanupsFeature);
+    scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
 
     // The implementation of dialog_controller_ may check state, and we are not
     // interested in ensuring how many times this is done, since it's not part
@@ -68,6 +84,11 @@
   }
 
   void SetUpOnMainThread() override {
+    cleanup_settings_page_url_ =
+        user_initiated_cleanups_enabled_
+            ? chrome::GetSettingsUrl(chrome::kCleanupSubPage)
+            : chrome::GetSettingsUrl("");
+
     run_loop_ = base::MakeUnique<base::RunLoop>();
   }
 
@@ -128,6 +149,8 @@
   }
 
   bool reboot_dialog_enabled_ = false;
+  bool user_initiated_cleanups_enabled_ = false;
+  GURL cleanup_settings_page_url_;
 
   StrictMock<MockChromeCleanerController> mock_cleaner_controller_;
   std::unique_ptr<MockPromptDelegate> mock_prompt_delegate_;
@@ -144,8 +167,8 @@
                        OnRebootRequired_SettingsPageActive) {
   SetExpectationsWhenSettingsPageIsActive();
 
-  OpenPage(GURL(chrome::kChromeUISettingsURL), browser());
-  ASSERT_TRUE(chrome_cleaner_util::SettingsPageIsActiveTab(browser()));
+  OpenPage(cleanup_settings_page_url_, browser());
+  ASSERT_TRUE(chrome_cleaner_util::CleanupPageIsActiveTab(browser()));
 
   ChromeCleanerRebootDialogControllerImpl::Create(
       &mock_cleaner_controller_, std::move(mock_prompt_delegate_));
@@ -167,9 +190,8 @@
       &mock_cleaner_controller_, std::move(mock_prompt_delegate_));
 
   EXPECT_FALSE(reboot_prompt_started_);
-  Browser* browser =
-      CreateBrowserShowingUrl(GURL(chrome::kChromeUISettingsURL));
-  ASSERT_TRUE(chrome_cleaner_util::SettingsPageIsActiveTab(browser));
+  Browser* browser = CreateBrowserShowingUrl(cleanup_settings_page_url_);
+  ASSERT_TRUE(chrome_cleaner_util::CleanupPageIsActiveTab(browser));
 
   EnsureCompletedExecution();
 }
@@ -204,9 +226,17 @@
   EnsureCompletedExecution();
 }
 
-INSTANTIATE_TEST_CASE_P(AllTests,
+INSTANTIATE_TEST_CASE_P(UserInitiatedCleanupsDisabled,
                         ChromeCleanerRebootFlowTest,
-                        ::testing::Bool());
+                        ::testing::Combine(::testing::Bool(),
+                                           ::testing::Values(false)));
+
+#if defined(GOOGLE_CHROME_BUILD)
+INSTANTIATE_TEST_CASE_P(UserInitiatedCleanupsEnabled,
+                        ChromeCleanerRebootFlowTest,
+                        ::testing::Combine(::testing::Bool(),
+                                           ::testing::Values(true)));
+#endif  // defined(GOOGLE_CHROME_BUILD)
 
 class ChromeCleanerRebootDialogResponseTest : public InProcessBrowserTest {
  public:
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_win.cc
index 724368dd..b652164 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_win.cc
@@ -51,7 +51,7 @@
 void PromptDelegateImpl::OpenSettingsPage(Browser* browser) {
   DCHECK(browser);
 
-  chrome_cleaner_util::OpenSettingsPage(
+  chrome_cleaner_util::OpenCleanupPage(
       browser, WindowOpenDisposition::NEW_BACKGROUND_TAB);
 }
 
@@ -166,7 +166,7 @@
 void ChromeCleanerRebootDialogControllerImpl::StartRebootPromptForBrowser(
     Browser* browser) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (chrome_cleaner_util::SettingsPageIsActiveTab(browser)) {
+  if (chrome_cleaner_util::CleanupPageIsActiveTab(browser)) {
     RecordSettingsPageActiveOnRebootRequired(
         SETTINGS_PAGE_ON_REBOOT_REQUIRED_ACTIVE_TAB);
 
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_win.h
index 3c093aa..8511ace 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_reboot_dialog_controller_impl_win.h
@@ -61,8 +61,9 @@
   void MaybeStartRebootPrompt();
 
   // Shows the reboot prompt dialog in |browser| if the reboot prompt experiment
-  // is on and the Settings page is not the currently active tab. Otherwise,
-  // this will reopen the Settings page on a background tab.
+  // is on and the Settings page containing Chrome Cleanup UI is not the
+  // currently active tab. Otherwise, this will reopen the Settings page on a
+  // background tab.
   void StartRebootPromptForBrowser(Browser* browser);
 
   void OnInteractionDone();
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.cc
index c3d5ec5..c823ce8d 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.cc
@@ -10,4 +10,9 @@
 
 MockChromeCleanerController::~MockChromeCleanerController() = default;
 
+void MockChromeCleanerController::OnSwReporterReady(
+    SwReporterInvocationSequence&& sequence) {
+  MockedOnSwReporterReady(sequence);
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.h b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.h
index be4fca7..1b8cc8b 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.h
@@ -16,6 +16,10 @@
   MockChromeCleanerController();
   ~MockChromeCleanerController() override;
 
+  // gmock does not support rvalue references in MOCK_METHOD. This method just
+  // relays the argument to OnSwReporterReady_.
+  void OnSwReporterReady(SwReporterInvocationSequence&& sequence) override;
+
   MOCK_METHOD0(ShouldShowCleanupInSettingsUI, bool());
   MOCK_METHOD0(IsPoweredByPartner, bool());
   MOCK_CONST_METHOD0(state, State());
@@ -27,6 +31,8 @@
   MOCK_METHOD1(RemoveObserver, void(Observer*));
   MOCK_METHOD0(OnReporterSequenceStarted, void());
   MOCK_METHOD1(OnReporterSequenceDone, void(SwReporterInvocationResult));
+  MOCK_METHOD0(RequestUserInitiatedScan, void());
+  MOCK_METHOD1(MockedOnSwReporterReady, void(SwReporterInvocationSequence&));
   MOCK_METHOD1(Scan, void(const safe_browsing::SwReporterInvocation&));
   MOCK_METHOD2(ReplyWithUserResponse, void(Profile*, UserResponse));
   MOCK_METHOD0(Reboot, void());
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc
index 6d56950..b1e0bd6 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc
@@ -211,7 +211,7 @@
                 OnReporterSequenceDone(Eq(expected_result)))
         .WillOnce(InvokeWithoutArgs(&on_sequence_done, &Waiter::Signal));
     auto invocations = CreateInvocationSequence(container);
-    RunSwReportersForTesting(invocation_type_, std::move(invocations));
+    MaybeStartSwReporter(invocation_type_, std::move(invocations));
     on_sequence_done.Wait();
   }
 
@@ -415,8 +415,8 @@
                   InvokeWithoutArgs(&first_sequence_done, &Waiter::Signal)));
 
     SwReporterInvocationSequence::Queue invocations1({CreateInvocation(path1)});
-    RunSwReportersForTesting(invocation_type1,
-                             CreateInvocationSequence(invocations1));
+    MaybeStartSwReporter(invocation_type1,
+                         CreateInvocationSequence(invocations1));
 
     EXPECT_CALL(
         mock_chrome_cleaner_controller_,
@@ -424,8 +424,8 @@
         .WillOnce(InvokeWithoutArgs(&second_sequence_done, &Waiter::Signal));
 
     SwReporterInvocationSequence::Queue invocations2({CreateInvocation(path2)});
-    RunSwReportersForTesting(invocation_type2,
-                             CreateInvocationSequence(invocations2));
+    MaybeStartSwReporter(invocation_type2,
+                         CreateInvocationSequence(invocations2));
 
     first_sequence_done.Wait();
 
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.cc
index 26a8fc8..e0ff43a 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.cc
@@ -1060,6 +1060,17 @@
       container_(std::move(invocations_sequence.container_)),
       on_sequence_done_(std::move(invocations_sequence.on_sequence_done_)) {}
 
+SwReporterInvocationSequence::SwReporterInvocationSequence(
+    const SwReporterInvocationSequence& invocations_sequence)
+    : version_(invocations_sequence.version_),
+      container_(invocations_sequence.container_) {
+  // As in the regular constructor: notify the cleaner controller once this
+  // sequence completes.
+  on_sequence_done_ =
+      base::BindOnce(&ChromeCleanerController::OnReporterSequenceDone,
+                     base::Unretained(GetCleanerController()));
+}
+
 SwReporterInvocationSequence::~SwReporterInvocationSequence() = default;
 
 void SwReporterInvocationSequence::operator=(
@@ -1094,8 +1105,8 @@
   return container_;
 }
 
-void RunSwReportersForTesting(SwReporterInvocationType invocation_type,
-                              SwReporterInvocationSequence&& invocations) {
+void MaybeStartSwReporter(SwReporterInvocationType invocation_type,
+                          SwReporterInvocationSequence&& invocations) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!invocations.container().empty());
 
@@ -1103,15 +1114,6 @@
                                         std::move(invocations));
 }
 
-void OnSwReporterReady(SwReporterInvocationSequence&& invocations) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(!invocations.container().empty());
-
-  // TODO(crbug.com/776538): Handle user-initiated cleanups.
-  ReporterRunner::MaybeStartInvocations(SwReporterInvocationType::kPeriodicRun,
-                                        std::move(invocations));
-}
-
 void SetSwReporterTestingDelegate(SwReporterTestingDelegate* delegate) {
   g_testing_delegate_ = delegate;
 }
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h
index 485a2c8..b497935 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h
+++ b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h
@@ -136,6 +136,9 @@
   kNotScheduled,
   // The reporter process timed-out while running.
   kTimedOut,
+  // The on-demand reporter run failed to download a new version of the reporter
+  // component.
+  kComponentNotAvailable,
   // The reporter failed to start.
   kProcessFailedToLaunch,
   // The reporter ended with a failure.
@@ -163,6 +166,8 @@
   explicit SwReporterInvocationSequence(
       const base::Version& version = base::Version());
   SwReporterInvocationSequence(SwReporterInvocationSequence&& queue);
+  SwReporterInvocationSequence(
+      const SwReporterInvocationSequence& invocations_sequence);
   virtual ~SwReporterInvocationSequence();
 
   void PushInvocation(const SwReporterInvocation& invocation);
@@ -184,12 +189,6 @@
   OnReporterSequenceDone on_sequence_done_;
 };
 
-// This is used only by tests and exists solely to make the browser tests happy
-// while we implement user-initiated runs.
-// TODO(proberge): Remove this by Q1 2018.
-void RunSwReportersForTesting(SwReporterInvocationType invocation_type,
-                              SwReporterInvocationSequence&& invocations);
-
 // Tries to run the given invocations. If this runs successfully, than any
 // calls made in the next |kDaysBetweenSuccessfulSwReporterRuns| days will be
 // ignored.
@@ -198,7 +197,8 @@
 // executions of the tool with different command lines. |invocations| is the
 // queue of SwReporters to execute as a single "run". When a new try is
 // scheduled the entire queue is executed.
-void OnSwReporterReady(SwReporterInvocationSequence&& invocations);
+void MaybeStartSwReporter(SwReporterInvocationType invocation_type,
+                          SwReporterInvocationSequence&& invocations);
 
 // A delegate used by tests to implement test doubles (e.g., stubs, fakes, or
 // mocks).
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index c37fbea0..897481bb 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -510,6 +510,8 @@
       : https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
         https_server_expired_(net::EmbeddedTestServer::TYPE_HTTPS),
         https_server_mismatched_(net::EmbeddedTestServer::TYPE_HTTPS),
+        https_server_sha1_(net::EmbeddedTestServer::TYPE_HTTPS),
+        https_server_common_name_only_(net::EmbeddedTestServer::TYPE_HTTPS),
         https_server_ocsp_ok_(
             net::SpawnedTestServer::TYPE_HTTPS,
             GetOCSPSSLOptions(net::SpawnedTestServer::SSLOptions::OCSP_OK),
@@ -533,6 +535,13 @@
         net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
     https_server_mismatched_.AddDefaultHandlers(base::FilePath(kDocRoot));
 
+    https_server_sha1_.SetSSLConfig(net::EmbeddedTestServer::CERT_SHA1_LEAF);
+    https_server_sha1_.AddDefaultHandlers(base::FilePath(kDocRoot));
+
+    https_server_common_name_only_.SetSSLConfig(
+        net::EmbeddedTestServer::CERT_COMMON_NAME_ONLY);
+    https_server_common_name_only_.AddDefaultHandlers(base::FilePath(kDocRoot));
+
     // Sometimes favicons load before tests check the authentication
     // state, and sometimes they load after. This is problematic on
     // tests that load pages with certificate errors, because the page
@@ -786,25 +795,32 @@
     }
   }
 
-  void UpdateChromePolicy(const policy::PolicyMap& policies) {
-    policy_provider_.UpdateChromePolicy(policies);
-    DCHECK(base::MessageLoop::current());
-    base::RunLoop loop;
-    loop.RunUntilIdle();
+  // Sets the policy identified by |policy_name| to be true, ensuring
+  // that the corresponding boolean pref |pref_name| is updated to match.
+  void EnablePolicy(const char* policy_name, const char* pref_name) {
+    policy::PolicyMap policy_map;
+    policy_map.Set(policy_name, policy::POLICY_LEVEL_MANDATORY,
+                   policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD,
+                   std::make_unique<base::Value>(true), nullptr);
+
+    EXPECT_NO_FATAL_FAILURE(UpdateChromePolicy(policy_map));
+
+    EXPECT_TRUE(g_browser_process->local_state()->GetBoolean(pref_name));
+    EXPECT_TRUE(
+        g_browser_process->local_state()->IsManagedPreference(pref_name));
   }
 
-  void EnableRevocationChecking() {
-    policy::PolicyMap policy_map;
-    policy_map.Set(policy::key::kEnableOnlineRevocationChecks,
-                   policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
-                   policy::POLICY_SOURCE_CLOUD,
-                   base::MakeUnique<base::Value>(true), nullptr);
-    UpdateChromePolicy(policy_map);
-
-    EXPECT_TRUE(g_browser_process->local_state()->GetBoolean(
-        ssl_config::prefs::kCertRevocationCheckingEnabled));
-    EXPECT_TRUE(g_browser_process->local_state()->IsManagedPreference(
-        ssl_config::prefs::kCertRevocationCheckingEnabled));
+  // Checks that the SSLConfig associated with the net::URLRequestContext
+  // of the |context_getter| has the SSLConfig member identified by |member|
+  // set to |expected|. This is sequenced such that any changes to prefs
+  // on the UI thread will have propogated before the config is examined.
+  void CheckSSLConfig(
+      scoped_refptr<net::URLRequestContextGetter> context_getter,
+      bool net::SSLConfig::*member,
+      bool expected) {
+    RunOnIOThreadBlocking(base::BindOnce(
+        &SSLUITestBase::CheckSSLConfigOnIOThread, base::Unretained(this),
+        context_getter, member, expected));
   }
 
   // Helper function for TestInterstitialLinksOpenInNewTab. Implemented as a
@@ -818,6 +834,9 @@
   net::EmbeddedTestServer https_server_;
   net::EmbeddedTestServer https_server_expired_;
   net::EmbeddedTestServer https_server_mismatched_;
+  net::EmbeddedTestServer https_server_sha1_;
+  net::EmbeddedTestServer https_server_common_name_only_;
+
   net::SpawnedTestServer https_server_ocsp_ok_;
   net::SpawnedTestServer https_server_ocsp_revoked_;
   net::SpawnedTestServer wss_server_expired_;
@@ -856,6 +875,34 @@
  private:
   typedef net::SpawnedTestServer::SSLOptions SSLOptions;
 
+  void UpdateChromePolicy(const policy::PolicyMap& policies) {
+    policy_provider_.UpdateChromePolicy(policies);
+    ASSERT_TRUE(base::MessageLoop::current());
+
+    base::RunLoop loop;
+    loop.RunUntilIdle();
+  }
+
+  void RunOnIOThreadBlocking(base::OnceClosure task) {
+    base::RunLoop run_loop;
+    content::BrowserThread::PostTaskAndReply(content::BrowserThread::IO,
+                                             FROM_HERE, std::move(task),
+                                             run_loop.QuitClosure());
+    run_loop.Run();
+  }
+
+  void CheckSSLConfigOnIOThread(
+      scoped_refptr<net::URLRequestContextGetter> context_getter,
+      bool net::SSLConfig::*member,
+      bool expected) {
+    net::URLRequestContext* context = context_getter->GetURLRequestContext();
+    ASSERT_TRUE(context);
+
+    net::SSLConfig config;
+    context->ssl_config_service()->GetSSLConfig(&config);
+    EXPECT_EQ(expected, config.*member);
+  }
+
   policy::MockConfigurationPolicyProvider policy_provider_;
 
   DISALLOW_COPY_AND_ASSIGN(SSLUITestBase);
@@ -1691,7 +1738,12 @@
 
 // Visits a page with revocation checking enabled and a valid OCSP response.
 IN_PROC_BROWSER_TEST_P(SSLUITest, TestHTTPSOCSPOk) {
-  EnableRevocationChecking();
+  bool net::SSLConfig::*member = &net::SSLConfig::rev_checking_enabled;
+  ASSERT_NO_FATAL_FAILURE(
+      EnablePolicy(policy::key::kEnableOnlineRevocationChecks,
+                   ssl_config::prefs::kCertRevocationCheckingEnabled));
+  ASSERT_NO_FATAL_FAILURE(
+      CheckSSLConfig(browser()->profile()->GetRequestContext(), member, true));
 
   ASSERT_TRUE(https_server_ocsp_ok_.Start());
 
@@ -1713,7 +1765,12 @@
 
 // Visits a page with revocation checking enabled and a revoked OCSP response.
 IN_PROC_BROWSER_TEST_P(SSLUITest, TestHTTPSOCSPRevoked) {
-  EnableRevocationChecking();
+  bool net::SSLConfig::*member = &net::SSLConfig::rev_checking_enabled;
+  ASSERT_NO_FATAL_FAILURE(
+      EnablePolicy(policy::key::kEnableOnlineRevocationChecks,
+                   ssl_config::prefs::kCertRevocationCheckingEnabled));
+  ASSERT_NO_FATAL_FAILURE(
+      CheckSSLConfig(browser()->profile()->GetRequestContext(), member, true));
 
   ASSERT_TRUE(https_server_ocsp_revoked_.Start());
 
@@ -1725,6 +1782,77 @@
       net::CERT_STATUS_REVOKED, AuthState::SHOWING_INTERSTITIAL);
 }
 
+// Visits a page that uses a SHA-1 leaf certificate, which should be rejected
+// by default.
+IN_PROC_BROWSER_TEST_P(SSLUITest, SHA1IsDefaultDisabled) {
+  bool net::SSLConfig::*member = &net::SSLConfig::sha1_local_anchors_enabled;
+
+  ASSERT_NO_FATAL_FAILURE(
+      CheckSSLConfig(browser()->profile()->GetRequestContext(), member, false));
+
+  ASSERT_TRUE(https_server_sha1_.Start());
+  ui_test_utils::NavigateToURL(browser(),
+                               https_server_sha1_.GetURL("/ssl/google.html"));
+
+  CheckAuthenticationBrokenState(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM,
+      AuthState::SHOWING_INTERSTITIAL);
+}
+
+// Enables support for SHA-1 certificates from locally installed CAs, then
+// attempts to navigate to such a site. No interstitial should be presented.
+IN_PROC_BROWSER_TEST_P(SSLUITest, SHA1PrefsCanEnable) {
+  bool net::SSLConfig::*member = &net::SSLConfig::sha1_local_anchors_enabled;
+
+  ASSERT_NO_FATAL_FAILURE(
+      EnablePolicy(policy::key::kEnableSha1ForLocalAnchors,
+                   ssl_config::prefs::kCertEnableSha1LocalAnchors));
+  ASSERT_NO_FATAL_FAILURE(
+      CheckSSLConfig(browser()->profile()->GetRequestContext(), member, true));
+
+  ASSERT_TRUE(https_server_sha1_.Start());
+  ui_test_utils::NavigateToURL(browser(),
+                               https_server_sha1_.GetURL("/ssl/google.html"));
+
+  CheckUnauthenticatedState(
+      browser()->tab_strip_model()->GetActiveWebContents(), AuthState::NONE);
+}
+
+IN_PROC_BROWSER_TEST_P(SSLUITest, CommonNameIsDefaultDisabled) {
+  bool net::SSLConfig::*member =
+      &net::SSLConfig::common_name_fallback_local_anchors_enabled;
+
+  ASSERT_NO_FATAL_FAILURE(
+      CheckSSLConfig(browser()->profile()->GetRequestContext(), member, false));
+
+  ASSERT_TRUE(https_server_common_name_only_.Start());
+  ui_test_utils::NavigateToURL(
+      browser(), https_server_common_name_only_.GetURL("/ssl/google.html"));
+
+  CheckAuthenticationBrokenState(
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      net::CERT_STATUS_COMMON_NAME_INVALID, AuthState::SHOWING_INTERSTITIAL);
+}
+
+IN_PROC_BROWSER_TEST_P(SSLUITest, CommonNamePrefsCanEnable) {
+  bool net::SSLConfig::*member =
+      &net::SSLConfig::common_name_fallback_local_anchors_enabled;
+
+  ASSERT_NO_FATAL_FAILURE(EnablePolicy(
+      policy::key::kEnableCommonNameFallbackForLocalAnchors,
+      ssl_config::prefs::kCertEnableCommonNameFallbackLocalAnchors));
+  ASSERT_NO_FATAL_FAILURE(
+      CheckSSLConfig(browser()->profile()->GetRequestContext(), member, true));
+
+  ASSERT_TRUE(https_server_common_name_only_.Start());
+  ui_test_utils::NavigateToURL(
+      browser(), https_server_common_name_only_.GetURL("/ssl/google.html"));
+
+  CheckAuthenticatedState(browser()->tab_strip_model()->GetActiveWebContents(),
+                          AuthState::NONE);
+}
+
 // Visit a HTTP page which request WSS connection to a server providing invalid
 // certificate. Close the page while WSS connection waits for SSLManager's
 // response from UI thread.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index a763cd64..75a7d48 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1536,6 +1536,7 @@
       "//ash/resources/vector_icons",
       "//ash/strings",
       "//chrome/browser/chromeos",
+      "//chromeos/components/tether",
       "//components/arc",
       "//components/drive:drive_chromeos",
       "//components/exo",
diff --git a/chrome/browser/ui/apps/chrome_app_delegate.cc b/chrome/browser/ui/apps/chrome_app_delegate.cc
index f0147378..0de1c79 100644
--- a/chrome/browser/ui/apps/chrome_app_delegate.cc
+++ b/chrome/browser/ui/apps/chrome_app_delegate.cc
@@ -298,7 +298,7 @@
   content::RenderFrameHost* host = web_contents->GetMainFrame();
   if (host) {
     extensions::mojom::AppWindowPtr app_window;
-    BindInterface(host->GetProcess(), &app_window);
+    host->GetRemoteInterfaces()->GetInterface(&app_window);
     app_window->SetVisuallyDeemphasized(blocked);
   }
 }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
index 0b1954c..019c266a 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -70,7 +70,6 @@
 #include "ui/app_list/app_list_switches.h"
 #include "ui/app_list/views/app_list_item_view.h"
 #include "ui/app_list/views/apps_grid_view.h"
-#include "ui/app_list/views/tile_item_view.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/test/mus/change_completion_waiter.h"
 #include "ui/aura/window.h"
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
index aea03a3..c2f4886 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -65,6 +65,8 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
 #include "chrome/browser/ui/ash/session_controller_client.h"
 #include "chrome/browser/ui/ash/tablet_mode_client.h"
+#include "chrome/browser/ui/ash/test_wallpaper_controller.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -1162,8 +1164,12 @@
     user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
         std::make_unique<chromeos::FakeChromeUserManager>());
 
-    // Initialize the WallpaperManager singleton.
+    // Initialize the WallpaperManager singleton and WallpaperControllerClient.
     chromeos::WallpaperManager::Initialize();
+    wallpaper_controller_client_ =
+        std::make_unique<WallpaperControllerClient>();
+    wallpaper_controller_client_->InitForTesting(
+        test_wallpaper_controller_.CreateInterfacePtr());
 
     // Initialize the rest.
     ChromeLauncherControllerTest::SetUp();
@@ -1180,6 +1186,7 @@
     ChromeLauncherControllerTest::TearDown();
     user_manager_enabler_.reset();
     chromeos::WallpaperManager::Shutdown();
+    wallpaper_controller_client_.reset();
 
     // A Task is leaked if we don't destroy everything, then run the message
     // loop.
@@ -1269,6 +1276,10 @@
 
   std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
 
+  std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_;
+
+  TestWallpaperController test_wallpaper_controller_;
+
   ProfileToNameMap created_profiles_;
 
   DISALLOW_COPY_AND_ASSIGN(
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
index a922ff2..983bf56 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
@@ -38,6 +38,8 @@
 #include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h"
 #include "chrome/browser/ui/ash/session_controller_client.h"
 #include "chrome/browser/ui/ash/session_util.h"
+#include "chrome/browser/ui/ash/test_wallpaper_controller.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -295,6 +297,10 @@
 
   user_manager::ScopedUserManager user_manager_enabler_;
 
+  std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_;
+
+  TestWallpaperController test_wallpaper_controller_;
+
   // The maximized window manager (if enabled).
   std::unique_ptr<TabletModeWindowManager> tablet_mode_window_manager_;
 
@@ -330,6 +336,9 @@
   MultiUserWindowManager::SetInstanceForTest(multi_user_window_manager_);
   EXPECT_TRUE(multi_user_window_manager_);
   chromeos::WallpaperManager::Initialize();
+  wallpaper_controller_client_ = std::make_unique<WallpaperControllerClient>();
+  wallpaper_controller_client_->InitForTesting(
+      test_wallpaper_controller_.CreateInterfacePtr());
 }
 
 void MultiUserWindowManagerChromeOSTest::TearDown() {
@@ -343,6 +352,7 @@
   MultiUserWindowManager::DeleteInstance();
   AshTestBase::TearDown();
   chromeos::WallpaperManager::Shutdown();
+  wallpaper_controller_client_.reset();
   profile_manager_.reset();
 }
 
diff --git a/chrome/browser/ui/browser_finder_chromeos_unittest.cc b/chrome/browser/ui/browser_finder_chromeos_unittest.cc
index 16b7677..70618375 100644
--- a/chrome/browser/ui/browser_finder_chromeos_unittest.cc
+++ b/chrome/browser/ui/browser_finder_chromeos_unittest.cc
@@ -11,6 +11,8 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
+#include "chrome/browser/ui/ash/test_wallpaper_controller.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/test_browser_window_aura.h"
 #include "chrome/test/base/testing_profile_manager.h"
@@ -66,6 +68,10 @@
     BrowserWithTestWindowTest::SetUp();
     profile_manager()->SetLoggedIn(true);
     chromeos::WallpaperManager::Initialize();
+    wallpaper_controller_client_ =
+        std::make_unique<WallpaperControllerClient>();
+    wallpaper_controller_client_->InitForTesting(
+        test_wallpaper_controller_.CreateInterfacePtr());
     second_profile_ = CreateMultiUserProfile(test_account_id2_);
   }
 
@@ -73,6 +79,7 @@
     MultiUserWindowManager::DeleteInstance();
     BrowserWithTestWindowTest::TearDown();
     chromeos::WallpaperManager::Shutdown();
+    wallpaper_controller_client_.reset();
   }
 
   TestingProfile* CreateProfile() override {
@@ -86,6 +93,10 @@
   chromeos::FakeChromeUserManager* fake_user_manager_;
   user_manager::ScopedUserManager user_manager_enabler_;
 
+  std::unique_ptr<WallpaperControllerClient> wallpaper_controller_client_;
+
+  TestWallpaperController test_wallpaper_controller_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserFinderChromeOSTest);
 };
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller_unittest.mm
index 5c4809a4..f33ed89 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller_unittest.mm
@@ -6,7 +6,7 @@
 
 #include "base/mac/scoped_nsobject.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/autofill/layout_view_unittest.mm b/chrome/browser/ui/cocoa/autofill/layout_view_unittest.mm
index 2524af4..59b99ef 100644
--- a/chrome/browser/ui/cocoa/autofill/layout_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/layout_view_unittest.mm
@@ -8,7 +8,7 @@
 #include "chrome/browser/ui/cocoa/autofill/simple_grid_layout.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_button_unittest.mm b/chrome/browser/ui/cocoa/profiles/avatar_button_unittest.mm
index cca632f..461a319b 100644
--- a/chrome/browser/ui/cocoa/profiles/avatar_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/profiles/avatar_button_unittest.mm
@@ -5,8 +5,8 @@
 #import "chrome/browser/ui/cocoa/profiles/avatar_button.h"
 
 #import "base/mac/scoped_nsobject.h"
+#import "ui/base/test/cocoa_helper.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 @interface AvatarButton (ExposedForTesting)
 - (void)performRightClick;
diff --git a/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa_unittest.mm b/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa_unittest.mm
index ef1ee89..3076eea 100644
--- a/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa_unittest.mm
+++ b/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa_unittest.mm
@@ -86,7 +86,9 @@
   target_->OnStarted(
       base::Bind(&ScreenCaptureNotificationUICocoaTest::StopCallback,
                  base::Unretained(this)));
-  EXPECT_EQ(460, NSWidth([[controller() window] frame]));
+  // Window size may not match the target value exactly (460), as we don't set
+  // it directly.
+  EXPECT_NEAR(NSWidth([[controller() window] frame]), 460.0, 5.0);
 }
 
 TEST_F(ScreenCaptureNotificationUICocoaTest, ClickStop) {
diff --git a/chrome/browser/ui/cocoa/spinner_view_unittest.mm b/chrome/browser/ui/cocoa/spinner_view_unittest.mm
index 1741af2..1244c85 100644
--- a/chrome/browser/ui/cocoa/spinner_view_unittest.mm
+++ b/chrome/browser/ui/cocoa/spinner_view_unittest.mm
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/cocoa/spinner_view.h"
 
 #include "base/mac/mac_util.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/cocoa/test/cocoa_test_helper.h b/chrome/browser/ui/cocoa/test/cocoa_test_helper.h
index 8120e93..95371bc 100644
--- a/chrome/browser/ui/cocoa/test/cocoa_test_helper.h
+++ b/chrome/browser/ui/cocoa/test/cocoa_test_helper.h
@@ -7,7 +7,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 // A test class that all tests that depend on AppKit should inherit from.
 // Sets up paths correctly, and makes sure that any windows created in the test
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc
index 78162ce..a1349c1b 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -78,6 +78,18 @@
   return base::FeatureList::IsEnabled(translate::kTranslateUI2016Q2);
 }
 
+// Container for |advanced_view_|. When the text on the "Translate"/"Done"
+// button changes a layout is required.
+class AdvancedViewContainer : public views::View {
+ public:
+  AdvancedViewContainer() {}
+
+  void ChildPreferredSizeChanged(views::View* child) override { Layout(); }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AdvancedViewContainer);
+};
+
 }  // namespace
 
 // static
@@ -928,7 +940,7 @@
     advanced_always_translate_checkbox_->set_listener(this);
   }
 
-  views::View* view = new views::View();
+  views::View* view = new AdvancedViewContainer();
   views::GridLayout* layout =
       view->SetLayoutManager(std::make_unique<views::GridLayout>(view));
 
diff --git a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
index 200dcb04..98c1270 100644
--- a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
+++ b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
@@ -151,8 +151,6 @@
 
     std::unique_ptr<history::FakeWebHistoryService> service =
         base::MakeUnique<history::FakeWebHistoryService>(
-            ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
-            SigninManagerFactory::GetForProfile(profile),
             profile->GetRequestContext());
     service->SetupFakeResponse(true /* success */, net::HTTP_OK);
     return std::move(service);
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index d7d3a15..ebeeb37 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -144,13 +144,10 @@
   source->AddLocalizedString("noExtensionsOrApps",
                              IDS_MD_EXTENSIONS_NO_INSTALLED_ITEMS);
   source->AddLocalizedString("noDescription", IDS_MD_EXTENSIONS_NO_DESCRIPTION);
-  // TODO(dschuyler): define "viewInStore" as IDS_MD_EXTENSIONS_VIEW_IN_STORE.
   source->AddLocalizedString("viewInStore",
-                             IDS_APPLICATION_INFO_WEB_STORE_LINK);
-  // TODO(dschuyler): define "developerWebsite" as
-  // IDS_MD_EXTENSIONS_DEVELOPER_WEBSITE.
-  source->AddLocalizedString("developerWebsite",
-                             IDS_APPLICATION_INFO_HOMEPAGE_LINK);
+                             IDS_MD_EXTENSIONS_ITEM_CHROME_WEB_STORE);
+  source->AddLocalizedString("extensionWebsite",
+                             IDS_MD_EXTENSIONS_ITEM_EXTENSION_WEBSITE);
   source->AddLocalizedString("noSearchResults", IDS_SEARCH_NO_RESULTS);
   source->AddLocalizedString("searchResults", IDS_SEARCH_RESULTS);
   source->AddLocalizedString("dropToInstall",
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
index 2cd8d3a9..bc04df3 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
@@ -9,12 +9,14 @@
 
 #include "base/base_switches.h"
 #include "base/command_line.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/flag_descriptions.h"
 #include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/previews/core/previews_experiments.h"
+#include "net/nqe/network_quality_estimator_params.h"
 
 namespace {
 
@@ -68,6 +70,16 @@
   return kDefaultFlagValue;
 }
 
+std::string GetNonFlagEctValue() {
+  std::map<std::string, std::string> nqe_params;
+  base::GetFieldTrialParams("NetworkQualityEstimator", &nqe_params);
+  if (nqe_params.find(net::kForceEffectiveConnectionType) != nqe_params.end()) {
+    return "Fieldtrial forced " +
+           nqe_params[net::kForceEffectiveConnectionType];
+  }
+  return kDefaultFlagValue;
+}
+
 }  // namespace
 
 InterventionsInternalsPageHandler::InterventionsInternalsPageHandler(
@@ -199,7 +211,7 @@
   std::string ect_value =
       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
           switches::kForceEffectiveConnectionType);
-  ect_status->value = ect_value.empty() ? kDefaultFlagValue : ect_value;
+  ect_status->value = ect_value.empty() ? GetNonFlagEctValue() : ect_value;
   ect_status->htmlId = kEctFlagHtmlId;
   flags.push_back(std::move(ect_status));
 
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
index efec74c..7215df62 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
@@ -13,6 +13,8 @@
 #include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
@@ -35,6 +37,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "net/nqe/effective_connection_type.h"
+#include "net/nqe/network_quality_estimator_params.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -459,6 +462,28 @@
   }
 }
 
+TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsEctForceFieldtrialValue) {
+  base::FieldTrialList field_trial_list_(nullptr);
+  const std::string trial_name = "NetworkQualityEstimator";
+  const std::string group_name = "Enabled";
+  const std::string expected_ect = "Slow-2G";
+
+  std::map<std::string, std::string> params;
+  params[net::kForceEffectiveConnectionType] = expected_ect;
+  ASSERT_TRUE(base::AssociateFieldTrialParams(trial_name, group_name, params));
+  base::FieldTrialList::CreateFieldTrial(trial_name, group_name);
+
+  page_handler_->GetPreviewsFlagsDetails(
+      base::BindOnce(&MockGetPreviewsFlagsCallback));
+
+  auto ect_flag = passed_in_flags.find(kEctFlagHtmlId);
+  ASSERT_NE(passed_in_flags.end(), ect_flag);
+  EXPECT_EQ(flag_descriptions::kForceEffectiveConnectionTypeName,
+            ect_flag->second->description);
+  EXPECT_EQ("Fieldtrial forced " + expected_ect, ect_flag->second->value);
+  EXPECT_EQ(kEctFlagLink, ect_flag->second->link);
+}
+
 TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsNoScriptDefaultValue) {
   page_handler_->GetPreviewsFlagsDetails(
       base::BindOnce(&MockGetPreviewsFlagsCallback));
diff --git a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc
index e01769d..a0e3aad 100644
--- a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc
+++ b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.cc
@@ -13,13 +13,16 @@
 #include "base/metrics/user_metrics_action.h"
 #include "base/synchronization/lock.h"
 #include "base/values.h"
+#include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/component_updater/sw_reporter_installer_win.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h"
 #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h"
+#include "chrome/grit/generated_resources.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_message_handler.h"
+#include "ui/base/l10n/l10n_util.h"
 
 using safe_browsing::ChromeCleanerController;
 
@@ -37,14 +40,36 @@
 };
 
 // Returns a ListValue containing a copy of the file paths stored in |files|.
-base::ListValue GetFilesAsListStorage(const std::set<base::FilePath>& files) {
-  base::ListValue value;
+std::unique_ptr<base::ListValue> GetFilesAsListStorage(
+    const std::set<base::FilePath>& files) {
+  auto value = base::MakeUnique<base::ListValue>();
   for (const base::FilePath& path : files)
-    value.AppendString(path.value());
+    value->AppendString(path.value());
 
   return value;
 }
 
+// Returns a ListValue containing a copy of the registry keys stored in
+// |registry_keys|.
+std::unique_ptr<base::ListValue> GetRegistryKeysAsListStorage(
+    const std::set<base::string16>& registry_keys) {
+  auto value = base::MakeUnique<base::ListValue>();
+  for (const base::string16& key : registry_keys)
+    value->AppendString(key);
+
+  return value;
+}
+
+base::DictionaryValue GetScannerResultsAsDictionary(
+    const safe_browsing::ChromeCleanerScannerResults& scanner_results) {
+  base::DictionaryValue value;
+  value.SetList("files",
+                GetFilesAsListStorage(scanner_results.files_to_delete()));
+  value.SetList("registryKeys",
+                GetRegistryKeysAsListStorage(scanner_results.registry_keys()));
+  return value;
+}
+
 std::string IdleReasonToString(
     ChromeCleanerController::IdleReason idle_reason) {
   switch (idle_reason) {
@@ -115,6 +140,15 @@
       base::BindRepeating(
           &ChromeCleanupHandler::HandleNotifyChromeCleanupLearnMoreClicked,
           base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getMoreItemsPluralString",
+      base::BindRepeating(&ChromeCleanupHandler::HandleGetMoreItemsPluralString,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getItemsToRemovePluralString",
+      base::BindRepeating(
+          &ChromeCleanupHandler::HandleGetItemsToRemovePluralString,
+          base::Unretained(this)));
 }
 
 void ChromeCleanupHandler::OnJavascriptAllowed() {
@@ -142,13 +176,13 @@
 void ChromeCleanupHandler::OnInfected(
     const safe_browsing::ChromeCleanerScannerResults& scanner_results) {
   FireWebUIListener("chrome-cleanup-on-infected",
-                    GetFilesAsListStorage(scanner_results.files_to_delete()));
+                    GetScannerResultsAsDictionary(scanner_results));
 }
 
 void ChromeCleanupHandler::OnCleaning(
     const safe_browsing::ChromeCleanerScannerResults& scanner_results) {
   FireWebUIListener("chrome-cleanup-on-cleaning",
-                    GetFilesAsListStorage(scanner_results.files_to_delete()));
+                    GetScannerResultsAsDictionary(scanner_results));
 }
 
 void ChromeCleanupHandler::OnRebootRequired() {
@@ -210,9 +244,7 @@
   // The state is propagated to all open tabs and should be consistent.
   DCHECK_EQ(controller_->logs_enabled(), allow_logs_upload);
 
-  // TODO(crbug.com/776538): Force a proper on-demand update of the component.
-  component_updater::RegisterSwReporterComponent(
-      g_browser_process->component_updater());
+  controller_->RequestUserInitiatedScan();
 
   base::RecordAction(
       base::UserMetricsAction("SoftwareReporter.CleanupWebui_StartScanning"));
@@ -289,4 +321,34 @@
       base::UserMetricsAction("SoftwareReporter.CleanupWebui_LearnMore"));
 }
 
+void ChromeCleanupHandler::HandleGetMoreItemsPluralString(
+    const base::ListValue* args) {
+#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+  GetPluralString(IDS_SETTINGS_RESET_CLEANUP_DETAILS_MORE, args);
+#endif  // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+}
+
+void ChromeCleanupHandler::HandleGetItemsToRemovePluralString(
+    const base::ListValue* args) {
+#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+  GetPluralString(IDS_SETTINGS_RESET_CLEANUP_DETAILS_ITEMS_TO_BE_REMOVED, args);
+#endif  // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
+}
+
+void ChromeCleanupHandler::GetPluralString(int id,
+                                           const base::ListValue* args) {
+  CHECK_EQ(2U, args->GetSize());
+
+  std::string callback_id;
+  CHECK(args->GetString(0, &callback_id));
+
+  int num_items = 0;
+  args->GetInteger(1, &num_items);
+  DCHECK_GT(0, num_items);
+
+  ResolveJavascriptCallback(
+      base::Value(callback_id),
+      base::Value(l10n_util::GetPluralStringFUTF16(id, num_items)));
+}
+
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h
index c0d61a2..c0d2a83 100644
--- a/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h
+++ b/chrome/browser/ui/webui/settings/chrome_cleanup_handler.h
@@ -76,6 +76,16 @@
   // the "learn more" link was clicked.
   void HandleNotifyChromeCleanupLearnMoreClicked(const base::ListValue* args);
 
+  // Callback for the "getMoreItemsPluralString" message, that obtains the text
+  // string for the "show more" items on the detailed view.
+  void HandleGetMoreItemsPluralString(const base::ListValue* args);
+
+  // Callback for the "getItemsToRemovePluralString" message, that obtains the
+  // text string for the detailed view when user-initiated cleanups are enabled.
+  void HandleGetItemsToRemovePluralString(const base::ListValue* args);
+
+  void GetPluralString(int id, const base::ListValue* args);
+
   // Raw pointer to a singleton. Must outlive this object.
   safe_browsing::ChromeCleanerController* controller_;
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
index 3aaa3065..38e54c5 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
@@ -11,6 +11,7 @@
 #include "base/values.h"
 #include "chrome/browser/chromeos/options/network_config_view.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/chromeos/tether/tether_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
@@ -71,14 +72,24 @@
 
 InternetHandler::InternetHandler(Profile* profile) : profile_(profile) {
   DCHECK(profile_);
+
   arc_vpn_provider_manager_ = app_list::ArcVpnProviderManager::Get(profile_);
   if (arc_vpn_provider_manager_)
     arc_vpn_provider_manager_->AddObserver(this);
+
+  TetherService* tether_service = TetherService::Get(profile);
+  gms_core_notifications_state_tracker_ =
+      tether_service ? tether_service->GetGmsCoreNotificationsStateTracker()
+                     : nullptr;
+  if (gms_core_notifications_state_tracker_)
+    gms_core_notifications_state_tracker_->AddObserver(this);
 }
 
 InternetHandler::~InternetHandler() {
   if (arc_vpn_provider_manager_)
     arc_vpn_provider_manager_->RemoveObserver(this);
+  if (gms_core_notifications_state_tracker_)
+    gms_core_notifications_state_tracker_->RemoveObserver(this);
 }
 
 void InternetHandler::RegisterMessages() {
@@ -126,6 +137,10 @@
   SendArcVpnProviders();
 }
 
+void InternetHandler::OnGmsCoreNotificationStateChanged() {
+  SetGmsCoreNotificationsDisabledDeviceNames();
+}
+
 void InternetHandler::AddNetwork(const base::ListValue* args) {
   std::string onc_type;
   if (args->GetSize() < 1 || !args->GetString(0, &onc_type)) {
@@ -217,12 +232,8 @@
 
 void InternetHandler::RequestGmsCoreNotificationsDisabledDeviceNames(
     const base::ListValue* args) {
-  // TODO(khorimoto): Send an actual list of device names. Currently, an empty
-  // list is sent. See crbug.com/765966.
-  std::vector<std::string> device_names;
-
   AllowJavascript();
-  SetGmsCoreNotificationsDisabledDeviceNames(device_names);
+  SetGmsCoreNotificationsDisabledDeviceNames();
 }
 
 void InternetHandler::SetArcVpnProviders(
@@ -248,9 +259,19 @@
   FireWebUIListener(kSendArcVpnProviders, arc_vpn_providers_value);
 }
 
-void InternetHandler::SetGmsCoreNotificationsDisabledDeviceNames(
-    const std::vector<std::string>& device_names) {
+void InternetHandler::SetGmsCoreNotificationsDisabledDeviceNames() {
+  if (!gms_core_notifications_state_tracker_) {
+    // No device names should be present in the list if
+    // |gms_core_notifications_state_tracker_| is null.
+    DCHECK(device_names_without_notifications_.empty());
+    return;
+  }
+
   device_names_without_notifications_.clear();
+
+  const std::vector<std::string> device_names =
+      gms_core_notifications_state_tracker_
+          ->GetGmsCoreNotificationsDisabledDeviceNames();
   for (const auto& device_name : device_names) {
     device_names_without_notifications_.emplace_back(
         std::make_unique<base::Value>(device_name));
@@ -274,5 +295,16 @@
   return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
 }
 
+void InternetHandler::SetGmsCoreNotificationsStateTrackerForTesting(
+    chromeos::tether::GmsCoreNotificationsStateTracker*
+        gms_core_notifications_state_tracker) {
+  if (gms_core_notifications_state_tracker_)
+    gms_core_notifications_state_tracker_->RemoveObserver(this);
+
+  gms_core_notifications_state_tracker_ = gms_core_notifications_state_tracker;
+  gms_core_notifications_state_tracker_->AddObserver(this);
+}
+
 }  // namespace settings
+
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler.h b/chrome/browser/ui/webui/settings/chromeos/internet_handler.h
index cc233c0..332d5dd8 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler.h
@@ -10,18 +10,26 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/app_list/arc/arc_vpn_provider_manager.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "chromeos/components/tether/gms_core_notifications_state_tracker.h"
 #include "ui/gfx/native_widget_types.h"
 
 class Profile;
 
 namespace chromeos {
+
+namespace tether {
+class GmsCoreNotificationsStateTracker;
+}  // namespace tether
+
 namespace settings {
 
 // Chrome OS Internet settings page UI handler.
 // TODO(lgcheng/stevenjb): Rename this ThirdPartyVpnHandler once configuration
 // is handled in the Settings UI (crbug.com/380937
-class InternetHandler : public app_list::ArcVpnProviderManager::Observer,
-                        public ::settings::SettingsPageUIHandler {
+class InternetHandler
+    : public app_list::ArcVpnProviderManager::Observer,
+      public chromeos::tether::GmsCoreNotificationsStateTracker::Observer,
+      public ::settings::SettingsPageUIHandler {
  public:
   explicit InternetHandler(Profile* profile);
   ~InternetHandler() override;
@@ -40,7 +48,12 @@
   void OnArcVpnProviderUpdated(app_list::ArcVpnProviderManager::ArcVpnProvider*
                                    arc_vpn_provider) override;
 
+  // chromeos::tether::GmsCoreNotificationsStateTracker::Observer:
+  void OnGmsCoreNotificationStateChanged() override;
+
  private:
+  friend class InternetHandlerTest;
+
   // Settings JS handlers.
   void AddNetwork(const base::ListValue* args);
   void ConfigureNetwork(const base::ListValue* args);
@@ -59,14 +72,17 @@
 
   // Sets list of names of devices whose "Google Play Services" notifications
   // are disabled.
-  void SetGmsCoreNotificationsDisabledDeviceNames(
-      const std::vector<std::string>& device_names);
+  void SetGmsCoreNotificationsDisabledDeviceNames();
 
   // Sends the list of names.
   void SendGmsCoreNotificationsDisabledDeviceNames();
 
   gfx::NativeWindow GetNativeWindow() const;
 
+  void SetGmsCoreNotificationsStateTrackerForTesting(
+      chromeos::tether::GmsCoreNotificationsStateTracker*
+          gms_core_notifications_state_tracker);
+
   std::map<std::string, std::unique_ptr<base::DictionaryValue>>
       arc_vpn_providers_;
 
@@ -74,7 +90,12 @@
 
   Profile* const profile_;
 
+  // |arc_vpn_provider_manager_| and |gms_core_notifications_state_tracker_| are
+  // provided by BrowserContextKeyedServices which are guaranteed to outlive
+  // WebUIMessageHandlers.
   app_list::ArcVpnProviderManager* arc_vpn_provider_manager_;
+  chromeos::tether::GmsCoreNotificationsStateTracker*
+      gms_core_notifications_state_tracker_;
 
   DISALLOW_COPY_AND_ASSIGN(InternetHandler);
 };
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/internet_handler_unittest.cc
new file mode 100644
index 0000000..679b5cf
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler_unittest.cc
@@ -0,0 +1,125 @@
+// 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/ui/webui/settings/chromeos/internet_handler.h"
+
+#include <memory>
+
+#include "base/macros.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chromeos/components/tether/fake_gms_core_notifications_state_tracker.h"
+#include "content/public/test/test_web_ui.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace settings {
+
+namespace {
+
+const char kWebCallbackFunctionName[] = "cr.webUIListenerCallback";
+const char kSendDeviceNamesMessageType[] =
+    "sendGmsCoreNotificationsDisabledDeviceNames";
+
+class TestInternetHandler : public InternetHandler {
+ public:
+  // Pull WebUIMessageHandler::set_web_ui() into public so SetUp() can call it.
+  using InternetHandler::set_web_ui;
+
+  explicit TestInternetHandler(TestingProfile* profile)
+      : InternetHandler(profile) {}
+};
+
+}  // namespace
+
+class InternetHandlerTest : public BrowserWithTestWindowTest {
+ protected:
+  InternetHandlerTest() = default;
+
+  void SetUp() override {
+    BrowserWithTestWindowTest::SetUp();
+
+    web_ui_ = std::make_unique<content::TestWebUI>();
+
+    handler_ = std::make_unique<TestInternetHandler>(profile());
+    handler_->set_web_ui(web_ui_.get());
+    handler_->RegisterMessages();
+    handler_->AllowJavascriptForTesting();
+
+    fake_tracker_ = std::make_unique<
+        chromeos::tether::FakeGmsCoreNotificationsStateTracker>();
+    handler_->SetGmsCoreNotificationsStateTrackerForTesting(
+        fake_tracker_.get());
+  }
+
+  void TearDown() override { BrowserWithTestWindowTest::TearDown(); }
+
+  void RequestGmsCoreNotificationsDisabledDeviceNames() {
+    handler_->RequestGmsCoreNotificationsDisabledDeviceNames(nullptr);
+  }
+
+  void VerifyMostRecentDeviceNamesSent(
+      const std::vector<std::string>& expected_device_names,
+      size_t expected_num_updates) {
+    EXPECT_EQ(expected_num_updates, web_ui_->call_data().size());
+
+    const content::TestWebUI::CallData* last_call_data =
+        web_ui_->call_data()[expected_num_updates - 1].get();
+    EXPECT_TRUE(last_call_data);
+
+    // The call is structured such that the function name is the "web callback"
+    // name and the first argument is the name of the message being sent.
+    EXPECT_EQ(kWebCallbackFunctionName, last_call_data->function_name());
+    EXPECT_EQ(kSendDeviceNamesMessageType, last_call_data->arg1()->GetString());
+
+    std::vector<std::string> actual_device_names;
+    for (const auto& device_name_value : last_call_data->arg2()->GetList())
+      actual_device_names.push_back(device_name_value.GetString());
+    EXPECT_EQ(expected_device_names, actual_device_names);
+  }
+
+  std::unique_ptr<content::TestWebUI> web_ui_;
+  std::unique_ptr<chromeos::tether::FakeGmsCoreNotificationsStateTracker>
+      fake_tracker_;
+  std::unique_ptr<TestInternetHandler> handler_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InternetHandlerTest);
+};
+
+TEST_F(InternetHandlerTest, TestSendsDeviceNames) {
+  RequestGmsCoreNotificationsDisabledDeviceNames();
+  VerifyMostRecentDeviceNamesSent({} /* expected_device_names */,
+                                  1u /* expected_num_updates */);
+
+  // Set two unique names.
+  fake_tracker_->set_device_names({"device1", "device2"});
+  fake_tracker_->NotifyGmsCoreNotificationStateChanged();
+  VerifyMostRecentDeviceNamesSent(
+      {"device1", "device2"} /* expected_device_names */,
+      2u /* expected_num_updates */);
+
+  // Set three names, two of them identical. Devices with the same name should
+  // be supported, since it is possible for a user to have two phones of the
+  // same model.
+  fake_tracker_->set_device_names({"device1", "device1", "device3"});
+  fake_tracker_->NotifyGmsCoreNotificationStateChanged();
+  VerifyMostRecentDeviceNamesSent(
+      {"device1", "device1", "device3"} /* expected_device_names */,
+      3u /* expected_num_updates */);
+}
+
+TEST_F(InternetHandlerTest, TestSendsDeviceNames_StartsWithDevices) {
+  // Start with two devices before the handler requests any names.
+  fake_tracker_->set_device_names({"device1", "device2"});
+
+  RequestGmsCoreNotificationsDisabledDeviceNames();
+  VerifyMostRecentDeviceNamesSent(
+      {"device1", "device2"} /* expected_device_names */,
+      1u /* expected_num_updates */);
+}
+
+}  // namespace settings
+
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 8243e46..4767004 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -763,7 +763,7 @@
        IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_SCAN_ERROR},
       {"chromeCleanupFindButtonLable",
        IDS_SETTINGS_RESET_CLEANUP_FIND_BUTTON_LABEL},
-      {"chromeCleanupLinkShowFiles",
+      {"chromeCleanupLinkShowItems",
        IDS_SETTINGS_RESET_CLEANUP_LINK_SHOW_FILES},
       {"chromeCleanupLogsUploadPermission", IDS_CHROME_CLEANUP_LOGS_PERMISSION},
       {"chromeCleanupRemoveButtonLabel",
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn
index a822fa8..6f05486 100644
--- a/chrome/browser/vr/BUILD.gn
+++ b/chrome/browser/vr/BUILD.gn
@@ -35,6 +35,8 @@
     "elements/audio_permission_prompt.h",
     "elements/audio_permission_prompt_texture.cc",
     "elements/audio_permission_prompt_texture.h",
+    "elements/background.cc",
+    "elements/background.h",
     "elements/button.cc",
     "elements/button.h",
     "elements/content_element.cc",
@@ -46,8 +48,6 @@
     "elements/disc_button.h",
     "elements/draw_phase.cc",
     "elements/draw_phase.h",
-    "elements/exclusive_screen_toast_texture.cc",
-    "elements/exclusive_screen_toast_texture.h",
     "elements/exit_prompt.cc",
     "elements/exit_prompt.h",
     "elements/exit_prompt_texture.cc",
@@ -74,11 +74,8 @@
     "elements/scaled_depth_adjuster.h",
     "elements/shadow.cc",
     "elements/shadow.h",
-    "elements/simple_textured_element.h",
     "elements/spinner.cc",
     "elements/spinner.h",
-    "elements/system_indicator_texture.cc",
-    "elements/system_indicator_texture.h",
     "elements/text.cc",
     "elements/text.h",
     "elements/text_input.cc",
@@ -87,6 +84,8 @@
     "elements/textured_element.h",
     "elements/throbber.cc",
     "elements/throbber.h",
+    "elements/toast.cc",
+    "elements/toast.h",
     "elements/transient_element.cc",
     "elements/transient_element.h",
     "elements/ui_element.cc",
@@ -144,7 +143,7 @@
     "model/text_input_info.h",
     "model/toolbar_state.cc",
     "model/toolbar_state.h",
-    "model/web_vr_timeout_state.h",
+    "model/web_vr_model.h",
     "pose_util.cc",
     "pose_util.h",
     "renderers/base_quad_renderer.cc",
diff --git a/chrome/browser/vr/elements/background.cc b/chrome/browser/vr/elements/background.cc
new file mode 100644
index 0000000..5f27982d
--- /dev/null
+++ b/chrome/browser/vr/elements/background.cc
@@ -0,0 +1,174 @@
+// 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/vr/elements/background.h"
+
+#include "base/memory/ptr_util.h"
+#include "chrome/browser/vr/skia_surface_provider.h"
+#include "chrome/browser/vr/ui_element_renderer.h"
+#include "chrome/browser/vr/vr_gl_util.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkSurface.h"
+
+namespace vr {
+
+namespace {
+
+// On the background sphere, this is the number of faces between poles.
+int kSteps = 20;
+
+// clang-format off
+constexpr char const* kVertexShader = SHADER(
+  precision mediump float;
+  uniform mat4 u_ModelViewProjMatrix;
+  attribute vec2 a_TexCoordinate;
+  varying vec2 v_TexCoordinate;
+
+  void main() {
+    vec4 sphereVertex;
+    float theta = a_TexCoordinate.x * 6.28319;
+    float phi = a_TexCoordinate.y * 3.14159;
+
+    // Place the background at 1000 m, an arbitrary large distance. This
+    // nullifies the translational portion of eye transforms, which is what we
+    // want for ODS backgrounds.
+    sphereVertex.x = 1000. * -cos(theta) * sin(phi);
+    sphereVertex.y = 1000. * cos(phi);
+    sphereVertex.z = 1000. * -sin(theta) * sin(phi);
+    sphereVertex.w = 1.0;
+
+    gl_Position = u_ModelViewProjMatrix * sphereVertex;
+    v_TexCoordinate = a_TexCoordinate;
+  }
+);
+
+constexpr char const* kFragmentShader = SHADER(
+  precision mediump float;
+  uniform sampler2D u_Texture;
+  varying vec2 v_TexCoordinate;
+
+  void main() {
+    gl_FragColor = texture2D(u_Texture, v_TexCoordinate);
+  }
+);
+/* clang-format on */
+
+}  // namespace
+
+Background::Background() {
+  set_hit_testable(false);
+}
+Background::~Background() = default;
+
+void Background::Render(UiElementRenderer* renderer,
+                        const CameraModel& model) const {
+  if (texture_handle_ != 0) {
+    renderer->DrawBackground(model.view_proj_matrix * world_space_transform(),
+                             texture_handle_);
+  }
+}
+
+void Background::Initialize(SkiaSurfaceProvider* provider) {
+  provider_ = provider;
+  if (initialization_bitmap_)
+    CreateTexture();
+}
+
+void Background::SetImage(std::unique_ptr<SkBitmap> bitmap) {
+  initialization_bitmap_ = std::move(bitmap);
+  if (provider_)
+    CreateTexture();
+}
+
+void Background::CreateTexture() {
+  DCHECK(provider_);
+  DCHECK(initialization_bitmap_);
+
+  // The bitmap data is thrown away after the texture is generated.
+  auto bitmap = std::move(initialization_bitmap_);
+
+  surface_ = provider_->MakeSurface({bitmap->width(), bitmap->height()});
+  DCHECK(surface_.get());
+  SkCanvas* canvas = surface_->getCanvas();
+  canvas->drawBitmap(*bitmap, 0, 0);
+  texture_handle_ = provider_->FlushSurface(surface_.get(), texture_handle_);
+}
+
+Background::Renderer::Renderer()
+    : BaseRenderer(kVertexShader, kFragmentShader) {
+  model_view_proj_matrix_handle_ =
+      glGetUniformLocation(program_handle_, "u_ModelViewProjMatrix");
+  position_handle_ = glGetAttribLocation(program_handle_, "a_TexCoordinate");
+  tex_uniform_handle_ = glGetUniformLocation(program_handle_, "u_Texture");
+
+  // Build the set of texture points representing the sphere.
+  std::vector<float> vertices;
+  for (int x = 0; x <= 2 * kSteps; x++) {
+    for (int y = 0; y <= kSteps; y++) {
+      vertices.push_back(static_cast<float>(x) / (kSteps * 2));
+      vertices.push_back(static_cast<float>(y) / kSteps);
+    }
+  }
+  std::vector<GLushort> indices;
+  int y_stride = kSteps + 1;
+  for (int x = 0; x < 2 * kSteps; x++) {
+    for (int y = 0; y < kSteps; y++) {
+      GLushort p0 = x * y_stride + y;
+      GLushort p1 = x * y_stride + y + 1;
+      GLushort p2 = (x + 1) * y_stride + y;
+      GLushort p3 = (x + 1) * y_stride + y + 1;
+      indices.push_back(p0);
+      indices.push_back(p1);
+      indices.push_back(p3);
+      indices.push_back(p0);
+      indices.push_back(p3);
+      indices.push_back(p2);
+    }
+  }
+
+  GLuint buffers[2];
+  glGenBuffersARB(2, buffers);
+  vertex_buffer_ = buffers[0];
+  index_buffer_ = buffers[1];
+  index_count_ = indices.size();
+
+  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
+  glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float),
+               vertices.data(), GL_STATIC_DRAW);
+
+  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
+  glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort),
+               indices.data(), GL_STATIC_DRAW);
+}
+
+Background::Renderer::~Renderer() = default;
+
+void Background::Renderer::Draw(const gfx::Transform& view_proj_matrix,
+                                int texture_data_handle) {
+  glUseProgram(program_handle_);
+
+  // Pass in model view project matrix.
+  glUniformMatrix4fv(model_view_proj_matrix_handle_, 1, false,
+                     MatrixToGLArray(view_proj_matrix).data());
+
+  // Set up vertex attributes.
+  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
+  glVertexAttribPointer(position_handle_, 2, GL_FLOAT, GL_FALSE, 0,
+                        VOID_OFFSET(0));
+  glEnableVertexAttribArray(position_handle_);
+
+  glActiveTexture(GL_TEXTURE0);
+  glBindTexture(GL_TEXTURE_2D, texture_data_handle);
+
+  // Set up uniforms.
+  glUniform1i(tex_uniform_handle_, 0);
+
+  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
+  glDrawElements(GL_TRIANGLES, index_count_, GL_UNSIGNED_SHORT, 0);
+
+  glDisableVertexAttribArray(position_handle_);
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/elements/background.h b/chrome/browser/vr/elements/background.h
new file mode 100644
index 0000000..b917113
--- /dev/null
+++ b/chrome/browser/vr/elements/background.h
@@ -0,0 +1,61 @@
+// 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_VR_ELEMENTS_BACKGROUND_H_
+#define CHROME_BROWSER_VR_ELEMENTS_BACKGROUND_H_
+
+#include "chrome/browser/vr/elements/ui_element.h"
+#include "chrome/browser/vr/renderers/base_quad_renderer.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+#include "ui/gl/gl_bindings.h"
+
+class SkBitmap;
+class SkSurface;
+
+namespace vr {
+
+class Background : public UiElement {
+ public:
+  Background();
+  ~Background() override;
+
+  // UiElement:
+  void Render(UiElementRenderer* renderer,
+              const CameraModel& model) const override;
+  void Initialize(SkiaSurfaceProvider* provider) override;
+
+  void SetImage(std::unique_ptr<SkBitmap> bitmap);
+
+  class Renderer : public BaseRenderer {
+   public:
+    Renderer();
+    ~Renderer() final;
+
+    void Draw(const gfx::Transform& view_proj_matrix, int texture_data_handle);
+
+   private:
+    GLuint model_view_proj_matrix_handle_;
+    GLuint tex_uniform_handle_;
+
+    GLuint vertex_buffer_;
+    GLuint index_buffer_;
+    GLuint index_count_;
+
+    DISALLOW_COPY_AND_ASSIGN(Renderer);
+  };
+
+ private:
+  void CreateTexture();
+
+  std::unique_ptr<SkBitmap> initialization_bitmap_;
+  GLuint texture_handle_ = 0;
+  sk_sp<SkSurface> surface_;
+  SkiaSurfaceProvider* provider_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(Background);
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_ELEMENTS_BACKGROUND_H_
diff --git a/chrome/browser/vr/elements/button.cc b/chrome/browser/vr/elements/button.cc
index 9374c93..5abc191 100644
--- a/chrome/browser/vr/elements/button.cc
+++ b/chrome/browser/vr/elements/button.cc
@@ -124,6 +124,11 @@
   hit_plane_->SetSize(size.width(), size.height());
 }
 
+void Button::OnSetCornerRadii(const CornerRadii& radii) {
+  background_->SetCornerRadii(radii);
+  hit_plane_->SetCornerRadii(radii);
+}
+
 void Button::NotifyClientSizeAnimated(const gfx::SizeF& size,
                                       int target_property_id,
                                       cc::Animation* animation) {
diff --git a/chrome/browser/vr/elements/button.h b/chrome/browser/vr/elements/button.h
index 84529bdc..d40d680 100644
--- a/chrome/browser/vr/elements/button.h
+++ b/chrome/browser/vr/elements/button.h
@@ -52,6 +52,7 @@
   void OnSetDrawPhase() override;
   void OnSetName() override;
   void OnSetSize(const gfx::SizeF& size) override;
+  void OnSetCornerRadii(const CornerRadii& radii) override;
   void NotifyClientSizeAnimated(const gfx::SizeF& size,
                                 int target_property_id,
                                 cc::Animation* animation) override;
diff --git a/chrome/browser/vr/elements/draw_phase.cc b/chrome/browser/vr/elements/draw_phase.cc
index c317e40..4ffdda01 100644
--- a/chrome/browser/vr/elements/draw_phase.cc
+++ b/chrome/browser/vr/elements/draw_phase.cc
@@ -11,8 +11,8 @@
 namespace {
 
 static const char* g_draw_phase_strings[] = {
-    "kPhaseNone",         "kPhaseBackground", "kPhaseOverlayBackground",
-    "kPhaseFloorCeiling", "kPhaseForeground", "kPhaseOverlayForeground",
+    "kPhaseNone", "kPhaseBackground", "kPhaseForeground",
+    "kPhaseOverlayForeground",
 };
 
 static_assert(
diff --git a/chrome/browser/vr/elements/draw_phase.h b/chrome/browser/vr/elements/draw_phase.h
index dbca452..b525fa50 100644
--- a/chrome/browser/vr/elements/draw_phase.h
+++ b/chrome/browser/vr/elements/draw_phase.h
@@ -10,12 +10,12 @@
 namespace vr {
 
 // Each draw phase is rendered independently in the order specified below.
+// TODO(https://crbug.com/796783): We don't really need all these draw phases as
+// the draw order depends on an element's insert order.
 enum DrawPhase : int {
   // kPhaseNone is to be used for elements that do not draw. Eg, layouts.
   kPhaseNone = 0,
   kPhaseBackground,
-  kPhaseOverlayBackground,
-  kPhaseFloorCeiling,
   kPhaseForeground,
   kPhaseOverlayForeground,
   kNumDrawPhases = kPhaseOverlayForeground
diff --git a/chrome/browser/vr/elements/exclusive_screen_toast_texture.cc b/chrome/browser/vr/elements/exclusive_screen_toast_texture.cc
deleted file mode 100644
index 7debfbd6..0000000
--- a/chrome/browser/vr/elements/exclusive_screen_toast_texture.cc
+++ /dev/null
@@ -1,78 +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/vr/elements/exclusive_screen_toast_texture.h"
-
-#include "cc/paint/skia_paint_canvas.h"
-#include "chrome/grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/font_list.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/vector2d.h"
-#include "ui/gfx/render_text.h"
-
-namespace vr {
-
-namespace {
-
-constexpr float kHeight = 0.064f;
-constexpr float kWidthHeightRatio = 16.0f;
-constexpr float kFontHeight = 0.024f;
-constexpr float kWidthPadding = 0.02f;
-constexpr float kCornerRadius = 0.004f;
-
-}  // namespace
-
-ExclusiveScreenToastTexture::ExclusiveScreenToastTexture() = default;
-
-ExclusiveScreenToastTexture::~ExclusiveScreenToastTexture() = default;
-
-void ExclusiveScreenToastTexture::Draw(SkCanvas* sk_canvas,
-                                       const gfx::Size& texture_size) {
-  cc::SkiaPaintCanvas paint_canvas(sk_canvas);
-  gfx::Canvas gfx_canvas(&paint_canvas, 1.0f);
-  gfx::Canvas* canvas = &gfx_canvas;
-
-  size_.set_height(texture_size.height());
-  SkPaint paint;
-  float meter_to_pixel_ratio = texture_size.height() / kHeight;
-
-  paint.setColor(background_color());
-  auto text = l10n_util::GetStringUTF16(IDS_PRESS_APP_TO_EXIT);
-  gfx::FontList fonts;
-  int pixel_font_size = meter_to_pixel_ratio * kFontHeight;
-  GetDefaultFontList(pixel_font_size, text, &fonts);
-  gfx::Rect text_size(0, pixel_font_size);
-
-  std::vector<std::unique_ptr<gfx::RenderText>> lines =
-      PrepareDrawStringRect(text, fonts, foreground_color(), &text_size,
-                            kTextAlignmentNone, kWrappingBehaviorNoWrap);
-
-  int pixel_padding = meter_to_pixel_ratio * kWidthPadding;
-  size_.set_width(2 * pixel_padding + text_size.width());
-  DCHECK_LE(size_.width(), texture_size.width());
-  int corner_radius = meter_to_pixel_ratio * kCornerRadius;
-  sk_canvas->drawRoundRect(SkRect::MakeWH(size_.width(), size_.height()),
-                           corner_radius, corner_radius, paint);
-
-  canvas->Save();
-  canvas->Translate(
-      gfx::Vector2d(meter_to_pixel_ratio * kWidthPadding,
-                    (kHeight - kFontHeight) / 2 * meter_to_pixel_ratio));
-  for (auto& render_text : lines)
-    render_text->Draw(canvas);
-  canvas->Restore();
-}
-
-gfx::Size ExclusiveScreenToastTexture::GetPreferredTextureSize(
-    int maximum_width) const {
-  return gfx::Size(maximum_width, maximum_width / kWidthHeightRatio);
-}
-
-gfx::SizeF ExclusiveScreenToastTexture::GetDrawnSize() const {
-  return size_;
-}
-
-}  // namespace vr
diff --git a/chrome/browser/vr/elements/exclusive_screen_toast_texture.h b/chrome/browser/vr/elements/exclusive_screen_toast_texture.h
deleted file mode 100644
index 0cafe33..0000000
--- a/chrome/browser/vr/elements/exclusive_screen_toast_texture.h
+++ /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.
-
-#ifndef CHROME_BROWSER_VR_ELEMENTS_EXCLUSIVE_SCREEN_TOAST_TEXTURE_H_
-#define CHROME_BROWSER_VR_ELEMENTS_EXCLUSIVE_SCREEN_TOAST_TEXTURE_H_
-
-#include "base/macros.h"
-#include "chrome/browser/vr/elements/ui_texture.h"
-
-namespace vr {
-
-class ExclusiveScreenToastTexture : public UiTexture {
- public:
-  ExclusiveScreenToastTexture();
-  ~ExclusiveScreenToastTexture() override;
-  gfx::Size GetPreferredTextureSize(int width) const override;
-  gfx::SizeF GetDrawnSize() const override;
-
- private:
-  void Draw(SkCanvas* canvas, const gfx::Size& texture_size) override;
-
-  gfx::SizeF size_;
-
-  DISALLOW_COPY_AND_ASSIGN(ExclusiveScreenToastTexture);
-};
-
-}  // namespace vr
-
-#endif  // CHROME_BROWSER_VR_ELEMENTS_EXCLUSIVE_SCREEN_TOAST_TEXTURE_H_
diff --git a/chrome/browser/vr/elements/simple_textured_element.h b/chrome/browser/vr/elements/simple_textured_element.h
deleted file mode 100644
index 6408ec28..0000000
--- a/chrome/browser/vr/elements/simple_textured_element.h
+++ /dev/null
@@ -1,46 +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_VR_ELEMENTS_SIMPLE_TEXTURED_ELEMENT_H_
-#define CHROME_BROWSER_VR_ELEMENTS_SIMPLE_TEXTURED_ELEMENT_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "chrome/browser/vr/elements/exclusive_screen_toast_texture.h"
-#include "chrome/browser/vr/elements/system_indicator_texture.h"
-#include "chrome/browser/vr/elements/textured_element.h"
-#include "chrome/browser/vr/elements/transient_element.h"
-#include "chrome/browser/vr/elements/ui_texture.h"
-
-namespace vr {
-
-template <typename T, typename R>
-class SimpleTexturedElement : public TexturedElement {
- public:
-  explicit SimpleTexturedElement(int maximum_width)
-      : TexturedElement(maximum_width, R()), texture_(base::MakeUnique<T>()) {}
-  ~SimpleTexturedElement() override {}
-  T* GetDerivedTexture() { return texture_.get(); }
-
- protected:
-  UiTexture* GetTexture() const override { return texture_.get(); }
-
- private:
-  std::unique_ptr<T> texture_;
-
-  DISALLOW_COPY_AND_ASSIGN(SimpleTexturedElement);
-};
-
-typedef SimpleTexturedElement<ExclusiveScreenToastTexture,
-                              TexturedElement::ResizeHorizontally>
-    ExclusiveScreenToast;
-typedef SimpleTexturedElement<SystemIndicatorTexture,
-                              TexturedElement::ResizeHorizontally>
-    SystemIndicator;
-
-}  // namespace vr
-
-#endif  // CHROME_BROWSER_VR_ELEMENTS_SIMPLE_TEXTURED_ELEMENT_H_
diff --git a/chrome/browser/vr/elements/system_indicator_texture.cc b/chrome/browser/vr/elements/system_indicator_texture.cc
deleted file mode 100644
index 44a06ebf..0000000
--- a/chrome/browser/vr/elements/system_indicator_texture.cc
+++ /dev/null
@@ -1,101 +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/vr/elements/system_indicator_texture.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "cc/paint/skia_paint_canvas.h"
-#include "chrome/browser/vr/elements/vector_icon.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/font_list.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/render_text.h"
-
-namespace vr {
-
-namespace {
-
-constexpr int kHeightWidthRatio = 8;
-constexpr float kBorderFactor = 0.1f;
-constexpr float kIconSizeFactor = 0.7f;
-constexpr float kFontSizeFactor = 0.40f;
-
-}  // namespace
-
-SystemIndicatorTexture::SystemIndicatorTexture() = default;
-SystemIndicatorTexture::~SystemIndicatorTexture() = default;
-
-void SystemIndicatorTexture::SetIcon(const gfx::VectorIcon& icon) {
-  SetAndDirty(&icon_.path, icon.path);
-}
-
-void SystemIndicatorTexture::SetMessageId(int id) {
-  SetAndDirty(&message_id_, id);
-}
-
-void SystemIndicatorTexture::Draw(SkCanvas* sk_canvas,
-                                  const gfx::Size& texture_size) {
-  cc::SkiaPaintCanvas paint_canvas(sk_canvas);
-  gfx::Canvas gfx_canvas(&paint_canvas, 1.0f);
-  gfx::Canvas* canvas = &gfx_canvas;
-
-  size_.set_height(texture_size.height());
-
-  float border_pixels = size_.height() * kBorderFactor;
-  float icon_pixels = size_.height() * kIconSizeFactor;
-  size_.set_width(icon_pixels + 2 * border_pixels);
-
-  SkPaint paint;
-  paint.setColor(background_color());
-
-  std::unique_ptr<gfx::RenderText> rendered_text;
-
-  if (message_id_) {
-    base::string16 text = l10n_util::GetStringUTF16(message_id_);
-
-    gfx::FontList fonts;
-    GetDefaultFontList(size_.height() * kFontSizeFactor, text, &fonts);
-    gfx::Rect text_size(0, size_.height());
-    std::vector<std::unique_ptr<gfx::RenderText>> lines;
-    lines = PrepareDrawStringRect(text, fonts, foreground_color(), &text_size,
-                                  kTextAlignmentNone, kWrappingBehaviorNoWrap);
-    DCHECK_EQ(lines.size(), 1u);
-    rendered_text = std::move(lines.front());
-
-    // Adust texture width according to text size.
-    size_.set_width(size_.width() + text_size.width() + 2 * border_pixels);
-  }
-
-  sk_canvas->drawRoundRect(SkRect::MakeWH(size_.width(), size_.height()),
-                           border_pixels, border_pixels, paint);
-
-  gfx::PointF icon_location(
-      (IsRTL() ? size_.width() - border_pixels - icon_pixels : border_pixels),
-      (size_.height() - icon_pixels) / 2.0);
-  VectorIcon::DrawVectorIcon(canvas, icon_, size_.height() * kIconSizeFactor,
-                             icon_location, foreground_color());
-
-  if (rendered_text) {
-    canvas->Save();
-    canvas->Translate(gfx::Vector2d(
-        (IsRTL() ? border_pixels : 3 * border_pixels + icon_pixels), 0));
-    rendered_text->Draw(canvas);
-    canvas->Restore();
-  }
-}
-
-gfx::Size SystemIndicatorTexture::GetPreferredTextureSize(
-    int maximum_width) const {
-  // All indicators need to be the same height, so compute height, and then
-  // re-compute with based on whether the indicator has text or not.
-  int height = maximum_width / kHeightWidthRatio;
-  return gfx::Size(message_id_ ? maximum_width : height, height);
-}
-
-gfx::SizeF SystemIndicatorTexture::GetDrawnSize() const {
-  return size_;
-}
-
-}  // namespace vr
diff --git a/chrome/browser/vr/elements/system_indicator_texture.h b/chrome/browser/vr/elements/system_indicator_texture.h
deleted file mode 100644
index 2571664..0000000
--- a/chrome/browser/vr/elements/system_indicator_texture.h
+++ /dev/null
@@ -1,37 +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_VR_ELEMENTS_SYSTEM_INDICATOR_TEXTURE_H_
-#define CHROME_BROWSER_VR_ELEMENTS_SYSTEM_INDICATOR_TEXTURE_H_
-
-#include "base/macros.h"
-#include "chrome/browser/vr/elements/ui_texture.h"
-#include "ui/gfx/vector_icon_types.h"
-
-namespace vr {
-
-// TODO(asimjour): compose the system indicator out of primitives.
-class SystemIndicatorTexture : public UiTexture {
- public:
-  SystemIndicatorTexture();
-  ~SystemIndicatorTexture() override;
-
-  void SetIcon(const gfx::VectorIcon& icon);
-  void SetMessageId(int id);
-
- private:
-  gfx::Size GetPreferredTextureSize(int width) const override;
-  gfx::SizeF GetDrawnSize() const override;
-  void Draw(SkCanvas* canvas, const gfx::Size& texture_size) override;
-
-  gfx::SizeF size_;
-  gfx::VectorIcon icon_;
-  int message_id_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(SystemIndicatorTexture);
-};
-
-}  // namespace vr
-
-#endif  // CHROME_BROWSER_VR_ELEMENTS_SYSTEM_INDICATOR_TEXTURE_H_
diff --git a/chrome/browser/vr/elements/text.cc b/chrome/browser/vr/elements/text.cc
index 8c746d1..31550499 100644
--- a/chrome/browser/vr/elements/text.cc
+++ b/chrome/browser/vr/elements/text.cc
@@ -36,10 +36,14 @@
 
 class TextTexture : public UiTexture {
  public:
-  explicit TextTexture(float font_height_dmms)
-      : font_height_dmms_(font_height_dmms) {}
+  TextTexture() = default;
+
   ~TextTexture() override {}
 
+  void SetFontHeightInDmm(float font_height_dmms) {
+    SetAndDirty(&font_height_dmms_, font_height_dmms);
+  }
+
   void SetText(const base::string16& text) { SetAndDirty(&text_, text); }
 
   void SetColor(SkColor color) { SetAndDirty(&color_, color); }
@@ -101,10 +105,16 @@
 };
 
 Text::Text(float font_height_dmms)
-    : TexturedElement(0),
-      texture_(base::MakeUnique<TextTexture>(font_height_dmms)) {}
+    : TexturedElement(0), texture_(base::MakeUnique<TextTexture>()) {
+  texture_->SetFontHeightInDmm(font_height_dmms);
+}
+
 Text::~Text() {}
 
+void Text::SetFontHeightInDmm(float font_height_dmms) {
+  texture_->SetFontHeightInDmm(font_height_dmms);
+}
+
 void Text::SetText(const base::string16& text) {
   texture_->SetText(text);
 }
@@ -146,7 +156,8 @@
 }
 
 void Text::OnSetSize(const gfx::SizeF& size) {
-  texture_->SetTextWidth(size.width());
+  if (IsFixedWidthLayout(text_layout_mode_))
+    texture_->SetTextWidth(size.width());
 }
 
 void Text::UpdateElementSize() {
diff --git a/chrome/browser/vr/elements/text.h b/chrome/browser/vr/elements/text.h
index d20a8f7..80d03f8 100644
--- a/chrome/browser/vr/elements/text.h
+++ b/chrome/browser/vr/elements/text.h
@@ -31,6 +31,7 @@
   explicit Text(float font_height_dmms);
   ~Text() override;
 
+  void SetFontHeightInDmm(float font_height_dmms);
   void SetText(const base::string16& text);
   void SetColor(SkColor color);
 
diff --git a/chrome/browser/vr/elements/textured_element.cc b/chrome/browser/vr/elements/textured_element.cc
index 695a7d4b..afb7624 100644
--- a/chrome/browser/vr/elements/textured_element.cc
+++ b/chrome/browser/vr/elements/textured_element.cc
@@ -21,12 +21,6 @@
 TexturedElement::TexturedElement(int maximum_width)
     : maximum_width_(maximum_width) {}
 
-TexturedElement::TexturedElement(int maximum_width, ResizeVertically unused)
-    : maximum_width_(maximum_width), resize_vertically_(true) {}
-
-TexturedElement::TexturedElement(int maximum_width, ResizeHorizontally unused)
-    : maximum_width_(maximum_width), resize_vertically_(false) {}
-
 TexturedElement::~TexturedElement() = default;
 
 void TexturedElement::Initialize(SkiaSurfaceProvider* provider) {
@@ -79,17 +73,10 @@
   // Adjust the width/height of this element according to the texture. Size in
   // the other direction is determined by the associated texture.
   gfx::SizeF drawn_size = GetTexture()->GetDrawnSize();
-  if (resize_vertically_) {
-    DCHECK_GT(stale_size().width(), 0.f);
-    float height =
-        drawn_size.height() / drawn_size.width() * stale_size().width();
-    SetSize(stale_size().width(), height);
-  } else {
-    DCHECK_GT(stale_size().height(), 0.f);
-    float width =
-        drawn_size.width() / drawn_size.height() * stale_size().height();
-    SetSize(width, stale_size().height());
-  }
+  DCHECK_GT(stale_size().width(), 0.f);
+  float height =
+      drawn_size.height() / drawn_size.width() * stale_size().width();
+  SetSize(stale_size().width(), height);
 }
 
 void TexturedElement::Render(UiElementRenderer* renderer,
diff --git a/chrome/browser/vr/elements/textured_element.h b/chrome/browser/vr/elements/textured_element.h
index b188141..22f846c 100644
--- a/chrome/browser/vr/elements/textured_element.h
+++ b/chrome/browser/vr/elements/textured_element.h
@@ -19,22 +19,11 @@
 
 class TexturedElement : public UiElement {
  public:
-  // These types are used to statically choose the right constructor for simple
-  // textured elements.
-  struct ResizeVertically {};
-  struct ResizeHorizontally {};
-
   // |preferred_width| is the element's desired width in meters. Constraints
   // implied by the texture being rendered may or may not allow it to be
   // rendered exactly at the preferred width.
   explicit TexturedElement(int maximum_width);
 
-  // These constructors set up the |resize_vertically_| member which determine
-  // how the textured element responds to a size change in the associated
-  // texture. (I.e., which dimension should be resized in order for this element
-  // to match the texture's aspect ratio).
-  TexturedElement(int maximum_width, ResizeVertically);
-  TexturedElement(int maximum_width, ResizeHorizontally);
   ~TexturedElement() override;
 
   void Initialize(SkiaSurfaceProvider* provider) final;
@@ -61,7 +50,6 @@
   GLuint texture_handle_ = 0;
   int maximum_width_;
   bool initialized_ = false;
-  bool resize_vertically_ = true;
 
   sk_sp<SkSurface> surface_;
   SkiaSurfaceProvider* provider_ = nullptr;
diff --git a/chrome/browser/vr/elements/toast.cc b/chrome/browser/vr/elements/toast.cc
new file mode 100644
index 0000000..44c5f6c8
--- /dev/null
+++ b/chrome/browser/vr/elements/toast.cc
@@ -0,0 +1,124 @@
+// 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/vr/elements/toast.h"
+
+#include "base/memory/ptr_util.h"
+#include "chrome/browser/vr/elements/linear_layout.h"
+#include "chrome/browser/vr/elements/rect.h"
+#include "chrome/browser/vr/elements/ui_element.h"
+#include "chrome/browser/vr/elements/ui_element_name.h"
+#include "chrome/browser/vr/elements/ui_element_type.h"
+#include "chrome/browser/vr/elements/vector_icon.h"
+#include "chrome/browser/vr/ui_scene_constants.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace vr {
+
+Toast::Toast() {
+  set_bounds_contain_children(true);
+
+  auto background = base::MakeUnique<Rect>();
+  background->SetType(kTypeToastBackground);
+  background->set_contributes_to_parent_bounds(false);
+  background->set_hit_testable(false);
+  background_ = background.get();
+
+  auto container = base::MakeUnique<LinearLayout>(LinearLayout::kRight);
+  container->SetType(kTypeToastContainer);
+  container->set_hit_testable(false);
+  container_ = container.get();
+
+  AddChild(std::move(background));
+  AddChild(std::move(container));
+}
+
+Toast::~Toast() = default;
+
+void Toast::Render(UiElementRenderer* renderer,
+                   const CameraModel& model) const {}
+
+void Toast::AddIcon(const gfx::VectorIcon& icon,
+                    int width_pixels,
+                    float icon_size) {
+  DCHECK(!icon_);
+  auto vector_icon = base::MakeUnique<VectorIcon>(width_pixels);
+  vector_icon->SetType(kTypeToastIcon);
+  vector_icon->set_hit_testable(false);
+  vector_icon->SetDrawPhase(draw_phase());
+  vector_icon->SetIcon(icon);
+  vector_icon->SetSize(icon_size, icon_size);
+  vector_icon->SetVisible(true);
+  vector_icon->set_owner_name_for_test(name());
+  icon_ = vector_icon.get();
+  container_->AddChild(std::move(vector_icon));
+}
+
+void Toast::AddText(const base::string16& text,
+                    float font_height_dmm,
+                    TextLayoutMode text_layout_mode) {
+  DCHECK(!text_);
+  auto text_element = base::MakeUnique<Text>(font_height_dmm);
+  text_element->SetType(kTypeToastText);
+  text_element->set_hit_testable(false);
+  text_element->SetDrawPhase(draw_phase());
+  text_element->SetText(text);
+  text_element->SetTextLayoutMode(text_layout_mode);
+  text_element->set_owner_name_for_test(name());
+  text_element->SetVisible(true);
+  text_ = text_element.get();
+  container_->AddChild(std::move(text_element));
+}
+
+void Toast::SetMargin(float margin) {
+  container_->set_margin(kIndicatorMargin);
+}
+
+void Toast::OnSetDrawPhase() {
+  background_->SetDrawPhase(draw_phase());
+  if (icon_)
+    icon_->SetDrawPhase(draw_phase());
+  if (text_)
+    text_->SetDrawPhase(draw_phase());
+}
+
+void Toast::OnSetName() {
+  background_->set_owner_name_for_test(name());
+  container_->set_owner_name_for_test(name());
+  if (icon_)
+    icon_->set_owner_name_for_test(name());
+  if (text_)
+    text_->set_owner_name_for_test(name());
+}
+
+void Toast::OnSetSize(const gfx::SizeF& size) {
+  background_->SetSize(size.width(), size.height());
+}
+
+void Toast::OnSetCornerRadii(const CornerRadii& radii) {
+  background_->SetCornerRadii(radii);
+}
+
+void Toast::SetForegroundColor(SkColor color) {
+  DCHECK(icon_ || text_);
+  if (icon_)
+    icon_->SetColor(color);
+  if (text_)
+    text_->SetColor(color);
+}
+
+void Toast::SetBackgroundColor(SkColor color) {
+  DCHECK(background_);
+  background_->SetColor(color);
+}
+
+void Toast::NotifyClientSizeAnimated(const gfx::SizeF& size,
+                                     int target_property_id,
+                                     cc::Animation* animation) {
+  if (target_property_id == BOUNDS)
+    background_->SetSize(size.width(), size.height());
+  UiElement::NotifyClientSizeAnimated(size, target_property_id, animation);
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/elements/toast.h b/chrome/browser/vr/elements/toast.h
new file mode 100644
index 0000000..393158f7
--- /dev/null
+++ b/chrome/browser/vr/elements/toast.h
@@ -0,0 +1,61 @@
+// 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_VR_ELEMENTS_TOAST_H_
+#define CHROME_BROWSER_VR_ELEMENTS_TOAST_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "chrome/browser/vr/elements/draw_phase.h"
+#include "chrome/browser/vr/elements/text.h"
+#include "chrome/browser/vr/elements/ui_element.h"
+#include "chrome/browser/vr/model/color_scheme.h"
+#include "ui/gfx/vector_icon_types.h"
+
+namespace vr {
+
+class LinearLayout;
+class Rect;
+class VectorIcon;
+
+// Toast may have a vector icon or a text or both as the foreground and rounded
+// rect background.
+class Toast : public UiElement {
+ public:
+  Toast();
+  ~Toast() override;
+
+  void Render(UiElementRenderer* renderer,
+              const CameraModel& model) const final;
+
+  void AddIcon(const gfx::VectorIcon& icon, int width_pixels, float icon_size);
+  void AddText(const base::string16& text,
+               float font_height_dmm,
+               TextLayoutMode text_layout_mode);
+  void SetMargin(float margin_in_dmms);
+
+  void SetForegroundColor(SkColor color);
+  void SetBackgroundColor(SkColor color);
+
+ private:
+  void OnSetDrawPhase() override;
+  void OnSetName() override;
+  void OnSetSize(const gfx::SizeF& size) override;
+  void OnSetCornerRadii(const CornerRadii& radii) override;
+  void NotifyClientSizeAnimated(const gfx::SizeF& size,
+                                int target_property_id,
+                                cc::Animation* animation) override;
+
+  LinearLayout* container_ = nullptr;
+  Rect* background_ = nullptr;
+  VectorIcon* icon_ = nullptr;
+  Text* text_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(Toast);
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_ELEMENTS_TOAST_H_
diff --git a/chrome/browser/vr/elements/ui_element.cc b/chrome/browser/vr/elements/ui_element.cc
index b414887..22006f1 100644
--- a/chrome/browser/vr/elements/ui_element.cc
+++ b/chrome/browser/vr/elements/ui_element.cc
@@ -275,6 +275,13 @@
                                       opacity);
 }
 
+void UiElement::SetCornerRadii(const CornerRadii& radii) {
+  corner_radii_ = radii;
+  OnSetCornerRadii(radii);
+}
+
+void UiElement::OnSetCornerRadii(const CornerRadii& radii) {}
+
 gfx::SizeF UiElement::GetTargetSize() const {
   return animation_player_.GetTargetSizeValue(TargetProperty::BOUNDS, size_);
 }
diff --git a/chrome/browser/vr/elements/ui_element.h b/chrome/browser/vr/elements/ui_element.h
index 688063bb..16176f7 100644
--- a/chrome/browser/vr/elements/ui_element.h
+++ b/chrome/browser/vr/elements/ui_element.h
@@ -241,7 +241,8 @@
   virtual void SetOpacity(float opacity);
 
   CornerRadii corner_radii() const { return corner_radii_; }
-  void set_corner_radii(const CornerRadii& radii) { corner_radii_ = radii; }
+  void SetCornerRadii(const CornerRadii& radii);
+  virtual void OnSetCornerRadii(const CornerRadii& radii);
 
   float corner_radius() const {
     DCHECK(corner_radii_.AllEqual());
@@ -250,7 +251,7 @@
 
   // Syntax sugar for setting all corner radii to the same value.
   void set_corner_radius(float corner_radius) {
-    set_corner_radii(
+    SetCornerRadii(
         {corner_radius, corner_radius, corner_radius, corner_radius});
   }
 
diff --git a/chrome/browser/vr/elements/ui_element_name.cc b/chrome/browser/vr/elements/ui_element_name.cc
index 22477ed..f5e0853 100644
--- a/chrome/browser/vr/elements/ui_element_name.cc
+++ b/chrome/browser/vr/elements/ui_element_name.cc
@@ -16,6 +16,8 @@
     "kRoot",
     "k2dBrowsingRoot",
     "k2dBrowsingBackground",
+    "k2dBrowsingDefaultBackground",
+    "k2dBrowsingTexturedBackground",
     "k2dBrowsingForeground",
     "k2dBrowsingContentGroup",
     "k2dBrowsingViewportAwareRoot",
@@ -45,6 +47,7 @@
     "kOmniboxOuterLayout",
     "kOmniboxShadow",
     "k2dBrowsingVisibiltyControlForOmnibox",
+    "k2dBrowsingVisibiltyControlForVoice",
     "kIndicatorLayout",
     "kAudioCaptureIndicator",
     "kVideoCaptureIndicator",
@@ -73,7 +76,6 @@
     "kSplashScreenTransientParent",
     "kSplashScreenViewportAwareRoot",
     "kSplashScreenText",
-    "kSplashScreenBackground",
     "kBackgroundFront",
     "kBackgroundLeft",
     "kBackgroundBack",
@@ -81,8 +83,9 @@
     "kBackgroundTop",
     "kBackgroundBottom",
     "kUnderDevelopmentNotice",
+    "kWebVrTimeoutRoot",
     "kWebVrTimeoutSpinner",
-    "kWebVrTimeoutSpinnerBackground",
+    "kWebVrBackground",
     "kWebVrTimeoutMessage",
     "kWebVrTimeoutMessageLayout",
     "kWebVrTimeoutMessageIcon",
diff --git a/chrome/browser/vr/elements/ui_element_name.h b/chrome/browser/vr/elements/ui_element_name.h
index fe3570c..6056152 100644
--- a/chrome/browser/vr/elements/ui_element_name.h
+++ b/chrome/browser/vr/elements/ui_element_name.h
@@ -15,6 +15,8 @@
   kRoot,
   k2dBrowsingRoot,
   k2dBrowsingBackground,
+  k2dBrowsingDefaultBackground,
+  k2dBrowsingTexturedBackground,
   k2dBrowsingForeground,
   k2dBrowsingContentGroup,
   k2dBrowsingViewportAwareRoot,
@@ -44,6 +46,7 @@
   kOmniboxOuterLayout,
   kOmniboxShadow,
   k2dBrowsingVisibiltyControlForOmnibox,
+  k2dBrowsingVisibiltyControlForVoice,
   kIndicatorLayout,
   kAudioCaptureIndicator,
   kVideoCaptureIndicator,
@@ -72,7 +75,6 @@
   kSplashScreenTransientParent,
   kSplashScreenViewportAwareRoot,
   kSplashScreenText,
-  kSplashScreenBackground,
   kBackgroundFront,
   kBackgroundLeft,
   kBackgroundBack,
@@ -80,8 +82,9 @@
   kBackgroundTop,
   kBackgroundBottom,
   kUnderDevelopmentNotice,
+  kWebVrTimeoutRoot,
   kWebVrTimeoutSpinner,
-  kWebVrTimeoutSpinnerBackground,
+  kWebVrBackground,
   kWebVrTimeoutMessage,
   kWebVrTimeoutMessageLayout,
   kWebVrTimeoutMessageIcon,
diff --git a/chrome/browser/vr/elements/ui_element_type.cc b/chrome/browser/vr/elements/ui_element_type.cc
index 0d4650d..9f0ca1ca 100644
--- a/chrome/browser/vr/elements/ui_element_type.cc
+++ b/chrome/browser/vr/elements/ui_element_type.cc
@@ -28,6 +28,10 @@
     "kTypeTextInputHint",
     "kTypeTextInputText",
     "kTypeTextInputCursor",
+    "kTypeToastBackground",
+    "kTypeToastContainer",
+    "kTypeToastIcon",
+    "kTypeToastText",
 };
 
 static_assert(
diff --git a/chrome/browser/vr/elements/ui_element_type.h b/chrome/browser/vr/elements/ui_element_type.h
index 21bd15a5..3ad5f93 100644
--- a/chrome/browser/vr/elements/ui_element_type.h
+++ b/chrome/browser/vr/elements/ui_element_type.h
@@ -28,6 +28,10 @@
   kTypeTextInputHint,
   kTypeTextInputText,
   kTypeTextInputCursor,
+  kTypeToastBackground,
+  kTypeToastContainer,
+  kTypeToastIcon,
+  kTypeToastText,
 
   // This must be last.
   kNumUiElementTypes,
diff --git a/chrome/browser/vr/model/color_scheme.cc b/chrome/browser/vr/model/color_scheme.cc
index 7603272d..e779124 100644
--- a/chrome/browser/vr/model/color_scheme.cc
+++ b/chrome/browser/vr/model/color_scheme.cc
@@ -30,6 +30,7 @@
   normal_scheme.floor = 0xFF8C8C8C;
   normal_scheme.ceiling = normal_scheme.floor;
   normal_scheme.floor_grid = 0x26FFFFFF;
+  normal_scheme.web_vr_background = SK_ColorBLACK;
   normal_scheme.element_foreground = 0xFF333333;
   normal_scheme.element_background = 0xCCB3B3B3;
   normal_scheme.element_background_hover = 0xCCE3E3E3;
@@ -50,8 +51,8 @@
   normal_scheme.exclusive_screen_toast_foreground = 0xCCFFFFFF;
   normal_scheme.exclusive_screen_toast_background = 0xCC2F2F2F;
 
-  normal_scheme.system_indicator_foreground = 0xFF444444;
-  normal_scheme.system_indicator_background = SK_ColorWHITE;
+  normal_scheme.system_indicator_foreground = normal_scheme.element_foreground;
+  normal_scheme.system_indicator_background = normal_scheme.element_background;
   normal_scheme.audio_permission_prompt_icon_foreground = 0xFF4285F4;
   normal_scheme.audio_permission_prompt_background = 0xFFF5F5F5;
   normal_scheme.audio_permission_prompt_secondary_button_colors.foreground =
@@ -106,10 +107,10 @@
   normal_scheme.dimmer_outer = 0xE6000000;
   normal_scheme.splash_screen_background = SK_ColorBLACK;
   normal_scheme.splash_screen_text_color = 0xA6FFFFFF;
-  normal_scheme.spinner_background = SK_ColorBLACK;
-  normal_scheme.spinner_color = 0xFFF3F3F3;
-  normal_scheme.timeout_message_background = 0xFF444444;
-  normal_scheme.timeout_message_foreground = normal_scheme.spinner_color;
+  normal_scheme.web_vr_timeout_spinner = 0xFFF3F3F3;
+  normal_scheme.web_vr_timeout_message_background = 0xFF444444;
+  normal_scheme.web_vr_timeout_message_foreground =
+      normal_scheme.web_vr_timeout_spinner;
   normal_scheme.speech_recognition_circle_background = 0xFF4285F4;
   normal_scheme.omnibox_background = 0xFFEEEEEE;
   normal_scheme.omnibox_icon = 0xA6000000;
@@ -147,6 +148,11 @@
   fullscreen_scheme.button_colors.background_down =
       fullscreen_scheme.element_background_down;
 
+  fullscreen_scheme.system_indicator_foreground =
+      fullscreen_scheme.element_foreground;
+  fullscreen_scheme.system_indicator_background =
+      fullscreen_scheme.element_background;
+
   g_incognito_scheme.Get() = normal_scheme;
   ColorScheme& incognito_scheme = g_incognito_scheme.Get();
   incognito_scheme.world_background = 0xFF2E2E2E;
@@ -158,6 +164,7 @@
   incognito_scheme.element_background = 0xFF454545;
   incognito_scheme.element_background_hover = 0xCC505050;
   incognito_scheme.element_background_down = 0xCC888888;
+
   incognito_scheme.button_colors.foreground =
       fullscreen_scheme.element_foreground;
   incognito_scheme.button_colors.foreground_disabled = 0x33E6E6E6;
@@ -168,6 +175,11 @@
   incognito_scheme.button_colors.background_down =
       fullscreen_scheme.element_background_down;
 
+  incognito_scheme.system_indicator_foreground =
+      incognito_scheme.element_foreground;
+  incognito_scheme.system_indicator_background =
+      incognito_scheme.element_background;
+
   incognito_scheme.url_bar.secure = 0xFFFFFFFF;
   incognito_scheme.url_bar.insecure = incognito_scheme.url_bar.secure;
   incognito_scheme.url_bar.emphasized = incognito_scheme.url_bar.secure;
diff --git a/chrome/browser/vr/model/color_scheme.h b/chrome/browser/vr/model/color_scheme.h
index 1607456..23aae46 100644
--- a/chrome/browser/vr/model/color_scheme.h
+++ b/chrome/browser/vr/model/color_scheme.h
@@ -55,6 +55,7 @@
   SkColor floor;
   SkColor ceiling;
   SkColor floor_grid;
+  SkColor web_vr_background;
 
   // The foreground color is used for text and sometimes for icons.
   SkColor element_foreground;
@@ -94,12 +95,9 @@
   SkColor splash_screen_background;
   SkColor splash_screen_text_color;
 
-  // WebVr timeout spinner colors.
-  SkColor spinner_background;
-  SkColor spinner_color;
-
-  SkColor timeout_message_background;
-  SkColor timeout_message_foreground;
+  SkColor web_vr_timeout_spinner;
+  SkColor web_vr_timeout_message_background;
+  SkColor web_vr_timeout_message_foreground;
 
   SkColor speech_recognition_circle_background;
 
diff --git a/chrome/browser/vr/model/model.h b/chrome/browser/vr/model/model.h
index c0fc8e43..4ee0c77 100644
--- a/chrome/browser/vr/model/model.h
+++ b/chrome/browser/vr/model/model.h
@@ -14,7 +14,7 @@
 #include "chrome/browser/vr/model/speech_recognition_model.h"
 #include "chrome/browser/vr/model/text_input_info.h"
 #include "chrome/browser/vr/model/toolbar_state.h"
-#include "chrome/browser/vr/model/web_vr_timeout_state.h"
+#include "chrome/browser/vr/model/web_vr_model.h"
 #include "chrome/browser/vr/ui_element_renderer.h"
 #include "ui/gfx/transform.h"
 
@@ -41,25 +41,15 @@
   unsigned int content_texture_id = 0;
   UiElementRenderer::TextureLocation content_location =
       UiElementRenderer::kTextureLocationLocal;
+  bool background_available = false;
+  bool background_loaded = false;
 
   // WebVR state.
-  bool web_vr_mode = false;
-  bool web_vr_show_toast = false;
-  bool web_vr_show_splash_screen = false;
-  // Indicates that we're waiting for the first WebVR frame to show up before we
-  // hide the splash screen. This is used in the case of WebVR auto-
-  // presentation.
-  bool web_vr_started_for_autopresentation = false;
-  bool should_render_web_vr() const {
-    return web_vr_mode && !web_vr_show_splash_screen;
-  }
-  bool browsing_mode() const {
-    return !web_vr_mode && !web_vr_show_splash_screen;
-  }
-  bool web_vr_has_produced_frames() const {
-    return web_vr_mode && web_vr_timeout_state == kWebVrNoTimeoutPending;
-  }
-  WebVrTimeoutState web_vr_timeout_state = kWebVrNoTimeoutPending;
+  WebVrModel web_vr;
+
+  // TODO(ymalik): This should be replaced by the concept of being in a "ui
+  // mode"
+  bool browsing_mode() const { return !web_vr.is_enabled(); }
 
   // Focused text state.
   bool editing_input = false;
diff --git a/chrome/browser/vr/model/web_vr_model.h b/chrome/browser/vr/model/web_vr_model.h
new file mode 100644
index 0000000..6be78e7
--- /dev/null
+++ b/chrome/browser/vr/model/web_vr_model.h
@@ -0,0 +1,48 @@
+// 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_VR_MODEL_WEB_VR_MODEL_H_
+#define CHROME_BROWSER_VR_MODEL_WEB_VR_MODEL_H_
+
+namespace vr {
+
+// As we wait for WebVR frames, we may pass through the following states.
+enum WebVrState {
+  // We are not awaiting a WebVR frame.
+  kWebVrNoTimeoutPending = 0,
+  kWebVrAwaitingFirstFrame,
+  // We are awaiting a WebVR frame, and we will soon exceed the amount of time
+  // that we're willing to wait. In this state, it could be appropriate to show
+  // an affordance to the user to let them know that WebVR is delayed (eg, this
+  // would be when we might show a spinner or progress bar).
+  kWebVrTimeoutImminent,
+  // In this case the time allotted for waiting for the first WebVR frame has
+  // been entirely exceeded. This would, for example, be an appropriate time to
+  // show "sad tab" UI to allow the user to bail on the WebVR content.
+  kWebVrTimedOut,
+  // We've received our first WebVR frame and are in WebVR presentation mode.
+  kWebVrPresenting,
+};
+
+struct WebVrModel {
+  WebVrState state = kWebVrNoTimeoutPending;
+
+  // Whether this WebVR session was started in auto-presentation mode.
+  // TODO(ymalik): We should remove these bits once we add the notion of "ui
+  // modes" and WebVR auto-presentation should simply be a mode.
+  bool started_for_autopresentation = false;
+  bool show_exit_toast = false;
+
+  bool is_enabled() const { return state >= kWebVrAwaitingFirstFrame; }
+  bool show_splash_screen() const {
+    return started_for_autopresentation && state == kWebVrAwaitingFirstFrame;
+  }
+  bool has_produced_frames() const {
+    return is_enabled() && state == kWebVrPresenting;
+  }
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_MODEL_WEB_VR_MODEL_H_
diff --git a/chrome/browser/vr/model/web_vr_timeout_state.h b/chrome/browser/vr/model/web_vr_timeout_state.h
deleted file mode 100644
index 84f756a..0000000
--- a/chrome/browser/vr/model/web_vr_timeout_state.h
+++ /dev/null
@@ -1,28 +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_VR_MODEL_WEB_VR_TIMEOUT_STATE_H_
-#define CHROME_BROWSER_VR_MODEL_WEB_VR_TIMEOUT_STATE_H_
-
-namespace vr {
-
-// As we wait for WebVR frames, we may pass through the following states.
-enum WebVrTimeoutState {
-  // We are not awaiting a WebVR frame.
-  kWebVrNoTimeoutPending,
-  kWebVrAwaitingFirstFrame,
-  // We are awaiting a WebVR frame, and we will soon exceed the amount of time
-  // that we're willing to wait. In this state, it could be appropriate to show
-  // an affordance to the user to let them know that WebVR is delayed (eg, this
-  // would be when we might show a spinner or progress bar).
-  kWebVrTimeoutImminent,
-  // In this case the time allotted for waiting for the first WebVR frame has
-  // been entirely exceeded. This would, for example, be an appropriate time to
-  // show "sad tab" UI to allow the user to bail on the WebVR content.
-  kWebVrTimedOut,
-};
-
-}  // namespace vr
-
-#endif  // CHROME_BROWSER_VR_MODEL_WEB_VR_TIMEOUT_STATE_H_
diff --git a/chrome/browser/vr/test/ui_test.cc b/chrome/browser/vr/test/ui_test.cc
index 4fbeac6c..60b88053 100644
--- a/chrome/browser/vr/test/ui_test.cc
+++ b/chrome/browser/vr/test/ui_test.cc
@@ -71,12 +71,32 @@
   browser_ = base::MakeUnique<testing::NiceMock<MockUiBrowserInterface>>();
 }
 
+void UiTest::CreateScene(const UiInitialState& state) {
+  auto content_input_delegate =
+      base::MakeUnique<testing::NiceMock<MockContentInputDelegate>>();
+  content_input_delegate_ = content_input_delegate.get();
+
+  ui_ = base::MakeUnique<Ui>(std::move(browser_.get()),
+                             std::move(content_input_delegate), nullptr,
+                             nullptr, state);
+  scene_ = ui_->scene();
+  model_ = ui_->model_for_test();
+
+  OnBeginFrame();
+}
+
 void UiTest::CreateScene(InCct in_cct, InWebVr in_web_vr) {
-  CreateSceneInternal(in_cct, in_web_vr, kNotAutopresented);
+  UiInitialState state;
+  state.in_cct = in_cct;
+  state.in_web_vr = in_web_vr;
+  CreateScene(state);
 }
 
 void UiTest::CreateSceneForAutoPresentation() {
-  CreateSceneInternal(kNotInCct, kNotInWebVr, kAutopresented);
+  UiInitialState state;
+  state.in_web_vr = true;
+  state.web_vr_autopresentation_expected = true;
+  CreateScene(state);
 }
 
 void UiTest::SetIncognito(bool incognito) {
@@ -109,14 +129,15 @@
   OnBeginFrame();
   SCOPED_TRACE(trace_context);
   for (const auto& element : scene_->root_element()) {
+    SCOPED_TRACE(element.DebugName());
     UiElementName name = element.name();
-    if (name == kNone)
-      name = element.owner_name_for_test();
-    if (element.draw_phase() == kPhaseNone) {
+    UiElementName owner_name = element.owner_name_for_test();
+    if (element.draw_phase() == kPhaseNone && owner_name == kNone) {
       EXPECT_TRUE(names.find(name) == names.end());
       continue;
     }
-    SCOPED_TRACE(element.DebugName());
+    if (name == kNone)
+      name = owner_name;
     bool should_be_visible = (names.find(name) != names.end());
     EXPECT_EQ(WillElementBeVisible(&element), should_be_visible);
   }
@@ -237,24 +258,4 @@
   *background_color = color;
 }
 
-void UiTest::CreateSceneInternal(InCct in_cct,
-                                 InWebVr in_web_vr,
-                                 WebVrAutopresented web_vr_autopresented) {
-  auto content_input_delegate =
-      base::MakeUnique<testing::NiceMock<MockContentInputDelegate>>();
-  content_input_delegate_ = content_input_delegate.get();
-
-  UiInitialState ui_initial_state;
-  ui_initial_state.in_cct = in_cct;
-  ui_initial_state.in_web_vr = in_web_vr;
-  ui_initial_state.web_vr_autopresentation_expected = web_vr_autopresented;
-  ui_ = base::MakeUnique<Ui>(std::move(browser_.get()),
-                             std::move(content_input_delegate), nullptr,
-                             nullptr, ui_initial_state);
-  scene_ = ui_->scene();
-  model_ = ui_->model_for_test();
-
-  OnBeginFrame();
-}
-
 }  // namespace vr
diff --git a/chrome/browser/vr/test/ui_test.h b/chrome/browser/vr/test/ui_test.h
index 0d6c9f8..cccc049 100644
--- a/chrome/browser/vr/test/ui_test.h
+++ b/chrome/browser/vr/test/ui_test.h
@@ -46,6 +46,7 @@
     kAutopresented = true,
   };
 
+  void CreateScene(const UiInitialState& state);
   void CreateScene(InCct in_cct, InWebVr in_web_vr);
   void CreateSceneForAutoPresentation();
 
@@ -104,10 +105,6 @@
   UiScene* scene_ = nullptr;
 
  private:
-  void CreateSceneInternal(InCct in_cct,
-                           InWebVr in_web_vr,
-                           WebVrAutopresented web_vr_autopresented);
-
   base::TimeTicks current_time_;
 };
 
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc
index 322ae37..56ed87c 100644
--- a/chrome/browser/vr/testapp/vr_test_context.cc
+++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -124,7 +124,7 @@
   ui_->ui_renderer()->Draw(render_info);
 
   // This is required in order to show the WebVR toasts.
-  if (model_->web_vr_has_produced_frames()) {
+  if (model_->web_vr.has_produced_frames()) {
     ui_->ui_renderer()->DrawWebVrOverlayForeground(render_info);
   }
 }
@@ -367,7 +367,7 @@
 }
 
 void VrTestContext::CycleWebVrModes() {
-  switch (model_->web_vr_timeout_state) {
+  switch (model_->web_vr.state) {
     case kWebVrNoTimeoutPending:
       ui_->SetWebVrMode(true, false);
       break;
@@ -380,6 +380,8 @@
     case kWebVrTimedOut:
       ui_->SetWebVrMode(false, false);
       break;
+    default:
+      break;
   }
 }
 
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc
index 57243f4..04e75da 100644
--- a/chrome/browser/vr/ui.cc
+++ b/chrome/browser/vr/ui.cc
@@ -63,13 +63,13 @@
 }
 
 void Ui::SetWebVrMode(bool enabled, bool show_toast) {
-  model_->web_vr_timeout_state =
-      enabled ? kWebVrAwaitingFirstFrame : kWebVrNoTimeoutPending;
-  model_->web_vr_mode = enabled;
-  model_->web_vr_show_toast = show_toast;
-  if (!enabled) {
-    model_->web_vr_show_splash_screen = false;
-    model_->web_vr_started_for_autopresentation = false;
+  model_->web_vr.show_exit_toast = show_toast;
+  if (enabled) {
+    model_->web_vr.state = kWebVrAwaitingFirstFrame;
+  } else {
+    model_->web_vr.state = kWebVrNoTimeoutPending;
+    // This gets set to true when the UI is initialized.
+    model_->web_vr.started_for_autopresentation = false;
   }
 }
 
@@ -174,7 +174,7 @@
 }
 
 bool Ui::ShouldRenderWebVr() {
-  return model_->should_render_web_vr();
+  return model_->web_vr.has_produced_frames();
 }
 
 void Ui::OnGlInitialized(unsigned int content_texture_id,
@@ -215,7 +215,7 @@
 
 void Ui::OnAppButtonClicked() {
   // App button clicks should be a no-op when auto-presenting WebVR.
-  if (model_->web_vr_started_for_autopresentation) {
+  if (model_->web_vr.started_for_autopresentation) {
     return;
   }
 
@@ -245,17 +245,18 @@
 }
 
 void Ui::OnWebVrFrameAvailable() {
-  model_->web_vr_timeout_state = kWebVrNoTimeoutPending;
+  if (model_->web_vr.is_enabled())
+    model_->web_vr.state = kWebVrPresenting;
 }
 
 void Ui::OnWebVrTimeoutImminent() {
-  model_->web_vr_timeout_state = kWebVrTimeoutImminent;
-  // We do not want to simultaneously show the splash screen and the timeout UI.
-  model_->web_vr_show_splash_screen = false;
+  if (model_->web_vr.is_enabled())
+    model_->web_vr.state = kWebVrTimeoutImminent;
 }
 
 void Ui::OnWebVrTimedOut() {
-  model_->web_vr_timeout_state = kWebVrTimedOut;
+  if (model_->web_vr.is_enabled())
+    model_->web_vr.state = kWebVrTimedOut;
 }
 
 void Ui::OnSwapContents(int new_content_id) {
@@ -287,24 +288,32 @@
   LOG(ERROR) << os.str();
 }
 
+void Ui::SetBackgroundImage(std::unique_ptr<SkBitmap> bitmap) {
+  Background* background = reinterpret_cast<Background*>(
+      scene_->GetUiElementByName(k2dBrowsingTexturedBackground));
+  DCHECK(background);
+  background->SetImage(std::move(bitmap));
+  model_->background_loaded = true;
+}
+
 void Ui::ReinitializeForTest(const UiInitialState& ui_initial_state) {
   InitializeModel(ui_initial_state);
 }
 
 void Ui::InitializeModel(const UiInitialState& ui_initial_state) {
-  model_->web_vr_started_for_autopresentation =
-      ui_initial_state.web_vr_autopresentation_expected;
-  model_->web_vr_show_splash_screen =
+  model_->web_vr.started_for_autopresentation =
       ui_initial_state.web_vr_autopresentation_expected;
   model_->experimental_features_enabled =
       base::FeatureList::IsEnabled(features::kVrBrowsingExperimentalFeatures);
   model_->speech.has_or_can_request_audio_permission =
       ui_initial_state.has_or_can_request_audio_permission;
-  model_->web_vr_mode = ui_initial_state.in_web_vr;
+  model_->web_vr.state = ui_initial_state.in_web_vr ? kWebVrAwaitingFirstFrame
+                                                    : kWebVrNoTimeoutPending;
   model_->in_cct = ui_initial_state.in_cct;
   model_->browsing_disabled = ui_initial_state.browsing_disabled;
   model_->skips_redraw_when_not_dirty =
       ui_initial_state.skips_redraw_when_not_dirty;
+  model_->background_available = ui_initial_state.assets_available;
 }
 
 }  // namespace vr
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h
index a88dc79..23bbbf1 100644
--- a/chrome/browser/vr/ui.h
+++ b/chrome/browser/vr/ui.h
@@ -114,6 +114,8 @@
 
   void Dump();
 
+  void SetBackgroundImage(std::unique_ptr<SkBitmap> bitmap);
+
   // Keyboard input related.
   void RequestFocus(int element_id);
   void RequestUnfocus(int element_id);
diff --git a/chrome/browser/vr/ui_element_renderer.cc b/chrome/browser/vr/ui_element_renderer.cc
index 1ede7fb..8f493de 100644
--- a/chrome/browser/vr/ui_element_renderer.cc
+++ b/chrome/browser/vr/ui_element_renderer.cc
@@ -45,6 +45,7 @@
   controller_renderer_ = base::MakeUnique<Controller::Renderer>();
   gradient_grid_renderer_ = base::MakeUnique<Grid::Renderer>();
   shadow_renderer_ = base::MakeUnique<Shadow::Renderer>();
+  background_renderer_ = base::MakeUnique<Background::Renderer>();
 }
 
 void UiElementRenderer::DrawTexturedQuad(
@@ -136,6 +137,13 @@
                          y_padding, y_offset, color, opacity, corner_radius);
 }
 
+void UiElementRenderer::DrawBackground(
+    const gfx::Transform& model_view_proj_matrix,
+    int texture_data_handle) {
+  FlushIfNecessary(background_renderer_.get());
+  background_renderer_->Draw(model_view_proj_matrix, texture_data_handle);
+}
+
 void UiElementRenderer::Flush() {
   textured_quad_renderer_->Flush();
   external_textured_quad_renderer_->Flush();
diff --git a/chrome/browser/vr/ui_element_renderer.h b/chrome/browser/vr/ui_element_renderer.h
index a48b8a8..586234b 100644
--- a/chrome/browser/vr/ui_element_renderer.h
+++ b/chrome/browser/vr/ui_element_renderer.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "chrome/browser/vr/controller_mesh.h"
+#include "chrome/browser/vr/elements/background.h"
 #include "chrome/browser/vr/elements/controller.h"
 #include "chrome/browser/vr/elements/grid.h"
 #include "chrome/browser/vr/elements/laser.h"
@@ -105,6 +106,10 @@
       float opacity,
       float corner_radius);
 
+  VIRTUAL_FOR_MOCKS void DrawBackground(
+      const gfx::Transform& model_view_proj_matrix,
+      int texture_data_handle);
+
   void Flush();
   void SetUpController(std::unique_ptr<ControllerMesh> mesh);
 
@@ -127,6 +132,7 @@
   std::unique_ptr<Controller::Renderer> controller_renderer_;
   std::unique_ptr<Grid::Renderer> gradient_grid_renderer_;
   std::unique_ptr<Shadow::Renderer> shadow_renderer_;
+  std::unique_ptr<Background::Renderer> background_renderer_;
 
   DISALLOW_COPY_AND_ASSIGN(UiElementRenderer);
 };
diff --git a/chrome/browser/vr/ui_renderer.cc b/chrome/browser/vr/ui_renderer.cc
index 507797c..8f15d26 100644
--- a/chrome/browser/vr/ui_renderer.cc
+++ b/chrome/browser/vr/ui_renderer.cc
@@ -21,61 +21,8 @@
 // rendering and be platform agnostic, each element should know how to render
 // itself correctly.
 void UiRenderer::Draw(const RenderInfo& render_info) {
-  Draw2dBrowsing(render_info);
-  DrawSplashScreen(render_info);
-  DrawInputModalElements(render_info);
-}
-
-void UiRenderer::Draw2dBrowsing(const RenderInfo& render_info) {
-  const auto& elements = scene_->GetVisible2dBrowsingElements();
-  const auto& elements_overlay = scene_->GetVisible2dBrowsingOverlayElements();
-  if (elements.empty() && elements_overlay.empty())
-    return;
-
-  if (!elements.empty()) {
-    // Note that we do not clear the color buffer. The scene's background
-    // elements are responsible for drawing a complete background.
-    glEnable(GL_CULL_FACE);
-    DrawUiView(render_info, elements);
-  }
-
-  if (elements_overlay.empty())
-    return;
-
-  // The overlays do not make use of depth testing or backface culling.
-  glDisable(GL_CULL_FACE);
-  DrawUiView(render_info, elements_overlay);
-}
-
-void UiRenderer::DrawSplashScreen(const RenderInfo& render_info) {
-  const auto& elements = scene_->GetVisibleSplashScreenElements();
-  if (elements.empty())
-    return;
-
-  // WebVR is incompatible with 3D world compositing since the
-  // depth buffer was already populated with unknown scaling - the
-  // WebVR app has full control over zNear/zFar. Just leave the
-  // existing content in place in the primary buffer without
-  // clearing. Currently, there aren't any world elements in WebVR
-  // mode, this will need further testing if those get added
-  // later.
-  glDisable(GL_CULL_FACE);
-  DrawUiView(render_info, elements);
-
-  // NB: we do not draw the viewport aware objects here. They get put into
-  // another buffer that is size optimized.
-}
-
-void UiRenderer::DrawInputModalElements(const RenderInfo& render_info) {
-  const auto& keyboard_elements = scene_->GetVisibleKeyboardElements();
-  const auto& controller_elements = scene_->GetVisibleControllerElements();
-  if (!keyboard_elements.empty()) {
-    DrawUiView(render_info, keyboard_elements);
-  }
-  if (!controller_elements.empty()) {
-    glEnable(GL_CULL_FACE);
-    DrawUiView(render_info, controller_elements);
-  }
+  glEnable(GL_CULL_FACE);
+  DrawUiView(render_info, scene_->GetVisibleElementsToDraw());
 }
 
 void UiRenderer::DrawWebVrOverlayForeground(const RenderInfo& render_info) {
@@ -85,11 +32,14 @@
 
   glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
   glClear(GL_COLOR_BUFFER_BIT);
-  DrawUiView(render_info, scene_->GetVisibleWebVrOverlayForegroundElements());
+  DrawUiView(render_info, scene_->GetVisibleWebVrOverlayElementsToDraw());
 }
 
 void UiRenderer::DrawUiView(const RenderInfo& render_info,
                             const std::vector<const UiElement*>& elements) {
+  if (elements.empty())
+    return;
+
   TRACE_EVENT0("gpu", "UiRenderer::DrawUiView");
 
   auto sorted_elements = GetElementsInDrawOrder(elements);
diff --git a/chrome/browser/vr/ui_renderer.h b/chrome/browser/vr/ui_renderer.h
index b33ba6ca..b1d53b37 100644
--- a/chrome/browser/vr/ui_renderer.h
+++ b/chrome/browser/vr/ui_renderer.h
@@ -42,10 +42,6 @@
       const std::vector<const UiElement*>& elements);
 
  private:
-  void Draw2dBrowsing(const RenderInfo& render_info);
-  void DrawSplashScreen(const RenderInfo& render_info);
-  void DrawInputModalElements(const RenderInfo& render_info);
-
   void DrawUiView(const RenderInfo& render_info,
                   const std::vector<const UiElement*>& elements);
   void DrawElements(const CameraModel& camera_model,
diff --git a/chrome/browser/vr/ui_scene.cc b/chrome/browser/vr/ui_scene.cc
index 0ea84e1..9a24dcd3 100644
--- a/chrome/browser/vr/ui_scene.cc
+++ b/chrome/browser/vr/ui_scene.cc
@@ -171,52 +171,20 @@
   return nullptr;
 }
 
-UiScene::Elements UiScene::GetVisible2dBrowsingElements() const {
-  return GetVisibleElements(
-      GetUiElementByName(k2dBrowsingRoot), [](UiElement* element) {
-        return element->draw_phase() == kPhaseForeground ||
-               element->draw_phase() == kPhaseFloorCeiling ||
-               element->draw_phase() == kPhaseBackground;
-      });
+UiScene::Elements UiScene::GetVisibleElementsToDraw() const {
+  return GetVisibleElements(GetUiElementByName(kRoot), [](UiElement* element) {
+    return element->draw_phase() == kPhaseForeground ||
+           element->draw_phase() == kPhaseBackground;
+  });
 }
 
-UiScene::Elements UiScene::GetVisible2dBrowsingOverlayElements() const {
-  return GetVisibleElements(
-      GetUiElementByName(k2dBrowsingRoot), [](UiElement* element) {
-        return element->draw_phase() == kPhaseOverlayBackground ||
-               element->draw_phase() == kPhaseOverlayForeground;
-      });
-}
-
-UiScene::Elements UiScene::GetVisibleSplashScreenElements() const {
-  return GetVisibleElements(
-      GetUiElementByName(kSplashScreenRoot), [](UiElement* element) {
-        return element->draw_phase() == kPhaseOverlayBackground ||
-               element->draw_phase() == kPhaseOverlayForeground;
-      });
-}
-
-UiScene::Elements UiScene::GetVisibleWebVrOverlayForegroundElements() const {
+UiScene::Elements UiScene::GetVisibleWebVrOverlayElementsToDraw() const {
   return GetVisibleElements(
       GetUiElementByName(kWebVrRoot), [](UiElement* element) {
         return element->draw_phase() == kPhaseOverlayForeground;
       });
 }
 
-UiScene::Elements UiScene::GetVisibleControllerElements() const {
-  return GetVisibleElements(GetUiElementByName(kControllerGroup),
-                            [](UiElement* element) {
-                              return element->draw_phase() == kPhaseForeground;
-                            });
-}
-
-UiScene::Elements UiScene::GetVisibleKeyboardElements() const {
-  return GetVisibleElements(GetUiElementByName(kKeyboard),
-                            [](UiElement* element) {
-                              return element->draw_phase() == kPhaseForeground;
-                            });
-}
-
 UiScene::Elements UiScene::GetPotentiallyVisibleElements() const {
   UiScene::Elements elements;
   for (auto& element : *root_element_) {
diff --git a/chrome/browser/vr/ui_scene.h b/chrome/browser/vr/ui_scene.h
index d49378c..a0680efc 100644
--- a/chrome/browser/vr/ui_scene.h
+++ b/chrome/browser/vr/ui_scene.h
@@ -54,23 +54,13 @@
 
   typedef std::vector<const UiElement*> Elements;
 
-  Elements GetVisible2dBrowsingElements() const;
-  Elements GetVisible2dBrowsingOverlayElements() const;
-  Elements GetVisibleSplashScreenElements() const;
-  Elements GetVisibleWebVrOverlayForegroundElements() const;
-  Elements GetVisibleControllerElements() const;
-  Elements GetVisibleKeyboardElements() const;
+  Elements GetVisibleElementsToDraw() const;
+  Elements GetVisibleWebVrOverlayElementsToDraw() const;
   Elements GetPotentiallyVisibleElements() const;
 
   float background_distance() const { return background_distance_; }
   void set_background_distance(float d) { background_distance_ = d; }
 
-  int first_foreground_draw_phase() const {
-    return first_foreground_draw_phase_;
-  }
-  void set_first_foreground_draw_phase(int phase) {
-    first_foreground_draw_phase_ = phase;
-  }
   void set_dirty() { is_dirty_ = true; }
 
   void OnGlInitialized(SkiaSurfaceProvider* provider);
@@ -84,7 +74,6 @@
 
   float background_distance_ = 10.0f;
   bool gl_initialized_ = false;
-  int first_foreground_draw_phase_ = 0;
   bool initialized_scene_ = false;
 
   // TODO(mthiesse): Convert everything that manipulates UI elements to
diff --git a/chrome/browser/vr/ui_scene_constants.h b/chrome/browser/vr/ui_scene_constants.h
index 83ae86b..f3c559f 100644
--- a/chrome/browser/vr/ui_scene_constants.h
+++ b/chrome/browser/vr/ui_scene_constants.h
@@ -39,9 +39,13 @@
 static constexpr float kFullscreenDistance = 3;
 // Make sure that the aspect ratio for fullscreen is 16:9. Otherwise, we may
 // experience visual artefacts for fullscreened videos.
-static constexpr float kFullscreenHeight = 0.64f * kFullscreenDistance;
+static constexpr float kFullscreenHeightDMM = 0.64f;
+static constexpr float kFullscreenHeight =
+    kFullscreenHeightDMM * kFullscreenDistance;
 static constexpr float kFullscreenWidth = 1.138f * kFullscreenDistance;
-static constexpr float kFullscreenVerticalOffset = -0.1f * kFullscreenDistance;
+static constexpr float kFullscreenVerticalOffsetDMM = -0.1f;
+static constexpr float kFullscreenVerticalOffset =
+    kFullscreenVerticalOffsetDMM * kFullscreenDistance;
 
 static constexpr float kExitPromptWidth = 0.672f * kContentDistance;
 static constexpr float kExitPromptHeight = 0.2f * kContentDistance;
@@ -62,6 +66,12 @@
 static constexpr float kAudionPermisionPromptDepth = 0.11f;
 
 static constexpr float kIndicatorHeight = 0.08f;
+static constexpr float kIndicatorXPadding = kIndicatorHeight * 0.1f;
+static constexpr float kIndicatorYPadding = kIndicatorHeight * 0.15f;
+static constexpr float kIndicatorIconSize = kIndicatorHeight * 0.7f;
+static constexpr float kIndicatorCornerRadius = kIndicatorHeight * 0.1f;
+static constexpr float kIndicatorMargin = kIndicatorHeight * 0.2f;
+static constexpr float kIndicatorFontHeightDmm = 0.032f;
 static constexpr float kIndicatorGap = 0.05f;
 static constexpr float kIndicatorVerticalOffset = 0.1f;
 static constexpr float kIndicatorDistanceOffset = 0.1f;
@@ -74,6 +84,7 @@
 static constexpr float kWebVrUrlToastHeight =
     kWebVrUrlToastHeightDMM * kWebVrUrlToastDistance;
 static constexpr int kWebVrUrlToastTimeoutSeconds = 6;
+static constexpr float kWebVrUrlToastOpacity = 0.8f;
 static constexpr float kWebVrUrlToastRotationRad = 14 * base::kPiFloat / 180;
 
 static constexpr float kWebVrToastDistance = 1.0;
@@ -81,6 +92,13 @@
 static constexpr float kToastWidthDMM = 0.512f;
 static constexpr float kToastHeightDMM = 0.064f;
 static constexpr float kToastOffsetDMM = 0.004f;
+static constexpr float kFullScreenToastOffsetDMM =
+    kFullscreenVerticalOffsetDMM + kFullscreenHeightDMM / 2 + kToastHeightDMM +
+    0.004f;
+static constexpr float kExclusiveScreenToastXPaddingDMM = 0.017f;
+static constexpr float kExclusiveScreenToastYPaddingDMM = 0.02f;
+static constexpr float kExclusiveScreenToastCornerRadiusDMM = 0.004f;
+static constexpr float kExclusiveScreenToastTextFontHeightDMM = 0.023f;
 // When changing the value here, make sure it doesn't collide with
 // kWarningAngleRadians.
 static constexpr float kWebVrAngleRadians = 9.88f * base::kPiFloat / 180;
@@ -90,7 +108,7 @@
 static constexpr float kSplashScreenTextFontHeightDMM = 0.05f;
 static constexpr float kSplashScreenTextWidthDMM = 0.9f;
 static constexpr float kSplashScreenTextVerticalOffsetDMM = -0.072f;
-static constexpr float kSplashScreenMinDurationSeconds = 3;
+static constexpr float kSplashScreenMinDurationSeconds = 2;
 
 static constexpr float kButtonDiameterDMM = 0.088f;
 static constexpr float kButtonZOffsetHoverDMM = 0.048;
@@ -146,11 +164,10 @@
     kVoiceSearchButtonYOffsetDMM + kVoiceSearchButtonDiameterDMM * 1.5f + 0.04f;
 static constexpr float kUnderDevelopmentNoticeRotationRad = -0.78f;
 
-static constexpr float kSpinnerWidth = kCloseButtonWidth;
-static constexpr float kSpinnerHeight = kCloseButtonHeight;
-static constexpr float kSpinnerDistance = kSplashScreenTextDistance;
-static constexpr float kSpinnerVerticalOffset =
-    kSplashScreenTextVerticalOffsetDMM * kSpinnerDistance;
+static constexpr float kTimeoutScreenDisatance = 2.5f;
+static constexpr float kTimeoutSpinnerSizeDMM = 0.088f;
+static constexpr float kTimeoutSpinnerVerticalOffsetDMM =
+    kSplashScreenTextVerticalOffsetDMM;
 
 static constexpr float kTimeoutMessageHorizontalPaddingDMM = 0.04f;
 static constexpr float kTimeoutMessageVerticalPaddingDMM = 0.024f;
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc
index 637ed004..c3d35945 100644
--- a/chrome/browser/vr/ui_scene_creator.cc
+++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/vr/databinding/binding.h"
 #include "chrome/browser/vr/databinding/vector_binding.h"
 #include "chrome/browser/vr/elements/audio_permission_prompt.h"
+#include "chrome/browser/vr/elements/background.h"
 #include "chrome/browser/vr/elements/button.h"
 #include "chrome/browser/vr/elements/content_element.h"
 #include "chrome/browser/vr/elements/controller.h"
@@ -26,11 +27,11 @@
 #include "chrome/browser/vr/elements/rect.h"
 #include "chrome/browser/vr/elements/reticle.h"
 #include "chrome/browser/vr/elements/scaled_depth_adjuster.h"
-#include "chrome/browser/vr/elements/simple_textured_element.h"
 #include "chrome/browser/vr/elements/spinner.h"
 #include "chrome/browser/vr/elements/text.h"
 #include "chrome/browser/vr/elements/text_input.h"
 #include "chrome/browser/vr/elements/throbber.h"
+#include "chrome/browser/vr/elements/toast.h"
 #include "chrome/browser/vr/elements/transient_element.h"
 #include "chrome/browser/vr/elements/ui_element.h"
 #include "chrome/browser/vr/elements/ui_element_name.h"
@@ -122,7 +123,7 @@
   description_text->SetDrawPhase(kPhaseForeground);
   description_text->SetType(kTypeOmniboxSuggestionDescriptionText);
   description_text->set_hit_testable(false);
-  content_text->SetTextLayoutMode(TextLayoutMode::kSingleLineFixedWidth);
+  description_text->SetTextLayoutMode(TextLayoutMode::kSingleLineFixedWidth);
   description_text->SetSize(kSuggestionTextFieldWidthDMM, 0);
   description_text->SetTextAlignment(UiTexture::kTextAlignmentLeft);
   BindColor(model, description_text.get(),
@@ -258,43 +259,52 @@
   CreateContentQuad();
   CreateExitPrompt();
   CreateAudioPermissionPrompt();
-  CreateWebVRExitWarning();
   CreateSystemIndicators();
   CreateUrlBar();
   CreateOmnibox();
-  CreateWebVrUrlToast();
   CreateCloseButton();
-  CreateToasts();
-  CreateSplashScreenForDirectWebVrLaunch();
-  CreateWebVrTimeoutScreen();
+  CreateFullscreenToast();
   CreateUnderDevelopmentNotice();
   CreateVoiceSearchUiGroup();
+  CreateExitWarning();
+  CreateWebVrSubtree();
   CreateController();
   CreateKeyboard();
 }
 
 void UiSceneCreator::Create2dBrowsingSubtreeRoots() {
-  auto element = base::MakeUnique<UiElement>();
-  element->SetName(k2dBrowsingRoot);
+  auto element = Create<UiElement>(k2dBrowsingRoot, kPhaseNone);
   element->set_hit_testable(false);
-  element->AddBinding(VR_BIND_FUNC(bool, Model, model_, browsing_mode(),
-                                   UiElement, element.get(), SetVisible));
+  element->AddBinding(base::MakeUnique<Binding<bool>>(
+      base::BindRepeating(
+          [](Model* m) {
+            bool ready = !m->background_available ||
+                         (m->background_available && m->background_loaded);
+            return m->browsing_mode() && ready;
+          },
+          base::Unretained(model_)),
+      base::BindRepeating([](UiElement* e, const bool& v) { e->SetVisible(v); },
+                          base::Unretained(element.get()))));
+
   scene_->AddUiElement(kRoot, std::move(element));
 
-  element = base::MakeUnique<UiElement>();
-  element->SetName(k2dBrowsingBackground);
+  element = Create<UiElement>(k2dBrowsingBackground, kPhaseNone);
   element->set_hit_testable(false);
   scene_->AddUiElement(k2dBrowsingRoot, std::move(element));
 
-  element = base::MakeUnique<UiElement>();
-  element->SetName(k2dBrowsingVisibiltyControlForOmnibox);
+  element =
+      Create<UiElement>(k2dBrowsingVisibiltyControlForOmnibox, kPhaseNone);
   element->set_hit_testable(false);
   element->AddBinding(VR_BIND(bool, Model, model_, omnibox_input_active,
                               UiElement, element.get(), SetVisible(!value)));
   scene_->AddUiElement(k2dBrowsingRoot, std::move(element));
 
-  element = base::MakeUnique<UiElement>();
-  element->SetName(k2dBrowsingForeground);
+  element = Create<UiElement>(k2dBrowsingVisibiltyControlForVoice, kPhaseNone);
+  element->set_hit_testable(false);
+  scene_->AddUiElement(k2dBrowsingVisibiltyControlForOmnibox,
+                       std::move(element));
+
+  element = Create<UiElement>(k2dBrowsingForeground, kPhaseNone);
   element->set_hit_testable(false);
   element->SetTransitionedProperties({OPACITY});
   element->SetTransitionDuration(base::TimeDelta::FromMilliseconds(
@@ -315,11 +325,9 @@
             }
           },
           base::Unretained(element.get()))));
-  scene_->AddUiElement(k2dBrowsingVisibiltyControlForOmnibox,
-                       std::move(element));
+  scene_->AddUiElement(k2dBrowsingVisibiltyControlForVoice, std::move(element));
 
-  element = base::MakeUnique<UiElement>();
-  element->SetName(k2dBrowsingContentGroup);
+  element = Create<UiElement>(k2dBrowsingContentGroup, kPhaseNone);
   element->SetTranslate(0, kContentVerticalOffset, -kContentDistance);
   element->SetSize(kContentWidth, kContentHeight);
   element->set_hit_testable(false);
@@ -342,10 +350,10 @@
   scene_->AddUiElement(kRoot, std::move(element));
 }
 
-void UiSceneCreator::CreateWebVRExitWarning() {
+void UiSceneCreator::CreateExitWarning() {
   auto scrim = base::MakeUnique<FullScreenRect>();
   scrim->SetName(kScreenDimmer);
-  scrim->SetDrawPhase(kPhaseOverlayBackground);
+  scrim->SetDrawPhase(kPhaseForeground);
   scrim->SetVisible(false);
   scrim->set_hit_testable(false);
   scrim->SetOpacity(kScreenDimmerOpacity);
@@ -353,13 +361,13 @@
   scrim->SetEdgeColor(model_->color_scheme().dimmer_outer);
   scrim->AddBinding(VR_BIND_FUNC(bool, Model, model_, exiting_vr, UiElement,
                                  scrim.get(), SetVisible));
-  scene_->AddUiElement(k2dBrowsingRoot, std::move(scrim));
+  scene_->AddUiElement(k2dBrowsingViewportAwareRoot, std::move(scrim));
 
   // Create transient exit warning.
   auto scaler = base::MakeUnique<ScaledDepthAdjuster>(kExitWarningDistance);
   auto exit_warning_text = base::MakeUnique<Text>(kExitWarningFontHeightDMM);
   exit_warning_text->SetName(kExitWarningText);
-  exit_warning_text->SetDrawPhase(kPhaseOverlayForeground);
+  exit_warning_text->SetDrawPhase(kPhaseForeground);
   exit_warning_text->SetText(
       l10n_util::GetStringUTF16(IDS_VR_BROWSER_UNSUPPORTED_PAGE));
   exit_warning_text->SetSize(kExitWarningTextWidthDMM, 0);
@@ -370,7 +378,7 @@
 
   auto exit_warning_bg = base::MakeUnique<Rect>();
   exit_warning_bg->SetName(kExitWarningBackground);
-  exit_warning_bg->SetDrawPhase(kPhaseOverlayForeground);
+  exit_warning_bg->SetDrawPhase(kPhaseForeground);
   exit_warning_bg->set_bounds_contain_children(true);
   exit_warning_bg->set_padding(kExitWarningXPaddingDMM,
                                kExitWarningYPaddingDMM);
@@ -420,21 +428,25 @@
   indicator_layout->AddBinding(
       VR_BIND_FUNC(bool, Model, model_, fullscreen == false, UiElement,
                    indicator_layout.get(), SetVisible));
-  scene_->AddUiElement(k2dBrowsingContentGroup, std::move(indicator_layout));
 
   for (const auto& indicator : indicators) {
-    auto element = base::MakeUnique<SystemIndicator>(512);
-    element->GetDerivedTexture()->SetIcon(indicator.icon);
-    element->GetDerivedTexture()->SetMessageId(indicator.resource_string);
+    auto element = base::MakeUnique<Toast>();
     element->SetName(indicator.name);
     element->SetDrawPhase(kPhaseForeground);
-    element->set_requires_layout(false);
-    element->SetSize(0, kIndicatorHeight);
-    element->SetVisible(false);
+    element->set_padding(kIndicatorXPadding, kIndicatorYPadding);
+    element->set_corner_radius(kIndicatorCornerRadius);
+    element->SetMargin(kIndicatorMargin);
+    element->AddIcon(indicator.icon, 64, kIndicatorIconSize);
+    if (indicator.resource_string != 0) {
+      element->AddText(l10n_util::GetStringUTF16(indicator.resource_string),
+                       kIndicatorFontHeightDmm,
+                       TextLayoutMode::kSingleLineFixedHeight);
+    }
+
     BindColor(model_, element.get(), &ColorScheme::system_indicator_background,
-              &TexturedElement::SetBackgroundColor);
+              &Toast::SetBackgroundColor);
     BindColor(model_, element.get(), &ColorScheme::system_indicator_foreground,
-              &TexturedElement::SetForegroundColor);
+              &Toast::SetForegroundColor);
     element->AddBinding(base::MakeUnique<Binding<bool>>(
         base::Bind(
             [](Model* m, bool PermissionsModel::*permission) {
@@ -447,8 +459,10 @@
               e->set_requires_layout(v);
             },
             base::Unretained(element.get()))));
-    scene_->AddUiElement(kIndicatorLayout, std::move(element));
+
+    indicator_layout->AddChild(std::move(element));
   }
+  scene_->AddUiElement(k2dBrowsingContentGroup, std::move(indicator_layout));
 }
 
 void UiSceneCreator::CreateContentQuad() {
@@ -489,18 +503,28 @@
                                   kBackgroundDistanceMultiplier);
 }
 
+void UiSceneCreator::CreateWebVrSubtree() {
+  CreateSplashScreenForDirectWebVrLaunch();
+  CreateWebVrOverlayElements();
+  CreateWebVrTimeoutScreen();
+
+  // Note, this cannot be a descendant of the viewport aware root, otherwise it
+  // will fade out when the viewport aware elements reposition.
+  auto bg = base::MakeUnique<FullScreenRect>();
+  bg->SetName(kWebVrBackground);
+  bg->SetDrawPhase(kPhaseBackground);
+  bg->SetVisible(false);
+  bg->set_hit_testable(false);
+  bg->SetColor(model_->color_scheme().web_vr_background);
+  bg->SetTransitionedProperties({OPACITY});
+  bg->AddBinding(
+      VR_BIND_FUNC(bool, Model, model_,
+                   web_vr.is_enabled() && !model->web_vr.has_produced_frames(),
+                   FullScreenRect, bg.get(), SetVisible));
+  scene_->AddUiElement(kWebVrRoot, std::move(bg));
+}
+
 void UiSceneCreator::CreateSplashScreenForDirectWebVrLaunch() {
-  auto element = base::MakeUnique<UiElement>();
-  element->SetName(kSplashScreenRoot);
-  element->set_hit_testable(false);
-  scene_->AddUiElement(kRoot, std::move(element));
-
-  // Create viewport aware root.
-  element = base::MakeUnique<ViewportAwareRoot>();
-  element->SetName(kSplashScreenViewportAwareRoot);
-  element->set_hit_testable(false);
-  scene_->AddUiElement(kSplashScreenRoot, std::move(element));
-
   // Create transient parent.
   // TODO(crbug.com/762074): We should timeout after some time and show an
   // error if the user is stuck on the splash screen.
@@ -510,26 +534,23 @@
       base::Bind(
           [](Model* model, UiBrowserInterface* browser,
              TransientElementHideReason reason) {
-            // NOTE: we are setting the model here. May want to post a task or
-            // fire an event object instead of setting it here directly.
-            model->web_vr_show_splash_screen = false;
             if (reason == TransientElementHideReason::kTimeout) {
               browser->ExitPresent();
             }
           },
           base::Unretained(model_), base::Unretained(browser_)));
   transient_parent->SetName(kSplashScreenTransientParent);
-  transient_parent->AddBinding(
-      VR_BIND_FUNC(bool, Model, model_, web_vr_show_splash_screen, UiElement,
-                   transient_parent.get(), SetVisible));
   transient_parent->set_hit_testable(false);
   transient_parent->SetTransitionedProperties({OPACITY});
   transient_parent->AddBinding(VR_BIND_FUNC(
+      bool, Model, model_, web_vr.started_for_autopresentation,
+      ShowUntilSignalTransientElement, transient_parent.get(), SetVisible));
+  transient_parent->AddBinding(VR_BIND_FUNC(
       bool, Model, model_,
-      web_vr_show_splash_screen && model->web_vr_has_produced_frames(),
+      web_vr.started_for_autopresentation &&
+          model->web_vr.state > kWebVrAwaitingFirstFrame,
       ShowUntilSignalTransientElement, transient_parent.get(), Signal));
-  scene_->AddUiElement(kSplashScreenViewportAwareRoot,
-                       std::move(transient_parent));
+  scene_->AddUiElement(kWebVrViewportAwareRoot, std::move(transient_parent));
 
   // Add "Running in Chrome" text.
   auto text_scaler =
@@ -539,83 +560,75 @@
             &Text::SetColor);
   text->SetText(l10n_util::GetStringUTF16(IDS_VR_RUNNING_IN_CHROME_MESSAGE));
   text->SetName(kSplashScreenText);
-  text->SetDrawPhase(kPhaseOverlayForeground);
+  text->SetDrawPhase(kPhaseForeground);
   text->set_hit_testable(false);
   text->SetSize(kSplashScreenTextWidthDMM, 0);
   text->SetTranslate(0, kSplashScreenTextVerticalOffsetDMM, 0);
   text_scaler->AddChild(std::move(text));
   scene_->AddUiElement(kSplashScreenTransientParent, std::move(text_scaler));
-
-  // Add splash screen background.
-  auto bg = base::MakeUnique<FullScreenRect>();
-  bg->SetName(kSplashScreenBackground);
-  bg->SetDrawPhase(kPhaseOverlayBackground);
-  bg->set_hit_testable(false);
-  bg->SetColor(model_->color_scheme().splash_screen_background);
-  scene_->AddUiElement(kSplashScreenText, std::move(bg));
-
-  auto spinner = base::MakeUnique<Spinner>(512);
-  spinner->SetName(kWebVrTimeoutSpinner);
-  spinner->SetDrawPhase(kPhaseOverlayForeground);
-  spinner->SetVisible(false);
-  spinner->SetSize(kSpinnerWidth, kSpinnerHeight);
-  spinner->SetTranslate(0, kSpinnerVerticalOffset, -kSpinnerDistance);
-  spinner->SetColor(model_->color_scheme().spinner_color);
-  spinner->AddBinding(VR_BIND_FUNC(
-      bool, Model, model_, web_vr_timeout_state == kWebVrTimeoutImminent,
-      Spinner, spinner.get(), SetVisible));
-  spinner->SetTransitionedProperties({OPACITY});
-  scene_->AddUiElement(kSplashScreenViewportAwareRoot, std::move(spinner));
-
-  // Note, this cannot be a descendant of the viewport aware root, otherwise it
-  // will fade out when the viewport aware elements reposition.
-  auto spinner_bg = base::MakeUnique<FullScreenRect>();
-  spinner_bg->SetName(kWebVrTimeoutSpinnerBackground);
-  spinner_bg->SetDrawPhase(kPhaseOverlayBackground);
-  spinner_bg->SetVisible(false);
-  spinner_bg->set_hit_testable(false);
-  spinner_bg->SetColor(model_->color_scheme().spinner_background);
-  spinner_bg->SetTransitionedProperties({OPACITY});
-  spinner_bg->SetTransitionDuration(base::TimeDelta::FromMilliseconds(200));
-  spinner_bg->AddBinding(VR_BIND_FUNC(
-      bool, Model, model_, web_vr_timeout_state != kWebVrNoTimeoutPending,
-      FullScreenRect, spinner_bg.get(), SetVisible));
-  scene_->AddUiElement(kSplashScreenRoot, std::move(spinner_bg));
 }
 
 void UiSceneCreator::CreateWebVrTimeoutScreen() {
-  auto scaler = base::MakeUnique<ScaledDepthAdjuster>(kSpinnerDistance);
+  auto scaler = base::MakeUnique<ScaledDepthAdjuster>(kTimeoutScreenDisatance);
+  scaler->SetName(kWebVrTimeoutRoot);
+  scaler->AddBinding(base::MakeUnique<Binding<bool>>(
+      base::BindRepeating(
+          [](Model* model, UiElement* splash_screen) {
+            // The timeout UI should only be visible when the splash screen is
+            // not visible.
+            return (model->web_vr.state == kWebVrTimeoutImminent ||
+                    model->web_vr.state == kWebVrTimedOut) &&
+                   splash_screen->GetTargetOpacity() == 0.f;
+          },
+          base::Unretained(model_),
+          base::Unretained(
+              scene_->GetUiElementByName(kSplashScreenTransientParent))),
+      base::BindRepeating(
+          [](UiElement* e, const bool& value) { e->SetVisible(value); },
+          base::Unretained(scaler.get()))));
 
-  auto timeout_message =
-      Create<Rect>(kWebVrTimeoutMessage, kPhaseOverlayForeground);
+  auto spinner = base::MakeUnique<Spinner>(512);
+  spinner->SetName(kWebVrTimeoutSpinner);
+  spinner->SetDrawPhase(kPhaseForeground);
+  spinner->SetTransitionedProperties({OPACITY});
+  spinner->SetVisible(false);
+  spinner->SetSize(kTimeoutSpinnerSizeDMM, kTimeoutSpinnerSizeDMM);
+  spinner->SetTranslate(0, kTimeoutSpinnerVerticalOffsetDMM, 0);
+  spinner->SetColor(model_->color_scheme().web_vr_timeout_spinner);
+  spinner->AddBinding(VR_BIND_FUNC(bool, Model, model_,
+                                   web_vr.state == kWebVrTimeoutImminent,
+                                   Spinner, spinner.get(), SetVisible));
+
+  auto timeout_message = Create<Rect>(kWebVrTimeoutMessage, kPhaseForeground);
   timeout_message->SetVisible(false);
   timeout_message->set_bounds_contain_children(true);
   timeout_message->set_corner_radius(kTimeoutMessageCornerRadiusDMM);
   timeout_message->SetTransitionedProperties({OPACITY, TRANSFORM});
   timeout_message->set_padding(kTimeoutMessageHorizontalPaddingDMM,
                                kTimeoutMessageVerticalPaddingDMM);
-  timeout_message->AddBinding(
-      VR_BIND_FUNC(bool, Model, model_, web_vr_timeout_state == kWebVrTimedOut,
-                   Rect, timeout_message.get(), SetVisible));
-  timeout_message->SetColor(model_->color_scheme().timeout_message_background);
+  timeout_message->AddBinding(VR_BIND_FUNC(bool, Model, model_,
+                                           web_vr.state == kWebVrTimedOut, Rect,
+                                           timeout_message.get(), SetVisible));
+  timeout_message->SetColor(
+      model_->color_scheme().web_vr_timeout_message_background);
 
   auto timeout_layout = Create<LinearLayout>(kWebVrTimeoutMessageLayout,
                                              kPhaseNone, LinearLayout::kRight);
   timeout_layout->set_hit_testable(false);
   timeout_layout->set_margin(kTimeoutMessageLayoutGapDMM);
 
-  auto timeout_icon = Create<VectorIcon>(kWebVrTimeoutMessageIcon,
-                                         kPhaseOverlayForeground, 512);
+  auto timeout_icon =
+      Create<VectorIcon>(kWebVrTimeoutMessageIcon, kPhaseForeground, 512);
   timeout_icon->SetIcon(kSadTabIcon);
   timeout_icon->SetSize(kTimeoutMessageIconWidthDMM,
                         kTimeoutMessageIconHeightDMM);
 
-  auto timeout_text =
-      Create<Text>(kWebVrTimeoutMessageText, kPhaseOverlayForeground,
-                   kTimeoutMessageTextFontHeightDMM);
+  auto timeout_text = Create<Text>(kWebVrTimeoutMessageText, kPhaseForeground,
+                                   kTimeoutMessageTextFontHeightDMM);
   timeout_text->SetText(
       l10n_util::GetStringUTF16(IDS_VR_WEB_VR_TIMEOUT_MESSAGE));
-  timeout_text->SetColor(model_->color_scheme().timeout_message_foreground);
+  timeout_text->SetColor(
+      model_->color_scheme().web_vr_timeout_message_foreground);
   timeout_text->SetTextAlignment(UiTexture::kTextAlignmentLeft);
   timeout_text->SetSize(kTimeoutMessageTextWidthDMM,
                         kTimeoutMessageTextHeightDMM);
@@ -624,7 +637,7 @@
       base::MakeUnique<ScaledDepthAdjuster>(kTimeoutButtonDepthOffset);
 
   auto button = Create<DiscButton>(
-      kWebVrTimeoutMessageButton, kPhaseOverlayForeground,
+      kWebVrTimeoutMessageButton, kPhaseForeground,
       base::Bind(&UiBrowserInterface::ExitPresent, base::Unretained(browser_)),
       vector_icons::kClose16Icon);
   button->SetVisible(false);
@@ -634,19 +647,19 @@
   button->SetSize(kWebVrTimeoutMessageButtonDiameterDMM,
                   kWebVrTimeoutMessageButtonDiameterDMM);
   button->AddBinding(VR_BIND_FUNC(bool, Model, model_,
-                                  web_vr_timeout_state == kWebVrTimedOut,
-                                  DiscButton, button.get(), SetVisible));
+                                  web_vr.state == kWebVrTimedOut, DiscButton,
+                                  button.get(), SetVisible));
   BindButtonColors(model_, button.get(), &ColorScheme::button_colors,
                    &DiscButton::SetButtonColors);
 
   auto timeout_button_text =
-      Create<Text>(kWebVrTimeoutMessageButtonText, kPhaseOverlayForeground,
+      Create<Text>(kWebVrTimeoutMessageButtonText, kPhaseForeground,
                    kTimeoutMessageTextFontHeightDMM);
 
   // Disk-style button text is not uppercase. See crbug.com/787654.
   timeout_button_text->SetText(
       l10n_util::GetStringUTF16(IDS_VR_WEB_VR_EXIT_BUTTON_LABEL));
-  timeout_button_text->SetColor(model_->color_scheme().spinner_color);
+  timeout_button_text->SetColor(model_->color_scheme().web_vr_timeout_spinner);
   timeout_button_text->SetSize(kTimeoutButtonTextWidthDMM,
                                kTimeoutButtonTextHeightDMM);
   timeout_button_text->set_y_anchoring(BOTTOM);
@@ -659,7 +672,8 @@
   button_scaler->AddChild(std::move(button));
   timeout_message->AddChild(std::move(button_scaler));
   scaler->AddChild(std::move(timeout_message));
-  scene_->AddUiElement(kSplashScreenViewportAwareRoot, std::move(scaler));
+  scaler->AddChild(std::move(spinner));
+  scene_->AddUiElement(kWebVrViewportAwareRoot, std::move(scaler));
 }
 
 void UiSceneCreator::CreateUnderDevelopmentNotice() {
@@ -679,6 +693,29 @@
 }
 
 void UiSceneCreator::CreateBackground() {
+  // Textured background.
+  auto background =
+      Create<Background>(k2dBrowsingTexturedBackground, kPhaseBackground);
+  background->SetVisible(false);
+  background->AddBinding(base::MakeUnique<Binding<bool>>(
+      base::BindRepeating(
+          [](Model* m) {
+            return m->background_available && m->background_loaded;
+          },
+          base::Unretained(model_)),
+      base::BindRepeating([](UiElement* e, const bool& v) { e->SetVisible(v); },
+                          base::Unretained(background.get()))));
+  scene_->AddUiElement(k2dBrowsingBackground, std::move(background));
+
+  auto element = Create<UiElement>(k2dBrowsingDefaultBackground, kPhaseNone);
+  element->set_hit_testable(false);
+  element->AddBinding(base::MakeUnique<Binding<bool>>(
+      base::BindRepeating([](Model* m) { return !m->background_available; },
+                          base::Unretained(model_)),
+      base::BindRepeating([](UiElement* e, const bool& v) { e->SetVisible(v); },
+                          base::Unretained(element.get()))));
+  scene_->AddUiElement(k2dBrowsingBackground, std::move(element));
+
   // Background solid-color panels.
   struct Panel {
     UiElementName name;
@@ -698,9 +735,7 @@
       {kBackgroundBottom, 0, -1, 0, 1, 0, -1},
   };
   for (auto& panel : panels) {
-    auto panel_element = base::MakeUnique<Rect>();
-    panel_element->SetName(panel.name);
-    panel_element->SetDrawPhase(kPhaseBackground);
+    auto panel_element = Create<Rect>(panel.name, kPhaseBackground);
     panel_element->SetSize(kSceneSize, kSceneSize);
     panel_element->SetTranslate(panel.x_offset * kSceneSize / 2,
                                 panel.y_offset * kSceneSize / 2,
@@ -711,15 +746,14 @@
     BindColor(model_, panel_element.get(), &ColorScheme::world_background,
               &Rect::SetColor);
     panel_element->AddBinding(
-        VR_BIND_FUNC(bool, Model, model_, should_render_web_vr() == false,
+        VR_BIND_FUNC(bool, Model, model_, web_vr.is_enabled() == false,
                      UiElement, panel_element.get(), SetVisible));
-    scene_->AddUiElement(k2dBrowsingBackground, std::move(panel_element));
+    scene_->AddUiElement(k2dBrowsingDefaultBackground,
+                         std::move(panel_element));
   }
 
   // Floor.
-  auto floor = base::MakeUnique<Grid>();
-  floor->SetName(kFloor);
-  floor->SetDrawPhase(kPhaseFloorCeiling);
+  auto floor = Create<Grid>(kFloor, kPhaseBackground);
   floor->SetSize(kSceneSize, kSceneSize);
   floor->SetTranslate(0.0, -kSceneHeight / 2, 0.0);
   floor->SetRotate(1, 0, 0, -base::kPiFloat / 2);
@@ -729,13 +763,11 @@
   BindColor(model_, floor.get(), &ColorScheme::world_background,
             &Grid::SetEdgeColor);
   BindColor(model_, floor.get(), &ColorScheme::floor_grid, &Grid::SetGridColor);
-  scene_->AddUiElement(k2dBrowsingBackground, std::move(floor));
+  scene_->AddUiElement(k2dBrowsingDefaultBackground, std::move(floor));
 
   // Ceiling.
-  auto ceiling = base::MakeUnique<Rect>();
+  auto ceiling = Create<Rect>(kCeiling, kPhaseBackground);
   ceiling->set_focusable(false);
-  ceiling->SetName(kCeiling);
-  ceiling->SetDrawPhase(kPhaseFloorCeiling);
   ceiling->SetSize(kSceneSize, kSceneSize);
   ceiling->SetTranslate(0.0, kSceneHeight / 2, 0.0);
   ceiling->SetRotate(1, 0, 0, base::kPiFloat / 2);
@@ -743,9 +775,7 @@
             &Rect::SetCenterColor);
   BindColor(model_, ceiling.get(), &ColorScheme::world_background,
             &Rect::SetEdgeColor);
-  scene_->AddUiElement(k2dBrowsingBackground, std::move(ceiling));
-
-  scene_->set_first_foreground_draw_phase(kPhaseForeground);
+  scene_->AddUiElement(k2dBrowsingDefaultBackground, std::move(ceiling));
 }
 
 void UiSceneCreator::CreateViewportAwareRoot() {
@@ -931,13 +961,13 @@
                    &DiscButton::SetButtonColors);
   scene_->AddUiElement(kSpeechRecognitionListening, std::move(close_button));
 
-  UiElement* browser_foregroud =
-      scene_->GetUiElementByName(k2dBrowsingForeground);
+  UiElement* foreground_control =
+      scene_->GetUiElementByName(k2dBrowsingVisibiltyControlForVoice);
   // k2dBrowsingForeground's visibility binding use the visibility of two
   // other elements which update their bindings after this one. So the
   // visibility of k2dBrowsingForeground will be one frame behind correct value.
   // This is not noticable in practice and simplify our logic a lot.
-  browser_foregroud->AddBinding(base::MakeUnique<Binding<bool>>(
+  foreground_control->AddBinding(base::MakeUnique<Binding<bool>>(
       base::Bind(
           [](UiElement* listening, UiElement* result) {
             return listening->GetTargetOpacity() == 0.f &&
@@ -946,17 +976,17 @@
           base::Unretained(listening_ui_root),
           base::Unretained(speech_result_parent)),
       base::Bind([](UiElement* e, const bool& value) { e->SetVisible(value); },
-                 base::Unretained(browser_foregroud))));
+                 base::Unretained(foreground_control))));
 }
 
 void UiSceneCreator::CreateController() {
   auto root = base::MakeUnique<UiElement>();
   root->SetName(kControllerRoot);
   root->set_hit_testable(false);
-  root->AddBinding(VR_BIND_FUNC(
-      bool, Model, model_,
-      browsing_mode() || model->web_vr_timeout_state == kWebVrTimedOut,
-      UiElement, root.get(), SetVisible));
+  root->AddBinding(
+      VR_BIND_FUNC(bool, Model, model_,
+                   browsing_mode() || model->web_vr.state == kWebVrTimedOut,
+                   UiElement, root.get(), SetVisible));
   scene_->AddUiElement(kRoot, std::move(root));
 
   auto group = base::MakeUnique<UiElement>();
@@ -1187,11 +1217,11 @@
       base::BindRepeating(
           [](Rect* r, const bool& v) {
             if (v) {
-              r->set_corner_radii(
+              r->SetCornerRadii(
                   {kOmniboxCornerRadiusDMM, kOmniboxCornerRadiusDMM,
                    kOmniboxCornerRadiusDMM, kOmniboxCornerRadiusDMM});
             } else {
-              r->set_corner_radii(
+              r->SetCornerRadii(
                   {0, 0, kOmniboxCornerRadiusDMM, kOmniboxCornerRadiusDMM});
             }
           },
@@ -1296,7 +1326,7 @@
                    &DiscButton::SetButtonColors);
 
   auto spacer = CreateOmniboxSpacer(model_);
-  spacer->set_corner_radii(
+  spacer->SetCornerRadii(
       {kOmniboxCornerRadiusDMM, kOmniboxCornerRadiusDMM, 0, 0});
   suggestions_outer_layout->AddChild(std::move(spacer));
   suggestions_outer_layout->AddChild(std::move(suggestions_layout));
@@ -1319,39 +1349,6 @@
   scene_->AddUiElement(k2dBrowsingRoot, std::move(scaler));
 }
 
-void UiSceneCreator::CreateWebVrUrlToast() {
-  auto* parent =
-      AddTransientParent(kWebVrUrlToastTransientParent, kWebVrViewportAwareRoot,
-                         kWebVrUrlToastTimeoutSeconds, true, scene_);
-  parent->AddBinding(VR_BIND_FUNC(bool, Model, model_,
-                                  web_vr_started_for_autopresentation &&
-                                      !model->web_vr_show_splash_screen &&
-                                      model->web_vr_has_produced_frames(),
-                                  UiElement, parent, SetVisible));
-
-  auto element = base::MakeUnique<WebVrUrlToast>(
-      512, base::Bind(&UiBrowserInterface::OnUnsupportedMode,
-                      base::Unretained(browser_)));
-  element->SetName(kWebVrUrlToast);
-  element->set_opacity_when_visible(0.8f);
-  element->SetDrawPhase(kPhaseOverlayForeground);
-  element->set_hit_testable(false);
-  element->SetTranslate(0, kWebVrToastDistance * sin(kWebVrUrlToastRotationRad),
-                        -kWebVrToastDistance * cos(kWebVrUrlToastRotationRad));
-  element->SetRotate(1, 0, 0, kWebVrUrlToastRotationRad);
-  element->SetSize(kWebVrUrlToastWidth, kWebVrUrlToastHeight);
-  BindColor(model_, element.get(),
-            &ColorScheme::web_vr_transient_toast_background,
-            &TexturedElement::SetBackgroundColor);
-  BindColor(model_, element.get(),
-            &ColorScheme::web_vr_transient_toast_foreground,
-            &TexturedElement::SetForegroundColor);
-  element->AddBinding(VR_BIND_FUNC(ToolbarState, Model, model_, toolbar_state,
-                                   WebVrUrlToast, element.get(),
-                                   SetToolbarState));
-  scene_->AddUiElement(kWebVrUrlToastTransientParent, std::move(element));
-}
-
 void UiSceneCreator::CreateCloseButton() {
   base::Callback<void()> click_handler = base::Bind(
       [](Model* model, UiBrowserInterface* browser) {
@@ -1399,8 +1396,8 @@
   // Place an invisible but hittable plane behind the exit prompt, to keep the
   // reticle roughly planar with the content if near content.
   auto backplane = base::MakeUnique<InvisibleHitTarget>();
-  backplane->SetName(kExitPromptBackplane);
   backplane->SetDrawPhase(kPhaseForeground);
+  backplane->SetName(kExitPromptBackplane);
   backplane->SetSize(kPromptBackplaneSize, kPromptBackplaneSize);
   backplane->SetTranslate(0.0,
                           kContentVerticalOffset + kExitPromptVerticalOffset,
@@ -1523,8 +1520,91 @@
   scene_->AddUiElement(k2dBrowsingRoot, std::move(backplane));
 }
 
-void UiSceneCreator::CreateToasts() {
-  // Create fullscreen toast.
+void UiSceneCreator::CreateWebVrOverlayElements() {
+  // Create url toast shown when WebVR is auto-presented.
+  auto* parent =
+      AddTransientParent(kWebVrUrlToastTransientParent, kWebVrViewportAwareRoot,
+                         kWebVrUrlToastTimeoutSeconds, true, scene_);
+  parent->AddBinding(base::MakeUnique<Binding<bool>>(
+      base::BindRepeating(
+          [](Model* model, UiElement* splash_screen) {
+            // The url toast should only be visible when the splash screen is
+            // not visible.
+            return model->web_vr.started_for_autopresentation &&
+                   model->web_vr.has_produced_frames() &&
+                   splash_screen->GetTargetOpacity() == 0.f;
+          },
+          base::Unretained(model_),
+          base::Unretained(
+              scene_->GetUiElementByName(kSplashScreenTransientParent))),
+      base::BindRepeating(
+          [](UiElement* e, const bool& value) { e->SetVisible(value); },
+          base::Unretained(parent))));
+
+  auto url_toast = base::MakeUnique<WebVrUrlToast>(
+      512, base::BindRepeating(&UiBrowserInterface::OnUnsupportedMode,
+                               base::Unretained(browser_)));
+  url_toast->SetName(kWebVrUrlToast);
+  url_toast->set_opacity_when_visible(kWebVrUrlToastOpacity);
+  url_toast->SetDrawPhase(kPhaseOverlayForeground);
+  url_toast->set_hit_testable(false);
+  url_toast->SetTranslate(
+      0, kWebVrToastDistance * sin(kWebVrUrlToastRotationRad),
+      -kWebVrToastDistance * cos(kWebVrUrlToastRotationRad));
+  url_toast->SetRotate(1, 0, 0, kWebVrUrlToastRotationRad);
+  url_toast->SetSize(kWebVrUrlToastWidth, kWebVrUrlToastHeight);
+  BindColor(model_, url_toast.get(),
+            &ColorScheme::web_vr_transient_toast_background,
+            &TexturedElement::SetBackgroundColor);
+  BindColor(model_, url_toast.get(),
+            &ColorScheme::web_vr_transient_toast_foreground,
+            &TexturedElement::SetForegroundColor);
+  url_toast->AddBinding(VR_BIND_FUNC(ToolbarState, Model, model_, toolbar_state,
+                                     WebVrUrlToast, url_toast.get(),
+                                     SetToolbarState));
+  scene_->AddUiElement(kWebVrUrlToastTransientParent, std::move(url_toast));
+
+  // Create "Press app button to exit" toast.
+  parent = AddTransientParent(kExclusiveScreenToastViewportAwareTransientParent,
+                              kWebVrViewportAwareRoot, kToastTimeoutSeconds,
+                              false, scene_);
+  // When we first get a web vr frame, we switch states to
+  // kWebVrNoTimeoutPending, when that happens, we want to SetVisible(true) to
+  // kick the visibility of this element.
+  parent->AddBinding(VR_BIND_FUNC(
+      bool, Model, model_,
+      web_vr.has_produced_frames() && model->web_vr.show_exit_toast, UiElement,
+      parent, SetVisible));
+
+  auto scaler = base::MakeUnique<ScaledDepthAdjuster>(kWebVrToastDistance);
+
+  auto exit_toast = base::MakeUnique<Toast>();
+  exit_toast->SetName(kExclusiveScreenToastViewportAware);
+  exit_toast->SetDrawPhase(kPhaseOverlayForeground);
+  exit_toast->set_hit_testable(false);
+  exit_toast->SetTranslate(0, sin(kWebVrAngleRadians),
+                           1.0 - cos(kWebVrAngleRadians));
+  exit_toast->SetRotate(1, 0, 0, kWebVrAngleRadians);
+  exit_toast->set_padding(kExclusiveScreenToastXPaddingDMM,
+                          kExclusiveScreenToastYPaddingDMM);
+  exit_toast->set_corner_radius(kExclusiveScreenToastCornerRadiusDMM);
+  exit_toast->AddText(l10n_util::GetStringUTF16(IDS_PRESS_APP_TO_EXIT),
+                      kExclusiveScreenToastTextFontHeightDMM,
+                      TextLayoutMode::kSingleLineFixedHeight);
+
+  BindColor(model_, exit_toast.get(),
+            &ColorScheme::exclusive_screen_toast_background,
+            &Toast::SetBackgroundColor);
+  BindColor(model_, exit_toast.get(),
+            &ColorScheme::exclusive_screen_toast_foreground,
+            &Toast::SetForegroundColor);
+
+  scaler->AddChild(std::move(exit_toast));
+  scene_->AddUiElement(kExclusiveScreenToastViewportAwareTransientParent,
+                       std::move(scaler));
+}
+
+void UiSceneCreator::CreateFullscreenToast() {
   auto* parent = AddTransientParent(kExclusiveScreenToastTransientParent,
                                     k2dBrowsingForeground, kToastTimeoutSeconds,
                                     false, scene_);
@@ -1532,58 +1612,32 @@
   // changed and makes sure fullscreen toast becomes invisible if entering
   // webvr mode.
   parent->AddBinding(VR_BIND_FUNC(bool, Model, model_,
-                                  fullscreen && !model->web_vr_mode, UiElement,
-                                  parent, SetVisible));
+                                  fullscreen && !model->web_vr.is_enabled(),
+                                  UiElement, parent, SetVisible));
 
-  auto element = base::MakeUnique<ExclusiveScreenToast>(512);
+  auto scaler = base::MakeUnique<ScaledDepthAdjuster>(kFullscreenToastDistance);
+
+  auto element = base::MakeUnique<Toast>();
   element->SetName(kExclusiveScreenToast);
   element->SetDrawPhase(kPhaseForeground);
-  element->SetSize(kToastWidthDMM, kToastHeightDMM);
-  element->SetTranslate(
-      0,
-      kFullscreenVerticalOffset + kFullscreenHeight / 2 +
-          (kToastOffsetDMM + kToastHeightDMM) * kFullscreenToastDistance,
-      -kFullscreenToastDistance);
-  element->SetScale(kFullscreenToastDistance, kFullscreenToastDistance, 1);
   element->set_hit_testable(false);
+  element->SetTranslate(0, kFullScreenToastOffsetDMM, 0);
+  element->set_padding(kExclusiveScreenToastXPaddingDMM,
+                       kExclusiveScreenToastYPaddingDMM);
+  element->set_corner_radius(kExclusiveScreenToastCornerRadiusDMM);
+  element->AddText(l10n_util::GetStringUTF16(IDS_PRESS_APP_TO_EXIT),
+                   kExclusiveScreenToastTextFontHeightDMM,
+                   TextLayoutMode::kSingleLineFixedHeight);
+
   BindColor(model_, element.get(),
             &ColorScheme::exclusive_screen_toast_background,
-            &TexturedElement::SetBackgroundColor);
+            &Toast::SetBackgroundColor);
   BindColor(model_, element.get(),
             &ColorScheme::exclusive_screen_toast_foreground,
-            &TexturedElement::SetForegroundColor);
-  scene_->AddUiElement(kExclusiveScreenToastTransientParent,
-                       std::move(element));
+            &Toast::SetForegroundColor);
 
-  // Create WebVR toast.
-  parent = AddTransientParent(kExclusiveScreenToastViewportAwareTransientParent,
-                              kWebVrViewportAwareRoot, kToastTimeoutSeconds,
-                              false, scene_);
-  // When we first get a web vr frame, we switch states to
-  // kWebVrNoTimeoutPending, when that happens, we want to SetVisible(true) to
-  // kick the visibility of this element.
-  parent->AddBinding(
-      VR_BIND_FUNC(bool, Model, model_,
-                   web_vr_has_produced_frames() && model->web_vr_show_toast,
-                   UiElement, parent, SetVisible));
-
-  element = base::MakeUnique<ExclusiveScreenToast>(512);
-  element->SetName(kExclusiveScreenToastViewportAware);
-  element->SetDrawPhase(kPhaseOverlayForeground);
-  element->SetSize(kToastWidthDMM, kToastHeightDMM);
-  element->SetTranslate(0, kWebVrToastDistance * sin(kWebVrAngleRadians),
-                        -kWebVrToastDistance * cos(kWebVrAngleRadians));
-  element->SetRotate(1, 0, 0, kWebVrAngleRadians);
-  element->SetScale(kWebVrToastDistance, kWebVrToastDistance, 1);
-  element->set_hit_testable(false);
-  BindColor(model_, element.get(),
-            &ColorScheme::exclusive_screen_toast_background,
-            &TexturedElement::SetBackgroundColor);
-  BindColor(model_, element.get(),
-            &ColorScheme::exclusive_screen_toast_foreground,
-            &TexturedElement::SetForegroundColor);
-  scene_->AddUiElement(kExclusiveScreenToastViewportAwareTransientParent,
-                       std::move(element));
+  scaler->AddChild(std::move(element));
+  scene_->AddUiElement(kExclusiveScreenToastTransientParent, std::move(scaler));
 }
 
 }  // namespace vr
diff --git a/chrome/browser/vr/ui_scene_creator.h b/chrome/browser/vr/ui_scene_creator.h
index 2ad517e..c493484 100644
--- a/chrome/browser/vr/ui_scene_creator.h
+++ b/chrome/browser/vr/ui_scene_creator.h
@@ -39,22 +39,23 @@
  private:
   void Create2dBrowsingSubtreeRoots();
   void CreateWebVrRoot();
-  void CreateWebVRExitWarning();
   void CreateSystemIndicators();
   void CreateContentQuad();
-  void CreateSplashScreenForDirectWebVrLaunch();
-  void CreateWebVrTimeoutScreen();
   void CreateUnderDevelopmentNotice();
   void CreateBackground();
   void CreateViewportAwareRoot();
   void CreateUrlBar();
   void CreateOmnibox();
-  void CreateWebVrUrlToast();
   void CreateCloseButton();
   void CreateExitPrompt();
   void CreateAudioPermissionPrompt();
-  void CreateToasts();
+  void CreateFullscreenToast();
   void CreateVoiceSearchUiGroup();
+  void CreateExitWarning();
+  void CreateWebVrSubtree();
+  void CreateWebVrOverlayElements();
+  void CreateSplashScreenForDirectWebVrLaunch();
+  void CreateWebVrTimeoutScreen();
   void CreateController();
   void CreateKeyboard();
 
diff --git a/chrome/browser/vr/ui_scene_unittest.cc b/chrome/browser/vr/ui_scene_unittest.cc
index adba8c8..5a66d25 100644
--- a/chrome/browser/vr/ui_scene_unittest.cc
+++ b/chrome/browser/vr/ui_scene_unittest.cc
@@ -164,10 +164,10 @@
   element->SetDrawPhase(kPhaseOverlayForeground);
   child->AddChild(std::move(element));
 
-  EXPECT_FALSE(scene.GetVisibleWebVrOverlayForegroundElements().empty());
+  EXPECT_FALSE(scene.GetVisibleWebVrOverlayElementsToDraw().empty());
   child->SetVisible(false);
   scene.OnBeginFrame(MsToTicks(0), kForwardVector);
-  EXPECT_TRUE(scene.GetVisibleWebVrOverlayForegroundElements().empty());
+  EXPECT_TRUE(scene.GetVisibleWebVrOverlayElementsToDraw().empty());
 }
 
 TEST(UiScene, InvisibleElementsDoNotCauseAnimationDirtiness) {
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc
index 16a6839..3295d78 100644
--- a/chrome/browser/vr/ui_unittest.cc
+++ b/chrome/browser/vr/ui_unittest.cc
@@ -81,84 +81,6 @@
 };
 const std::set<UiElementName> kElementsVisibleWithExitWarning = {
     kScreenDimmer, kExitWarningBackground, kExitWarningText};
-const std::vector<std::string> kElementsInDrawOrder = {
-    "kBackgroundFront",
-    "kBackgroundLeft",
-    "kBackgroundBack",
-    "kBackgroundRight",
-    "kBackgroundTop",
-    "kBackgroundBottom",
-    "kScreenDimmer",
-    "kSplashScreenBackground",
-    "kWebVrTimeoutSpinnerBackground",
-    "kFloor",
-    "kCeiling",
-    "kBackplane",
-    "kContentQuad",
-    "kAudioCaptureIndicator",
-    "kVideoCaptureIndicator",
-    "kScreenCaptureIndicator",
-    "kBluetoothConnectedIndicator",
-    "kLocationAccessIndicator",
-    "kUrlBar",
-    "kLoadingIndicator",
-    "kLoadingIndicatorForeground",
-    "kUnderDevelopmentNotice",
-    "kVoiceSearchButton",
-    "kVoiceSearchButton:kTypeButtonBackground",
-    "kVoiceSearchButton:kTypeButtonForeground",
-    "kVoiceSearchButton:kTypeButtonHitTarget",
-    "kCloseButton",
-    "kCloseButton:kTypeButtonBackground",
-    "kCloseButton:kTypeButtonForeground",
-    "kCloseButton:kTypeButtonHitTarget",
-    "kExclusiveScreenToast",
-    "kExitPromptBackplane",
-    "kExitPrompt",
-    "kAudioPermissionPromptBackplane",
-    "kAudioPermissionPromptShadow",
-    "kAudioPermissionPrompt",
-    "kOmniboxShadow",
-    "kOmniboxContainer",
-    "kOmniboxTextField:kTypeTextInputHint",
-    "kOmniboxTextField:kTypeTextInputText",
-    "kOmniboxTextField:kTypeTextInputCursor",
-    "kNone:kTypeOmniboxSuggestionSpacer",
-    "kNone:kTypeOmniboxSuggestionSpacer",
-    "kOmniboxCloseButton",
-    "kOmniboxCloseButton:kTypeButtonBackground",
-    "kOmniboxCloseButton:kTypeButtonForeground",
-    "kOmniboxCloseButton:kTypeButtonHitTarget",
-    "kSpeechRecognitionResultText",
-    "kSpeechRecognitionResultCircle",
-    "kSpeechRecognitionResultMicrophoneIcon",
-    "kSpeechRecognitionResultBackplane",
-    "kSpeechRecognitionListeningGrowingCircle",
-    "kSpeechRecognitionListeningInnerCircle",
-    "kSpeechRecognitionListeningMicrophoneIcon",
-    "kSpeechRecognitionListeningCloseButton",
-    "kSpeechRecognitionListeningCloseButton:kTypeButtonBackground",
-    "kSpeechRecognitionListeningCloseButton:kTypeButtonForeground",
-    "kSpeechRecognitionListeningCloseButton:kTypeButtonHitTarget",
-    "kController",
-    "kLaser",
-    "kReticle",
-    "kKeyboard",
-    "kExitWarningBackground",
-    "kExitWarningText",
-    "kWebVrUrlToast",
-    "kExclusiveScreenToastViewportAware",
-    "kSplashScreenText",
-    "kWebVrTimeoutSpinner",
-    "kWebVrTimeoutMessage",
-    "kWebVrTimeoutMessageIcon",
-    "kWebVrTimeoutMessageText",
-    "kWebVrTimeoutMessageButton",
-    "kWebVrTimeoutMessageButton:kTypeButtonBackground",
-    "kWebVrTimeoutMessageButton:kTypeButtonForeground",
-    "kWebVrTimeoutMessageButton:kTypeButtonHitTarget",
-    "kWebVrTimeoutMessageButtonText",
-};
 
 static constexpr float kTolerance = 1e-5f;
 static constexpr float kSmallDelaySeconds = 0.1f;
@@ -344,8 +266,7 @@
   CreateSceneForAutoPresentation();
 
   // Initially, we should only show the splash screen.
-  VerifyOnlyElementsVisible("Initial",
-                            {kSplashScreenText, kSplashScreenBackground});
+  VerifyOnlyElementsVisible("Initial", {kSplashScreenText, kWebVrBackground});
 
   // Enter WebVR with autopresentation.
   ui_->SetWebVrMode(true, false);
@@ -371,15 +292,16 @@
   CreateSceneForAutoPresentation();
 
   // Initially, we should only show the splash screen.
-  VerifyOnlyElementsVisible("Initial",
-                            {kSplashScreenText, kSplashScreenBackground});
+  VerifyOnlyElementsVisible("Initial", {kSplashScreenText, kWebVrBackground});
 
   ui_->SetWebVrMode(true, false);
   ui_->OnWebVrTimeoutImminent();
 
-  VerifyOnlyElementsVisible(
-      "Timeout imminent",
-      {kWebVrTimeoutSpinner, kWebVrTimeoutSpinnerBackground});
+  EXPECT_TRUE(RunFor(MsToDelta(
+      1000 * (kSplashScreenMinDurationSeconds + kSmallDelaySeconds * 2))));
+
+  VerifyOnlyElementsVisible("Timeout imminent",
+                            {kWebVrTimeoutSpinner, kWebVrBackground});
 }
 
 TEST_F(UiTest, AppButtonClickForAutopresentation) {
@@ -559,16 +481,25 @@
   model_->permissions.location_access = true;
   model_->permissions.bluetooth_connected = true;
 
-  auto* web_vr_root = scene_->GetUiElementByName(kWebVrRoot);
-  for (auto& element : *web_vr_root) {
-    SCOPED_TRACE(element.name());
-    EXPECT_TRUE(element.draw_phase() == kPhaseNone ||
-                element.draw_phase() == kPhaseOverlayBackground ||
-                element.draw_phase() == kPhaseOverlayForeground);
-  }
+  VerifyOnlyElementsVisible("Elements hidden",
+                            std::set<UiElementName>{kWebVrBackground});
+}
 
-  // All elements should be hidden.
+// This test verifies that we ignore the WebVR frame when we're not expecting
+// WebVR presentation. You can get an unexpected frame when for example, the
+// user hits the app button to exit WebVR mode, but the site continues to pump
+// frames. If the frame is not ignored, our UI will think we're in WebVR mode.
+TEST_F(UiTest, WebVrFramesIgnoredWhenUnexpected) {
+  CreateScene(kNotInCct, kInWebVr);
+
+  ui_->OnWebVrFrameAvailable();
   VerifyOnlyElementsVisible("Elements hidden", std::set<UiElementName>{});
+  // Disable WebVR mode.
+  ui_->SetWebVrMode(false, false);
+
+  // New frame available after exiting WebVR mode.
+  ui_->OnWebVrFrameAvailable();
+  VerifyOnlyElementsVisible("Browser visible", kElementsVisibleInBrowsing);
 }
 
 TEST_F(UiTest, UiUpdateTransitionToWebVR) {
@@ -726,7 +657,7 @@
   CreateScene(kNotInCct, kInWebVr);
 
   ui_->SetWebVrMode(true, false);
-  model_->web_vr_timeout_state = kWebVrAwaitingFirstFrame;
+  model_->web_vr.state = kWebVrAwaitingFirstFrame;
 
   RunFor(MsToDelta(500));
   VerifyVisibility(
@@ -739,11 +670,11 @@
       false);
   VerifyVisibility(
       {
-          kWebVrTimeoutSpinnerBackground,
+          kWebVrBackground,
       },
       true);
 
-  model_->web_vr_timeout_state = kWebVrTimeoutImminent;
+  model_->web_vr.state = kWebVrTimeoutImminent;
   RunFor(MsToDelta(500));
   VerifyVisibility(
       {
@@ -754,11 +685,11 @@
       false);
   VerifyVisibility(
       {
-          kWebVrTimeoutSpinner, kWebVrTimeoutSpinnerBackground,
+          kWebVrTimeoutSpinner, kWebVrBackground,
       },
       true);
 
-  model_->web_vr_timeout_state = kWebVrTimedOut;
+  model_->web_vr.state = kWebVrTimedOut;
   RunFor(MsToDelta(500));
   VerifyVisibility(
       {
@@ -767,10 +698,9 @@
       false);
   VerifyVisibility(
       {
-          kWebVrTimeoutSpinnerBackground, kWebVrTimeoutMessage,
-          kWebVrTimeoutMessageLayout, kWebVrTimeoutMessageIcon,
-          kWebVrTimeoutMessageText, kWebVrTimeoutMessageButton,
-          kWebVrTimeoutMessageButtonText,
+          kWebVrBackground, kWebVrTimeoutMessage, kWebVrTimeoutMessageLayout,
+          kWebVrTimeoutMessageIcon, kWebVrTimeoutMessageText,
+          kWebVrTimeoutMessageButton, kWebVrTimeoutMessageButtonText,
       },
       true);
 }
@@ -1002,19 +932,6 @@
   ui_->OnAppButtonClicked();
 }
 
-// This test ensures that the render order matches the expected tree state. All
-// phases are merged, as the order is the same. Unnamed and unrenderable
-// elements are skipped.
-TEST_F(UiTest, UiRendererSortingTest) {
-  CreateScene(kNotInCct, kNotInWebVr);
-  auto unsorted = scene_->GetPotentiallyVisibleElements();
-  auto sorted = UiRenderer::GetElementsInDrawOrder(unsorted);
-  EXPECT_EQ(kElementsInDrawOrder.size(), sorted.size());
-  for (size_t i = 0; i < sorted.size(); ++i) {
-    ASSERT_EQ(kElementsInDrawOrder[i], sorted[i]->DebugName());
-  }
-}
-
 // Tests that transient elements will show, even if there is a long delay
 // between when they are asked to appear and when we issue the first frame with
 // them visible.
@@ -1022,9 +939,7 @@
   CreateSceneForAutoPresentation();
 
   // Initially, we should only show the splash screen.
-  VerifyOnlyElementsVisible("Initial",
-                            {kSplashScreenText, kSplashScreenBackground});
-
+  VerifyOnlyElementsVisible("Initial", {kSplashScreenText, kWebVrBackground});
   // Enter WebVR with autopresentation.
   ui_->SetWebVrMode(true, false);
   EXPECT_TRUE(RunFor(MsToDelta(2000)));
@@ -1041,4 +956,31 @@
   VerifyOnlyElementsVisible("Autopresented", {kWebVrUrlToast});
 }
 
+TEST_F(UiTest, DefaultBackgroundWhenNoAssetAvailable) {
+  UiInitialState state;
+  state.assets_available = false;
+  CreateScene(state);
+
+  EXPECT_FALSE(IsVisible(k2dBrowsingTexturedBackground));
+  EXPECT_TRUE(IsVisible(k2dBrowsingDefaultBackground));
+  EXPECT_TRUE(IsVisible(kContentQuad));
+}
+
+TEST_F(UiTest, TextureBackgroundAfterAssetLoaded) {
+  UiInitialState state;
+  state.assets_available = true;
+  CreateScene(state);
+
+  EXPECT_FALSE(IsVisible(k2dBrowsingTexturedBackground));
+  EXPECT_FALSE(IsVisible(k2dBrowsingDefaultBackground));
+  EXPECT_FALSE(IsVisible(kContentQuad));
+
+  auto bitmap = base::MakeUnique<SkBitmap>();
+  ui_->SetBackgroundImage(std::move(bitmap));
+
+  EXPECT_TRUE(IsVisible(k2dBrowsingTexturedBackground));
+  EXPECT_TRUE(IsVisible(kContentQuad));
+  EXPECT_FALSE(IsVisible(k2dBrowsingDefaultBackground));
+}
+
 }  // namespace vr
diff --git a/chrome/browser/vr/webvr_tab_browser_test.cc b/chrome/browser/vr/webvr_tab_browser_test.cc
new file mode 100644
index 0000000..8b0e261
--- /dev/null
+++ b/chrome/browser/vr/webvr_tab_browser_test.cc
@@ -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 "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/vr/test/vr_browser_test.h"
+#include "chrome/browser/vr/test/vr_transition_utils.h"
+#include "url/gurl.h"
+#include "url/url_constants.h"
+
+// Browser test equivalent of
+// chrome/android/javatests/src/.../browser/vr_shell/WebVrTabTest.java.
+// End-to-end tests for testing WebVR's interaction with multiple tabss.
+
+namespace vr {
+
+// Tests that non-focused tabs cannot get pose information
+IN_PROC_BROWSER_TEST_F(VrBrowserTest, REQUIRES_GPU(TestPoseDataUnfocusedTab)) {
+  LoadUrlAndAwaitInitialization(
+      GetHtmlTestFile("test_pose_data_unfocused_tab"));
+  ExecuteStepAndWait("stepCheckFrameDataWhileFocusedTab()",
+                     GetFirstTabWebContents());
+  chrome::AddTabAt(browser(), GURL(url::kAboutBlankURL),
+                   -1 /* index, append to end */, true /* foreground */);
+  ExecuteStepAndWait("stepCheckFrameDataWhileNonFocusedTab()",
+                     GetFirstTabWebContents());
+  EndTest(GetFirstTabWebContents());
+}
+
+}  // namespace vr
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index 4a20b35..e9ba9bf 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -49,6 +49,7 @@
 #include "gpu/config/gpu_info.h"
 #include "gpu/config/gpu_util.h"
 #include "media/base/media_switches.h"
+#include "media/base/video_codecs.h"
 #include "media/media_features.h"
 #include "net/http/http_util.h"
 #include "pdf/features.h"
@@ -129,7 +130,7 @@
 #if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)
 bool IsWidevineAvailable(base::FilePath* adapter_path,
                          base::FilePath* cdm_path,
-                         std::vector<std::string>* codecs_supported,
+                         std::vector<media::VideoCodec>* codecs_supported,
                          bool* supports_persistent_license) {
   static enum {
     NOT_CHECKED,
@@ -150,10 +151,10 @@
     if (widevine_cdm_file_check == FOUND) {
       // Add the supported codecs as if they came from the component manifest.
       // This list must match the CDM that is being bundled with Chrome.
-      codecs_supported->push_back(kCdmSupportedCodecVp8);
-      codecs_supported->push_back(kCdmSupportedCodecVp9);
+      codecs_supported->push_back(media::VideoCodec::kCodecVP8);
+      codecs_supported->push_back(media::VideoCodec::kCodecVP9);
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
-      codecs_supported->push_back(kCdmSupportedCodecAvc1);
+      codecs_supported->push_back(media::VideoCodec::kCodecH264);
 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
 
 // TODO(crbug.com/767941): Push persistent-license support info here once
@@ -229,9 +230,9 @@
 #if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)
   base::FilePath adapter_path;
   base::FilePath cdm_path;
-  std::vector<std::string> codecs_supported;
+  std::vector<media::VideoCodec> video_codecs_supported;
   bool supports_persistent_license;
-  if (IsWidevineAvailable(&adapter_path, &cdm_path, &codecs_supported,
+  if (IsWidevineAvailable(&adapter_path, &cdm_path, &video_codecs_supported,
                           &supports_persistent_license)) {
     content::PepperPluginInfo info;
     info.is_out_of_process = true;
@@ -248,6 +249,17 @@
                                          kWidevineCdmPluginMimeTypeDescription);
 
     // Put codec support string in additional param.
+    std::vector<std::string> codecs_supported;
+    for (const auto& codec : video_codecs_supported) {
+      if (codec == media::VideoCodec::kCodecVP8)
+        codecs_supported.push_back(kCdmSupportedCodecVp8);
+      else if (codec == media::VideoCodec::kCodecVP9)
+        codecs_supported.push_back(kCdmSupportedCodecVp9);
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+      else if (codec == media::VideoCodec::kCodecH264)
+        codecs_supported.push_back(kCdmSupportedCodecAvc1);
+#endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
+    }
     mime_type.additional_params.emplace_back(
         base::ASCIIToUTF16(kCdmSupportedCodecsParamName),
         base::ASCIIToUTF16(base::JoinString(
@@ -573,18 +585,19 @@
 #if defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)
     base::FilePath adapter_path;
     base::FilePath cdm_path;
-    std::vector<std::string> codecs_supported;
+    std::vector<media::VideoCodec> video_codecs_supported;
     bool supports_persistent_license;
-    if (IsWidevineAvailable(&adapter_path, &cdm_path, &codecs_supported,
+    if (IsWidevineAvailable(&adapter_path, &cdm_path, &video_codecs_supported,
                             &supports_persistent_license)) {
       // CdmInfo needs |path| to be the actual Widevine library,
       // not the adapter, so adjust as necessary. It will be in the
       // same directory as the installed adapter.
       const base::Version version(WIDEVINE_CDM_VERSION_STRING);
       DCHECK(version.IsValid());
+
       cdms->push_back(content::CdmInfo(
           kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_path,
-          kWidevineCdmFileSystemId, codecs_supported,
+          kWidevineCdmFileSystemId, video_codecs_supported,
           supports_persistent_license, kWidevineKeySystem, false));
     }
 #endif  // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)
diff --git a/chrome/common/extensions/api/automation.idl b/chrome/common/extensions/api/automation.idl
index 51ed85f..f1316aab4 100644
--- a/chrome/common/extensions/api/automation.idl
+++ b/chrome/common/extensions/api/automation.idl
@@ -712,8 +712,10 @@
     AutomationNode? lastChild;
     AutomationNode? previousSibling;
     AutomationNode? nextSibling;
-    AutomationNode? nextOnLine;
     AutomationNode? previousOnLine;
+    AutomationNode? nextOnLine;
+    AutomationNode? previousFocus;
+    AutomationNode? nextFocus;
 
     // The index of this node in its parent node's list of children. If this is
     // the root node, this will be undefined.
diff --git a/chrome/common/profiling/profiling_service.mojom b/chrome/common/profiling/profiling_service.mojom
index 93ed8c6..0d38f3b 100644
--- a/chrome/common/profiling/profiling_service.mojom
+++ b/chrome/common/profiling/profiling_service.mojom
@@ -44,8 +44,14 @@
   // Dumps the memory log of all profiled processes into shared buffers. The
   // contents of each shared buffer is a JSON string compatible with
   // TRACE_EVENT* macros. Processes that fail to dump will be omitted from
-  // |buffers|.
-  DumpProcessesForTracing(bool keep_small_allocations) =>
+  // |buffers|. When |strip_path_from_mapped_files| is true, only the base name
+  // of mapped files is emitted. This prevents usernames from sneaking into the
+  // trace.
+  // |strip_path_from_mapped_files| should only be true for traces that will be
+  // uploaded to the crash servers - this strips potential PII, but prevents
+  // symbolization of local builds.
+  DumpProcessesForTracing(bool keep_small_allocations,
+                          bool strip_path_from_mapped_files) =>
       (array<SharedBufferWithSize> buffers);
 
   // Returns the pids of all profiled processes.
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 6c89fdf..e83c0d34 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -285,7 +285,10 @@
 #else
 const char kCreateProfileSubPage[] = "createProfile";
 const char kManageProfileSubPage[] = "manageProfile";
-#endif
+#endif  // defined(OS_CHROMEOS)
+#if defined(OS_WIN)
+const char kCleanupSubPage[] = "cleanup";
+#endif  // defined(OS_WIN)
 
 // Extension sub pages.
 const char kExtensionConfigureCommandsSubPage[] = "configureCommands";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 647a98a..fad9a860 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -276,6 +276,9 @@
 extern const char kPowerSubPage[];
 extern const char kStylusSubPage[];
 #endif
+#if defined(OS_WIN)
+extern const char kCleanupSubPage[];
+#endif
 
 // Extensions sub pages.
 extern const char kExtensionConfigureCommandsSubPage[];
diff --git a/chrome/installer/linux/debian/dist_package_versions.json b/chrome/installer/linux/debian/dist_package_versions.json
index 9ece0e76..6266402f 100644
--- a/chrome/installer/linux/debian/dist_package_versions.json
+++ b/chrome/installer/linux/debian/dist_package_versions.json
@@ -8,7 +8,6 @@
         "libcups2": "2.2.6-2",
         "libdbus-1-3": "1.12.2-1",
         "libexpat1": "2.2.3-2",
-        "libfontconfig1": "2.12.6-0.1",
         "libgcc1": "1:7.2.0-17",
         "libgdk-pixbuf2.0-0": "2.36.11-1",
         "libglib2.0-0": "2.54.1-1",
@@ -41,7 +40,6 @@
         "libcups2": "1.7.5-11+deb8u1",
         "libdbus-1-3": "1.8.22-0+deb8u1",
         "libexpat1": "2.1.0-6+deb8u4",
-        "libfontconfig1": "2.11.0-6.3+deb8u1",
         "libgcc1": "1:4.9.2-10",
         "libgdk-pixbuf2.0-0": "2.31.1-2+deb8u6",
         "libglib2.0-0": "2.42.1-1+b1",
@@ -74,7 +72,6 @@
         "libcups2": "2.2.1-8",
         "libdbus-1-3": "1.10.24-0+deb9u1",
         "libexpat1": "2.2.0-2+deb9u1",
-        "libfontconfig1": "2.11.0-6.7+b1",
         "libgcc1": "1:6.3.0-18",
         "libgdk-pixbuf2.0-0": "2.36.5-2+deb9u1",
         "libglib2.0-0": "2.50.3-2",
@@ -107,7 +104,6 @@
         "libcups2": "1.7.2-0ubuntu1.7",
         "libdbus-1-3": "1.6.18-0ubuntu4.4",
         "libexpat1": "2.1.0-4ubuntu1.4",
-        "libfontconfig1": "2.11.0-0ubuntu4.2",
         "libgcc1": "1:4.9.3-0ubuntu4",
         "libgdk-pixbuf2.0-0": "2.30.7-0ubuntu1.7",
         "libglib2.0-0": "2.40.2-0ubuntu1",
@@ -140,7 +136,6 @@
         "libcups2": "2.1.3-4ubuntu0.3",
         "libdbus-1-3": "1.10.6-1ubuntu3.1",
         "libexpat1": "2.1.0-7ubuntu0.16.04.3",
-        "libfontconfig1": "2.11.94-0ubuntu1.1",
         "libgcc1": "1:6.0.1-0ubuntu1",
         "libgdk-pixbuf2.0-0": "2.32.2-1ubuntu1.3",
         "libglib2.0-0": "2.48.2-0ubuntu1",
@@ -173,7 +168,6 @@
         "libcups2": "2.2.2-1ubuntu1",
         "libdbus-1-3": "1.10.10-1ubuntu2",
         "libexpat1": "2.2.0-2ubuntu0.1",
-        "libfontconfig1": "2.11.94-0ubuntu2",
         "libgcc1": "1:6.3.0-12ubuntu2",
         "libgdk-pixbuf2.0-0": "2.36.5-3ubuntu0.2",
         "libglib2.0-0": "2.52.0-1",
@@ -206,7 +200,6 @@
         "libcups2": "2.2.4-7ubuntu3",
         "libdbus-1-3": "1.10.22-1ubuntu1",
         "libexpat1": "2.2.3-1",
-        "libfontconfig1": "2.11.94-0ubuntu2",
         "libgcc1": "1:7.2.0-8ubuntu3",
         "libgdk-pixbuf2.0-0": "2.36.11-1",
         "libglib2.0-0": "2.54.1-1ubuntu1",
diff --git a/chrome/installer/linux/debian/update_dist_package_versions.py b/chrome/installer/linux/debian/update_dist_package_versions.py
index e065630..6cfb414 100755
--- a/chrome/installer/linux/debian/update_dist_package_versions.py
+++ b/chrome/installer/linux/debian/update_dist_package_versions.py
@@ -43,7 +43,6 @@
     "libcups2",
     "libdbus-1-3",
     "libexpat1",
-    "libfontconfig1",
     "libgcc1",
     "libgdk-pixbuf2.0-0",
     "libglib2.0-0",
diff --git a/chrome/installer/linux/rpm/dist_package_provides.json b/chrome/installer/linux/rpm/dist_package_provides.json
index 662c70f..c231d2e 100644
--- a/chrome/installer/linux/rpm/dist_package_provides.json
+++ b/chrome/installer/linux/rpm/dist_package_provides.json
@@ -63,7 +63,6 @@
         "libdl.so.2(GLIBC_2.3.4)(64bit)",
         "libexpat.so.0()(64bit)",
         "libexpat.so.1()(64bit)",
-        "libfontconfig.so.1()(64bit)",
         "libgcc_s.so.1()(64bit)",
         "libgcc_s.so.1(GCC_3.0)(64bit)",
         "libgcc_s.so.1(GCC_3.3)(64bit)",
@@ -303,7 +302,6 @@
         "libdl.so.2(GLIBC_2.3.4)(64bit)",
         "libexpat.so.0()(64bit)",
         "libexpat.so.1()(64bit)",
-        "libfontconfig.so.1()(64bit)",
         "libgcc_s.so.1()(64bit)",
         "libgcc_s.so.1(GCC_3.0)(64bit)",
         "libgcc_s.so.1(GCC_3.3)(64bit)",
@@ -548,7 +546,6 @@
         "libdl.so.2(GLIBC_2.3.3)(64bit)",
         "libdl.so.2(GLIBC_2.3.4)(64bit)",
         "libexpat.so.1()(64bit)",
-        "libfontconfig.so.1()(64bit)",
         "libgcc_s.so.1()(64bit)",
         "libgcc_s.so.1(GCC_3.0)(64bit)",
         "libgcc_s.so.1(GCC_3.3)(64bit)",
@@ -856,8 +853,6 @@
         "libexpat.so.0()(64bit)",
         "libexpat.so.1",
         "libexpat.so.1()(64bit)",
-        "libfontconfig.so.1",
-        "libfontconfig.so.1()(64bit)",
         "libgcc_s.so.1",
         "libgcc_s.so.1()(64bit)",
         "libgcc_s.so.1(GCC_3.0)",
@@ -1307,8 +1302,6 @@
         "libexpat.so.0()(64bit)",
         "libexpat.so.1",
         "libexpat.so.1()(64bit)",
-        "libfontconfig.so.1",
-        "libfontconfig.so.1()(64bit)",
         "libgcc_s.so.1",
         "libgcc_s.so.1()(64bit)",
         "libgcc_s.so.1(GCC_3.0)",
diff --git a/chrome/installer/linux/rpm/update_package_provides.py b/chrome/installer/linux/rpm/update_package_provides.py
index 9eaf50a..4b1718e 100755
--- a/chrome/installer/linux/rpm/update_package_provides.py
+++ b/chrome/installer/linux/rpm/update_package_provides.py
@@ -35,7 +35,6 @@
     "libdbus-1.so",
     "libdl.so",
     "libexpat.so",
-    "libfontconfig.so",
     "libgcc_s.so",
     "libgdk-3.so",
     "libgdk_pixbuf-2.0.so",
diff --git a/chrome/profiling/json_exporter.cc b/chrome/profiling/json_exporter.cc
index 3422aa2..ad66f26 100644
--- a/chrome/profiling/json_exporter.cc
+++ b/chrome/profiling/json_exporter.cc
@@ -162,7 +162,7 @@
 void WriteMemoryMaps(const ExportParams& params, std::ostream& out) {
   base::trace_event::TracedValue traced_value;
   memory_instrumentation::TracingObserver::MemoryMapsAsValueInto(
-      params.maps, &traced_value, params.is_argument_filtering_enabled);
+      params.maps, &traced_value, params.strip_path_from_mapped_files);
   out << "\"process_mmaps\":" << traced_value.ToString();
 }
 
diff --git a/chrome/profiling/json_exporter.h b/chrome/profiling/json_exporter.h
index f039c3a5..7334478 100644
--- a/chrome/profiling/json_exporter.h
+++ b/chrome/profiling/json_exporter.h
@@ -39,8 +39,10 @@
   size_t min_size_threshold = 0;
   size_t min_count_threshold = 0;
 
-  // Whether or not the outputted JSON should filter strings (anonymized trace).
-  bool is_argument_filtering_enabled = false;
+  // Whether or not the paths should be stripped from mapped files. Doing so
+  // anonymizes the trace, since the paths could potentially contain a username.
+  // However, it prevents symbolization of locally built instances of Chrome.
+  bool strip_path_from_mapped_files = false;
 };
 
 // Creates a JSON string representing a JSON dictionary that contains memory
diff --git a/chrome/profiling/memlog_connection_manager.cc b/chrome/profiling/memlog_connection_manager.cc
index 6beb8eca..6a6291e 100644
--- a/chrome/profiling/memlog_connection_manager.cc
+++ b/chrome/profiling/memlog_connection_manager.cc
@@ -201,6 +201,7 @@
 
 void MemlogConnectionManager::DumpProcessesForTracing(
     bool keep_small_allocations,
+    bool strip_path_from_mapped_files,
     mojom::ProfilingService::DumpProcessesForTracingCallback callback,
     memory_instrumentation::mojom::GlobalMemoryDumpPtr dump) {
   base::AutoLock lock(connections_lock_);
@@ -235,7 +236,8 @@
         barrier_id, task_runner,
         base::BindOnce(&MemlogConnectionManager::DoDumpOneProcessForTracing,
                        weak_factory_.GetWeakPtr(), tracking, pid,
-                       connection->process_type, keep_small_allocations));
+                       connection->process_type, keep_small_allocations,
+                       strip_path_from_mapped_files));
     connection->client->FlushMemlogPipe(barrier_id);
   }
 }
@@ -245,6 +247,7 @@
     base::ProcessId pid,
     mojom::ProcessType process_type,
     bool keep_small_allocations,
+    bool strip_path_from_mapped_files,
     bool success,
     AllocationCountMap counts,
     AllocationTracker::ContextMap context) {
@@ -282,7 +285,7 @@
   params.process_type = process_type;
   params.min_size_threshold = keep_small_allocations ? 0 : kMinSizeThreshold;
   params.min_count_threshold = keep_small_allocations ? 0 : kMinCountThreshold;
-  params.is_argument_filtering_enabled = true;
+  params.strip_path_from_mapped_files = strip_path_from_mapped_files;
 
   std::ostringstream oss;
   ExportMemoryMapsAndV2StackTraceToJSON(params, oss);
diff --git a/chrome/profiling/memlog_connection_manager.h b/chrome/profiling/memlog_connection_manager.h
index 41b94d1..7b5621f 100644
--- a/chrome/profiling/memlog_connection_manager.h
+++ b/chrome/profiling/memlog_connection_manager.h
@@ -65,6 +65,7 @@
   // fired.
   void DumpProcessesForTracing(
       bool keep_small_allocations,
+      bool strip_path_from_mapped_files,
       mojom::ProfilingService::DumpProcessesForTracingCallback callback,
       memory_instrumentation::mojom::GlobalMemoryDumpPtr dump);
 
@@ -85,6 +86,7 @@
       base::ProcessId pid,
       mojom::ProcessType process_type,
       bool keep_small_allocations,
+      bool strip_path_from_mapped_files,
       bool success,
       AllocationCountMap counts,
       AllocationTracker::ContextMap context);
diff --git a/chrome/profiling/profiling_service.cc b/chrome/profiling/profiling_service.cc
index a3722d9..88645d2 100644
--- a/chrome/profiling/profiling_service.cc
+++ b/chrome/profiling/profiling_service.cc
@@ -71,6 +71,7 @@
 
 void ProfilingService::DumpProcessesForTracing(
     bool keep_small_allocations,
+    bool strip_path_from_mapped_files,
     DumpProcessesForTracingCallback callback) {
   // Need a memory map to make sense of the dump. The dump will be triggered
   // in the memory map global dump callback.
@@ -79,7 +80,7 @@
       ->GetVmRegionsForHeapProfiler(base::Bind(
           &ProfilingService::OnGetVmRegionsCompleteForDumpProcessesForTracing,
           weak_factory_.GetWeakPtr(), keep_small_allocations,
-          base::Passed(&callback)));
+          strip_path_from_mapped_files, base::Passed(&callback)));
 }
 
 void ProfilingService::GetProfiledPids(GetProfiledPidsCallback callback) {
@@ -88,6 +89,7 @@
 
 void ProfilingService::OnGetVmRegionsCompleteForDumpProcessesForTracing(
     bool keep_small_allocations,
+    bool strip_path_from_mapped_files,
     mojom::ProfilingService::DumpProcessesForTracingCallback callback,
     bool success,
     memory_instrumentation::mojom::GlobalMemoryDumpPtr dump) {
@@ -100,7 +102,8 @@
   // TODO(bug 752621) we should be asking and getting the memory map of only
   // the process we want rather than querying all processes and filtering.
   connection_manager_.DumpProcessesForTracing(
-      keep_small_allocations, std::move(callback), std::move(dump));
+      keep_small_allocations, strip_path_from_mapped_files, std::move(callback),
+      std::move(dump));
 }
 
 }  // namespace profiling
diff --git a/chrome/profiling/profiling_service.h b/chrome/profiling/profiling_service.h
index 0bd8ea0..9d0ca2dec 100644
--- a/chrome/profiling/profiling_service.h
+++ b/chrome/profiling/profiling_service.h
@@ -48,6 +48,7 @@
                           mojom::ProcessType process_type) override;
   void DumpProcessesForTracing(
       bool keep_small_allocations,
+      bool strip_path_from_mapped_files,
       DumpProcessesForTracingCallback callback) override;
   void GetProfiledPids(GetProfiledPidsCallback callback) override;
 
@@ -63,6 +64,7 @@
 
   void OnGetVmRegionsCompleteForDumpProcessesForTracing(
       bool keep_small_allocations,
+      bool strip_path_from_mapped_files,
       mojom::ProfilingService::DumpProcessesForTracingCallback callback,
       bool success,
       memory_instrumentation::mojom::GlobalMemoryDumpPtr dump);
diff --git a/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc b/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc
index 536f798..95958133 100644
--- a/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc
+++ b/chrome/renderer/extensions/extension_hooks_delegate_unittest.cc
@@ -5,7 +5,9 @@
 #include "chrome/renderer/extensions/extension_hooks_delegate.h"
 
 #include "base/strings/stringprintf.h"
+#include "content/public/common/child_process_host.h"
 #include "extensions/common/extension_builder.h"
+#include "extensions/common/extension_messages.h"
 #include "extensions/common/value_builder.h"
 #include "extensions/renderer/bindings/api_binding_test_util.h"
 #include "extensions/renderer/message_target.h"
@@ -161,4 +163,57 @@
   check_access("chrome.extension.onMessageExternal", DOESNT_THROW);
 }
 
+// Ensure that the extension.sendRequest() method doesn't close the channel if
+// the listener does not reply and also does not return `true` (unlike the
+// runtime.sendMessage() method, which will).
+TEST_F(ExtensionHooksDelegateTest, SendRequestChannelLeftOpenToReplyAsync) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  constexpr char kRegisterListener[] =
+      "(function() {\n"
+      "  chrome.extension.onRequest.addListener(\n"
+      "      function(message, sender, reply) {});\n"
+      "})";
+  v8::Local<v8::Function> add_listener =
+      FunctionFromString(context, kRegisterListener);
+  RunFunctionOnGlobal(add_listener, context, 0, nullptr);
+
+  const std::string kChannel = "chrome.extension.sendRequest";
+  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
+  const PortId port_id(other_context_id, 0, false);
+
+  ExtensionMsg_TabConnectionInfo tab_connection_info;
+  tab_connection_info.frame_id = 0;
+  const int tab_id = 10;
+  GURL source_url("http://example.com");
+  tab_connection_info.tab.Swap(
+      DictionaryBuilder().Set("tabId", tab_id).Build().get());
+  ExtensionMsg_ExternalConnectionInfo external_connection_info;
+  external_connection_info.target_id = extension()->id();
+  external_connection_info.source_id = extension()->id();
+  external_connection_info.source_url = source_url;
+  external_connection_info.guest_process_id =
+      content::ChildProcessHost::kInvalidUniqueID;
+  external_connection_info.guest_render_frame_routing_id = 0;
+
+  // Open a receiver for the message.
+  EXPECT_CALL(*ipc_message_sender(),
+              SendOpenMessagePort(MSG_ROUTING_NONE, port_id));
+  messaging_service()->DispatchOnConnect(
+      *script_context_set(), port_id, kChannel, tab_connection_info,
+      external_connection_info, std::string(), nullptr);
+  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
+  EXPECT_TRUE(
+      messaging_service()->HasPortForTesting(script_context(), port_id));
+
+  // Post the message to the receiver. Since the receiver doesn't respond, the
+  // channel should remain open.
+  messaging_service()->DeliverMessage(*script_context_set(), port_id,
+                                      Message("\"message\"", false), nullptr);
+  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
+  EXPECT_TRUE(
+      messaging_service()->HasPortForTesting(script_context(), port_id));
+}
+
 }  // namespace extensions
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc
index cc1f7fa..bd0fc9c 100644
--- a/chrome/renderer/media/chrome_key_systems.cc
+++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -94,6 +94,8 @@
       "org.chromium.externalclearkey.storageidtest";
   static const char kExternalClearKeyDifferentGuidTestKeySystem[] =
       "org.chromium.externalclearkey.differentguid";
+  static const char kExternalClearKeyCdmProxyTestKeySystem[] =
+      "org.chromium.externalclearkey.cdmproxytest";
 
   std::vector<WebPluginMimeType::Param> additional_params;
   if (!IsPepperCdmAvailable(cdm::kExternalClearKeyPepperType,
@@ -145,6 +147,10 @@
   // A key system that is registered with a different CDM GUID.
   concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties(
       kExternalClearKeyDifferentGuidTestKeySystem));
+
+  // A key system that triggers CDM Proxy test in ClearKeyCdm.
+  concrete_key_systems->emplace_back(new cdm::ExternalClearKeyProperties(
+      kExternalClearKeyCdmProxyTestKeySystem));
 }
 
 #if defined(WIDEVINE_CDM_AVAILABLE)
diff --git a/chrome/renderer/resources/extensions/automation/automation_node.js b/chrome/renderer/resources/extensions/automation/automation_node.js
index 1452120a..d0a6a6d 100644
--- a/chrome/renderer/resources/extensions/automation/automation_node.js
+++ b/chrome/renderer/resources/extensions/automation/automation_node.js
@@ -877,7 +877,9 @@
 var nodeRefAttributes = [
     ['activedescendantId', 'activeDescendant'],
     ['inPageLinkTargetId', 'inPageLinkTarget'],
+    ['nextFocusId', 'nextFocus'],
     ['nextOnLineId', 'nextOnLine'],
+    ['previousFocusId', 'previousFocus'],
     ['previousOnLineId', 'previousOnLine'],
     ['tableColumnHeaderId', 'tableColumnHeader'],
     ['tableHeaderId', 'tableHeader'],
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index ccf72b4..d07b588a 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -558,6 +558,7 @@
       "../browser/media/webrtc/webrtc_browsertest_common.h",
       "../browser/media/webrtc/webrtc_browsertest_perf.cc",
       "../browser/media/webrtc/webrtc_browsertest_perf.h",
+      "../browser/media/webrtc/webrtc_desktop_capture_browsertest.cc",
       "../browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc",
       "../browser/media/webrtc/webrtc_getmediadevices_browsertest.cc",
       "../browser/media/webrtc/webrtc_internals_perf_browsertest.cc",
@@ -1857,6 +1858,7 @@
         "../browser/vr/test/vr_browser_test.h",
         "../browser/vr/test/vr_transition_utils.cc",
         "../browser/vr/test/vr_transition_utils.h",
+        "../browser/vr/webvr_tab_browser_test.cc",
         "../browser/vr/webvr_transition_browser_test.cc",
       ]
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/BottomSheetTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/BottomSheetTestRule.java
index 82e05478..2df8b24 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/BottomSheetTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/BottomSheetTestRule.java
@@ -6,7 +6,6 @@
 
 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
 import static org.chromium.chrome.browser.ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE;
-import static org.chromium.chrome.test.ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG;
 
 import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.UiDevice;
@@ -28,7 +27,7 @@
 /**
  * Junit4 rule for tests testing the Chrome Home bottom sheet.
  */
-@CommandLineFlags.Add({DISABLE_FIRST_RUN_EXPERIENCE, DISABLE_NETWORK_PREDICTION_FLAG})
+@CommandLineFlags.Add({DISABLE_FIRST_RUN_EXPERIENCE})
 public class BottomSheetTestRule extends ChromeTabbedActivityTestRule {
     /** An observer used to record events that occur with respect to the bottom sheet. */
     public static class Observer extends EmptyBottomSheetObserver {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
index 362569d..c95b186 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -77,9 +77,6 @@
     // The number of ms to wait for the rendering activity to be started.
     private static final int ACTIVITY_START_TIMEOUT_MS = 1000;
 
-    // TODO(mariakhomenko): crbug.com/796312 Remove all references.
-    public static final String DISABLE_NETWORK_PREDICTION_FLAG = "notarealflag";
-
     private static final long OMNIBOX_FIND_SUGGESTION_TIMEOUT_MS = 10 * 1000;
 
     protected boolean mSkipClearAppData;
diff --git a/chrome/test/chromedriver/test/test_expectations b/chrome/test/chromedriver/test/test_expectations
index fedf552c..0c98d27 100644
--- a/chrome/test/chromedriver/test/test_expectations
+++ b/chrome/test/chromedriver/test/test_expectations
@@ -290,6 +290,8 @@
         'PageLoadingTest.testShouldBeAbleToGetAFragmentOnTheCurrentPage',
          # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2076
         'CorrectEventFiringTest.testShouldReportTheXAndYCoordinatesWhenClicking',
+	 # https://bugs.chromium.org/p/chromedriver/issues/detail?id=2077
+        'CorrectEventFiringTest.testShouldEmitClickEventWhenClickingOnATextInputElement',
     ]
 )
 _OS_NEGATIVE_FILTER['android:chromedriver_webview_shell'] = (
diff --git a/chrome/test/data/extensions/desktop_capture/background.js b/chrome/test/data/extensions/desktop_capture/background.js
new file mode 100644
index 0000000..cf540930
--- /dev/null
+++ b/chrome/test/data/extensions/desktop_capture/background.js
@@ -0,0 +1,18 @@
+/**
+ * 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.
+ */
+
+// We need this thing because we can only run chooseDesktopMedia from inside
+// the extension.
+
+chrome.runtime.onMessage.addListener(
+  function(request, sender, sendResponse) {
+    if (request.desktopSourceTypes) {
+      chrome.desktopCapture.chooseDesktopMedia(request.desktopSourceTypes,
+          sender.tab, function(id) {
+        chrome.tabs.sendMessage(sender.tab.id, {streamId: id});
+      });
+    }
+  });
diff --git a/chrome/test/data/extensions/desktop_capture/content.js b/chrome/test/data/extensions/desktop_capture/content.js
new file mode 100644
index 0000000..ce66aea
--- /dev/null
+++ b/chrome/test/data/extensions/desktop_capture/content.js
@@ -0,0 +1,20 @@
+/**
+ * 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.
+ */
+
+chrome.runtime.onMessage.addListener(
+  function(request, sender, sendResponse) {
+    // Callback from extension, ChooseDesktopMedia has completed.
+    window.postMessage(request, "*");
+});
+
+window.addEventListener('message', function(message) {
+  if (event.source != window || !event.data) {
+    return;
+  }
+
+  // Send request to extension. event.data contains desktopSourceTypes.
+  chrome.runtime.sendMessage(event.data);
+});
diff --git a/chrome/test/data/extensions/desktop_capture/manifest.json b/chrome/test/data/extensions/desktop_capture/manifest.json
new file mode 100644
index 0000000..d1d6c1f0
--- /dev/null
+++ b/chrome/test/data/extensions/desktop_capture/manifest.json
@@ -0,0 +1,19 @@
+{
+  "manifest_version": 2,
+  "name": "Basic Desktop Capture",
+  "version": "0.1",
+  "description": "Allows WebRTC screensharing.",
+  "background": {
+    "scripts": ["background.js"]
+  },
+  "content_scripts": [{
+        "js": ["content.js"],
+        "matches": [
+          "<all_urls>"
+        ],
+        "run_at": "document_start"
+  }],
+  "permissions": [
+      "desktopCapture"
+  ]
+}
diff --git a/chrome/test/data/vr/e2e_test_files/html/test_device_capabilities_match_expectations.html b/chrome/test/data/vr/e2e_test_files/html/test_device_capabilities_match_expectations.html
index 772de82..bf31dfc13 100644
--- a/chrome/test/data/vr/e2e_test_files/html/test_device_capabilities_match_expectations.html
+++ b/chrome/test/data/vr/e2e_test_files/html/test_device_capabilities_match_expectations.html
@@ -29,6 +29,15 @@
         "hammerhead": android_expectation,  // Nexus 5
         "marlin": android_expectation,  // Pixel XL
         "sailfish": android_expectation,  // Pixel
+        "VR Orientation Device": { // GVR-less Magic Window implementation
+          "isPresenting": false,
+          "capabilities": {
+            "hasPosition": false,
+            "hasExternalDisplay": false,
+            "canPresent": false,
+            "maxLayers": 0,
+          }
+        },
       }
       var t = async_test("Device capabilities match expectations");
       function stepCheckDeviceCapabilities(device) {
diff --git a/chrome/test/data/webrtc/getusermedia.js b/chrome/test/data/webrtc/getusermedia.js
index 20d2602..64edac63 100644
--- a/chrome/test/data/webrtc/getusermedia.js
+++ b/chrome/test/data/webrtc/getusermedia.js
@@ -173,3 +173,14 @@
 
   returnToTest('request-callback-denied');
 }
+
+function openDesktopMediaStream() {
+  window.addEventListener('message', function(event) {
+    // Only trigger if streamId is present (callback from, not to, extension).
+    if (typeof event.data.streamId !== 'undefined') {
+      returnToTest(event.data.streamId);
+    }
+  });
+
+  window.postMessage({desktopSourceTypes: ['window', 'screen']}, '*');
+}
diff --git a/chrome/test/data/webui/extensions/extension_detail_view_test.js b/chrome/test/data/webui/extensions/extension_detail_view_test.js
index f848edde..12df13f 100644
--- a/chrome/test/data/webui/extensions/extension_detail_view_test.js
+++ b/chrome/test/data/webui/extensions/extension_detail_view_test.js
@@ -108,10 +108,10 @@
 
       item.set('data.manifestHomePageUrl', 'http://example.com');
       Polymer.dom.flush();
-      expectTrue(testIsVisible('#developerWebsite'));
+      expectTrue(testIsVisible('#extensionWebsite'));
       item.set('data.manifestHomePageUrl', '');
       Polymer.dom.flush();
-      expectFalse(testIsVisible('#developerWebsite'));
+      expectFalse(testIsVisible('#extensionWebsite'));
 
       item.set('data.webStoreUrl', 'http://example.com');
       Polymer.dom.flush();
diff --git a/chrome/test/data/webui/extensions/extension_shortcut_input_test.js b/chrome/test/data/webui/extensions/extension_shortcut_input_test.js
index c514682..afd3224 100644
--- a/chrome/test/data/webui/extensions/extension_shortcut_input_test.js
+++ b/chrome/test/data/webui/extensions/extension_shortcut_input_test.js
@@ -52,22 +52,22 @@
             // Press ctrl.
             MockInteractions.keyDownOn(field, 17, ['ctrl']);
             expectEquals('Ctrl', field.value);
-            expectEquals('Need a character', field.errorMessage);
+            expectEquals('Type a letter', field.errorMessage);
             // Add shift.
             MockInteractions.keyDownOn(field, 16, ['ctrl', 'shift']);
             expectEquals('Ctrl + Shift', field.value);
-            expectEquals('Need a character', field.errorMessage);
+            expectEquals('Type a letter', field.errorMessage);
             // Remove shift.
             MockInteractions.keyUpOn(field, 16, ['ctrl']);
             expectEquals('Ctrl', field.value);
-            expectEquals('Need a character', field.errorMessage);
+            expectEquals('Type a letter', field.errorMessage);
             // Add alt (ctrl + alt is invalid).
             MockInteractions.keyDownOn(field, 18, ['ctrl', 'alt']);
             expectEquals('Ctrl', field.value);
             // Remove alt.
             MockInteractions.keyUpOn(field, 18, ['ctrl']);
             expectEquals('Ctrl', field.value);
-            expectEquals('Need a character', field.errorMessage);
+            expectEquals('Type a letter', field.errorMessage);
 
             // Add 'A'. Once a valid shortcut is typed (like Ctrl + A), it is
             // committed.
diff --git a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
index 15cf4a7..9099613 100644
--- a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
+++ b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
@@ -105,6 +105,18 @@
   this.runMochaTest(settings_sections_tests.TestNames.SetColor);
 });
 
+TEST_F('PrintPreviewSettingsSectionsTest', 'SetMediaSize', function() {
+  this.runMochaTest(settings_sections_tests.TestNames.SetMediaSize);
+});
+
+TEST_F('PrintPreviewSettingsSectionsTest', 'SetDpi', function() {
+  this.runMochaTest(settings_sections_tests.TestNames.SetDpi);
+});
+
+TEST_F('PrintPreviewSettingsSectionsTest', 'SetMargins', function() {
+  this.runMochaTest(settings_sections_tests.TestNames.SetMargins);
+});
+
 PrintPreviewRestoreStateTest = class extends NewPrintPreviewTest {
   /** @override */
   get browsePreload() {
diff --git a/chrome/test/data/webui/print_preview/settings_section_test.js b/chrome/test/data/webui/print_preview/settings_section_test.js
index e76ee82..6b1e744 100644
--- a/chrome/test/data/webui/print_preview/settings_section_test.js
+++ b/chrome/test/data/webui/print_preview/settings_section_test.js
@@ -16,6 +16,9 @@
     SetCopies: 'set copies',
     SetLayout: 'set layout',
     SetColor: 'set color',
+    SetMediaSize: 'set media size',
+    SetDpi: 'set dpi',
+    SetMargins: 'set margins',
   };
 
   const suiteName = 'SettingsSectionsTests';
@@ -36,6 +39,8 @@
           print_preview_test_utils.getCddTemplate(fooDestination.id)
               .capabilities;
       page.set('destination_', fooDestination);
+      setPdfDocument(false);
+      Polymer.dom.flush();
     });
 
     /** @param {boolean} isPdf Whether the document should be a PDF. */
@@ -353,6 +358,78 @@
       colorInput.dispatchEvent(new CustomEvent('change'));
       expectEquals(false, page.settings.color.value);
     });
+
+    test(assert(TestNames.SetMediaSize), function() {
+      const mediaSizeElement = page.$$('print-preview-media-size-settings');
+      expectEquals(false, mediaSizeElement.hidden);
+
+      const mediaSizeCapabilities =
+          page.destination_.capabilities.printer.media_size;
+      const letterOption = JSON.stringify(mediaSizeCapabilities.option[0]);
+      const squareOption = JSON.stringify(mediaSizeCapabilities.option[1]);
+
+      // Default is letter
+      const mediaSizeInput =
+          mediaSizeElement.$$('print-preview-settings-select').$$('select');
+      expectEquals(letterOption, mediaSizeInput.value);
+      expectEquals(letterOption, JSON.stringify(page.settings.mediaSize.value));
+
+      // Change to square
+      mediaSizeInput.value = squareOption;
+      mediaSizeInput.dispatchEvent(new CustomEvent('change'));
+
+      expectEquals(squareOption, JSON.stringify(page.settings.mediaSize.value));
+    });
+
+    test(assert(TestNames.SetDpi), function() {
+      const dpiElement = page.$$('print-preview-dpi-settings');
+      expectEquals(false, dpiElement.hidden);
+
+      const dpiCapabilities = page.destination_.capabilities.printer.dpi;
+      const highQualityOption = dpiCapabilities.option[0];
+      const lowQualityOption = dpiCapabilities.option[1];
+
+      // Default is 200
+      const dpiInput =
+          dpiElement.$$('print-preview-settings-select').$$('select');
+      const isDpiEqual = function(value1, value2) {
+        return value1.horizontal_dpi == value2.horizontal_dpi &&
+            value1.vertical_dpi == value2.vertical_dpi &&
+            value1.vendor_id == value2.vendor_id;
+      };
+      expectTrue(isDpiEqual(highQualityOption, JSON.parse(dpiInput.value)));
+      expectTrue(isDpiEqual(highQualityOption, page.settings.dpi.value));
+
+      // Change to 100
+      dpiInput.value =
+          JSON.stringify(dpiElement.capabilityWithLabels_.option[1]);
+      dpiInput.dispatchEvent(new CustomEvent('change'));
+
+      expectTrue(isDpiEqual(lowQualityOption, JSON.parse(dpiInput.value)));
+      expectTrue(isDpiEqual(lowQualityOption, page.settings.dpi.value));
+    });
+
+    test(assert(TestNames.SetMargins), function() {
+      const marginsElement = page.$$('print-preview-margins-settings');
+      expectEquals(false, marginsElement.hidden);
+
+      // Default is DEFAULT_MARGINS
+      const marginsInput = marginsElement.$$('select');
+      expectEquals(
+          print_preview_new.MarginsTypeValue.DEFAULT.toString(),
+          marginsInput.value);
+      expectEquals(
+          print_preview_new.MarginsTypeValue.DEFAULT,
+          page.settings.margins.value);
+
+      // Change to black and white.
+      marginsInput.value =
+          print_preview_new.MarginsTypeValue.MINIMUM.toString();
+      marginsInput.dispatchEvent(new CustomEvent('change'));
+      expectEquals(
+          print_preview_new.MarginsTypeValue.MINIMUM,
+          page.settings.margins.value);
+    });
   });
 
   return {
diff --git a/chrome/test/data/webui/settings/chrome_cleanup_page_test.js b/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
index 7f3c7a7..61040ee 100644
--- a/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
+++ b/chrome/test/data/webui/settings/chrome_cleanup_page_test.js
@@ -14,6 +14,8 @@
       'startScanning',
       'notifyShowDetails',
       'notifyLearnMoreClicked',
+      'getMoreItemsPluralString',
+      'getItemsToRemovePluralString',
     ]);
   }
 
@@ -56,6 +58,18 @@
   notifyLearnMoreClicked() {
     this.methodCalled('notifyLearnMoreClicked');
   }
+
+  /** @override */
+  getMoreItemsPluralString(numHiddenItems) {
+    this.methodCalled('getMoreItemsPluralString', numHiddenItems);
+    return Promise.resolve('');
+  }
+
+  /** @override */
+  getItemsToRemovePluralString(numItems) {
+    this.methodCalled('getItemsToRemovePluralString', numItems);
+    return Promise.resolve('');
+  }
 }
 
 var chromeCleanupPage = null;
@@ -63,6 +77,23 @@
 /** @type {?TestDownloadsBrowserProxy} */
 var ChromeCleanupProxy = null;
 
+var shortFileList = ['file 1', 'file 2', 'file 3'];
+var exactSizeFileList = ['file 1', 'file 2', 'file 3', 'file 4'];
+var longFileList = ['file 1', 'file 2', 'file 3', 'file 4', 'file 5'];
+var shortRegistryKeysList = ['key 1', 'key 2'];
+var exactSizeRegistryKeysList = ['key 1', 'key 2', 'key 3', 'key 4'];
+var longRegistryKeysList =
+    ['key 1', 'key 2', 'key 3', 'key 4', 'key 5', 'key 6'];
+
+var defaultScannerResults = {
+  'files': shortFileList,
+  'registryKeys': shortRegistryKeysList,
+};
+
+/**
+ * @param {boolean} userInitiatedCleanupsEnabled Whether the user initiated
+ *     cleanup feature is enabled.
+ */
 function initParametrizedTest(userInitiatedCleanupsEnabled) {
   ChromeCleanupProxy = new TestChromeCleanupProxy();
   settings.ChromeCleanupProxyImpl.instance_ = ChromeCleanupProxy;
@@ -77,18 +108,73 @@
   document.body.appendChild(chromeCleanupPage);
 }
 
-function startCleanupFromInfected() {
+/**
+ * @param {!Array} originalItems
+ * @param {!Array} visibleItems
+ * @param {boolean} listCanBeShortened
+ */
+function validateVisibleItemsList(
+    originalItems, visibleItems, listCanBeShortened) {
+  var visibleItemsList = visibleItems.querySelectorAll('.visible-item');
+  var moreItemsLInk = visibleItems.querySelector('#more-items-link');
+
+  if (!listCanBeShortened ||
+      originalItems.length <= settings.CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW) {
+    assertEquals(visibleItemsList.length, originalItems.length);
+    assertTrue(moreItemsLInk.hidden);
+  } else {
+    assertEquals(
+        visibleItemsList.length,
+        settings.CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW - 1);
+    assertFalse(moreItemsLInk.hidden);
+
+    // Tapping on the "show more" link should expand the list.
+    MockInteractions.tap(moreItemsLInk);
+    Polymer.dom.flush();
+
+    visibleItemsList = visibleItems.querySelectorAll('.visible-item');
+    assertEquals(visibleItemsList.length, originalItems.length);
+    assertTrue(moreItemsLInk.hidden);
+  }
+}
+
+/**
+ * @param {boolean} userInitiatedCleanupsEnabled Whether the user initiated
+ *     cleanup feature is enabled.
+ * @param {!Array} files The list of files to be cleaned
+ * @param {!Array} registryKeys The list of registry entires to be cleaned.
+ */
+function startCleanupFromInfected(
+    userInitiatedCleanupsEnabled, files, registryKeys) {
+  var scannerResults = {'files': files, 'registryKeys': registryKeys};
+
   cr.webUIListenerCallback('chrome-cleanup-upload-permission-change', false);
-  cr.webUIListenerCallback(
-      'chrome-cleanup-on-infected', ['file 1', 'file 2', 'file 3']);
+  cr.webUIListenerCallback('chrome-cleanup-on-infected', scannerResults);
   Polymer.dom.flush();
 
-  var showFilesButton = chromeCleanupPage.$$('#show-files-button');
-  assertTrue(!!showFilesButton);
-  MockInteractions.tap(showFilesButton);
-  filesToRemove = chromeCleanupPage.$$('#files-to-remove-list');
-  assertTrue(!!filesToRemove);
-  assertEquals(filesToRemove.getElementsByTagName('li').length, 3);
+  var showItemsButton = chromeCleanupPage.$$('#show-items-button');
+  assertTrue(!!showItemsButton);
+  MockInteractions.tap(showItemsButton);
+
+  var filesToRemoveList =
+      chromeCleanupPage.$$('#files-to-remove-list').$$('#list');
+  assertTrue(!!filesToRemoveList);
+  validateVisibleItemsList(
+      files, filesToRemoveList,
+      userInitiatedCleanupsEnabled /* listCanBeShortened */);
+
+  var registryKeysListContainer = chromeCleanupPage.$$('#registry-keys-list');
+  assertTrue(!!registryKeysListContainer);
+  if (userInitiatedCleanupsEnabled && registryKeys.length > 0) {
+    assertFalse(registryKeysListContainer.hidden);
+    var registryKeysList = registryKeysListContainer.$$('#list');
+    assertTrue(!!registryKeysList);
+    validateVisibleItemsList(
+        registryKeys, registryKeysList,
+        true /* listCanBeShortened */);
+  } else {
+    assertTrue(registryKeysListContainer.hidden);
+  }
 
   var actionButton = chromeCleanupPage.$$('#action-button');
   assertTrue(!!actionButton);
@@ -96,7 +182,8 @@
   return ChromeCleanupProxy.whenCalled('startCleanup')
       .then(function(logsUploadEnabled) {
         assertFalse(logsUploadEnabled);
-        cr.webUIListenerCallback('chrome-cleanup-on-cleaning', false);
+        cr.webUIListenerCallback(
+            'chrome-cleanup-on-cleaning', defaultScannerResults);
         Polymer.dom.flush();
 
         var spinner = chromeCleanupPage.$$('#waiting-spinner');
@@ -114,9 +201,13 @@
   return ChromeCleanupProxy.whenCalled('restartComputer');
 }
 
+/**
+ * @param {boolean} userInitiatedCleanupsEnabled Whether the user initiated
+ *     cleanup feature is enabled.
+ */
 function cleanupFailure(userInitiatedCleanupsEnabled) {
   cr.webUIListenerCallback('chrome-cleanup-upload-permission-change', false);
-  cr.webUIListenerCallback('chrome-cleanup-on-cleaning', false);
+  cr.webUIListenerCallback('chrome-cleanup-on-cleaning', defaultScannerResults);
   cr.webUIListenerCallback(
       'chrome-cleanup-on-idle',
       settings.ChromeCleanupIdleReason.CLEANING_FAILED);
@@ -132,8 +223,12 @@
   }
 }
 
+/**
+ * @param {boolean} userInitiatedCleanupsEnabled Whether the user initiated
+ *     cleanup feature is enabled.
+ */
 function cleanupSuccess(userInitiatedCleanupsEnabled) {
-  cr.webUIListenerCallback('chrome-cleanup-on-cleaning', false);
+  cr.webUIListenerCallback('chrome-cleanup-on-cleaning', defaultScannerResults);
   cr.webUIListenerCallback(
       'chrome-cleanup-on-idle',
       settings.ChromeCleanupIdleReason.CLEANING_SUCCEEDED);
@@ -149,10 +244,14 @@
   }
 }
 
+/**
+ * @param {boolean} testingScanOffered Whether to test the case where scanning
+ *     is offered to the user.
+ */
 function testLogsUploading(testingScanOffered) {
   if (testingScanOffered) {
     cr.webUIListenerCallback(
-        'chrome-cleanup-on-infected', ['file 1', 'file 2', 'file 3']);
+        'chrome-cleanup-on-infected', defaultScannerResults);
   } else {
     cr.webUIListenerCallback(
         'chrome-cleanup-on-idle', settings.ChromeCleanupIdleReason.INITIAL);
@@ -179,11 +278,78 @@
 
 suite('ChromeCleanupHandler_UserInitiatedCleanupsDisabled', function() {
   setup(function() {
-    initParametrizedTest(false);
+    initParametrizedTest(false /* userInitiatedCleanupsEnabled */);
   });
 
-  test('startCleanupFromInfected', function() {
-    return startCleanupFromInfected();
+  test('startCleanupFromInfected_FewFilesNoRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, shortFileList, []);
+  });
+
+  test('startCleanupFromInfected_FewFilesFewRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, shortFileList,
+        shortRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_FewFilesExactSizeRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, shortFileList,
+        exactSizeRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_FewFilesManyRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, shortFileList,
+        longRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_ExactSizeFilesNoRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, exactSizeFileList, []);
+  });
+
+  test('startCleanupFromInfected_ExactSizeFilesFewRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, exactSizeFileList,
+        shortRegistryKeysList);
+  });
+
+  test(
+      'startCleanupFromInfected_ExactSizeFilesExactSizeRegistryKeys',
+      function() {
+        return startCleanupFromInfected(
+            false /* userInitiatedCleanupsEnabled */, exactSizeFileList,
+            exactSizeRegistryKeysList);
+      });
+
+  test('startCleanupFromInfected_ExactSizeFilesManyRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, exactSizeFileList,
+        longRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_ManyFilesNoRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, longFileList, []);
+  });
+
+  test('startCleanupFromInfected_ManyFilesFewRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, longFileList,
+        shortRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_ManyFilesExactSizeRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, longFileList,
+        exactSizeRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_ManyFilesManyRegistryKeys', function() {
+    return startCleanupFromInfected(
+        false /* userInitiatedCleanupsEnabled */, longFileList,
+        longRegistryKeysList);
   });
 
   test('rebootFromRebootRequired', function() {
@@ -191,21 +357,21 @@
   });
 
   test('cleanupFailure', function() {
-    return cleanupFailure(false);
+    return cleanupFailure(false /* userInitiatedCleanupsEnabled */);
   });
 
   test('cleanupSuccess', function() {
-    return cleanupSuccess(false);
+    return cleanupSuccess(false /* userInitiatedCleanupsEnabled */);
   });
 
   test('logsUploadingOnInfected', function() {
-    return testLogsUploading(false);
+    return testLogsUploading(false /* testingScanOffered */);
   });
 });
 
 suite('ChromeCleanupHandler_UserInitiatedCleanupsEnabled', function() {
   setup(function() {
-    initParametrizedTest(true);
+    initParametrizedTest(true /* userInitiatedCleanupsEnabled */);
   });
 
   function scanOfferedOnInitiallyIdle(idleReason) {
@@ -320,8 +486,75 @@
     assertFalse(!!actionButton);
   });
 
-  test('startCleanupFromInfected', function() {
-    return startCleanupFromInfected();
+  test('startCleanupFromInfected_FewFilesNoRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, shortFileList, []);
+  });
+
+  test('startCleanupFromInfected_FewFilesFewRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, shortFileList,
+        shortRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_FewFilesExactSizeRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, shortFileList,
+        exactSizeRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_FewFilesManyRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, shortFileList,
+        longRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_ExactSizeFilesNoRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, exactSizeFileList, []);
+  });
+
+  test('startCleanupFromInfected_ExactSizeFilesFewRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, exactSizeFileList,
+        shortRegistryKeysList);
+  });
+
+  test(
+      'startCleanupFromInfected_ExactSizeFilesExactSizeRegistryKeys',
+      function() {
+        return startCleanupFromInfected(
+            true /* userInitiatedCleanupsEnabled */, exactSizeFileList,
+            exactSizeRegistryKeysList);
+      });
+
+  test('startCleanupFromInfected_ExactSizeFilesManyRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, exactSizeFileList,
+        longRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_ManyFilesNoRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, longFileList, []);
+  });
+
+  test('startCleanupFromInfected_ManyFilesFewRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, longFileList,
+        shortRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_ManyFilesExactSizeRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, longFileList,
+        exactSizeRegistryKeysList);
+  });
+
+  test('startCleanupFromInfected_ManyFilesManyRegistryKeys', function() {
+    return startCleanupFromInfected(
+        true /* userInitiatedCleanupsEnabled */, longFileList,
+        longRegistryKeysList);
   });
 
   test('rebootFromRebootRequired', function() {
@@ -329,18 +562,18 @@
   });
 
   test('cleanupFailure', function() {
-    return cleanupFailure(true);
+    return cleanupFailure(true /* userInitiatedCleanupsEnabled */);
   });
 
   test('cleanupSuccess', function() {
-    return cleanupSuccess(true);
+    return cleanupSuccess(true /* userInitiatedCleanupsEnabled */);
   });
 
   test('logsUploadingOnScanOffered', function() {
-    return testLogsUploading(true);
+    return testLogsUploading(true /* testingScanOffered */);
   });
 
   test('logsUploadingOnInfected', function() {
-    return testLogsUploading(false);
+    return testLogsUploading(false /* testingScanOffered */);
   });
 });
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index df4a5bd1..46602a3c 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -296,6 +296,9 @@
 // Disables Settings based network configuration dialogs.
 const char kDisableNetworkSettingsConfig[] = "disable-network-settings-config";
 
+// Enables using a random url for captive portal detection.
+const char kEnableCaptivePortalRandomUrl[] = "enable-captive-portal-random-url";
+
 // Enables notifications about captive portals in session.
 const char kEnableNetworkPortalNotification[] =
     "enable-network-portal-notification";
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index 07884718..f13d39f 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -78,6 +78,7 @@
 CHROMEOS_EXPORT extern const char kEnableAndroidWallpapersApp[];
 CHROMEOS_EXPORT extern const char kEnableArc[];
 CHROMEOS_EXPORT extern const char kEnableArcOOBEOptIn[];
+CHROMEOS_EXPORT extern const char kEnableCaptivePortalRandomUrl[];
 CHROMEOS_EXPORT extern const char kEnableCastReceiver[];
 CHROMEOS_EXPORT extern const char kEnableChromeVoxArcSupport[];
 CHROMEOS_EXPORT extern const char kEnableConsumerKiosk[];
diff --git a/chromeos/components/tether/BUILD.gn b/chromeos/components/tether/BUILD.gn
index 9e2fa9c..cca2712 100644
--- a/chromeos/components/tether/BUILD.gn
+++ b/chromeos/components/tether/BUILD.gn
@@ -175,6 +175,8 @@
     "fake_disconnect_tethering_request_sender.h",
     "fake_error_tolerant_ble_advertisement.cc",
     "fake_error_tolerant_ble_advertisement.h",
+    "fake_gms_core_notifications_state_tracker.cc",
+    "fake_gms_core_notifications_state_tracker.h",
     "fake_host_scan_cache.cc",
     "fake_host_scan_cache.h",
     "fake_host_scan_scheduler.cc",
diff --git a/chromeos/components/tether/ble_connection_manager.cc b/chromeos/components/tether/ble_connection_manager.cc
index 805bf58..42ba671 100644
--- a/chromeos/components/tether/ble_connection_manager.cc
+++ b/chromeos/components/tether/ble_connection_manager.cc
@@ -585,7 +585,7 @@
     return;
   }
 
-  UMA_HISTOGRAM_TIMES(
+  UMA_HISTOGRAM_MEDIUM_TIMES(
       "InstantTethering.Performance.AdvertisementToConnectionDuration",
       device_id_to_status_connected_time_map_[device_id] -
           device_id_to_advertising_start_time_map_[device_id]);
diff --git a/chromeos/components/tether/fake_gms_core_notifications_state_tracker.cc b/chromeos/components/tether/fake_gms_core_notifications_state_tracker.cc
new file mode 100644
index 0000000..b57619f
--- /dev/null
+++ b/chromeos/components/tether/fake_gms_core_notifications_state_tracker.cc
@@ -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.
+
+#include "chromeos/components/tether/fake_gms_core_notifications_state_tracker.h"
+
+namespace chromeos {
+
+namespace tether {
+
+FakeGmsCoreNotificationsStateTracker::FakeGmsCoreNotificationsStateTracker() =
+    default;
+
+FakeGmsCoreNotificationsStateTracker::~FakeGmsCoreNotificationsStateTracker() =
+    default;
+
+void FakeGmsCoreNotificationsStateTracker::
+    NotifyGmsCoreNotificationStateChanged() {
+  GmsCoreNotificationsStateTracker::NotifyGmsCoreNotificationStateChanged();
+}
+
+std::vector<std::string> FakeGmsCoreNotificationsStateTracker::
+    GetGmsCoreNotificationsDisabledDeviceNames() {
+  return device_names_;
+}
+
+}  // namespace tether
+
+}  // namespace chromeos
diff --git a/chromeos/components/tether/fake_gms_core_notifications_state_tracker.h b/chromeos/components/tether/fake_gms_core_notifications_state_tracker.h
new file mode 100644
index 0000000..f24f9fd
--- /dev/null
+++ b/chromeos/components/tether/fake_gms_core_notifications_state_tracker.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 CHROMEOS_COMPONENTS_TETHER_FAKE_GMS_CORE_NOTIFICATIONS_STATE_TRACKER_H_
+#define CHROMEOS_COMPONENTS_TETHER_FAKE_GMS_CORE_NOTIFICATIONS_STATE_TRACKER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "chromeos/components/tether/gms_core_notifications_state_tracker.h"
+
+namespace chromeos {
+
+namespace tether {
+
+// Test double for GmsCoreNotificationsStateTracker.
+class FakeGmsCoreNotificationsStateTracker
+    : public GmsCoreNotificationsStateTracker {
+ public:
+  FakeGmsCoreNotificationsStateTracker();
+  ~FakeGmsCoreNotificationsStateTracker() override;
+
+  void set_device_names(const std::vector<std::string>& device_names) {
+    device_names_ = device_names;
+  }
+
+  void NotifyGmsCoreNotificationStateChanged();
+
+  // GmsCoreNotificationsStateTracker:
+  std::vector<std::string> GetGmsCoreNotificationsDisabledDeviceNames()
+      override;
+
+ private:
+  std::vector<std::string> device_names_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeGmsCoreNotificationsStateTracker);
+};
+
+}  // namespace tether
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_COMPONENTS_TETHER_FAKE_GMS_CORE_NOTIFICATIONS_STATE_TRACKER_H_
diff --git a/chromeos/dbus/OWNERS b/chromeos/dbus/OWNERS
index d33c0344..4d6cd32 100644
--- a/chromeos/dbus/OWNERS
+++ b/chromeos/dbus/OWNERS
@@ -7,3 +7,4 @@
 per-file *auth_policy*=tnagel@chromium.org
 per-file *cryptohome*=dkrahn@chromium.org
 per-file *power*=derat@chromium.org
+per-file *smb_provider*=zentaro@chromium.org
diff --git a/chromeos/dbus/fake_smb_provider_client.cc b/chromeos/dbus/fake_smb_provider_client.cc
index 45c135f..b1fa40a 100644
--- a/chromeos/dbus/fake_smb_provider_client.cc
+++ b/chromeos/dbus/fake_smb_provider_client.cc
@@ -48,4 +48,18 @@
       base::BindOnce(std::move(callback), smbprovider::ERROR_OK, entry));
 }
 
+void FakeSmbProviderClient::OpenFile(int32_t mount_id,
+                                     const base::FilePath& file_path,
+                                     bool writeable,
+                                     OpenFileCallback callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), smbprovider::ERROR_OK, 1));
+}
+
+void FakeSmbProviderClient::CloseFile(int32_t file_id,
+                                      CloseFileCallback callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), smbprovider::ERROR_OK));
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/fake_smb_provider_client.h b/chromeos/dbus/fake_smb_provider_client.h
index c794ae6..5b03ee3 100644
--- a/chromeos/dbus/fake_smb_provider_client.h
+++ b/chromeos/dbus/fake_smb_provider_client.h
@@ -27,6 +27,11 @@
   void GetMetadataEntry(int32_t mount_id,
                         const base::FilePath& entry_path,
                         GetMetdataEntryCallback callback) override;
+  void OpenFile(int32_t mount_id,
+                const base::FilePath& file_path,
+                bool writeable,
+                OpenFileCallback callback) override;
+  void CloseFile(int32_t file_id, CloseFileCallback callback) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(FakeSmbProviderClient);
diff --git a/chromeos/dbus/smb_provider_client.cc b/chromeos/dbus/smb_provider_client.cc
index c0cc2ca..efd86cc 100644
--- a/chromeos/dbus/smb_provider_client.cc
+++ b/chromeos/dbus/smb_provider_client.cc
@@ -34,7 +34,7 @@
     return smbprovider::ERROR_DBUS_PARSE_FAILED;
   }
   dbus::MessageReader reader(response);
-  smbprovider::ErrorType error(GetErrorFromReader(&reader));
+  smbprovider::ErrorType error = GetErrorFromReader(&reader);
   if (error != smbprovider::ERROR_OK) {
     return error;
   }
@@ -53,65 +53,60 @@
 
   void Mount(const base::FilePath& share_path,
              MountCallback callback) override {
-    dbus::MethodCall method_call(smbprovider::kSmbProviderInterface,
-                                 smbprovider::kMountMethod);
-    dbus::MessageWriter writer(&method_call);
-    smbprovider::MountOptions mount_options;
-    mount_options.set_path(share_path.value());
-    writer.AppendProtoAsArrayOfBytes(mount_options);
-    proxy_->CallMethod(
-        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
-        base::Bind(&SmbProviderClientImpl::HandleMountCallback,
-                   weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)));
+    smbprovider::MountOptions options;
+    options.set_path(share_path.value());
+    CallMethod(smbprovider::kMountMethod, options,
+               &SmbProviderClientImpl::HandleMountCallback, &callback);
   }
 
   void Unmount(int32_t mount_id, UnmountCallback callback) override {
-    dbus::MethodCall method_call(smbprovider::kSmbProviderInterface,
-                                 smbprovider::kUnmountMethod);
-    dbus::MessageWriter writer(&method_call);
-    smbprovider::UnmountOptions unmount_options;
-    unmount_options.set_mount_id(mount_id);
-    writer.AppendProtoAsArrayOfBytes(unmount_options);
-    proxy_->CallMethod(
-        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
-        base::Bind(&SmbProviderClientImpl::HandleUnmountCallback,
-                   weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)));
+    smbprovider::UnmountOptions options;
+    options.set_mount_id(mount_id);
+    CallMethod(smbprovider::kUnmountMethod, options,
+               &SmbProviderClientImpl::HandleUnmountCallback, &callback);
   }
 
   void ReadDirectory(int32_t mount_id,
                      const base::FilePath& directory_path,
                      ReadDirectoryCallback callback) override {
-    dbus::MethodCall method_call(smbprovider::kSmbProviderInterface,
-                                 smbprovider::kReadDirectoryMethod);
-    dbus::MessageWriter writer(&method_call);
-    smbprovider::ReadDirectoryOptions read_directory_options;
-    read_directory_options.set_mount_id(mount_id);
-    read_directory_options.set_directory_path(directory_path.value());
-    writer.AppendProtoAsArrayOfBytes(read_directory_options);
-    proxy_->CallMethod(
-        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
-        base::BindOnce(&SmbProviderClientImpl::HandleProtoCallback<
-                           smbprovider::DirectoryEntryList>,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       base::Passed(&callback)));
+    smbprovider::ReadDirectoryOptions options;
+    options.set_mount_id(mount_id);
+    options.set_directory_path(directory_path.value());
+    CallMethod(smbprovider::kReadDirectoryMethod, options,
+               &SmbProviderClientImpl::HandleProtoCallback<
+                   smbprovider::DirectoryEntryList>,
+               &callback);
   }
 
   void GetMetadataEntry(int32_t mount_id,
                         const base::FilePath& entry_path,
                         GetMetdataEntryCallback callback) override {
-    dbus::MethodCall method_call(smbprovider::kSmbProviderInterface,
-                                 smbprovider::kGetMetadataEntryMethod);
-    dbus::MessageWriter writer(&method_call);
-    smbprovider::GetMetadataEntryOptions get_metadata_entry_options;
-    get_metadata_entry_options.set_mount_id(mount_id);
-    get_metadata_entry_options.set_entry_path(entry_path.value());
-    writer.AppendProtoAsArrayOfBytes(get_metadata_entry_options);
-    proxy_->CallMethod(
-        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
-        base::BindOnce(&SmbProviderClientImpl::HandleProtoCallback<
-                           smbprovider::DirectoryEntry>,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       base::Passed(&callback)));
+    smbprovider::GetMetadataEntryOptions options;
+    options.set_mount_id(mount_id);
+    options.set_entry_path(entry_path.value());
+    CallMethod(smbprovider::kGetMetadataEntryMethod, options,
+               &SmbProviderClientImpl::HandleProtoCallback<
+                   smbprovider::DirectoryEntry>,
+               &callback);
+  }
+
+  void OpenFile(int32_t mount_id,
+                const base::FilePath& file_path,
+                bool writeable,
+                OpenFileCallback callback) override {
+    smbprovider::OpenFileOptions options;
+    options.set_mount_id(mount_id);
+    options.set_file_path(file_path.value());
+    options.set_writeable(writeable);
+    CallMethod(smbprovider::kOpenFileMethod, options,
+               &SmbProviderClientImpl::HandleOpenFileCallback, &callback);
+  }
+
+  void CloseFile(int32_t file_id, CloseFileCallback callback) override {
+    smbprovider::CloseFileOptions options;
+    options.set_file_id(file_id);
+    CallMethod(smbprovider::kCloseFileMethod, options,
+               &SmbProviderClientImpl::HandleCloseFileCallback, &callback);
   }
 
  protected:
@@ -124,6 +119,22 @@
   }
 
  private:
+  // Calls the DBUS method |name|, passing the |protobuf| as an argument.
+  // |handler| is the member function in this class that receives
+  // the response and then passes the processed response to |callback|.
+  template <typename CallbackHandler, typename Callback>
+  void CallMethod(const char* name,
+                  const google::protobuf::MessageLite& protobuf,
+                  CallbackHandler handler,
+                  Callback callback) {
+    dbus::MethodCall method_call(smbprovider::kSmbProviderInterface, name);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendProtoAsArrayOfBytes(protobuf);
+    proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+                       base::Bind(handler, weak_ptr_factory_.GetWeakPtr(),
+                                  base::Passed(callback)));
+  }
+
   // Handles D-Bus callback for mount.
   void HandleMountCallback(MountCallback callback, dbus::Response* response) {
     if (!response) {
@@ -157,6 +168,40 @@
     std::move(callback).Run(GetErrorFromReader(&reader));
   }
 
+  // Handles D-Bus callback for OpenFile.
+  void HandleOpenFileCallback(OpenFileCallback callback,
+                              dbus::Response* response) {
+    if (!response) {
+      DLOG(ERROR) << "OpenFile: failed to call smbprovider";
+      std::move(callback).Run(smbprovider::ERROR_DBUS_PARSE_FAILED, -1);
+      return;
+    }
+    dbus::MessageReader reader(response);
+    smbprovider::ErrorType error = GetErrorFromReader(&reader);
+    if (error != smbprovider::ERROR_OK) {
+      std::move(callback).Run(error, -1);
+      return;
+    }
+    int32_t file_id = -1;
+    if (!reader.PopInt32(&file_id) || file_id < 0) {
+      LOG(ERROR) << "OpenFile: failed to parse mount id";
+      std::move(callback).Run(smbprovider::ERROR_DBUS_PARSE_FAILED, -1);
+      return;
+    }
+    std::move(callback).Run(smbprovider::ERROR_OK, file_id);
+  }
+
+  // Handles D-Bus callback for CloseFile.
+  void HandleCloseFileCallback(CloseFileCallback callback,
+                               dbus::Response* response) {
+    if (!response) {
+      DLOG(ERROR) << "CloseFile: failed to call smbprovider";
+      std::move(callback).Run(smbprovider::ERROR_DBUS_PARSE_FAILED);
+    }
+    dbus::MessageReader reader(response);
+    std::move(callback).Run(GetErrorFromReader(&reader));
+  }
+
   // Handles D-Bus responses for methods that return an error and a protobuf
   // object.
   template <class T>
@@ -179,9 +224,9 @@
 
 }  // namespace
 
-SmbProviderClient::SmbProviderClient() {}
+SmbProviderClient::SmbProviderClient() = default;
 
-SmbProviderClient::~SmbProviderClient() {}
+SmbProviderClient::~SmbProviderClient() = default;
 
 // static
 SmbProviderClient* SmbProviderClient::Create() {
diff --git a/chromeos/dbus/smb_provider_client.h b/chromeos/dbus/smb_provider_client.h
index 94ba9cf6..71762178 100644
--- a/chromeos/dbus/smb_provider_client.h
+++ b/chromeos/dbus/smb_provider_client.h
@@ -30,6 +30,10 @@
   using GetMetdataEntryCallback =
       base::OnceCallback<void(smbprovider::ErrorType error,
                               const smbprovider::DirectoryEntry& entry)>;
+  using OpenFileCallback =
+      base::OnceCallback<void(smbprovider::ErrorType error, int32_t file_id)>;
+  using CloseFileCallback =
+      base::OnceCallback<void(smbprovider::ErrorType error)>;
 
   ~SmbProviderClient() override;
 
@@ -61,6 +65,18 @@
                                 const base::FilePath& entry_path,
                                 GetMetdataEntryCallback callback) = 0;
 
+  // Calls OpenFile. Using the corresponding mount |mount_id|, this opens the
+  // file at a given |file_path|, and passes a file handle to the supplied
+  // OpenFileCallback.
+  virtual void OpenFile(int32_t mount_id,
+                        const base::FilePath& file_path,
+                        bool writeable,
+                        OpenFileCallback callback) = 0;
+
+  // Calls CloseFile. This closes the file with handle |file_id|. Subsequent
+  // operations using file with this handle will fail.
+  virtual void CloseFile(int32_t file_id, CloseFileCallback callback) = 0;
+
  protected:
   // Create() should be used instead.
   SmbProviderClient();
diff --git a/chromeos/login/auth/mock_url_fetchers.cc b/chromeos/login/auth/mock_url_fetchers.cc
index 9f1e10a..59b44ef 100644
--- a/chromeos/login/auth/mock_url_fetchers.cc
+++ b/chromeos/login/auth/mock_url_fetchers.cc
@@ -77,6 +77,12 @@
 SuccessFetcher::~SuccessFetcher() = default;
 
 void SuccessFetcher::Start() {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&SuccessFetcher::RunDelegate, weak_factory_.GetWeakPtr()));
+}
+
+void SuccessFetcher::RunDelegate() {
   delegate()->OnURLFetchComplete(this);
 }
 
diff --git a/chromeos/login/auth/mock_url_fetchers.h b/chromeos/login/auth/mock_url_fetchers.h
index 8e977a7..39c8488e0 100644
--- a/chromeos/login/auth/mock_url_fetchers.h
+++ b/chromeos/login/auth/mock_url_fetchers.h
@@ -69,6 +69,9 @@
   void Start() override;
 
  private:
+  void RunDelegate();
+
+  base::WeakPtrFactory<SuccessFetcher> weak_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(SuccessFetcher);
 };
 
diff --git a/chromeos/network/onc/onc_signature.cc b/chromeos/network/onc/onc_signature.cc
index 5d989db..d23c9f73 100644
--- a/chromeos/network/onc/onc_signature.cc
+++ b/chromeos/network/onc/onc_signature.cc
@@ -138,6 +138,7 @@
     {::onc::openvpn::kStaticChallenge, &kStringSignature},
     {::onc::openvpn::kTLSAuthContents, &kStringSignature},
     {::onc::openvpn::kTLSRemote, &kStringSignature},
+    {::onc::openvpn::kTLSVersionMin, &kStringSignature},
     {::onc::openvpn::kUserAuthenticationType, &kStringSignature},
     {::onc::vpn::kUsername, &kStringSignature},
     // Not supported, yet.
diff --git a/chromeos/network/onc/onc_translation_tables.cc b/chromeos/network/onc/onc_translation_tables.cc
index 2266cf6..857b968 100644
--- a/chromeos/network/onc/onc_translation_tables.cc
+++ b/chromeos/network/onc/onc_translation_tables.cc
@@ -104,6 +104,7 @@
     {::onc::openvpn::kStaticChallenge, shill::kOpenVPNStaticChallengeProperty},
     {::onc::openvpn::kTLSAuthContents, shill::kOpenVPNTLSAuthContentsProperty},
     {::onc::openvpn::kTLSRemote, shill::kOpenVPNTLSRemoteProperty},
+    {::onc::openvpn::kTLSVersionMin, shill::kOpenVPNTLSVersionMinProperty},
     {::onc::vpn::kUsername, shill::kOpenVPNUserProperty},
     {::onc::openvpn::kVerifyHash, shill::kOpenVPNVerifyHashProperty},
     {NULL}};
diff --git a/chromeos/test/data/network/openvpn_clientcert_with_cert_pems.onc b/chromeos/test/data/network/openvpn_clientcert_with_cert_pems.onc
index 41032b590..2e73711 100644
--- a/chromeos/test/data/network/openvpn_clientcert_with_cert_pems.onc
+++ b/chromeos/test/data/network/openvpn_clientcert_with_cert_pems.onc
@@ -31,6 +31,7 @@
             "Proto": "udp",
             "Recommended": [ "Username", "Password", "OTP" ],
             "SaveCredentials": true,
+            "TLSVersionMin": "1.2",
             "Username": "hans"
         },
         "Type": "OpenVPN"
diff --git a/chromeos/test/data/network/openvpn_with_password.onc b/chromeos/test/data/network/openvpn_with_password.onc
index 5cd3717b..56ff0fe 100644
--- a/chromeos/test/data/network/openvpn_with_password.onc
+++ b/chromeos/test/data/network/openvpn_with_password.onc
@@ -17,6 +17,7 @@
             "PushPeerInfo": true,
             "SaveCredentials": false,
             "ServerPollTimeout": 10,
+            "TLSVersionMin": "1.1",
             "UserAuthenticationType": "Password",
             "Username": "abc ${LOGIN_EMAIL} def",
         }
diff --git a/chromeos/test/data/network/shill_openvpn.json b/chromeos/test/data/network/shill_openvpn.json
index 51b8dbe..016bf38 100644
--- a/chromeos/test/data/network/shill_openvpn.json
+++ b/chromeos/test/data/network/shill_openvpn.json
@@ -25,6 +25,7 @@
   "OpenVPN.StaticChallenge":"Please enter token OTP",
   "OpenVPN.TLSAuthContents":"-----BEGIN OpenVPN Static key V1-----\n83f8e7ccd99be189b4663e18615f9166\nd885cdea6c8accb0ebf5be304f0b8081\n5404f2a6574e029815d7a2fb65b83d0c\n676850714c6a56b23415a78e06aad6b1\n34900dd512049598382039e4816cb5ff\n1848532b71af47578c9b4a14b5bca49f\n99e0ae4dae2f4e5eadfea374aeb8fb1e\na6fdf02adc73ea778dfd43d64bf7bc75\n7779d629498f8c2fbfd32812bfdf6df7\n8cebafafef3e5496cb13202274f2768a\n1959bc53d67a70945c4c8c6f34b63327\nfb60dc84990ffec1243461e0b6310f61\ne90aee1f11fb6292d6f5fcd7cd508aab\n50d80f9963589c148cb4b933ec86128d\ned77d3fad6005b62f36369e2319f52bd\n09c6d2e52cce2362a05009dc29b6b39a\n-----END OpenVPN Static key V1-----\n",
   "OpenVPN.TLSRemote":"my.domain.com",
+  "OpenVPN.TLSVersionMin":"1.1",
   "OpenVPN.User":"abc ${LOGIN_EMAIL} def",
   "OpenVPN.VerifyHash":"some hash",
   "OpenVPN.VerifyX509Name":"some x509 name",
diff --git a/chromeos/test/data/network/shill_openvpn_clientcert.json b/chromeos/test/data/network/shill_openvpn_clientcert.json
index 8a936f9..59aa87a 100644
--- a/chromeos/test/data/network/shill_openvpn_clientcert.json
+++ b/chromeos/test/data/network/shill_openvpn_clientcert.json
@@ -8,6 +8,7 @@
    "OpenVPN.Password": "some password",
    "OpenVPN.Port": "1234",
    "OpenVPN.Proto": "udp",
+   "OpenVPN.TLSVersionMin": "1.2",
    "OpenVPN.User": "hans",
    "OpenVPN.RemoteCertKU":"",
    "Provider.Host": "terminus.muc",
diff --git a/chromeos/test/data/network/valid_openvpn_with_cert_pems.onc b/chromeos/test/data/network/valid_openvpn_with_cert_pems.onc
index 908deefc..bcfdedc 100644
--- a/chromeos/test/data/network/valid_openvpn_with_cert_pems.onc
+++ b/chromeos/test/data/network/valid_openvpn_with_cert_pems.onc
@@ -29,6 +29,7 @@
             "StaticChallenge": "Please enter token OTP",
             "TLSAuthContents": "-----BEGIN OpenVPN Static key V1-----\n83f8e7ccd99be189b4663e18615f9166\nd885cdea6c8accb0ebf5be304f0b8081\n5404f2a6574e029815d7a2fb65b83d0c\n676850714c6a56b23415a78e06aad6b1\n34900dd512049598382039e4816cb5ff\n1848532b71af47578c9b4a14b5bca49f\n99e0ae4dae2f4e5eadfea374aeb8fb1e\na6fdf02adc73ea778dfd43d64bf7bc75\n7779d629498f8c2fbfd32812bfdf6df7\n8cebafafef3e5496cb13202274f2768a\n1959bc53d67a70945c4c8c6f34b63327\nfb60dc84990ffec1243461e0b6310f61\ne90aee1f11fb6292d6f5fcd7cd508aab\n50d80f9963589c148cb4b933ec86128d\ned77d3fad6005b62f36369e2319f52bd\n09c6d2e52cce2362a05009dc29b6b39a\n-----END OpenVPN Static key V1-----\n",
             "TLSRemote": "my.domain.com",
+            "TLSVersionMin": "1.1",
             "Username": "abc ${LOGIN_EMAIL} def",
             "UserAuthenticationType": "OTP",
             "VerifyHash": "some hash",
diff --git a/components/BUILD.gn b/components/BUILD.gn
index fa3473a..3d8ab7a 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -70,6 +70,7 @@
     "//components/browsing_data/core:unit_tests",
     "//components/bubble:unit_tests",
     "//components/captive_portal:unit_tests",
+    "//components/cbor:unit_tests",
     "//components/client_update_protocol:unit_tests",
     "//components/cloud_devices/common:unit_tests",
     "//components/component_updater:unit_tests",
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc
index 5beba32..3bf9b02 100644
--- a/components/autofill/core/browser/autofill_metrics.cc
+++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -79,8 +79,7 @@
 ukm::SourceId NewUkmSourceWithUrl(ukm::UkmRecorder* ukm_recorder,
                                   const GURL& url) {
   ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
-  if (ukm_recorder)
-    ukm_recorder->UpdateSourceURL(source_id, url);
+  AutofillMetrics::UpdateSourceURL(ukm_recorder, source_id, url);
   return source_id;
 }
 
@@ -617,6 +616,14 @@
 }  // namespace
 
 // static
+void AutofillMetrics::UpdateSourceURL(ukm::UkmRecorder* ukm_recorder,
+                                      ukm::SourceId source_id,
+                                      const GURL& url) {
+  if (ukm_recorder)
+    ukm_recorder->UpdateSourceURL(source_id, url);
+}
+
+// static
 void AutofillMetrics::LogSubmittedServerCardExpirationStatusMetric(
     SubmittedServerCardExpirationStatusMetric metric) {
   DCHECK_LT(metric, NUM_SUBMITTED_SERVER_CARD_EXPIRATION_STATUS_METRICS);
@@ -1714,7 +1721,7 @@
     const GURL& url) {
   url_ = url;
   if (CanLog())
-    ukm_recorder_->UpdateSourceURL(source_id_, url_);
+    AutofillMetrics::UpdateSourceURL(ukm_recorder_, source_id_, url_);
 }
 
 bool AutofillMetrics::FormInteractionsUkmLogger::CanLog() const {
@@ -1732,7 +1739,7 @@
 
 void AutofillMetrics::FormInteractionsUkmLogger::GetNewSourceID() {
   source_id_ = ukm_recorder_->GetNewSourceID();
-  ukm_recorder_->UpdateSourceURL(source_id_, url_);
+  AutofillMetrics::UpdateSourceURL(ukm_recorder_, source_id_, url_);
 }
 
 AutofillMetrics::UkmTimestampPin::UkmTimestampPin(
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h
index 8e2659f..09e1d06 100644
--- a/components/autofill/core/browser/autofill_metrics.h
+++ b/components/autofill/core/browser/autofill_metrics.h
@@ -683,6 +683,11 @@
     DISALLOW_IMPLICIT_CONSTRUCTORS(UkmTimestampPin);
   };
 
+  // Friended Helper for recording main frame URLs to UKM.
+  static void UpdateSourceURL(ukm::UkmRecorder* ukm_recorder,
+                              ukm::SourceId source_id,
+                              const GURL& url);
+
   // If a credit card that matches a server card (unmasked or not) was submitted
   // on a form, logs whether the submitted card's expiration date matched the
   // server card's known expiration date.
diff --git a/components/browsing_data/core/history_notice_utils_unittest.cc b/components/browsing_data/core/history_notice_utils_unittest.cc
index 2701c85..0126a676 100644
--- a/components/browsing_data/core/history_notice_utils_unittest.cc
+++ b/components/browsing_data/core/history_notice_utils_unittest.cc
@@ -10,10 +10,6 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "components/history/core/test/fake_web_history_service.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-#include "components/signin/core/browser/fake_signin_manager.h"
-#include "components/signin/core/browser/test_signin_client.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/driver/fake_sync_service.h"
 #include "components/version_info/version_info.h"
@@ -64,16 +60,11 @@
 
 class HistoryNoticeUtilsTest : public ::testing::Test {
  public:
-  HistoryNoticeUtilsTest()
-    : signin_client_(nullptr),
-      signin_manager_(&signin_client_, &account_tracker_) {
-  }
+  HistoryNoticeUtilsTest() {}
 
   void SetUp() override {
     sync_service_.reset(new TestSyncService());
     history_service_.reset(new history::FakeWebHistoryService(
-        &oauth2_token_service_,
-        &signin_manager_,
         url_request_context_));
     history_service_->SetupFakeResponse(true /* success */, net::HTTP_OK);
   }
@@ -120,10 +111,6 @@
       run_loop_->Quit();
   }
 
-  FakeProfileOAuth2TokenService oauth2_token_service_;
-  AccountTrackerService account_tracker_;
-  TestSigninClient signin_client_;
-  FakeSigninManagerBase signin_manager_;
   scoped_refptr<net::URLRequestContextGetter> url_request_context_;
   std::unique_ptr<TestSyncService> sync_service_;
   std::unique_ptr<history::FakeWebHistoryService> history_service_;
diff --git a/components/cast_channel/BUILD.gn b/components/cast_channel/BUILD.gn
index 15db44c..2ca9b39 100644
--- a/components/cast_channel/BUILD.gn
+++ b/components/cast_channel/BUILD.gn
@@ -48,6 +48,7 @@
     "//base",
     "//components/cast_channel/proto:cast_channel_proto",
     "//net",
+    "//net:test_support",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/components/cast_channel/cast_socket.cc b/components/cast_channel/cast_socket.cc
index 0b9e88e..9399587 100644
--- a/components/cast_channel/cast_socket.cc
+++ b/components/cast_channel/cast_socket.cc
@@ -455,7 +455,9 @@
                           << CastMessageToString(challenge_message);
 
   ResetConnectLoopCallback();
-  transport_->SendMessage(challenge_message, connect_loop_callback_.callback());
+  // TODO(https://crbug.com/656607): Add proper annotation.
+  transport_->SendMessage(challenge_message, connect_loop_callback_.callback(),
+                          NO_TRAFFIC_ANNOTATION_BUG_656607);
 
   // Always return IO_PENDING since the result is always asynchronous.
   return net::ERR_IO_PENDING;
diff --git a/components/cast_channel/cast_socket_unittest.cc b/components/cast_channel/cast_socket_unittest.cc
index ae543df..37626eb1 100644
--- a/components/cast_channel/cast_socket_unittest.cc
+++ b/components/cast_channel/cast_socket_unittest.cc
@@ -45,6 +45,7 @@
 #include "net/ssl/ssl_server_config.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/test_data_directory.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -403,7 +404,7 @@
     socket_->SetupMockTransport();
     CastMessage challenge_proto = CreateAuthChallenge();
     EXPECT_CALL(*socket_->GetMockTransport(),
-                SendMessage(EqualsProto(challenge_proto), _))
+                SendMessage(EqualsProto(challenge_proto), _, _))
         .WillOnce(PostCompletionCallbackTask<1>(net::OK));
     EXPECT_CALL(*socket_->GetMockTransport(), Start());
     EXPECT_CALL(handler_, OnConnectComplete(socket_.get()));
@@ -618,7 +619,7 @@
 
   CastMessage challenge_proto = CreateAuthChallenge();
   EXPECT_CALL(*socket_->GetMockTransport(),
-              SendMessage(EqualsProto(challenge_proto), _))
+              SendMessage(EqualsProto(challenge_proto), _, _))
       .WillOnce(PostCompletionCallbackTask<1>(net::OK));
   EXPECT_CALL(*socket_->GetMockTransport(), Start());
   EXPECT_CALL(handler_, OnConnectComplete(socket_.get()));
@@ -783,7 +784,7 @@
   socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK);
   socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK);
   EXPECT_CALL(*socket_->GetMockTransport(),
-              SendMessage(EqualsProto(CreateAuthChallenge()), _))
+              SendMessage(EqualsProto(CreateAuthChallenge()), _, _))
       .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET));
 
   EXPECT_CALL(handler_, OnConnectComplete(socket_.get()));
@@ -803,7 +804,7 @@
   socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK);
   socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK);
   EXPECT_CALL(*socket_->GetMockTransport(),
-              SendMessage(EqualsProto(CreateAuthChallenge()), _))
+              SendMessage(EqualsProto(CreateAuthChallenge()), _, _))
       .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET));
   socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete,
                               base::Unretained(&handler_)));
@@ -819,7 +820,7 @@
   socket_->SetupTcpConnect(net::SYNCHRONOUS, net::OK);
   socket_->SetupSslConnect(net::SYNCHRONOUS, net::OK);
   EXPECT_CALL(*socket_->GetMockTransport(),
-              SendMessage(EqualsProto(CreateAuthChallenge()), _))
+              SendMessage(EqualsProto(CreateAuthChallenge()), _, _))
       .WillOnce(PostCompletionCallbackTask<1>(net::OK));
   socket_->AddReadResult(net::SYNCHRONOUS, net::ERR_FAILED);
   EXPECT_CALL(*observer_, OnError(_, ChannelError::CAST_SOCKET_ERROR));
@@ -847,7 +848,7 @@
   EXPECT_CALL(*observer_, OnError(_, ChannelError::AUTHENTICATION_ERROR));
   CastMessage challenge_proto = CreateAuthChallenge();
   EXPECT_CALL(*socket_->GetMockTransport(),
-              SendMessage(EqualsProto(challenge_proto), _))
+              SendMessage(EqualsProto(challenge_proto), _, _))
       .WillOnce(PostCompletionCallbackTask<1>(net::OK));
   EXPECT_CALL(handler_, OnConnectComplete(socket_.get()));
   EXPECT_CALL(*socket_->GetMockTransport(), Start());
@@ -897,8 +898,10 @@
   // Send the test message through a real transport object.
   EXPECT_CALL(handler_, OnWriteComplete(net::OK));
   socket_->transport()->SendMessage(
-      test_message, base::Bind(&CompleteHandler::OnWriteComplete,
-                               base::Unretained(&handler_)));
+      test_message,
+      base::Bind(&CompleteHandler::OnWriteComplete,
+                 base::Unretained(&handler_)),
+      TRAFFIC_ANNOTATION_FOR_TESTS);
   RunPendingTasks();
 
   EXPECT_EQ(ReadyState::OPEN, socket_->ready_state());
@@ -939,8 +942,10 @@
   // Send the test message through a real transport object.
   EXPECT_CALL(handler_, OnWriteComplete(net::OK));
   socket_->transport()->SendMessage(
-      test_message, base::Bind(&CompleteHandler::OnWriteComplete,
-                               base::Unretained(&handler_)));
+      test_message,
+      base::Bind(&CompleteHandler::OnWriteComplete,
+                 base::Unretained(&handler_)),
+      TRAFFIC_ANNOTATION_FOR_TESTS);
   RunPendingTasks();
 
   EXPECT_EQ(ReadyState::OPEN, socket_->ready_state());
@@ -1093,8 +1098,10 @@
 
   EXPECT_CALL(handler_, OnWriteComplete(net::OK));
   socket_->transport()->SendMessage(
-      test_message, base::Bind(&CompleteHandler::OnWriteComplete,
-                               base::Unretained(&handler_)));
+      test_message,
+      base::Bind(&CompleteHandler::OnWriteComplete,
+                 base::Unretained(&handler_)),
+      TRAFFIC_ANNOTATION_FOR_TESTS);
   RunPendingTasks();
 
   read = ReadExactLength(test_message_buffer.get(), test_message_length,
diff --git a/components/cast_channel/cast_test_util.h b/components/cast_channel/cast_test_util.h
index c60da66..4fff1ad8 100644
--- a/components/cast_channel/cast_test_util.h
+++ b/components/cast_channel/cast_test_util.h
@@ -15,6 +15,7 @@
 #include "components/cast_channel/cast_transport.h"
 #include "components/cast_channel/proto/cast_channel.pb.h"
 #include "net/base/ip_endpoint.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace cast_channel {
@@ -27,9 +28,11 @@
   void SetReadDelegate(
       std::unique_ptr<CastTransport::Delegate> delegate) override;
 
-  MOCK_METHOD2(SendMessage,
-               void(const CastMessage& message,
-                    const net::CompletionCallback& callback));
+  MOCK_METHOD3(
+      SendMessage,
+      void(const CastMessage& message,
+           const net::CompletionCallback& callback,
+           const net::NetworkTrafficAnnotationTag& traffic_annotation));
 
   MOCK_METHOD0(Start, void(void));
 
diff --git a/components/cast_channel/cast_transport.cc b/components/cast_channel/cast_transport.cc
index ad71aaa..8036767 100644
--- a/components/cast_channel/cast_transport.cc
+++ b/components/cast_channel/cast_transport.cc
@@ -83,8 +83,10 @@
   }
 }
 
-void CastTransportImpl::SendMessage(const CastMessage& message,
-                                    const net::CompletionCallback& callback) {
+void CastTransportImpl::SendMessage(
+    const CastMessage& message,
+    const net::CompletionCallback& callback,
+    const net::NetworkTrafficAnnotationTag& traffic_annotation) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::string serialized_message;
   if (!MessageFramer::Serialize(message, &serialized_message)) {
@@ -92,8 +94,8 @@
         FROM_HERE, base::Bind(callback, net::ERR_FAILED));
     return;
   }
-  WriteRequest write_request(message.namespace_(), serialized_message,
-                             callback);
+  WriteRequest write_request(message.namespace_(), serialized_message, callback,
+                             traffic_annotation);
 
   write_queue_.push(write_request);
   if (write_state_ == WriteState::IDLE) {
@@ -105,8 +107,11 @@
 CastTransportImpl::WriteRequest::WriteRequest(
     const std::string& namespace_,
     const std::string& payload,
-    const net::CompletionCallback& callback)
-    : message_namespace(namespace_), callback(callback) {
+    const net::CompletionCallback& callback,
+    const net::NetworkTrafficAnnotationTag& traffic_annotation)
+    : message_namespace(namespace_),
+      callback(callback),
+      traffic_annotation_(traffic_annotation) {
   VLOG(2) << "WriteRequest size: " << payload.size();
   io_buffer = new net::DrainableIOBuffer(new net::StringIOBuffer(payload),
                                          payload.size());
@@ -198,7 +203,8 @@
 
   int rv = socket_->Write(
       request.io_buffer.get(), request.io_buffer->BytesRemaining(),
-      base::Bind(&CastTransportImpl::OnWriteResult, base::Unretained(this)));
+      base::Bind(&CastTransportImpl::OnWriteResult, base::Unretained(this)),
+      request.traffic_annotation_);
   return rv;
 }
 
diff --git a/components/cast_channel/cast_transport.h b/components/cast_channel/cast_transport.h
index 3c5d1bc4..7eab1d9 100644
--- a/components/cast_channel/cast_transport.h
+++ b/components/cast_channel/cast_transport.h
@@ -16,6 +16,7 @@
 #include "components/cast_channel/logger.h"
 #include "net/base/completion_callback.h"
 #include "net/base/ip_endpoint.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 
 namespace net {
 class DrainableIOBuffer;
@@ -53,8 +54,10 @@
   // |message|: The message to send.
   // |callback|: Callback to be invoked when the write operation has finished.
   // Virtual for testing.
-  virtual void SendMessage(const CastMessage& message,
-                           const net::CompletionCallback& callback) = 0;
+  virtual void SendMessage(
+      const CastMessage& message,
+      const net::CompletionCallback& callback,
+      const net::NetworkTrafficAnnotationTag& traffic_annotation) = 0;
 
   // Initializes the reading state machine and starts reading from the
   // underlying socket.
@@ -87,8 +90,10 @@
   ~CastTransportImpl() override;
 
   // CastTransport interface.
-  void SendMessage(const CastMessage& message,
-                   const net::CompletionCallback& callback) override;
+  void SendMessage(
+      const CastMessage& message,
+      const net::CompletionCallback& callback,
+      const net::NetworkTrafficAnnotationTag& traffic_annotation) override;
   void Start() override;
   void SetReadDelegate(std::unique_ptr<Delegate> delegate) override;
 
@@ -96,9 +101,11 @@
   // Holds a message to be written to the socket. |callback| is invoked when the
   // message is fully written or an error occurrs.
   struct WriteRequest {
-    explicit WriteRequest(const std::string& namespace_,
-                          const std::string& payload,
-                          const net::CompletionCallback& callback);
+    explicit WriteRequest(
+        const std::string& namespace_,
+        const std::string& payload,
+        const net::CompletionCallback& callback,
+        const net::NetworkTrafficAnnotationTag& traffic_annotation);
     WriteRequest(const WriteRequest& other);
     ~WriteRequest();
 
@@ -109,6 +116,8 @@
     net::CompletionCallback callback;
     // Buffer with outgoing data.
     scoped_refptr<net::DrainableIOBuffer> io_buffer;
+    // Traffic Annotation.
+    net::NetworkTrafficAnnotationTag traffic_annotation_;
   };
 
   static bool IsTerminalReadState(ReadState read_state);
diff --git a/components/cast_channel/cast_transport_unittest.cc b/components/cast_channel/cast_transport_unittest.cc
index 919a1bb..98cb3250 100644
--- a/components/cast_channel/cast_transport_unittest.cc
+++ b/components/cast_channel/cast_transport_unittest.cc
@@ -22,7 +22,7 @@
 #include "net/base/net_errors.h"
 #include "net/log/test_net_log.h"
 #include "net/socket/socket.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -185,7 +185,8 @@
   EXPECT_CALL(write_handler, Complete(net::OK));
   transport_->SendMessage(
       message,
-      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)));
+      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)),
+      TRAFFIC_ANNOTATION_FOR_TESTS);
   RunPendingTasks();
   socket_cbs.Pop(serialized_message.size());
   RunPendingTasks();
@@ -219,7 +220,8 @@
 
   transport_->SendMessage(
       message,
-      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)));
+      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)),
+      TRAFFIC_ANNOTATION_FOR_TESTS);
   RunPendingTasks();
   EXPECT_EQ(serialized_message, output);
   socket_cbs.Pop(1);
@@ -243,7 +245,8 @@
   EXPECT_CALL(*delegate_, OnError(ChannelError::CAST_SOCKET_ERROR));
   transport_->SendMessage(
       message,
-      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)));
+      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)),
+      TRAFFIC_ANNOTATION_FOR_TESTS);
   RunPendingTasks();
   socket_cbs.Pop(net::ERR_CONNECTION_RESET);
   RunPendingTasks();
@@ -267,7 +270,8 @@
   EXPECT_CALL(write_handler, Complete(net::OK));
   transport_->SendMessage(
       message,
-      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)));
+      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)),
+      TRAFFIC_ANNOTATION_FOR_TESTS);
   RunPendingTasks();
   EXPECT_EQ(serialized_message, output);
 }
@@ -293,7 +297,8 @@
   EXPECT_CALL(write_handler, Complete(net::OK));
   transport_->SendMessage(
       message,
-      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)));
+      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)),
+      TRAFFIC_ANNOTATION_FOR_TESTS);
   RunPendingTasks();
   EXPECT_EQ(serialized_message.substr(1, serialized_message.size() - 1),
             output);
@@ -307,7 +312,8 @@
   EXPECT_CALL(write_handler, Complete(net::ERR_FAILED));
   transport_->SendMessage(
       message,
-      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)));
+      base::Bind(&CompleteHandler::Complete, base::Unretained(&write_handler)),
+      TRAFFIC_ANNOTATION_FOR_TESTS);
   RunPendingTasks();
   EXPECT_EQ(ChannelEvent::SOCKET_WRITE,
             logger_->GetLastError(kChannelId).channel_event);
diff --git a/components/cast_channel/keep_alive_delegate.cc b/components/cast_channel/keep_alive_delegate.cc
index d753062ce..72adf69c 100644
--- a/components/cast_channel/keep_alive_delegate.cc
+++ b/components/cast_channel/keep_alive_delegate.cc
@@ -134,9 +134,12 @@
                                              const char* message_type) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   VLOG(2) << "Sending " << message_type;
+  // TODO(https://crbug.com/656607): Add proper annotation.
   socket_->transport()->SendMessage(
-      message, base::Bind(&KeepAliveDelegate::SendKeepAliveMessageComplete,
-                          base::Unretained(this), message_type));
+      message,
+      base::Bind(&KeepAliveDelegate::SendKeepAliveMessageComplete,
+                 base::Unretained(this), message_type),
+      NO_TRAFFIC_ANNOTATION_BUG_656607);
 }
 
 void KeepAliveDelegate::SendKeepAliveMessageComplete(const char* message_type,
diff --git a/components/cast_channel/keep_alive_delegate_unittest.cc b/components/cast_channel/keep_alive_delegate_unittest.cc
index 95fc36d61..3770af0 100644
--- a/components/cast_channel/keep_alive_delegate_unittest.cc
+++ b/components/cast_channel/keep_alive_delegate_unittest.cc
@@ -102,7 +102,7 @@
   EXPECT_CALL(*socket_.mock_transport(),
               SendMessage(EqualsProto(KeepAliveDelegate::CreateKeepAliveMessage(
                               KeepAliveDelegate::kHeartbeatPingType)),
-                          _))
+                          _, _))
       .WillOnce(PostCompletionCallbackTask<1>(net::OK));
   EXPECT_CALL(*inner_delegate_, Start());
   EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(2);
@@ -123,7 +123,7 @@
   EXPECT_CALL(*socket_.mock_transport(),
               SendMessage(EqualsProto(KeepAliveDelegate::CreateKeepAliveMessage(
                               KeepAliveDelegate::kHeartbeatPingType)),
-                          _))
+                          _, _))
       .WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET));
   EXPECT_CALL(*inner_delegate_, Start());
   EXPECT_CALL(*inner_delegate_, OnError(ChannelError::CAST_SOCKET_ERROR));
@@ -145,7 +145,7 @@
   EXPECT_CALL(*socket_.mock_transport(),
               SendMessage(EqualsProto(KeepAliveDelegate::CreateKeepAliveMessage(
                               KeepAliveDelegate::kHeartbeatPingType)),
-                          _))
+                          _, _))
       .WillOnce(PostCompletionCallbackTask<1>(net::OK));
   EXPECT_CALL(*inner_delegate_, OnError(ChannelError::PING_TIMEOUT));
   EXPECT_CALL(*inner_delegate_, Start());
@@ -244,7 +244,7 @@
   EXPECT_CALL(*socket_.mock_transport(),
               SendMessage(EqualsProto(KeepAliveDelegate::CreateKeepAliveMessage(
                               KeepAliveDelegate::kHeartbeatPingType)),
-                          _))
+                          _, _))
       .WillOnce(PostCompletionCallbackTask<1>(net::OK));
   // Forward 1s, at time 1, fire ping timer.
   mock_time_task_runner->FastForwardBy(
diff --git a/components/cbor/BUILD.gn b/components/cbor/BUILD.gn
new file mode 100644
index 0000000..ae9ec5b2
--- /dev/null
+++ b/components/cbor/BUILD.gn
@@ -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.
+
+import("//testing/libfuzzer/fuzzer_test.gni")
+
+component("cbor") {
+  sources = [
+    "cbor_binary.h",
+    "cbor_reader.cc",
+    "cbor_reader.h",
+    "cbor_values.cc",
+    "cbor_values.h",
+    "cbor_writer.cc",
+    "cbor_writer.h",
+  ]
+
+  defines = [ "CBOR_IMPLEMENTATION" ]
+
+  deps = [
+    "//base",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [
+    "cbor_reader_unittest.cc",
+    "cbor_values_unittest.cc",
+    "cbor_writer_unittest.cc",
+  ]
+
+  deps = [
+    ":cbor",
+    "//base",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
+
+fuzzer_test("cbor_reader_fuzzer") {
+  sources = [
+    "cbor_reader_fuzzer.cc",
+  ]
+  deps = [
+    ":cbor",
+    "//base",
+  ]
+  seed_corpus = "cbor_reader_fuzzer_corpus/"
+  libfuzzer_options = [ "max_len=65535" ]
+}
diff --git a/components/cbor/OWNERS b/components/cbor/OWNERS
new file mode 100644
index 0000000..85cda96d
--- /dev/null
+++ b/components/cbor/OWNERS
@@ -0,0 +1,2 @@
+jochen@chromium.org
+engedy@chromium.org
diff --git a/content/browser/webauth/cbor/cbor_binary.h b/components/cbor/cbor_binary.h
similarity index 82%
rename from content/browser/webauth/cbor/cbor_binary.h
rename to components/cbor/cbor_binary.h
index 14a182d..f179065 100644
--- a/content/browser/webauth/cbor/cbor_binary.h
+++ b/components/cbor/cbor_binary.h
@@ -4,11 +4,11 @@
 
 #include <stdint.h>
 
-#ifndef CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_BINARY_H_
-#define CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_BINARY_H_
+#ifndef COMPONENTS_CBOR_CBOR_BINARY_H_
+#define COMPONENTS_CBOR_CBOR_BINARY_H_
 
-namespace content {
-namespace impl {
+namespace cbor {
+namespace constants {
 
 // Mask selecting the low-order 5 bits of the "initial byte", which is where
 // the additional information is encoded.
@@ -29,7 +29,7 @@
 // Indicates the integer is in the next 8 bytes.
 static constexpr uint8_t kAdditionalInformation8Bytes = 27u;
 
-}  // namespace impl
-}  // namespace content
+}  // namespace constants
+}  // namespace cbor
 
-#endif  // CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_BINARY_H_
+#endif  // COMPONENTS_CBOR_CBOR_BINARY_H_
diff --git a/components/cbor/cbor_export.h b/components/cbor/cbor_export.h
new file mode 100644
index 0000000..1b932e6
--- /dev/null
+++ b/components/cbor/cbor_export.h
@@ -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.
+
+#ifndef COMPONENTS_CBOR_CBOR_EXPORT_H_
+#define COMPONENTS_CBOR_CBOR_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(CBOR_IMPLEMENTATION)
+#define CBOR_EXPORT __declspec(dllexport)
+#else
+#define CBOR_EXPORT __declspec(dllimport)
+#endif  // defined(CBOR_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(CBOR_IMPLEMENTATION)
+#define CBOR_EXPORT __attribute__((visibility("default")))
+#else
+#define CBOR_EXPORT
+#endif
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define CBOR_EXPORT
+#endif
+
+#endif  // COMPONENTS_CBOR_CBOR_EXPORT_H_
diff --git a/content/browser/webauth/cbor/cbor_reader.cc b/components/cbor/cbor_reader.cc
similarity index 83%
rename from content/browser/webauth/cbor/cbor_reader.cc
rename to components/cbor/cbor_reader.cc
index f0abecb..c21f4df 100644
--- a/content/browser/webauth/cbor/cbor_reader.cc
+++ b/components/cbor/cbor_reader.cc
@@ -2,27 +2,29 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/webauth/cbor/cbor_reader.h"
+#include "components/cbor/cbor_reader.h"
 
 #include <math.h>
 #include <utility>
 
+#include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
-#include "content/browser/webauth/cbor/cbor_binary.h"
+#include "components/cbor/cbor_binary.h"
 
-namespace content {
+namespace cbor {
 
 namespace {
 
 CBORValue::Type GetMajorType(uint8_t initial_data_byte) {
   return static_cast<CBORValue::Type>(
-      (initial_data_byte & impl::kMajorTypeMask) >> impl::kMajorTypeBitShift);
+      (initial_data_byte & constants::kMajorTypeMask) >>
+      constants::kMajorTypeBitShift);
 }
 
 uint8_t GetAdditionalInfo(uint8_t initial_data_byte) {
-  return initial_data_byte & impl::kAdditionalInformationMask;
+  return initial_data_byte & constants::kAdditionalInformationMask;
 }
 
 // Error messages that correspond to each of the error codes.
@@ -47,6 +49,8 @@
     "Unsupported or unassigned simple value.";
 const char kUnsupportedFloatingPointValue[] =
     "Floating point numbers are not supported.";
+const char kOutOfRangeIntegerValue[] =
+    "Integer values must be between INT64_MIN and INT64_MAX.";
 
 }  // namespace
 
@@ -61,7 +65,7 @@
   CBORReader reader(data.begin(), data.end());
   base::Optional<CBORValue> decoded_cbor = reader.DecodeCBOR(max_nesting_level);
 
-  if (decoded_cbor.has_value())
+  if (decoded_cbor)
     reader.CheckExtraneousData();
   if (error_code_out)
     *error_code_out = reader.GetErrorCode();
@@ -86,23 +90,25 @@
   const auto major_type = GetMajorType(initial_byte);
   const uint8_t additional_info = GetAdditionalInfo(initial_byte);
 
-  uint64_t length;
-  if (!ReadUnsignedInt(additional_info, &length))
+  uint64_t value;
+  if (!ReadVariadicLengthInteger(additional_info, &value))
     return base::nullopt;
 
   switch (major_type) {
     case CBORValue::Type::UNSIGNED:
-      return CBORValue(length);
+      return DecodeValueToUnsigned(value);
+    case CBORValue::Type::NEGATIVE:
+      return DecodeValueToNegative(value);
     case CBORValue::Type::BYTE_STRING:
-      return ReadBytes(length);
+      return ReadBytes(value);
     case CBORValue::Type::STRING:
-      return ReadString(length);
+      return ReadString(value);
     case CBORValue::Type::ARRAY:
-      return ReadCBORArray(length, max_nesting_level);
+      return ReadCBORArray(value, max_nesting_level);
     case CBORValue::Type::MAP:
-      return ReadCBORMap(length, max_nesting_level);
+      return ReadCBORMap(value, max_nesting_level);
     case CBORValue::Type::SIMPLE_VALUE:
-      return ReadSimpleValue(additional_info, length);
+      return ReadSimpleValue(additional_info, value);
     case CBORValue::Type::NONE:
       break;
   }
@@ -111,7 +117,8 @@
   return base::nullopt;
 }
 
-bool CBORReader::ReadUnsignedInt(uint8_t additional_info, uint64_t* value) {
+bool CBORReader::ReadVariadicLengthInteger(uint8_t additional_info,
+                                           uint64_t* value) {
   uint8_t additional_bytes = 0;
   if (additional_info < 24) {
     *value = additional_info;
@@ -141,7 +148,25 @@
   }
 
   *value = int_data;
-  return CheckUintEncodedByteLength(additional_bytes, int_data);
+  return CheckMinimalEncoding(additional_bytes, int_data);
+}
+
+base::Optional<CBORValue> CBORReader::DecodeValueToNegative(uint64_t value) {
+  auto negative_value = -base::CheckedNumeric<int64_t>(value) - 1;
+  if (!negative_value.IsValid()) {
+    error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
+    return base::nullopt;
+  }
+  return CBORValue(negative_value.ValueOrDie());
+}
+
+base::Optional<CBORValue> CBORReader::DecodeValueToUnsigned(uint64_t value) {
+  auto unsigned_value = base::CheckedNumeric<int64_t>(value);
+  if (!unsigned_value.IsValid()) {
+    error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
+    return base::nullopt;
+  }
+  return CBORValue(unsigned_value.ValueOrDie());
 }
 
 base::Optional<CBORValue> CBORReader::ReadSimpleValue(uint8_t additional_info,
@@ -238,8 +263,8 @@
   return false;
 }
 
-bool CBORReader::CheckUintEncodedByteLength(uint8_t additional_bytes,
-                                            uint64_t uint_data) {
+bool CBORReader::CheckMinimalEncoding(uint8_t additional_bytes,
+                                      uint64_t uint_data) {
   if ((additional_bytes == 1 && uint_data < 24) ||
       uint_data <= (1ULL << 8 * (additional_bytes >> 1)) - 1) {
     error_code_ = DecoderError::NON_MINIMAL_CBOR_ENCODING;
@@ -313,10 +338,12 @@
       return kUnsupportedSimpleValue;
     case DecoderError::UNSUPPORTED_FLOATING_POINT_VALUE:
       return kUnsupportedFloatingPointValue;
+    case DecoderError::OUT_OF_RANGE_INTEGER_VALUE:
+      return kOutOfRangeIntegerValue;
     default:
       NOTREACHED();
       return "Unknown error code.";
   }
 }
 
-}  // namespace content
+}  // namespace cbor
diff --git a/content/browser/webauth/cbor/cbor_reader.h b/components/cbor/cbor_reader.h
similarity index 87%
rename from content/browser/webauth/cbor/cbor_reader.h
rename to components/cbor/cbor_reader.h
index e831676..35558891 100644
--- a/content/browser/webauth/cbor/cbor_reader.h
+++ b/components/cbor/cbor_reader.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 CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_READER_H_
-#define CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_READER_H_
+#ifndef COMPONENTS_CBOR_CBOR_READER_H_
+#define COMPONENTS_CBOR_CBOR_READER_H_
 
 #include <stddef.h>
 #include <string>
 #include <vector>
 
 #include "base/optional.h"
-#include "content/browser/webauth/cbor/cbor_values.h"
-#include "content/common/content_export.h"
+#include "components/cbor/cbor_export.h"
+#include "components/cbor/cbor_values.h"
 
 // Concise Binary Object Representation (CBOR) decoder as defined by
 // https://tools.ietf.org/html/rfc7049. This decoder only accepts canonical
@@ -46,9 +46,9 @@
 //  - Simple values that are unassigned/reserved as per RFC 7049 are not
 //    supported and treated as errors.
 
-namespace content {
+namespace cbor {
 
-class CONTENT_EXPORT CBORReader {
+class CBOR_EXPORT CBORReader {
  public:
   using Bytes = std::vector<uint8_t>;
 
@@ -66,6 +66,7 @@
     NON_MINIMAL_CBOR_ENCODING,
     UNSUPPORTED_SIMPLE_VALUE,
     UNSUPPORTED_FLOATING_POINT_VALUE,
+    OUT_OF_RANGE_INTEGER_VALUE,
   };
 
   // CBOR nested depth sufficient for most use cases.
@@ -88,9 +89,11 @@
  private:
   CBORReader(Bytes::const_iterator it, const Bytes::const_iterator end);
   base::Optional<CBORValue> DecodeCBOR(int max_nesting_level);
-  bool ReadUnsignedInt(uint8_t additional_info, uint64_t* length);
+  base::Optional<CBORValue> DecodeValueToNegative(uint64_t value);
+  base::Optional<CBORValue> DecodeValueToUnsigned(uint64_t value);
   base::Optional<CBORValue> ReadSimpleValue(uint8_t additional_info,
                                             uint64_t value);
+  bool ReadVariadicLengthInteger(uint8_t additional_info, uint64_t* value);
   base::Optional<CBORValue> ReadBytes(uint64_t num_bytes);
   base::Optional<CBORValue> ReadString(uint64_t num_bytes);
   base::Optional<CBORValue> ReadCBORArray(uint64_t length,
@@ -101,7 +104,7 @@
   bool CheckDuplicateKey(const CBORValue& new_key, CBORValue::MapValue* map);
   bool HasValidUTF8Format(const std::string& string_data);
   bool CheckOutOfOrderKey(const CBORValue& new_key, CBORValue::MapValue* map);
-  bool CheckUintEncodedByteLength(uint8_t additional_bytes, uint64_t uint_data);
+  bool CheckMinimalEncoding(uint8_t additional_bytes, uint64_t uint_data);
 
   DecoderError GetErrorCode();
 
@@ -112,6 +115,6 @@
   DISALLOW_COPY_AND_ASSIGN(CBORReader);
 };
 
-}  // namespace content
+}  // namespace cbor
 
-#endif  // CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_READER_H_
+#endif  // COMPONENTS_CBOR_CBOR_READER_H_
diff --git a/content/test/fuzzer/cbor_reader_fuzzer.cc b/components/cbor/cbor_reader_fuzzer.cc
similarity index 74%
rename from content/test/fuzzer/cbor_reader_fuzzer.cc
rename to components/cbor/cbor_reader_fuzzer.cc
index f457236..4809e70 100644
--- a/content/test/fuzzer/cbor_reader_fuzzer.cc
+++ b/components/cbor/cbor_reader_fuzzer.cc
@@ -5,12 +5,10 @@
 #include <stdint.h>
 #include <algorithm>
 
-#include "content/browser/webauth/cbor/cbor_reader.h"  // nogncheck
-#include "content/browser/webauth/cbor/cbor_writer.h"  // nogncheck
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "components/cbor/cbor_reader.h"  // nogncheck
+#include "components/cbor/cbor_writer.h"  // nogncheck
 
-namespace content {
+namespace cbor {
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   std::vector<uint8_t> input(data, data + size);
@@ -29,4 +27,4 @@
   return 0;
 }
 
-}  // namespace content
+}  // namespace cbor
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor0 b/components/cbor/cbor_reader_fuzzer_corpus/cbor0
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor0
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor0
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor1 b/components/cbor/cbor_reader_fuzzer_corpus/cbor1
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor1
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor1
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor10 b/components/cbor/cbor_reader_fuzzer_corpus/cbor10
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor10
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor10
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor11 b/components/cbor/cbor_reader_fuzzer_corpus/cbor11
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor11
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor11
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor12 b/components/cbor/cbor_reader_fuzzer_corpus/cbor12
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor12
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor12
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor13 b/components/cbor/cbor_reader_fuzzer_corpus/cbor13
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor13
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor13
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor14 b/components/cbor/cbor_reader_fuzzer_corpus/cbor14
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor14
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor14
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor15 b/components/cbor/cbor_reader_fuzzer_corpus/cbor15
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor15
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor15
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor16 b/components/cbor/cbor_reader_fuzzer_corpus/cbor16
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor16
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor16
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor17 b/components/cbor/cbor_reader_fuzzer_corpus/cbor17
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor17
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor17
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor18 b/components/cbor/cbor_reader_fuzzer_corpus/cbor18
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor18
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor18
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor19 b/components/cbor/cbor_reader_fuzzer_corpus/cbor19
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor19
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor19
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor2 b/components/cbor/cbor_reader_fuzzer_corpus/cbor2
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor2
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor2
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor20 b/components/cbor/cbor_reader_fuzzer_corpus/cbor20
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor20
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor20
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor21 b/components/cbor/cbor_reader_fuzzer_corpus/cbor21
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor21
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor21
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor22 b/components/cbor/cbor_reader_fuzzer_corpus/cbor22
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor22
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor22
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor23 b/components/cbor/cbor_reader_fuzzer_corpus/cbor23
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor23
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor23
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor24 b/components/cbor/cbor_reader_fuzzer_corpus/cbor24
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor24
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor24
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor25 b/components/cbor/cbor_reader_fuzzer_corpus/cbor25
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor25
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor25
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor26 b/components/cbor/cbor_reader_fuzzer_corpus/cbor26
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor26
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor26
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor27 b/components/cbor/cbor_reader_fuzzer_corpus/cbor27
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor27
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor27
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor28 b/components/cbor/cbor_reader_fuzzer_corpus/cbor28
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor28
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor28
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor29 b/components/cbor/cbor_reader_fuzzer_corpus/cbor29
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor29
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor29
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor3 b/components/cbor/cbor_reader_fuzzer_corpus/cbor3
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor3
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor3
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor30 b/components/cbor/cbor_reader_fuzzer_corpus/cbor30
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor30
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor30
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor31 b/components/cbor/cbor_reader_fuzzer_corpus/cbor31
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor31
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor31
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor32 b/components/cbor/cbor_reader_fuzzer_corpus/cbor32
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor32
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor32
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor33 b/components/cbor/cbor_reader_fuzzer_corpus/cbor33
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor33
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor33
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor34 b/components/cbor/cbor_reader_fuzzer_corpus/cbor34
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor34
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor34
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor35 b/components/cbor/cbor_reader_fuzzer_corpus/cbor35
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor35
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor35
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor36 b/components/cbor/cbor_reader_fuzzer_corpus/cbor36
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor36
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor36
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor37 b/components/cbor/cbor_reader_fuzzer_corpus/cbor37
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor37
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor37
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor38 b/components/cbor/cbor_reader_fuzzer_corpus/cbor38
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor38
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor38
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor39 b/components/cbor/cbor_reader_fuzzer_corpus/cbor39
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor39
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor39
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor4 b/components/cbor/cbor_reader_fuzzer_corpus/cbor4
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor4
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor4
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor40 b/components/cbor/cbor_reader_fuzzer_corpus/cbor40
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor40
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor40
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor41 b/components/cbor/cbor_reader_fuzzer_corpus/cbor41
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor41
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor41
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor42 b/components/cbor/cbor_reader_fuzzer_corpus/cbor42
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor42
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor42
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor43 b/components/cbor/cbor_reader_fuzzer_corpus/cbor43
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor43
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor43
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor44 b/components/cbor/cbor_reader_fuzzer_corpus/cbor44
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor44
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor44
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor45 b/components/cbor/cbor_reader_fuzzer_corpus/cbor45
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor45
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor45
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor46 b/components/cbor/cbor_reader_fuzzer_corpus/cbor46
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor46
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor46
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor47 b/components/cbor/cbor_reader_fuzzer_corpus/cbor47
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor47
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor47
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor48 b/components/cbor/cbor_reader_fuzzer_corpus/cbor48
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor48
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor48
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor49 b/components/cbor/cbor_reader_fuzzer_corpus/cbor49
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor49
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor49
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor5 b/components/cbor/cbor_reader_fuzzer_corpus/cbor5
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor5
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor5
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor50 b/components/cbor/cbor_reader_fuzzer_corpus/cbor50
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor50
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor50
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor51 b/components/cbor/cbor_reader_fuzzer_corpus/cbor51
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor51
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor51
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor52 b/components/cbor/cbor_reader_fuzzer_corpus/cbor52
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor52
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor52
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor53 b/components/cbor/cbor_reader_fuzzer_corpus/cbor53
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor53
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor53
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor54 b/components/cbor/cbor_reader_fuzzer_corpus/cbor54
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor54
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor54
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor55 b/components/cbor/cbor_reader_fuzzer_corpus/cbor55
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor55
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor55
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor56 b/components/cbor/cbor_reader_fuzzer_corpus/cbor56
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor56
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor56
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor57 b/components/cbor/cbor_reader_fuzzer_corpus/cbor57
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor57
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor57
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor58 b/components/cbor/cbor_reader_fuzzer_corpus/cbor58
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor58
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor58
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor59 b/components/cbor/cbor_reader_fuzzer_corpus/cbor59
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor59
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor59
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor6 b/components/cbor/cbor_reader_fuzzer_corpus/cbor6
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor6
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor6
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor60 b/components/cbor/cbor_reader_fuzzer_corpus/cbor60
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor60
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor60
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor61 b/components/cbor/cbor_reader_fuzzer_corpus/cbor61
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor61
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor61
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor62 b/components/cbor/cbor_reader_fuzzer_corpus/cbor62
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor62
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor62
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor63 b/components/cbor/cbor_reader_fuzzer_corpus/cbor63
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor63
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor63
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor64 b/components/cbor/cbor_reader_fuzzer_corpus/cbor64
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor64
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor64
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor65 b/components/cbor/cbor_reader_fuzzer_corpus/cbor65
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor65
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor65
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor66 b/components/cbor/cbor_reader_fuzzer_corpus/cbor66
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor66
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor66
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor67 b/components/cbor/cbor_reader_fuzzer_corpus/cbor67
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor67
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor67
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor68 b/components/cbor/cbor_reader_fuzzer_corpus/cbor68
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor68
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor68
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor69 b/components/cbor/cbor_reader_fuzzer_corpus/cbor69
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor69
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor69
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor7 b/components/cbor/cbor_reader_fuzzer_corpus/cbor7
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor7
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor7
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor70 b/components/cbor/cbor_reader_fuzzer_corpus/cbor70
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor70
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor70
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor71 b/components/cbor/cbor_reader_fuzzer_corpus/cbor71
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor71
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor71
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor72 b/components/cbor/cbor_reader_fuzzer_corpus/cbor72
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor72
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor72
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor73 b/components/cbor/cbor_reader_fuzzer_corpus/cbor73
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor73
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor73
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor74 b/components/cbor/cbor_reader_fuzzer_corpus/cbor74
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor74
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor74
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor75 b/components/cbor/cbor_reader_fuzzer_corpus/cbor75
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor75
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor75
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor76 b/components/cbor/cbor_reader_fuzzer_corpus/cbor76
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor76
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor76
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor77 b/components/cbor/cbor_reader_fuzzer_corpus/cbor77
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor77
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor77
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor78 b/components/cbor/cbor_reader_fuzzer_corpus/cbor78
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor78
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor78
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor79 b/components/cbor/cbor_reader_fuzzer_corpus/cbor79
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor79
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor79
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor8 b/components/cbor/cbor_reader_fuzzer_corpus/cbor8
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor8
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor8
Binary files differ
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor80 b/components/cbor/cbor_reader_fuzzer_corpus/cbor80
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor80
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor80
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor81 b/components/cbor/cbor_reader_fuzzer_corpus/cbor81
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor81
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor81
diff --git a/content/test/data/fuzzer_corpus/cbor_data/cbor9 b/components/cbor/cbor_reader_fuzzer_corpus/cbor9
similarity index 100%
rename from content/test/data/fuzzer_corpus/cbor_data/cbor9
rename to components/cbor/cbor_reader_fuzzer_corpus/cbor9
Binary files differ
diff --git a/content/browser/webauth/cbor/cbor_reader_unittest.cc b/components/cbor/cbor_reader_unittest.cc
similarity index 83%
rename from content/browser/webauth/cbor/cbor_reader_unittest.cc
rename to components/cbor/cbor_reader_unittest.cc
index 396d76f..e9819bf 100644
--- a/content/browser/webauth/cbor/cbor_reader_unittest.cc
+++ b/components/cbor/cbor_reader_unittest.cc
@@ -2,45 +2,46 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <limits>
 #include <utility>
 
-#include "content/browser/webauth/cbor/cbor_reader.h"
+#include "components/cbor/cbor_reader.h"
+
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 /* Leveraging RFC 7049 examples from
    https://github.com/cbor/test-vectors/blob/master/appendix_a.json. */
-namespace content {
+namespace cbor {
 
 TEST(CBORReaderTest, TestReadUint) {
-  typedef struct {
-    const uint64_t value;
+  struct UintTestCase {
+    const int64_t value;
     const std::vector<uint8_t> cbor_data;
-  } UintTestCase;
+  };
 
   static const UintTestCase kUintTestCases[] = {
       {0, {0x00}},
       {1, {0x01}},
-      {10, {0x0a}},
       {23, {0x17}},
       {24, {0x18, 0x18}},
-      {25, {0x18, 0x19}},
-      {100, {0x18, 0x64}},
-      {1000, {0x19, 0x03, 0xe8}},
-      {1000000, {0x1a, 0x00, 0x0f, 0x42, 0x40}},
-      {0xFFFFFFFF, {0x1a, 0xff, 0xff, 0xff, 0xff}},
+      {std::numeric_limits<uint8_t>::max(), {0x18, 0xff}},
+      {1LL << 8, {0x19, 0x01, 0x00}},
+      {std::numeric_limits<uint16_t>::max(), {0x19, 0xff, 0xff}},
+      {1LL << 16, {0x1a, 0x00, 0x01, 0x00, 0x00}},
+      {std::numeric_limits<uint32_t>::max(), {0x1a, 0xff, 0xff, 0xff, 0xff}},
+      {1LL << 32, {0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}},
+      {std::numeric_limits<int64_t>::max(),
+       {0x1b, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
   };
 
-  int test_case_index = 0;
   for (const UintTestCase& test_case : kUintTestCases) {
-    testing::Message scope_message;
-    scope_message << "testing uint at index : " << test_case_index++;
-    SCOPED_TRACE(scope_message);
+    SCOPED_TRACE(testing::Message() << "testing uint: " << test_case.value);
 
     base::Optional<CBORValue> cbor = CBORReader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
     ASSERT_EQ(cbor.value().type(), CBORValue::Type::UNSIGNED);
-    EXPECT_EQ(cbor.value().GetUnsigned(), test_case.value);
+    EXPECT_EQ(cbor.value().GetInteger(), test_case.value);
   }
 }
 
@@ -84,9 +85,8 @@
   int test_case_index = 0;
   CBORReader::DecoderError error_code;
   for (const auto& non_minimal_uint : non_minimal_uint_encodings) {
-    testing::Message scope_message;
-    scope_message << "testing element at index " << test_case_index++;
-    SCOPED_TRACE(scope_message);
+    SCOPED_TRACE(testing::Message()
+                 << "testing element at index : " << test_case_index++);
 
     base::Optional<CBORValue> cbor =
         CBORReader::Read(non_minimal_uint, &error_code);
@@ -95,11 +95,39 @@
   }
 }
 
+TEST(CBORReaderTest, TestReadNegativeInt) {
+  struct NegativeIntTestCase {
+    const int64_t negative_int;
+    const std::vector<uint8_t> cbor_data;
+  };
+
+  static const NegativeIntTestCase kNegativeIntTestCases[] = {
+      {-1LL, {0x20}},
+      {-24LL, {0x37}},
+      {-25LL, {0x38, 0x18}},
+      {-256LL, {0x38, 0xff}},
+      {-1000LL, {0x39, 0x03, 0xe7}},
+      {-1000000LL, {0x3a, 0x00, 0x0f, 0x42, 0x3f}},
+      {-4294967296LL, {0x3a, 0xff, 0xff, 0xff, 0xff}},
+      {std::numeric_limits<int64_t>::min(),
+       {0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}};
+
+  for (const NegativeIntTestCase& test_case : kNegativeIntTestCases) {
+    SCOPED_TRACE(testing::Message()
+                 << "testing negative int : " << test_case.negative_int);
+
+    base::Optional<CBORValue> cbor = CBORReader::Read(test_case.cbor_data);
+    ASSERT_TRUE(cbor.has_value());
+    ASSERT_EQ(cbor.value().type(), CBORValue::Type::NEGATIVE);
+    EXPECT_EQ(cbor.value().GetInteger(), test_case.negative_int);
+  }
+}
+
 TEST(CBORReaderTest, TestReadBytes) {
-  typedef struct {
+  struct ByteTestCase {
     const std::vector<uint8_t> value;
     const std::vector<uint8_t> cbor_data;
-  } ByteTestCase;
+  };
 
   static const ByteTestCase kByteStringTestCases[] = {
       // clang-format off
@@ -110,9 +138,8 @@
 
   int element_index = 0;
   for (const ByteTestCase& test_case : kByteStringTestCases) {
-    testing::Message scope_message;
-    scope_message << "testing string test case at : " << element_index++;
-    SCOPED_TRACE(scope_message);
+    SCOPED_TRACE(testing::Message()
+                 << "testing string test case at : " << element_index++);
 
     base::Optional<CBORValue> cbor = CBORReader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
@@ -122,10 +149,10 @@
 }
 
 TEST(CBORReaderTest, TestReadString) {
-  typedef struct {
+  struct StringTestCase {
     const std::string value;
     const std::vector<uint8_t> cbor_data;
-  } StringTestCase;
+  };
 
   static const StringTestCase kStringTestCases[] = {
       {"", {0x60}},
@@ -138,9 +165,8 @@
   };
 
   for (const StringTestCase& test_case : kStringTestCases) {
-    testing::Message scope_message;
-    scope_message << "testing string value : " << test_case.value;
-    SCOPED_TRACE(scope_message);
+    SCOPED_TRACE(testing::Message()
+                 << "testing string value : " << test_case.value);
 
     base::Optional<CBORValue> cbor = CBORReader::Read(test_case.cbor_data);
     ASSERT_TRUE(cbor.has_value());
@@ -211,13 +237,11 @@
 
   std::vector<CBORValue> array;
   for (int i = 0; i < 25; i++) {
-    testing::Message scope_message;
-    scope_message << "testing array element at index " << i;
-    SCOPED_TRACE(scope_message);
+    SCOPED_TRACE(testing::Message() << "testing array element at index " << i);
 
     ASSERT_EQ(cbor_array.GetArray()[i].type(), CBORValue::Type::UNSIGNED);
-    EXPECT_EQ(cbor_array.GetArray()[i].GetUnsigned(),
-              static_cast<uint64_t>(i + 1));
+    EXPECT_EQ(cbor_array.GetArray()[i].GetInteger(),
+              static_cast<int64_t>(i + 1));
   }
 }
 
@@ -343,7 +367,7 @@
   ASSERT_EQ(cbor_val.GetMap().count(key_a), 1u);
   ASSERT_EQ(cbor_val.GetMap().find(key_a)->second.type(),
             CBORValue::Type::UNSIGNED);
-  EXPECT_EQ(cbor_val.GetMap().find(key_a)->second.GetUnsigned(), 1u);
+  EXPECT_EQ(cbor_val.GetMap().find(key_a)->second.GetInteger(), 1u);
 
   const CBORValue key_b("b");
   ASSERT_EQ(cbor_val.GetMap().count(key_b), 1u);
@@ -354,8 +378,8 @@
   ASSERT_EQ(nested_array.GetArray().size(), 2u);
   for (int i = 0; i < 2; i++) {
     ASSERT_THAT(nested_array.GetArray()[i].type(), CBORValue::Type::UNSIGNED);
-    EXPECT_EQ(nested_array.GetArray()[i].GetUnsigned(),
-              static_cast<uint64_t>(i + 2));
+    EXPECT_EQ(nested_array.GetArray()[i].GetInteger(),
+              static_cast<int64_t>(i + 2));
   }
 }
 
@@ -386,7 +410,7 @@
   ASSERT_EQ(cbor_val.GetMap().count(key_a), 1u);
   ASSERT_EQ(cbor_val.GetMap().find(key_a)->second.type(),
             CBORValue::Type::UNSIGNED);
-  EXPECT_EQ(cbor_val.GetMap().find(key_a)->second.GetUnsigned(), 1u);
+  EXPECT_EQ(cbor_val.GetMap().find(key_a)->second.GetInteger(), 1u);
 
   const CBORValue key_b("b");
   ASSERT_EQ(cbor_val.GetMap().count(key_b), 1u);
@@ -398,13 +422,49 @@
   ASSERT_EQ(nested_map.GetMap().count(key_c), 1u);
   ASSERT_EQ(nested_map.GetMap().find(key_c)->second.type(),
             CBORValue::Type::UNSIGNED);
-  EXPECT_EQ(nested_map.GetMap().find(key_c)->second.GetUnsigned(), 2u);
+  EXPECT_EQ(nested_map.GetMap().find(key_c)->second.GetInteger(), 2u);
 
   const CBORValue key_d("d");
   ASSERT_EQ(nested_map.GetMap().count(key_d), 1u);
   ASSERT_EQ(nested_map.GetMap().find(key_d)->second.type(),
             CBORValue::Type::UNSIGNED);
-  EXPECT_EQ(nested_map.GetMap().find(key_d)->second.GetUnsigned(), 3u);
+  EXPECT_EQ(nested_map.GetMap().find(key_d)->second.GetInteger(), 3u);
+}
+
+TEST(CBORReaderTest, TestIntegerRange) {
+  static const std::vector<uint8_t> kMaxPositiveInt = {
+      0x1b, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+  static const std::vector<uint8_t> kMinNegativeInt = {
+      0x3b, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+  base::Optional<CBORValue> max_positive_int =
+      CBORReader::Read(kMaxPositiveInt);
+  ASSERT_TRUE(max_positive_int.has_value());
+  EXPECT_EQ(max_positive_int.value().GetInteger(), INT64_MAX);
+
+  base::Optional<CBORValue> min_negative_int =
+      CBORReader::Read(kMinNegativeInt);
+  ASSERT_TRUE(min_negative_int.has_value());
+  EXPECT_EQ(min_negative_int.value().GetInteger(), INT64_MIN);
+}
+
+TEST(CBORReaderTest, TestIntegerOutOfRangeError) {
+  static const std::vector<uint8_t> kOutOfRangePositiveInt = {
+      0x1b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+  static const std::vector<uint8_t> kOutOfRangeNegativeInt = {
+      0x3b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+  CBORReader::DecoderError error_code;
+  base::Optional<CBORValue> positive_int_out_of_range_cbor =
+      CBORReader::Read(kOutOfRangePositiveInt, &error_code);
+  EXPECT_FALSE(positive_int_out_of_range_cbor.has_value());
+  EXPECT_EQ(error_code, CBORReader::DecoderError::OUT_OF_RANGE_INTEGER_VALUE);
+
+  base::Optional<CBORValue> negative_int_out_of_range_cbor =
+      CBORReader::Read(kOutOfRangeNegativeInt, &error_code);
+  EXPECT_FALSE(negative_int_out_of_range_cbor.has_value());
+  EXPECT_EQ(error_code, CBORReader::DecoderError::OUT_OF_RANGE_INTEGER_VALUE);
 }
 
 TEST(CBORReaderTest, TestReadSimpleValue) {
@@ -471,10 +531,8 @@
 
   int test_element_index = 0;
   for (const auto& incomplete_data : incomplete_cbor_list) {
-    testing::Message scope_message;
-    scope_message << "testing incomplete data at index : "
-                  << test_element_index++;
-    SCOPED_TRACE(scope_message);
+    SCOPED_TRACE(testing::Message() << "testing incomplete data at index : "
+                                    << test_element_index++);
 
     CBORReader::DecoderError error_code;
     base::Optional<CBORValue> cbor =
@@ -529,9 +587,8 @@
 
   int test_element_index = 0;
   for (const auto& incorrect_cbor : kUnknownAdditionalInfoList) {
-    testing::Message scope_message;
-    scope_message << "testing data : " << test_element_index++;
-    SCOPED_TRACE(scope_message);
+    SCOPED_TRACE(testing::Message()
+                 << "testing data at index : " << test_element_index++);
 
     CBORReader::DecoderError error_code;
     base::Optional<CBORValue> cbor =
@@ -557,10 +614,8 @@
 
   int test_element_index = 0;
   for (const auto& zero_depth_data : kZeroDepthCBORList) {
-    testing::Message scope_message;
-    scope_message << "testing zero nested data : " << test_element_index++;
-    SCOPED_TRACE(scope_message);
-
+    SCOPED_TRACE(testing::Message()
+                 << "testing zero nested data : " << test_element_index++);
     CBORReader::DecoderError error_code;
     base::Optional<CBORValue> cbor =
         CBORReader::Read(zero_depth_data, &error_code, 0);
@@ -684,10 +739,8 @@
   int test_element_index = 0;
   CBORReader::DecoderError error_code;
   for (const auto& cbor_byte : utf8_character_encodings) {
-    testing::Message scope_message;
-    scope_message << "testing cbor data utf8 encoding : "
-                  << test_element_index++;
-    SCOPED_TRACE(scope_message);
+    SCOPED_TRACE(testing::Message() << "testing cbor data utf8 encoding : "
+                                    << test_element_index++);
 
     base::Optional<CBORValue> correctly_encoded_cbor =
         CBORReader::Read(cbor_byte, &error_code);
@@ -719,9 +772,8 @@
 
   int test_element_index = 0;
   for (const auto& extraneous_cbor_data : zero_padded_cbor_list) {
-    testing::Message scope_message;
-    scope_message << "testing cbor extraneous data : " << test_element_index++;
-    SCOPED_TRACE(scope_message);
+    SCOPED_TRACE(testing::Message()
+                 << "testing cbor extraneous data : " << test_element_index++);
 
     CBORReader::DecoderError error_code;
     base::Optional<CBORValue> cbor =
@@ -766,4 +818,4 @@
   }
 }
 
-}  // namespace content
+}  // namespace cbor
diff --git a/content/browser/webauth/cbor/cbor_values.cc b/components/cbor/cbor_values.cc
similarity index 84%
rename from content/browser/webauth/cbor/cbor_values.cc
rename to components/cbor/cbor_values.cc
index bd0f1e9..b4517650 100644
--- a/content/browser/webauth/cbor/cbor_values.cc
+++ b/components/cbor/cbor_values.cc
@@ -2,14 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/webauth/cbor/cbor_values.h"
+#include "components/cbor/cbor_values.h"
 
 #include <new>
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/string_util.h"
 
-namespace content {
+namespace cbor {
 
 CBORValue::CBORValue() noexcept : type_(Type::NONE) {}
 
@@ -21,7 +22,8 @@
   // Initialize with the default value.
   switch (type_) {
     case Type::UNSIGNED:
-      unsigned_value_ = 0;
+    case Type::NEGATIVE:
+      integer_value_ = 0;
       return;
     case Type::BYTE_STRING:
       new (&bytestring_value_) BinaryValue();
@@ -44,8 +46,12 @@
   NOTREACHED();
 }
 
-CBORValue::CBORValue(uint64_t in_unsigned)
-    : type_(Type::UNSIGNED), unsigned_value_(in_unsigned) {}
+CBORValue::CBORValue(int integer_value)
+    : CBORValue(base::checked_cast<int64_t>(integer_value)) {}
+
+CBORValue::CBORValue(int64_t integer_value) : integer_value_(integer_value) {
+  type_ = integer_value >= 0 ? Type::UNSIGNED : Type::NEGATIVE;
+}
 
 CBORValue::CBORValue(const BinaryValue& in_bytes)
     : type_(Type::BYTE_STRING), bytestring_value_(in_bytes) {}
@@ -105,7 +111,8 @@
     case Type::NONE:
       return CBORValue();
     case Type::UNSIGNED:
-      return CBORValue(unsigned_value_);
+    case Type::NEGATIVE:
+      return CBORValue(integer_value_);
     case Type::BYTE_STRING:
       return CBORValue(bytestring_value_);
     case Type::STRING:
@@ -122,9 +129,21 @@
   return CBORValue();
 }
 
-const uint64_t& CBORValue::GetUnsigned() const {
+const int64_t& CBORValue::GetInteger() const {
+  CHECK(is_integer());
+  return integer_value_;
+}
+
+const int64_t& CBORValue::GetUnsigned() const {
   CHECK(is_unsigned());
-  return unsigned_value_;
+  CHECK_GE(integer_value_, 0);
+  return integer_value_;
+}
+
+const int64_t& CBORValue::GetNegative() const {
+  CHECK(is_negative());
+  CHECK_LT(integer_value_, 0);
+  return integer_value_;
 }
 
 const std::string& CBORValue::GetString() const {
@@ -157,7 +176,8 @@
 
   switch (type_) {
     case Type::UNSIGNED:
-      unsigned_value_ = that.unsigned_value_;
+    case Type::NEGATIVE:
+      integer_value_ = that.integer_value_;
       return;
     case Type::BYTE_STRING:
       new (&bytestring_value_) BinaryValue(std::move(that.bytestring_value_));
@@ -196,10 +216,11 @@
       break;
     case Type::NONE:
     case Type::UNSIGNED:
+    case Type::NEGATIVE:
     case Type::SIMPLE_VALUE:
       break;
   }
   type_ = Type::NONE;
 }
 
-}  // namespace content
+}  // namespace cbor
diff --git a/content/browser/webauth/cbor/cbor_values.h b/components/cbor/cbor_values.h
similarity index 83%
rename from content/browser/webauth/cbor/cbor_values.h
rename to components/cbor/cbor_values.h
index 9b35fda..53eea21 100644
--- a/content/browser/webauth/cbor/cbor_values.h
+++ b/components/cbor/cbor_values.h
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_VALUES_H_
-#define CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_VALUES_H_
+#ifndef COMPONENTS_CBOR_CBOR_VALUES_H_
+#define COMPONENTS_CBOR_CBOR_VALUES_H_
 
+#include <stdint.h>
 #include <string>
 #include <tuple>
 #include <vector>
@@ -12,16 +13,15 @@
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/strings/string_piece.h"
-#include "content/common/content_export.h"
+#include "components/cbor/cbor_export.h"
 
-namespace content {
+namespace cbor {
 
 // A class for Concise Binary Object Representation (CBOR) values.
 // This does not support:
-//  * Negative integers.
 //  * Floating-point numbers.
 //  * Indefinite-length encodings.
-class CONTENT_EXPORT CBORValue {
+class CBOR_EXPORT CBORValue {
  public:
   struct CTAPLess {
     // Comparison predicate to order keys in a dictionary as required by the
@@ -43,13 +43,15 @@
     // types are compared first. Thus the shortest key sorts first by the RFC
     // rules (irrespective of the major type), but may not by CTAP rules.
     bool operator()(const CBORValue& a, const CBORValue& b) const {
-      DCHECK((a.is_unsigned() || a.is_string()) &&
-             (b.is_unsigned() || b.is_string()));
+      DCHECK((a.is_integer() || a.is_string()) &&
+             (b.is_integer() || b.is_string()));
       if (a.type() != b.type())
         return a.type() < b.type();
       switch (a.type()) {
         case Type::UNSIGNED:
-          return a.GetUnsigned() < b.GetUnsigned();
+          return a.GetInteger() < b.GetInteger();
+        case Type::NEGATIVE:
+          return a.GetInteger() > b.GetInteger();
         case Type::STRING: {
           const auto& a_str = a.GetString();
           const size_t a_length = a_str.size();
@@ -74,6 +76,7 @@
 
   enum class Type {
     UNSIGNED = 0,
+    NEGATIVE = 1,
     BYTE_STRING = 2,
     STRING = 3,
     ARRAY = 4,
@@ -93,7 +96,9 @@
   CBORValue() noexcept;  // A NONE value.
 
   explicit CBORValue(Type type);
-  explicit CBORValue(uint64_t in_unsigned);
+  explicit CBORValue(int integer_value);
+  explicit CBORValue(int64_t integer_value);
+  explicit CBORValue(uint64_t integer_value) = delete;
 
   explicit CBORValue(const BinaryValue& in_bytes);
   explicit CBORValue(BinaryValue&& in_bytes) noexcept;
@@ -125,6 +130,8 @@
   bool is_type(Type type) const { return type == type_; }
   bool is_none() const { return type() == Type::NONE; }
   bool is_unsigned() const { return type() == Type::UNSIGNED; }
+  bool is_negative() const { return type() == Type::NEGATIVE; }
+  bool is_integer() const { return is_unsigned() || is_negative(); }
   bool is_bytestring() const { return type() == Type::BYTE_STRING; }
   bool is_string() const { return type() == Type::STRING; }
   bool is_array() const { return type() == Type::ARRAY; }
@@ -132,8 +139,10 @@
   bool is_simple() const { return type() == Type::SIMPLE_VALUE; }
 
   // These will all fatally assert if the type doesn't match.
-  const uint64_t& GetUnsigned() const;
   SimpleValue GetSimpleValue() const;
+  const int64_t& GetInteger() const;
+  const int64_t& GetUnsigned() const;
+  const int64_t& GetNegative() const;
   const BinaryValue& GetBytestring() const;
   // Returned string may contain NUL characters.
   const std::string& GetString() const;
@@ -145,7 +154,7 @@
 
   union {
     SimpleValue simple_value_;
-    uint64_t unsigned_value_;
+    int64_t integer_value_;
     BinaryValue bytestring_value_;
     std::string string_value_;
     ArrayValue array_value_;
@@ -157,6 +166,6 @@
 
   DISALLOW_COPY_AND_ASSIGN(CBORValue);
 };
-}  // namespace content
+}  // namespace cbor
 
-#endif  // CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_VALUES_H_
+#endif  // COMPONENTS_CBOR_CBOR_VALUES_H_
diff --git a/content/browser/webauth/cbor/cbor_values_unittest.cc b/components/cbor/cbor_values_unittest.cc
similarity index 83%
rename from content/browser/webauth/cbor/cbor_values_unittest.cc
rename to components/cbor/cbor_values_unittest.cc
index 4ef956a..b003e83 100644
--- a/content/browser/webauth/cbor/cbor_values_unittest.cc
+++ b/components/cbor/cbor_values_unittest.cc
@@ -2,15 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/webauth/cbor/cbor_values.h"
+#include "components/cbor/cbor_values.h"
 
 #include <string>
 #include <utility>
 
-#include "base/strings/string_piece.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace content {
+namespace cbor {
 
 TEST(CBORValuesTest, TestNothrow) {
   static_assert(std::is_nothrow_move_constructible<CBORValue>::value,
@@ -33,7 +32,13 @@
 TEST(CBORValuesTest, ConstructUnsigned) {
   CBORValue value(37);
   ASSERT_EQ(CBORValue::Type::UNSIGNED, value.type());
-  EXPECT_EQ(37u, value.GetUnsigned());
+  EXPECT_EQ(37u, value.GetInteger());
+}
+
+TEST(CBORValuesTest, ConstructNegative) {
+  CBORValue value(-1);
+  ASSERT_EQ(CBORValue::Type::NEGATIVE, value.type());
+  EXPECT_EQ(-1, value.GetInteger());
 }
 
 TEST(CBORValuesTest, ConstructStringFromConstCharPtr) {
@@ -133,13 +138,26 @@
   CBORValue value(74);
   CBORValue copied_value(value.Clone());
   ASSERT_EQ(value.type(), copied_value.type());
-  EXPECT_EQ(value.GetUnsigned(), copied_value.GetUnsigned());
+  EXPECT_EQ(value.GetInteger(), copied_value.GetInteger());
 
   CBORValue blank;
 
   blank = value.Clone();
   ASSERT_EQ(value.type(), blank.type());
-  EXPECT_EQ(value.GetUnsigned(), blank.GetUnsigned());
+  EXPECT_EQ(value.GetInteger(), blank.GetInteger());
+}
+
+TEST(CBORValuesTest, CopyNegativeInt) {
+  CBORValue value(-74);
+  CBORValue copied_value(value.Clone());
+  ASSERT_EQ(value.type(), copied_value.type());
+  EXPECT_EQ(value.GetInteger(), copied_value.GetInteger());
+
+  CBORValue blank;
+
+  blank = value.Clone();
+  ASSERT_EQ(value.type(), blank.type());
+  EXPECT_EQ(value.GetInteger(), blank.GetInteger());
 }
 
 TEST(CBORValuesTest, CopyString) {
@@ -175,8 +193,9 @@
 
   CBORValue copied_value(value.Clone());
   ASSERT_EQ(1u, copied_value.GetArray().size());
-  EXPECT_EQ(value.GetArray()[0].GetUnsigned(),
-            copied_value.GetArray()[0].GetUnsigned());
+  ASSERT_TRUE(copied_value.GetArray()[0].is_unsigned());
+  EXPECT_EQ(value.GetArray()[0].GetInteger(),
+            copied_value.GetArray()[0].GetInteger());
 
   CBORValue blank;
   blank = value.Clone();
@@ -194,16 +213,16 @@
   ASSERT_EQ(value.GetMap().count(key_a), 1u);
   ASSERT_EQ(copied_value.GetMap().count(key_a), 1u);
   ASSERT_TRUE(copied_value.GetMap().find(key_a)->second.is_unsigned());
-  EXPECT_EQ(value.GetMap().find(key_a)->second.GetUnsigned(),
-            copied_value.GetMap().find(key_a)->second.GetUnsigned());
+  EXPECT_EQ(value.GetMap().find(key_a)->second.GetInteger(),
+            copied_value.GetMap().find(key_a)->second.GetInteger());
 
   CBORValue blank;
   blank = value.Clone();
   EXPECT_EQ(1u, blank.GetMap().size());
   ASSERT_EQ(blank.GetMap().count(key_a), 1u);
   ASSERT_TRUE(blank.GetMap().find(key_a)->second.is_unsigned());
-  EXPECT_EQ(value.GetMap().find(key_a)->second.GetUnsigned(),
-            blank.GetMap().find(key_a)->second.GetUnsigned());
+  EXPECT_EQ(value.GetMap().find(key_a)->second.GetInteger(),
+            blank.GetMap().find(key_a)->second.GetInteger());
 }
 
 TEST(CBORValuesTest, CopySimpleValue) {
@@ -224,13 +243,26 @@
   CBORValue value(74);
   CBORValue moved_value(std::move(value));
   EXPECT_EQ(CBORValue::Type::UNSIGNED, moved_value.type());
-  EXPECT_EQ(74u, moved_value.GetUnsigned());
+  EXPECT_EQ(74u, moved_value.GetInteger());
 
   CBORValue blank;
 
   blank = CBORValue(654);
   EXPECT_EQ(CBORValue::Type::UNSIGNED, blank.type());
-  EXPECT_EQ(654u, blank.GetUnsigned());
+  EXPECT_EQ(654u, blank.GetInteger());
+}
+
+TEST(CBORValuesTest, MoveNegativeInteger) {
+  CBORValue value(-74);
+  CBORValue moved_value(std::move(value));
+  EXPECT_EQ(CBORValue::Type::NEGATIVE, moved_value.type());
+  EXPECT_EQ(-74, moved_value.GetInteger());
+
+  CBORValue blank;
+
+  blank = CBORValue(-654);
+  EXPECT_EQ(CBORValue::Type::NEGATIVE, blank.type());
+  EXPECT_EQ(-654, blank.GetInteger());
 }
 
 TEST(CBORValuesTest, MoveString) {
@@ -270,7 +302,7 @@
   ASSERT_EQ(CBORValue::Type::MAP, moved_value.type());
   ASSERT_EQ(moved_value.GetMap().count(key_a), 1u);
   ASSERT_TRUE(moved_value.GetMap().find(key_a)->second.is_unsigned());
-  EXPECT_EQ(123u, moved_value.GetMap().find(key_a)->second.GetUnsigned());
+  EXPECT_EQ(123u, moved_value.GetMap().find(key_a)->second.GetInteger());
 }
 
 TEST(CBORValuesTest, MoveAssignMap) {
@@ -283,7 +315,7 @@
   ASSERT_TRUE(blank.is_map());
   ASSERT_EQ(blank.GetMap().count(key_a), 1u);
   ASSERT_TRUE(blank.GetMap().find(key_a)->second.is_unsigned());
-  EXPECT_EQ(123u, blank.GetMap().find(key_a)->second.GetUnsigned());
+  EXPECT_EQ(123u, blank.GetMap().find(key_a)->second.GetInteger());
 }
 
 TEST(CBORValuesTest, MoveArray) {
@@ -292,18 +324,12 @@
   CBORValue value(array);
   CBORValue moved_value(std::move(value));
   EXPECT_EQ(CBORValue::Type::ARRAY, moved_value.type());
-  EXPECT_EQ(123u, moved_value.GetArray().back().GetUnsigned());
+  EXPECT_EQ(123u, moved_value.GetArray().back().GetInteger());
 
   CBORValue blank;
   blank = CBORValue(std::move(array));
   EXPECT_EQ(CBORValue::Type::ARRAY, blank.type());
-  EXPECT_EQ(123u, blank.GetArray().back().GetUnsigned());
-}
-
-TEST(CBORValuesTest, SelfSwap) {
-  CBORValue test(1);
-  std::swap(test, test);
-  EXPECT_EQ(test.GetUnsigned(), 1u);
+  EXPECT_EQ(123u, blank.GetArray().back().GetInteger());
 }
 
 TEST(CBORValuesTest, MoveSimpleValue) {
@@ -319,4 +345,10 @@
   EXPECT_EQ(CBORValue::SimpleValue::UNDEFINED, blank.GetSimpleValue());
 }
 
-}  // namespace content
+TEST(CBORValuesTest, SelfSwap) {
+  CBORValue test(1);
+  std::swap(test, test);
+  EXPECT_EQ(test.GetInteger(), 1u);
+}
+
+}  // namespace cbor
diff --git a/content/browser/webauth/cbor/cbor_writer.cc b/components/cbor/cbor_writer.cc
similarity index 80%
rename from content/browser/webauth/cbor/cbor_writer.cc
rename to components/cbor/cbor_writer.cc
index 0206cee1..d6e09fa5 100644
--- a/content/browser/webauth/cbor/cbor_writer.cc
+++ b/components/cbor/cbor_writer.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 "content/browser/webauth/cbor/cbor_writer.h"
+#include "components/cbor/cbor_writer.h"
 
 #include <string>
 
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_piece.h"
-#include "content/browser/webauth/cbor/cbor_binary.h"
+#include "components/cbor/cbor_binary.h"
 
-namespace content {
+namespace cbor {
 
 CBORWriter::~CBORWriter() {}
 
@@ -39,8 +39,15 @@
 
     // Represents unsigned integers.
     case CBORValue::Type::UNSIGNED: {
-      uint64_t value = node.GetUnsigned();
-      StartItem(CBORValue::Type::UNSIGNED, value);
+      int64_t value = node.GetUnsigned();
+      StartItem(CBORValue::Type::UNSIGNED, static_cast<uint64_t>(value));
+      return true;
+    }
+
+    // Represents negative integers.
+    case CBORValue::Type::NEGATIVE: {
+      int64_t value = node.GetNegative();
+      StartItem(CBORValue::Type::NEGATIVE, static_cast<uint64_t>(-(value + 1)));
       return true;
     }
 
@@ -106,16 +113,16 @@
 
 void CBORWriter::StartItem(CBORValue::Type type, uint64_t size) {
   encoded_cbor_->push_back(base::checked_cast<uint8_t>(
-      static_cast<unsigned>(type) << impl::kMajorTypeBitShift));
+      static_cast<unsigned>(type) << constants::kMajorTypeBitShift));
   SetUint(size);
 }
 
 void CBORWriter::SetAdditionalInformation(uint8_t additional_information) {
   DCHECK(!encoded_cbor_->empty());
-  DCHECK_EQ(additional_information & impl::kAdditionalInformationMask,
+  DCHECK_EQ(additional_information & constants::kAdditionalInformationMask,
             additional_information);
   encoded_cbor_->back() |=
-      (additional_information & impl::kAdditionalInformationMask);
+      (additional_information & constants::kAdditionalInformationMask);
 }
 
 void CBORWriter::SetUint(uint64_t value) {
@@ -129,19 +136,19 @@
       SetAdditionalInformation(base::checked_cast<uint8_t>(value));
       break;
     case 1:
-      SetAdditionalInformation(impl::kAdditionalInformation1Byte);
+      SetAdditionalInformation(constants::kAdditionalInformation1Byte);
       shift = 0;
       break;
     case 2:
-      SetAdditionalInformation(impl::kAdditionalInformation2Bytes);
+      SetAdditionalInformation(constants::kAdditionalInformation2Bytes);
       shift = 1;
       break;
     case 4:
-      SetAdditionalInformation(impl::kAdditionalInformation4Bytes);
+      SetAdditionalInformation(constants::kAdditionalInformation4Bytes);
       shift = 3;
       break;
     case 8:
-      SetAdditionalInformation(impl::kAdditionalInformation8Bytes);
+      SetAdditionalInformation(constants::kAdditionalInformation8Bytes);
       shift = 7;
       break;
     default:
@@ -166,4 +173,4 @@
   return 8;
 }
 
-}  // namespace content
+}  // namespace cbor
diff --git a/content/browser/webauth/cbor/cbor_writer.h b/components/cbor/cbor_writer.h
similarity index 89%
rename from content/browser/webauth/cbor/cbor_writer.h
rename to components/cbor/cbor_writer.h
index 32dd602..89e24da 100644
--- a/content/browser/webauth/cbor/cbor_writer.h
+++ b/components/cbor/cbor_writer.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 CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_WRITER_H_
-#define CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_WRITER_H_
+#ifndef COMPONENTS_CBOR_CBOR_WRITER_H_
+#define COMPONENTS_CBOR_CBOR_WRITER_H_
 
 #include <stddef.h>
 #include <stdint.h>
 #include <vector>
 
 #include "base/optional.h"
-#include "content/browser/webauth/cbor/cbor_values.h"
-#include "content/common/content_export.h"
+#include "components/cbor/cbor_export.h"
+#include "components/cbor/cbor_values.h"
 
 // A basic Concise Binary Object Representation (CBOR) encoder as defined by
 // https://tools.ietf.org/html/rfc7049. This is a generic encoder that supplies
@@ -19,7 +19,8 @@
 // (see https://tools.ietf.org/html/rfc7049#section-3.2).
 // Supported:
 //  * Major types:
-//     * 0: Unsigned integers, up to 64-bit.
+//     * 0: Unsigned integers, up to INT64_MAX.
+//     * 1: Negative integers, to INT64_MIN.
 //     * 2: Byte strings.
 //     * 3: UTF-8 strings.
 //     * 4: Arrays, with the number of elements known at the start.
@@ -28,7 +29,6 @@
 //     * 7: Simple values.
 //
 // Unsupported:
-//  * Negative integers.
 //  * Floating-point numbers.
 //  * Indefinite-length encodings.
 //  * Parsing.
@@ -50,9 +50,9 @@
 // Current implementation of CBORWriter encoder meets all the requirements of
 // canonical CBOR.
 
-namespace content {
+namespace cbor {
 
-class CONTENT_EXPORT CBORWriter {
+class CBOR_EXPORT CBORWriter {
  public:
   // Default that should be sufficiently large for most use cases.
   static constexpr size_t kDefaultMaxNestingDepth = 16;
@@ -95,6 +95,6 @@
   DISALLOW_COPY_AND_ASSIGN(CBORWriter);
 };
 
-}  // namespace content
+}  // namespace cbor
 
-#endif  // CONTENT_BROWSER_WEBAUTH_CBOR_CBOR_WRITER_H_
+#endif  // COMPONENTS_CBOR_CBOR_WRITER_H_
diff --git a/content/browser/webauth/cbor/cbor_writer_unittest.cc b/components/cbor/cbor_writer_unittest.cc
similarity index 76%
rename from content/browser/webauth/cbor/cbor_writer_unittest.cc
rename to components/cbor/cbor_writer_unittest.cc
index 2de0c7c9..5b047b6d 100644
--- a/content/browser/webauth/cbor/cbor_writer_unittest.cc
+++ b/components/cbor/cbor_writer_unittest.cc
@@ -2,21 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/webauth/cbor/cbor_writer.h"
+#include "components/cbor/cbor_writer.h"
 
+#include <limits>
 #include <string>
 
-#include "base/strings/string_piece.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 /* Leveraging RFC 7049 examples from
    https://github.com/cbor/test-vectors/blob/master/appendix_a.json. */
-namespace content {
+namespace cbor {
 
 TEST(CBORWriterTest, TestWriteUint) {
   typedef struct {
-    const uint64_t value;
+    const int64_t value;
     const base::StringPiece cbor;
   } UintTestCase;
 
@@ -33,7 +33,10 @@
       {1000, base::StringPiece("\x19\x03\xe8")},
       {1000000, base::StringPiece("\x1a\x00\x0f\x42\x40", 5)},
       {0xFFFFFFFF, base::StringPiece("\x1a\xff\xff\xff\xff")},
-  };
+      {0x100000000,
+       base::StringPiece("\x1b\x00\x00\x00\x01\x00\x00\x00\x00", 9)},
+      {std::numeric_limits<int64_t>::max(),
+       base::StringPiece("\x1b\x7f\xff\xff\xff\xff\xff\xff\xff")}};
 
   for (const UintTestCase& test_case : kUintTestCases) {
     auto cbor = CBORWriter::Write(CBORValue(test_case.value));
@@ -42,6 +45,35 @@
   }
 }
 
+TEST(CBORWriterTest, TestWriteNegativeInteger) {
+  static const struct {
+    const int64_t negative_int;
+    const base::StringPiece cbor;
+  } kNegativeIntTestCases[] = {
+      {-1LL, base::StringPiece("\x20")},
+      {-10LL, base::StringPiece("\x29")},
+      {-23LL, base::StringPiece("\x36")},
+      {-24LL, base::StringPiece("\x37")},
+      {-25LL, base::StringPiece("\x38\x18")},
+      {-100LL, base::StringPiece("\x38\x63")},
+      {-1000LL, base::StringPiece("\x39\x03\xe7")},
+      {-4294967296LL, base::StringPiece("\x3a\xff\xff\xff\xff")},
+      {-4294967297LL,
+       base::StringPiece("\x3b\x00\x00\x00\x01\x00\x00\x00\x00", 9)},
+      {std::numeric_limits<int64_t>::min(),
+       base::StringPiece("\x3b\x7f\xff\xff\xff\xff\xff\xff\xff")},
+  };
+
+  for (const auto& test_case : kNegativeIntTestCases) {
+    SCOPED_TRACE(testing::Message() << "testing  negative int at index: "
+                                    << test_case.negative_int);
+
+    auto cbor = CBORWriter::Write(CBORValue(test_case.negative_int));
+    ASSERT_TRUE(cbor.has_value());
+    EXPECT_THAT(cbor.value(), testing::ElementsAreArray(test_case.cbor));
+  }
+}
+
 TEST(CBORWriterTest, TestWriteBytes) {
   typedef struct {
     const std::vector<uint8_t> bytes;
@@ -76,6 +108,9 @@
       {"\xf0\x90\x85\x91", base::StringPiece("\x64\xf0\x90\x85\x91")}};
 
   for (const StringTestCase& test_case : kStringTestCases) {
+    SCOPED_TRACE(testing::Message()
+                 << "testing encoding string : " << test_case.string);
+
     auto cbor = CBORWriter::Write(CBORValue(test_case.string));
     ASSERT_TRUE(cbor.has_value());
     EXPECT_THAT(cbor.value(), testing::ElementsAreArray(test_case.cbor));
@@ -92,7 +127,7 @@
       // clang-format on
   };
   std::vector<CBORValue> array;
-  for (int i = 1; i <= 25; i++) {
+  for (int64_t i = 1; i <= 25; i++) {
     array.push_back(CBORValue(i));
   }
   auto cbor = CBORWriter::Write(CBORValue(array));
@@ -105,7 +140,7 @@
 TEST(CBORWriterTest, TestWriteMapWithMapValue) {
   static const uint8_t kMapTestCaseCbor[] = {
       // clang-format off
-      0xAF,  // map of 7 pairs:
+      0xb6,  // map of 8 pairs:
         0x00,          // key 0
         0x61, 0x61,    // value "a"
 
@@ -113,7 +148,7 @@
         0x61,  0x62,   // value "b"
 
         0x18, 0x18,    // key 24
-        0x61,   0x63,  // value "c"
+        0x61, 0x63,  // value "c"
 
         0x18, 0xFF,        // key 255
         0x61,  0x64,       // value "d"
@@ -134,18 +169,42 @@
         0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
         0x61, 0x69,  //  value "i"
 
+        // key INT64_MAX
+        0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0x61, 0x6a,  //  value "j"
+
+        0x20,          // key -1
+        0x61, 0x6b,    // value "k"
+
+        0x37,          // key -24
+        0x61,  0x6c,   // value "l"
+
+        0x38, 0x18,    // key -25
+        0x61, 0x6d,  // value "m"
+
+        0x38, 0xFF,        // key -256
+        0x61, 0x6e,       // value "n"
+
+        0x39, 0x01, 0x00,  // key -257
+        0x61, 0x6f,        // value "o"
+
+        0x3A, 0x00, 0x01, 0x00, 0x00,   // key -65537
+        0x61, 0x70,                     // value "p"
+
+        0x3A, 0xFF, 0xFF, 0xFF, 0xFF,   // key -4294967296
+        0x61, 0x71,                     // value "q"
+
+        // key -4294967297
+        0x3B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+        0x61, 0x72,  //  value "r"
+
+        // key INT64_MIN
+        0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0x61, 0x73,  //  value "s"
+
         0x60,        // key ""
         0x61, 0x2e,  // value "."
 
-        0x61, 0x62,  // key "b"
-        0x61, 0x42,  // value "B"
-
-        0x61, 0x63,  // key "c"
-        0x61, 0x43,  // value "C"
-
-        0x61, 0x64,  // key "d"
-        0x61, 0x44,  // value "D"
-
         0x61, 0x65,  // key "e"
         0x61, 0x45,  // value "E"
 
@@ -157,26 +216,34 @@
   // Shorter strings sort first in CTAP, thus the “aa” value should be
   // serialised last in the map.
   map[CBORValue("aa")] = CBORValue("AA");
-  map[CBORValue("d")] = CBORValue("D");
-  map[CBORValue("b")] = CBORValue("B");
   map[CBORValue("e")] = CBORValue("E");
-  map[CBORValue("c")] = CBORValue("C");
   // The empty string is shorter than all others, so should appear first among
   // the strings.
   map[CBORValue("")] = CBORValue(".");
   // Map keys are sorted by major type, by byte length, and then by
   // byte-wise lexical order. So all integer type keys should appear before
-  // key "".
-  map[CBORValue(uint64_t(0))] = CBORValue("a");
+  // key "" and all positive integer keys should appear before negative integer
+  // keys.
+  map[CBORValue(-1)] = CBORValue("k");
+  map[CBORValue(-24)] = CBORValue("l");
+  map[CBORValue(-25)] = CBORValue("m");
+  map[CBORValue(-256)] = CBORValue("n");
+  map[CBORValue(-257)] = CBORValue("o");
+  map[CBORValue(-65537)] = CBORValue("p");
+  map[CBORValue(int64_t(-4294967296))] = CBORValue("q");
+  map[CBORValue(int64_t(-4294967297))] = CBORValue("r");
+  map[CBORValue(std::numeric_limits<int64_t>::min())] = CBORValue("s");
+  map[CBORValue(0)] = CBORValue("a");
   map[CBORValue(23)] = CBORValue("b");
   map[CBORValue(24)] = CBORValue("c");
-  map[CBORValue(255)] = CBORValue("d");
+  map[CBORValue(std::numeric_limits<uint8_t>::max())] = CBORValue("d");
   map[CBORValue(256)] = CBORValue("e");
-  map[CBORValue(65535)] = CBORValue("f");
+  map[CBORValue(std::numeric_limits<uint16_t>::max())] = CBORValue("f");
   map[CBORValue(65536)] = CBORValue("g");
-  map[CBORValue(4294967295)] = CBORValue("h");
-  map[CBORValue(4294967296)] = CBORValue("i");
-
+  map[CBORValue(int64_t(std::numeric_limits<uint32_t>::max()))] =
+      CBORValue("h");
+  map[CBORValue(int64_t(4294967296))] = CBORValue("i");
+  map[CBORValue(std::numeric_limits<int64_t>::max())] = CBORValue("j");
   auto cbor = CBORWriter::Write(CBORValue(map));
   ASSERT_TRUE(cbor.has_value());
   EXPECT_THAT(cbor.value(), testing::ElementsAreArray(
@@ -361,4 +428,4 @@
   EXPECT_FALSE(CBORWriter::Write(CBORValue(map), 4).has_value());
 }
 
-}  // namespace content
+}  // namespace cbor
diff --git a/components/cdm/browser/DEPS b/components/cdm/browser/DEPS
index 836cdf4..3a2cd64 100644
--- a/components/cdm/browser/DEPS
+++ b/components/cdm/browser/DEPS
@@ -8,5 +8,4 @@
 
   # For testing
   "+content/public/test",
-  "+content/test",
 ]
diff --git a/components/cdm/browser/media_drm_storage_impl_unittest.cc b/components/cdm/browser/media_drm_storage_impl_unittest.cc
index d44fb882..30e93d5 100644
--- a/components/cdm/browser/media_drm_storage_impl_unittest.cc
+++ b/components/cdm/browser/media_drm_storage_impl_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/unguessable_token.h"
 #include "components/prefs/testing_pref_service.h"
 #include "content/public/test/navigation_simulator.h"
-#include "content/test/test_render_frame_host.h"
+#include "content/public/test/test_renderer_host.h"
 #include "media/mojo/services/mojo_media_drm_storage.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
diff --git a/components/component_updater/component_updater_service.h b/components/component_updater/component_updater_service.h
index d965ef4c7..64322b53 100644
--- a/components/component_updater/component_updater_service.h
+++ b/components/component_updater/component_updater_service.h
@@ -159,6 +159,7 @@
   friend class DownloadableStringsComponentInstallerPolicy;
   friend class ::ComponentsUI;
   friend class ::PluginObserver;
+  friend class SwReporterOnDemandFetcher;
 #if defined(OS_CHROMEOS)
   friend class CrOSComponent;
 #endif  // defined(OS_CHROMEOS)
diff --git a/components/contextual_search/BUILD.gn b/components/contextual_search/BUILD.gn
index 7aee372..b8331d1 100644
--- a/components/contextual_search/BUILD.gn
+++ b/components/contextual_search/BUILD.gn
@@ -7,7 +7,9 @@
 mojom("mojo_bindings") {
   sources = [
     "common/contextual_search_js_api_service.mojom",
-    "common/overlay_page_notifier_service.mojom",
+  ]
+  public_deps = [
+    "//url/mojo:url_mojom_gurl",
   ]
 }
 
@@ -45,8 +47,6 @@
     "renderer/contextual_search_wrapper.h",
     "renderer/overlay_js_render_frame_observer.cc",
     "renderer/overlay_js_render_frame_observer.h",
-    "renderer/overlay_page_notifier_service_impl.cc",
-    "renderer/overlay_page_notifier_service_impl.h",
   ]
   deps = [
     ":mojo_bindings",
diff --git a/components/contextual_search/browser/contextual_search_js_api_handler.h b/components/contextual_search/browser/contextual_search_js_api_handler.h
index c8b0eb7..a45a78c 100644
--- a/components/contextual_search/browser/contextual_search_js_api_handler.h
+++ b/components/contextual_search/browser/contextual_search_js_api_handler.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "components/contextual_search/common/contextual_search_js_api_service.mojom.h"
 
 namespace contextual_search {
 
@@ -18,6 +19,16 @@
   ContextualSearchJsApiHandler() {}
   virtual ~ContextualSearchJsApiHandler() {}
 
+  // Enabling API, determines if the JS API should be enabled for the given URL.
+  virtual void ShouldEnableJsApi(
+      const GURL& gurl,
+      contextual_search::mojom::ContextualSearchJsApiService::
+          ShouldEnableJsApiCallback callback) = 0;
+
+  //=======
+  // JS API
+  //=======
+
   // Set the caption in the Contextual Search Bar, and indicate whether
   // the caption provides an answer (such as an actual definition), rather than
   // just general notification of what kind of answer may be available.
diff --git a/components/contextual_search/browser/contextual_search_js_api_service_impl.cc b/components/contextual_search/browser/contextual_search_js_api_service_impl.cc
index 1cecfbc2..db92f87 100644
--- a/components/contextual_search/browser/contextual_search_js_api_service_impl.cc
+++ b/components/contextual_search/browser/contextual_search_js_api_service_impl.cc
@@ -18,6 +18,14 @@
 
 ContextualSearchJsApiServiceImpl::~ContextualSearchJsApiServiceImpl() {}
 
+void ContextualSearchJsApiServiceImpl::ShouldEnableJsApi(
+    const GURL& gurl,
+    contextual_search::mojom::ContextualSearchJsApiService::
+        ShouldEnableJsApiCallback callback) {
+  contextual_search_js_api_handler_->ShouldEnableJsApi(gurl,
+                                                       std::move(callback));
+}
+
 void ContextualSearchJsApiServiceImpl::HandleSetCaption(
     const std::string& caption,
     bool does_answer) {
diff --git a/components/contextual_search/browser/contextual_search_js_api_service_impl.h b/components/contextual_search/browser/contextual_search_js_api_service_impl.h
index 648d3d7f..fbf1fe8 100644
--- a/components/contextual_search/browser/contextual_search_js_api_service_impl.h
+++ b/components/contextual_search/browser/contextual_search_js_api_service_impl.h
@@ -20,6 +20,15 @@
   ~ContextualSearchJsApiServiceImpl() override;
 
   // Mojo ContextualSearchApiService implementation.
+  // Determines if the JavaScript API should be enabled for the given |gurl|.
+  // The given |callback| will be notified with the answer.
+  void ShouldEnableJsApi(
+      const GURL& gurl,
+      contextual_search::mojom::ContextualSearchJsApiService::
+          ShouldEnableJsApiCallback callback) override;
+
+  // Handles a JavaScript call to set the caption in the Bar to
+  // the given |message|.
   void HandleSetCaption(const std::string& message, bool does_answer) override;
 
  private:
diff --git a/components/contextual_search/common/contextual_search_js_api_service.mojom b/components/contextual_search/common/contextual_search_js_api_service.mojom
index b1c7522..7185815 100644
--- a/components/contextual_search/common/contextual_search_js_api_service.mojom
+++ b/components/contextual_search/common/contextual_search_js_api_service.mojom
@@ -4,10 +4,16 @@
 
 module contextual_search.mojom;
 
+import "url/mojo/url.mojom";
+
 // This service is implemented by the browser process and is used by the
 // renderer when a Contextual Search JavaScript API function is called.
 interface ContextualSearchJsApiService {
 
+  // Determines if this JavaScript API should be enabled for the given URL.
+  // The asynchronous callback will be notified with the answer.
+  ShouldEnableJsApi(url.mojom.Url url) => (bool should_enable);
+
   // Handle a call from the JS API to set the caption, and indicate whether
   // the caption provides an answer (such as an actual definition), rather than
   // just general notification of what kind of answer may be available.
diff --git a/components/contextual_search/common/overlay_page_notifier_service.mojom b/components/contextual_search/common/overlay_page_notifier_service.mojom
deleted file mode 100644
index 37773b5..0000000
--- a/components/contextual_search/common/overlay_page_notifier_service.mojom
+++ /dev/null
@@ -1,11 +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.
-
-module contextual_search.mojom;
-
-// This service is implemented in the renderer process and is used by the
-// browser to notify a renderer that its page is presented in an overlay panel.
-interface OverlayPageNotifierService {
-  NotifyIsContextualSearchOverlay();
-};
diff --git a/components/contextual_search/renderer/overlay_js_render_frame_observer.cc b/components/contextual_search/renderer/overlay_js_render_frame_observer.cc
index a2b5c19c..99a71d7 100644
--- a/components/contextual_search/renderer/overlay_js_render_frame_observer.cc
+++ b/components/contextual_search/renderer/overlay_js_render_frame_observer.cc
@@ -9,10 +9,12 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "components/contextual_search/renderer/contextual_search_wrapper.h"
-#include "components/contextual_search/renderer/overlay_page_notifier_service_impl.h"
 #include "content/public/renderer/render_frame.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
 #include "v8/include/v8.h"
 
 namespace contextual_search {
@@ -20,54 +22,40 @@
 OverlayJsRenderFrameObserver::OverlayJsRenderFrameObserver(
     content::RenderFrame* render_frame,
     service_manager::BinderRegistry* registry)
-    : RenderFrameObserver(render_frame),
-      is_contextual_search_overlay_(false),
-      weak_factory_(this) {
-  registry->AddInterface(base::Bind(
-      &OverlayJsRenderFrameObserver::CreateOverlayPageNotifierService,
-      weak_factory_.GetWeakPtr()));
-}
+    : RenderFrameObserver(render_frame), weak_factory_(this) {}
 
 OverlayJsRenderFrameObserver::~OverlayJsRenderFrameObserver() {}
 
-void OverlayJsRenderFrameObserver::DidStartProvisionalLoad(
-    blink::WebDocumentLoader* document_loader) {
-  can_bind_requests_ = true;
-}
-
-void OverlayJsRenderFrameObserver::CreateOverlayPageNotifierService(
-    mojom::OverlayPageNotifierServiceRequest request) {
-  if (!can_bind_requests_)
-    return;
-  mojo::MakeStrongBinding(
-      base::MakeUnique<OverlayPageNotifierServiceImpl>(
-          weak_factory_.GetWeakPtr()),
-      std::move(request));
-}
-
-void OverlayJsRenderFrameObserver::SetIsContextualSearchOverlay() {
-  is_contextual_search_overlay_ = true;
-}
-
 void OverlayJsRenderFrameObserver::DidClearWindowObject() {
-  if (is_contextual_search_overlay_) {
-    contextual_search::ContextualSearchWrapper::Install(render_frame());
+  if (!did_start_enabling_js_api_) {
+    blink::WebURL url = render_frame()->GetWebFrame()->GetDocument().Url();
+    GURL gurl(url);
+    if (!url.IsEmpty() && EnsureServiceConnected()) {
+      did_start_enabling_js_api_ = true;
+      contextual_search_js_api_service_->ShouldEnableJsApi(
+          gurl, base::BindOnce(&OverlayJsRenderFrameObserver::EnableJsApi,
+                               weak_factory_.GetWeakPtr()));
+    }
   }
 }
 
-void OverlayJsRenderFrameObserver::DidFinishLoad() {
-  // If no message about the Contextual Search overlay was received at this
-  // point, there will not be one; remove the OverlayPageNotifierService
-  // from the registry.
-  DestroyOverlayPageNotifierService();
+void OverlayJsRenderFrameObserver::EnableJsApi(bool should_enable) {
+  if (!should_enable)
+    return;
+  contextual_search::ContextualSearchWrapper::Install(render_frame());
 }
 
-void OverlayJsRenderFrameObserver::DestroyOverlayPageNotifierService() {
-  can_bind_requests_ = false;
+bool OverlayJsRenderFrameObserver::EnsureServiceConnected() {
+  if (render_frame() && (!contextual_search_js_api_service_ ||
+                         !contextual_search_js_api_service_.is_bound())) {
+    render_frame()->GetRemoteInterfaces()->GetInterface(
+        &contextual_search_js_api_service_);
+    return true;
+  }
+  return false;
 }
 
 void OverlayJsRenderFrameObserver::OnDestruct() {
-  DestroyOverlayPageNotifierService();
   delete this;
 }
 
diff --git a/components/contextual_search/renderer/overlay_js_render_frame_observer.h b/components/contextual_search/renderer/overlay_js_render_frame_observer.h
index f55275a..ab9421a 100644
--- a/components/contextual_search/renderer/overlay_js_render_frame_observer.h
+++ b/components/contextual_search/renderer/overlay_js_render_frame_observer.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "components/contextual_search/common/overlay_page_notifier_service.mojom.h"
+#include "components/contextual_search/common/contextual_search_js_api_service.mojom.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
@@ -27,31 +27,27 @@
   ~OverlayJsRenderFrameObserver() override;
 
   // RenderFrameObserver implementation.
-  void DidStartProvisionalLoad(
-      blink::WebDocumentLoader* document_loader) override;
   void DidClearWindowObject() override;
-  void DidFinishLoad() override;
-
-  // Flag the current page as a contextual search overlay.
-  void SetIsContextualSearchOverlay();
 
  private:
   // RenderFrameObserver implementation.
   void OnDestruct() override;
 
-  // Creates the OverlayPageNotifierService connecting the browser to this
-  // observer.
-  void CreateOverlayPageNotifierService(
-      mojom::OverlayPageNotifierServiceRequest request);
-  // Destroys the OverlayPageNotifierService.
-  void DestroyOverlayPageNotifierService();
+  // Helper function to ensure that this class has connected to the CS service.
+  // Returns false if cannot connect.
+  bool EnsureServiceConnected();
 
-  // Track if the current page is presented in the contextual search overlay.
-  bool is_contextual_search_overlay_;
+  // Enables or disables the JS API.
+  void EnableJsApi(bool should_enable);
 
-  // Requests for mojom::OverlayPageNotifierService are only bound while
-  // a load is active.
-  bool can_bind_requests_ = false;
+  // The CS service to notify when deciding to enable the API or when API calls
+  // are made.
+  mojom::ContextualSearchJsApiServicePtr contextual_search_js_api_service_;
+
+  // Remembers whether we did start enabling the JS API by making a request
+  // to the Contextaual Search service to ask if we should enable for this
+  // URL or not.
+  bool did_start_enabling_js_api_ = false;
 
   base::WeakPtrFactory<OverlayJsRenderFrameObserver> weak_factory_;
 
diff --git a/components/contextual_search/renderer/overlay_page_notifier_service_impl.cc b/components/contextual_search/renderer/overlay_page_notifier_service_impl.cc
deleted file mode 100644
index c0ebfc4c..0000000
--- a/components/contextual_search/renderer/overlay_page_notifier_service_impl.cc
+++ /dev/null
@@ -1,24 +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 "components/contextual_search/renderer/overlay_page_notifier_service_impl.h"
-
-#include <utility>
-
-#include "components/contextual_search/renderer/overlay_js_render_frame_observer.h"
-
-namespace contextual_search {
-
-OverlayPageNotifierServiceImpl::OverlayPageNotifierServiceImpl(
-    base::WeakPtr<OverlayJsRenderFrameObserver> observer)
-    : overlay_js_observer_(observer) {}
-
-OverlayPageNotifierServiceImpl::~OverlayPageNotifierServiceImpl() {}
-
-void OverlayPageNotifierServiceImpl::NotifyIsContextualSearchOverlay() {
-  if (overlay_js_observer_ != nullptr)
-    overlay_js_observer_->SetIsContextualSearchOverlay();
-}
-
-}  // namespace contextual_search
diff --git a/components/contextual_search/renderer/overlay_page_notifier_service_impl.h b/components/contextual_search/renderer/overlay_page_notifier_service_impl.h
deleted file mode 100644
index b382644..0000000
--- a/components/contextual_search/renderer/overlay_page_notifier_service_impl.h
+++ /dev/null
@@ -1,40 +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.
-
-#ifndef COMPONENTS_CONTEXTUAL_SEARCH_RENDERER_OVERLAY_PAGE_NOTIFIER_SERVICE_IMPL_H_
-#define COMPONENTS_CONTEXTUAL_SEARCH_RENDERER_OVERLAY_PAGE_NOTIFIER_SERVICE_IMPL_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "components/contextual_search/common/overlay_page_notifier_service.mojom.h"
-#include "components/contextual_search/renderer/overlay_js_render_frame_observer.h"
-
-namespace contextual_search {
-
-class OverlayJsRenderFrameObserver;
-
-// mojom::OverlayPageNotifierService is responsible for listening to the browser
-// for messages about whether a page is presented in an overlay panel.
-// No message is received if the page is not presented in an overlay panel.
-// This service should be removed from the registry once the page is done
-// loading.
-class OverlayPageNotifierServiceImpl
-    : public mojom::OverlayPageNotifierService {
- public:
-  explicit OverlayPageNotifierServiceImpl(
-      base::WeakPtr<OverlayJsRenderFrameObserver> observer);
-  ~OverlayPageNotifierServiceImpl() override;
-
-  // Implementation of mojo interface OverlayPageNotifierService.
-  void NotifyIsContextualSearchOverlay() override;
-
- private:
-  base::WeakPtr<OverlayJsRenderFrameObserver> overlay_js_observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(OverlayPageNotifierServiceImpl);
-};
-
-}  // namespace contextual_search
-
-#endif  // COMPONENTS_CONTEXTUAL_SEARCH_RENDERER_OVERLAY_PAGE_NOTIFIER_SERVICE_IMPL_H_
diff --git a/components/crash/core/common/crash_key_breakpad.cc b/components/crash/core/common/crash_key_breakpad.cc
index dcd406c..0351e01 100644
--- a/components/crash/core/common/crash_key_breakpad.cc
+++ b/components/crash/core/common/crash_key_breakpad.cc
@@ -31,6 +31,9 @@
 
 static TransitionalCrashKeyStorage* g_storage = nullptr;
 
+constexpr size_t kUnsetStorageSlotSentinel =
+    TransitionalCrashKeyStorage::num_entries;
+
 }  // namespace
 
 TransitionalCrashKeyStorage* GetCrashKeyStorage() {
@@ -64,7 +67,32 @@
     return;
   }
 
-  // Otherwise, break the value into chunks labeled name-1 through name-N,
+  // If the value fits in a single slot, the name of the key should not
+  // end with the __1 suffix of the chunked format.
+  if (value.length() < kCrashKeyStorageValueSize - 1) {
+    if (index_array_[1] != kUnsetStorageSlotSentinel) {
+      // If switching from chunked to non-chunked, clear all the values.
+      Clear();
+      index_array_[0] = storage->SetKeyValue(name_, value.data());
+    } else if (index_array_[0] != kUnsetStorageSlotSentinel) {
+      // The single entry was previously set.
+      storage->SetValueAtIndex(index_array_[0], value.data());
+    } else {
+      // This key was not previously set.
+      index_array_[0] = storage->SetKeyValue(name_, value.data());
+    }
+    return;
+  }
+
+  // If the key was previously set, but only using one slot, then the chunk
+  // name will change (from |name| to |name__1|).
+  if (index_array_[0] != kUnsetStorageSlotSentinel &&
+      index_array_[1] == kUnsetStorageSlotSentinel) {
+    storage->RemoveAtIndex(index_array_[0]);
+    index_array_[0] = kUnsetStorageSlotSentinel;
+  }
+
+  // Otherwise, break the value into chunks labeled name__1 through name__N,
   // where N is |index_array_count_|.
   size_t offset = 0;
   for (size_t i = 0; i < index_array_count_; ++i) {
@@ -75,7 +103,7 @@
           value.substr(offset, kCrashKeyStorageValueSize - 1);
       offset += chunk.length();
 
-      if (index_array_[i] == TransitionalCrashKeyStorage::num_entries) {
+      if (index_array_[i] == kUnsetStorageSlotSentinel) {
         std::string chunk_name =
             base::StringPrintf(kChunkFormatString, name_, i + 1);
         index_array_[i] =
@@ -85,7 +113,7 @@
       }
     } else {
       storage->RemoveAtIndex(index_array_[i]);
-      index_array_[i] = TransitionalCrashKeyStorage::num_entries;
+      index_array_[i] = kUnsetStorageSlotSentinel;
     }
   }
 }
@@ -93,12 +121,12 @@
 void CrashKeyStringImpl::Clear() {
   for (size_t i = 0; i < index_array_count_; ++i) {
     GetCrashKeyStorage()->RemoveAtIndex(index_array_[i]);
-    index_array_[i] = TransitionalCrashKeyStorage::num_entries;
+    index_array_[i] = kUnsetStorageSlotSentinel;
   }
 }
 
 bool CrashKeyStringImpl::is_set() const {
-  return index_array_[0] != TransitionalCrashKeyStorage::num_entries;
+  return index_array_[0] != kUnsetStorageSlotSentinel;
 }
 
 }  // namespace internal
diff --git a/components/crash/core/common/crash_key_breakpad_unittest.cc b/components/crash/core/common/crash_key_breakpad_unittest.cc
index 9164d3c..e077766 100644
--- a/components/crash/core/common/crash_key_breakpad_unittest.cc
+++ b/components/crash/core/common/crash_key_breakpad_unittest.cc
@@ -168,4 +168,31 @@
   EXPECT_EQ(std::string(2, '3'), storage()->GetValueForKey("big__5"));
 }
 
+TEST_F(CrashKeyBreakpadTest, ChunkSingleEntry) {
+  static CrashKeyString<200> crash_key("split");
+
+  EXPECT_EQ(0u, storage()->GetCount());
+
+  crash_key.Set("test");
+
+  ASSERT_EQ(1u, storage()->GetCount());
+  EXPECT_STREQ("test", storage()->GetValueForKey("split"));
+
+  crash_key.Set(std::string(127, 'z') + "bloop");
+
+  ASSERT_EQ(2u, storage()->GetCount());
+  EXPECT_EQ(std::string(127, 'z'), storage()->GetValueForKey("split__1"));
+  EXPECT_STREQ("bloop", storage()->GetValueForKey("split__2"));
+
+  crash_key.Set("abcdefg");
+
+  ASSERT_EQ(1u, storage()->GetCount());
+  EXPECT_STREQ("abcdefg", storage()->GetValueForKey("split"));
+
+  crash_key.Set("hijklmnop");
+
+  ASSERT_EQ(1u, storage()->GetCount());
+  EXPECT_STREQ("hijklmnop", storage()->GetValueForKey("split"));
+}
+
 }  // namespace crash_reporter
diff --git a/components/crash/core/common/crash_keys.cc b/components/crash/core/common/crash_keys.cc
index 559313f3..716e534 100644
--- a/components/crash/core/common/crash_keys.cc
+++ b/components/crash/core/common/crash_keys.cc
@@ -64,28 +64,6 @@
 #endif
 }
 
-void SetVariationsList(const std::vector<std::string>& variations) {
-  static crash_reporter::CrashKeyString<8> num_variations_key(
-      "num-experiments");
-  num_variations_key.Set(base::NumberToString(variations.size()));
-
-  static constexpr size_t kVariationsKeySize = 2048;
-  static crash_reporter::CrashKeyString<kVariationsKeySize> crash_key(
-      "variations");
-
-  std::string variations_string;
-  variations_string.reserve(kVariationsKeySize);
-
-  for (const auto& variation : variations) {
-    // Do not truncate an individual experiment.
-    if (variations_string.size() + variation.size() >= kVariationsKeySize)
-      break;
-    variations_string += variation;
-    variations_string += ",";
-  }
-  crash_key.Set(variations_string);
-}
-
 using SwitchesCrashKey = crash_reporter::CrashKeyString<64>;
 static SwitchesCrashKey switches_keys[] = {
     {"switch-1", SwitchesCrashKey::Tag::kArray},
diff --git a/components/crash/core/common/crash_keys.h b/components/crash/core/common/crash_keys.h
index 23945fa..f469952 100644
--- a/components/crash/core/common/crash_keys.h
+++ b/components/crash/core/common/crash_keys.h
@@ -8,7 +8,6 @@
 #include <stddef.h>
 
 #include <string>
-#include <vector>
 
 #include "base/debug/crash_logging.h"
 #include "build/build_config.h"
@@ -26,9 +25,6 @@
 void SetMetricsClientIdFromGUID(const std::string& metrics_client_guid);
 void ClearMetricsClientId();
 
-// Sets the list of active experiment/variations info.
-void SetVariationsList(const std::vector<std::string>& variations);
-
 // A function returning true if |flag| is a switch that should be filtered out
 // of crash keys.
 using SwitchFilterFunction = bool (*)(const std::string& flag);
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn
index 0428186..f4613c4 100644
--- a/components/cronet/android/BUILD.gn
+++ b/components/cronet/android/BUILD.gn
@@ -170,6 +170,7 @@
     ":cronet_version_header",
     "//base",
     "//base/third_party/dynamic_annotations",
+    "//components/cronet/native:cronet_native_impl",
     "//components/metrics",
     "//components/prefs",
     "//net",
@@ -226,6 +227,11 @@
   }
 }
 
+config("hide_all_but_jni_onload_and_cronet") {
+  ldflags = [ "-Wl,--version-script=" + rebase_path(
+                  "//components/cronet/android/android_only_jni_onload_and_cronet_exports.lst") ]
+}
+
 _cronet_shared_lib_name = "cronet.$chrome_version_full"
 _cronet_shared_lib_file_name = "lib" + _cronet_shared_lib_name + ".so"
 
@@ -239,6 +245,8 @@
     "//base",
     "//net:net",
   ]
+  configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
+  configs += [ ":hide_all_but_jni_onload_and_cronet" ]
 }
 
 cronet_api_srcjar_deps = [ ":cronet_api_version_srcjar" ]
@@ -500,11 +508,13 @@
   ]
 
   deps = [
+    ":cronet",
     ":cronet_tests_jni_headers",
     ":cronet_version_header",
     "//base",
     "//base:i18n",
     "//base/test:test_support",
+    "//components/cronet/native:cronet_native_tests",
     "//components/prefs",
     "//net",
     "//net:simple_quic_tools",
@@ -887,7 +897,7 @@
     ":cronet_static",
     "//base",
     "//base/test:test_support",
-    "//components/cronet/native:cronet_native_impl_tests",
+    "//components/cronet/native:cronet_native_unittests",
     "//components/metrics",
     "//components/prefs:test_support",
     "//net",
diff --git a/components/cronet/android/android_only_jni_onload_and_cronet_exports.lst b/components/cronet/android/android_only_jni_onload_and_cronet_exports.lst
new file mode 100644
index 0000000..363860d
--- /dev/null
+++ b/components/cronet/android/android_only_jni_onload_and_cronet_exports.lst
@@ -0,0 +1,13 @@
+# 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.
+
+# Linker script that exports only symbols required for JNI and Cronet Native
+# API to work.
+{
+  global:
+    JNI_OnLoad;
+    Cronet_*;
+  local:
+    *;
+};
diff --git a/components/cronet/ios/BUILD.gn b/components/cronet/ios/BUILD.gn
index 16cd233..282a1e97 100644
--- a/components/cronet/ios/BUILD.gn
+++ b/components/cronet/ios/BUILD.gn
@@ -8,6 +8,7 @@
 import("//build/mac/tweak_info_plist.gni")
 import("//build/util/process_version.gni")
 import("//build/util/version.gni")
+import("//components/cronet/native/include/headers.gni")
 import("//components/grpc_support/include/headers.gni")
 import("//testing/test.gni")
 import("//url/features.gni")
@@ -53,6 +54,7 @@
   ":cronet_version_header",
   ":generate_accept_languages",
   "//base:base",
+  "//components/cronet/native:cronet_native_impl",
   "//components/grpc_support",
   "//components/metrics:metrics",
   "//third_party/metrics_proto",
@@ -85,6 +87,7 @@
 
 _cronet_public_headers = [ "Cronet.h" ]
 _cronet_public_headers += grpc_public_headers
+_cronet_public_headers += cronet_native_public_headers
 
 source_set("cronet_sources") {
   deps = _cronet_deps
@@ -162,6 +165,7 @@
     ":cronet_sources_with_global_state",
     "//base",
     "//base/test:test_support",
+    "//components/cronet/native:cronet_native_unittests",
     "//components/metrics",
     "//net",
     "//testing/gtest",
diff --git a/components/cronet/ios/test/BUILD.gn b/components/cronet/ios/test/BUILD.gn
index 8957469..575f2728 100644
--- a/components/cronet/ios/test/BUILD.gn
+++ b/components/cronet/ios/test/BUILD.gn
@@ -29,7 +29,7 @@
     "//base",
     "//base:i18n",
     "//components/cronet/ios:cronet_framework+link",
-    "//components/cronet/native:cronet_native_impl_tests",
+    "//components/cronet/native:cronet_native_tests",
     "//components/grpc_support:bidirectional_stream_unittest",
     "//components/grpc_support/test:quic_test_server",
     "//net",
diff --git a/components/cronet/native/BUILD.gn b/components/cronet/native/BUILD.gn
index a2a3125..afba5a7 100644
--- a/components/cronet/native/BUILD.gn
+++ b/components/cronet/native/BUILD.gn
@@ -1,9 +1,15 @@
-import("//mojo/public/tools/bindings/mojom.gni")
+import("//components/cronet/native/include/headers.gni")
 import("//testing/test.gni")
 
-# Cronet native API implementation. Currently just generated from cronet.idl.
+# Cronet native API implementation.
 source_set("cronet_native_impl") {
   sources = [
+    "buffer.cc",
+    "include/cronet_c.h",
+    "runnables.cc",
+    "runnables.h",
+
+    # Generated from cronet.idl.
     "generated/cronet.idl_c.h",
     "generated/cronet.idl_impl_interface.cc",
     "generated/cronet.idl_impl_interface.h",
@@ -14,10 +20,15 @@
     "//base",
     "//net",
   ]
+  include_dirs = [
+    "//components/cronet/native/generated",
+    "//components/cronet/native/include",
+  ]
 }
 
-# Tests for Cronet native API. Currently just generated from cronet.idl.
-source_set("cronet_native_impl_tests") {
+# Unit tests for Cronet native API. Depends on cronet_native_impl to test
+# implementation details.
+source_set("cronet_native_unittests") {
   testonly = true
 
   deps = [
@@ -25,8 +36,41 @@
     "//net:test_support",
   ]
 
+  include_dirs = [
+    "//components/cronet/native/generated",
+    "//components/cronet/native/include",
+  ]
+
   sources = [
+    "runnables_unittest.cc",
+    "test_util.cc",
+    "test_util.h",
+
+    # Generated from cronet.idl.
     "generated/cronet.idl_impl_interface_unittest.cc",
     "generated/cronet.idl_impl_struct_unittest.cc",
   ]
 }
+
+# Tests for publicly exported Cronet Native API. This target does NOT depend on
+# cronet_native_impl to prevent static linking of implementation into test app.
+source_set("cronet_native_tests") {
+  testonly = true
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//testing/gtest",
+  ]
+
+  include_dirs = [
+    "//components/cronet/native/generated",
+    "//components/cronet/native/include",
+  ]
+  sources = [
+    "buffer_test.cc",
+    "executors_test.cc",
+    "test_util.cc",
+    "test_util.h",
+  ]
+}
diff --git a/components/cronet/native/buffer.cc b/components/cronet/native/buffer.cc
new file mode 100644
index 0000000..3013a743
--- /dev/null
+++ b/components/cronet/native/buffer.cc
@@ -0,0 +1,99 @@
+// 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/cronet/native/generated/cronet.idl_impl_interface.h"
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/macros.h"
+
+namespace {
+
+// Implementation of Cronet_BufferCallback that calls free() to malloc() buffer.
+class Cronet_BufferCallbackFree : public Cronet_BufferCallback {
+ public:
+  Cronet_BufferCallbackFree() = default;
+  ~Cronet_BufferCallbackFree() override = default;
+
+  // Singleton instance doesn't allow means to set app-specific context.
+  void SetContext(Cronet_BufferCallbackContext context) override {}
+  Cronet_BufferCallbackContext GetContext() override { return nullptr; }
+
+  void OnDestroy(Cronet_BufferPtr buffer) override { free(buffer->GetData()); }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Cronet_BufferCallbackFree);
+};
+
+base::LazyInstance<Cronet_BufferCallbackFree>::Leaky
+    g_cronet_buffer_callback_free = LAZY_INSTANCE_INITIALIZER;
+
+// Concrete implementation of abstract Cronet_Buffer interface.
+class Cronet_BufferImpl : public Cronet_Buffer {
+ public:
+  Cronet_BufferImpl() = default;
+  ~Cronet_BufferImpl() override;
+
+  // Cronet_Buffer implementation
+  void SetContext(Cronet_BufferContext context) override;
+  Cronet_BufferContext GetContext() override;
+  void InitWithDataAndCallback(RawDataPtr data,
+                               uint64_t size,
+                               Cronet_BufferCallbackPtr callback) override;
+  void InitWithAlloc(uint64_t size) override;
+  uint64_t GetSize() override;
+  RawDataPtr GetData() override;
+
+ private:
+  RawDataPtr data_ = nullptr;
+  uint64_t size_ = 0;
+  Cronet_BufferCallbackPtr callback_ = nullptr;
+  Cronet_BufferContext context_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(Cronet_BufferImpl);
+};
+
+Cronet_BufferImpl::~Cronet_BufferImpl() {
+  if (callback_)
+    callback_->OnDestroy(this);
+}
+
+void Cronet_BufferImpl::SetContext(Cronet_BufferContext context) {
+  context_ = context;
+}
+
+Cronet_BufferContext Cronet_BufferImpl::GetContext() {
+  return context_;
+}
+
+void Cronet_BufferImpl::InitWithDataAndCallback(
+    RawDataPtr data,
+    uint64_t size,
+    Cronet_BufferCallbackPtr callback) {
+  data_ = data;
+  size_ = size;
+  callback_ = callback;
+}
+
+void Cronet_BufferImpl::InitWithAlloc(uint64_t size) {
+  data_ = malloc(size);
+  if (!data_)
+    return;
+  size_ = size;
+  callback_ = g_cronet_buffer_callback_free.Pointer();
+}
+
+uint64_t Cronet_BufferImpl::GetSize() {
+  return size_;
+}
+
+RawDataPtr Cronet_BufferImpl::GetData() {
+  return data_;
+}
+
+}  // namespace
+
+CRONET_EXPORT Cronet_BufferPtr Cronet_Buffer_Create() {
+  return new Cronet_BufferImpl();
+}
diff --git a/components/cronet/native/buffer_test.cc b/components/cronet/native/buffer_test.cc
new file mode 100644
index 0000000..f8f36a34e
--- /dev/null
+++ b/components/cronet/native/buffer_test.cc
@@ -0,0 +1,118 @@
+// 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 "cronet_c.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/cronet/native/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class BufferTest : public ::testing::Test {
+ public:
+  BufferTest() = default;
+  ~BufferTest() override {}
+
+ protected:
+  static void BufferCallback_OnDestroy(Cronet_BufferCallbackPtr self,
+                                       Cronet_BufferPtr buffer);
+  bool on_destroy_called() const { return on_destroy_called_; }
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ private:
+  void set_on_destroy_called(bool value) { on_destroy_called_ = value; }
+
+  bool on_destroy_called_ = false;
+  DISALLOW_COPY_AND_ASSIGN(BufferTest);
+};
+
+const uint64_t kTestBufferSize = 20;
+
+// static
+void BufferTest::BufferCallback_OnDestroy(Cronet_BufferCallbackPtr self,
+                                          Cronet_BufferPtr buffer) {
+  CHECK(self);
+  Cronet_BufferCallbackContext context = Cronet_BufferCallback_GetContext(self);
+  BufferTest* test = static_cast<BufferTest*>(context);
+  CHECK(test);
+  test->set_on_destroy_called(true);
+  // Free buffer_data.
+  void* buffer_data = Cronet_Buffer_GetData(buffer);
+  CHECK(buffer_data);
+  free(buffer_data);
+}
+
+// Test on_destroy that destroys the buffer set in context.
+void TestRunnable_DestroyBuffer(Cronet_RunnablePtr self) {
+  CHECK(self);
+  Cronet_RunnableContext context = Cronet_Runnable_GetContext(self);
+  Cronet_BufferPtr buffer = static_cast<Cronet_BufferPtr>(context);
+  CHECK(buffer);
+  // Destroy buffer. TestCronet_BufferCallback_OnDestroy should be invoked.
+  Cronet_Buffer_Destroy(buffer);
+}
+
+// Example of allocating buffer with reasonable size.
+TEST_F(BufferTest, TestInitWithAlloc) {
+  // Create Cronet buffer and allocate buffer data.
+  Cronet_BufferPtr buffer = Cronet_Buffer_Create();
+  Cronet_Buffer_InitWithAlloc(buffer, kTestBufferSize);
+  ASSERT_TRUE(Cronet_Buffer_GetData(buffer));
+  ASSERT_EQ(Cronet_Buffer_GetSize(buffer), kTestBufferSize);
+  Cronet_Buffer_Destroy(buffer);
+  ASSERT_FALSE(on_destroy_called());
+}
+
+// Example of allocating buffer with hugereasonable size.
+TEST_F(BufferTest, TestInitWithHugeAllocFails) {
+  // Create Cronet buffer and allocate buffer data.
+  Cronet_BufferPtr buffer = Cronet_Buffer_Create();
+  Cronet_Buffer_InitWithAlloc(buffer, 1000 * 1000 * 1000 * 1000);
+  ASSERT_FALSE(Cronet_Buffer_GetData(buffer));
+  ASSERT_EQ(Cronet_Buffer_GetSize(buffer), 0ull);
+  Cronet_Buffer_Destroy(buffer);
+  ASSERT_FALSE(on_destroy_called());
+}
+
+// Example of intializing buffer with app-allocated data.
+TEST_F(BufferTest, TestInitWithDataAndCallback) {
+  Cronet_BufferCallbackPtr buffer_callback =
+      Cronet_BufferCallback_CreateStub(BufferCallback_OnDestroy);
+  Cronet_BufferCallback_SetContext(buffer_callback, this);
+  // Create Cronet buffer and allocate buffer data.
+  Cronet_BufferPtr buffer = Cronet_Buffer_Create();
+  Cronet_Buffer_InitWithDataAndCallback(buffer, malloc(kTestBufferSize),
+                                        kTestBufferSize, buffer_callback);
+  ASSERT_TRUE(Cronet_Buffer_GetData(buffer));
+  ASSERT_EQ(Cronet_Buffer_GetSize(buffer), kTestBufferSize);
+  Cronet_Buffer_Destroy(buffer);
+  ASSERT_TRUE(on_destroy_called());
+}
+
+// Example of posting application on_destroy to the executor and passing
+// buffer to it, expecting buffer to be destroyed and freed.
+TEST_F(BufferTest, TestCronetBufferAsync) {
+  // Executor provided by the application.
+  Cronet_ExecutorPtr executor = cronet::test::CreateTestExecutor();
+  Cronet_BufferCallbackPtr buffer_callback =
+      Cronet_BufferCallback_CreateStub(BufferCallback_OnDestroy);
+  Cronet_BufferCallback_SetContext(buffer_callback, this);
+  // Create Cronet buffer and allocate buffer data.
+  Cronet_BufferPtr buffer = Cronet_Buffer_Create();
+  Cronet_Buffer_InitWithDataAndCallback(buffer, malloc(kTestBufferSize),
+                                        kTestBufferSize, buffer_callback);
+  Cronet_RunnablePtr runnable =
+      Cronet_Runnable_CreateStub(TestRunnable_DestroyBuffer);
+  Cronet_Runnable_SetContext(runnable, buffer);
+  Cronet_Executor_Execute(executor, runnable);
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_TRUE(on_destroy_called());
+  Cronet_Executor_Destroy(executor);
+}
+
+}  // namespace
diff --git a/components/cronet/native/cronet.idl b/components/cronet/native/cronet.idl
index 3f3d6f9..c1b7505 100644
--- a/components/cronet/native/cronet.idl
+++ b/components/cronet/native/cronet.idl
@@ -12,44 +12,42 @@
 /**
  * Data buffer provided by the application to read and write data.
  */
-struct Buffer {
+interface Buffer {
   /**
-   * Size of |data| buffer in bytes. Limited to int32 for Java compatibility.
+   * Initialize Buffer with raw buffer |data| of |size| allocated by the app.
+   * The |callback| is invoked when buffer is destroyed.
    */
-  int32 size = 0;
+  InitWithDataAndCallback(handle data, uint64 size, BufferCallback callback);
 
   /**
-   * Maximum |position| in |data| for reading or writing of data. Cannot exceed
-   * |size|.
+   * Initialize Buffer by allocating buffer of |size|. The content of allocated
+   * data is not initialized.
    */
-  int32 limit = 0;
+  InitWithAlloc(uint64 size);
 
   /**
-   * Current position in |data| for reading or writing of data. Cannot exceed
-   * |size|.
+   * Return size of data owned by this buffer.
    */
-  int32 position = 0;
+  [Sync]
+  GetSize() => (uint64 size);
 
   /**
-   * App-provided buffer of |size| bytes. Allocated by the app, and owned by
-   * Buffer until BufferCallback.OnDestroy is invoked.
+   * Return raw pointer to |data| owned by this buffer.
    */
-  handle data;
-
-  /**
-   * App-provided callback that gets invoked when Buffer is destroyed, so
-   * |data| can be freed.
-   */
-  BufferCallback callback;
+  [Sync]
+  GetData() => (handle data);
 };
 
 /**
- * App-provided callback that gets invoked when Buffer is destroyed.
+ * App-provided callback passed to Buffer::InitWithDataAndCallback that gets invoked
+ * when Buffer is destroyed.
  */
 [Abstract]
 interface BufferCallback {
   /**
-   * Method invoked when |buffer| is destroyed so its app-allocated |data| can be freed.
+   * Method invoked when |buffer| is destroyed so its app-allocated |data| can
+   * be freed. If a UrlRequest has ownership of a Buffer and the UrlRequest is destroyed
+   * (e.g. Cronet_UrlRequest_Destroy() is called), then Cronet will call OnDestroy().
    */
   OnDestroy(Buffer buffer);
 };
@@ -168,6 +166,10 @@
  */
 [Abstract]
 interface Executor {
+  /**
+   * Takes ownership of |command| and runs it synchronously or asynchronously.
+   * Destroys the |command| after execution.
+   */
   Execute(Runnable command);
 };
 
diff --git a/components/cronet/native/executors_test.cc b/components/cronet/native/executors_test.cc
new file mode 100644
index 0000000..3c25203
--- /dev/null
+++ b/components/cronet/native/executors_test.cc
@@ -0,0 +1,76 @@
+// 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 "cronet_c.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/cronet/native/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class ExecutorsTest : public ::testing::Test {
+ public:
+  ExecutorsTest() = default;
+  ~ExecutorsTest() override = default;
+
+ protected:
+  static void TestRunnable_Run(Cronet_RunnablePtr self);
+  bool runnable_called() const { return runnable_called_; }
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ private:
+  void set_runnable_called(bool value) { runnable_called_ = value; }
+
+  bool runnable_called_ = false;
+  DISALLOW_COPY_AND_ASSIGN(ExecutorsTest);
+};
+
+// App implementation of Cronet_Executor methods.
+void TestExecutor_Execute(Cronet_ExecutorPtr self, Cronet_RunnablePtr command) {
+  CHECK(self);
+  Cronet_Runnable_Run(command);
+  Cronet_Runnable_Destroy(command);
+}
+
+// Implementation of TestRunnable methods.
+// static
+void ExecutorsTest::TestRunnable_Run(Cronet_RunnablePtr self) {
+  CHECK(self);
+  Cronet_RunnableContext context = Cronet_Runnable_GetContext(self);
+  ExecutorsTest* test = static_cast<ExecutorsTest*>(context);
+  CHECK(test);
+  test->set_runnable_called(true);
+}
+
+// Test that custom Executor defined by the app runs the runnable.
+TEST_F(ExecutorsTest, TestCustom) {
+  ASSERT_FALSE(runnable_called());
+  Cronet_RunnablePtr runnable =
+      Cronet_Runnable_CreateStub(ExecutorsTest::TestRunnable_Run);
+  Cronet_Runnable_SetContext(runnable, this);
+  Cronet_ExecutorPtr executor =
+      Cronet_Executor_CreateStub(TestExecutor_Execute);
+  Cronet_Executor_Execute(executor, runnable);
+  Cronet_Executor_Destroy(executor);
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_TRUE(runnable_called());
+}
+
+// Test that cronet::test::TestExecutor runs the runnable.
+TEST_F(ExecutorsTest, TestTestExecutor) {
+  ASSERT_FALSE(runnable_called());
+  Cronet_RunnablePtr runnable = Cronet_Runnable_CreateStub(TestRunnable_Run);
+  Cronet_Runnable_SetContext(runnable, this);
+  Cronet_ExecutorPtr executor = cronet::test::CreateTestExecutor();
+  Cronet_Executor_Execute(executor, runnable);
+  Cronet_Executor_Destroy(executor);
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_TRUE(runnable_called());
+}
+
+}  // namespace
diff --git a/components/cronet/native/generated/cronet.idl_c.h b/components/cronet/native/generated/cronet.idl_c.h
index c2c7d10..d5169f07 100644
--- a/components/cronet/native/generated/cronet.idl_c.h
+++ b/components/cronet/native/generated/cronet.idl_c.h
@@ -6,6 +6,7 @@
 
 #ifndef COMPONENTS_CRONET_NATIVE_GENERATED_CRONET_IDL_C_H_
 #define COMPONENTS_CRONET_NATIVE_GENERATED_CRONET_IDL_C_H_
+#include "cronet_export.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -17,6 +18,9 @@
 typedef void* RawDataPtr;
 
 // Forward declare interfaces.
+typedef struct Cronet_Buffer Cronet_Buffer;
+typedef struct Cronet_Buffer* Cronet_BufferPtr;
+typedef void* Cronet_BufferContext;
 typedef struct Cronet_BufferCallback Cronet_BufferCallback;
 typedef struct Cronet_BufferCallback* Cronet_BufferCallbackPtr;
 typedef void* Cronet_BufferCallbackContext;
@@ -47,8 +51,6 @@
 typedef void* Cronet_UrlRequestContext;
 
 // Forward declare structs.
-typedef struct Cronet_Buffer Cronet_Buffer;
-typedef struct Cronet_Buffer* Cronet_BufferPtr;
 typedef struct Cronet_Exception Cronet_Exception;
 typedef struct Cronet_Exception* Cronet_ExceptionPtr;
 typedef struct Cronet_QuicHint Cronet_QuicHint;
@@ -115,20 +117,66 @@
 } Cronet_UrlRequestStatusListener_Status;
 
 ///////////////////////
+// Concrete interface Cronet_Buffer.
+
+// Create an instance of Cronet_Buffer.
+CRONET_EXPORT Cronet_BufferPtr Cronet_Buffer_Create();
+// Destroy an instance of Cronet_Buffer.
+CRONET_EXPORT void Cronet_Buffer_Destroy(Cronet_BufferPtr self);
+// Set and get app-specific Cronet_BufferContext.
+CRONET_EXPORT void Cronet_Buffer_SetContext(Cronet_BufferPtr self,
+                                            Cronet_BufferContext);
+CRONET_EXPORT Cronet_BufferContext
+Cronet_Buffer_GetContext(Cronet_BufferPtr self);
+// Concrete methods of Cronet_Buffer implemented by Cronet.
+// The app calls them to manipulate Cronet_Buffer.
+CRONET_EXPORT
+void Cronet_Buffer_InitWithDataAndCallback(Cronet_BufferPtr self,
+                                           RawDataPtr data,
+                                           uint64_t size,
+                                           Cronet_BufferCallbackPtr callback);
+CRONET_EXPORT
+void Cronet_Buffer_InitWithAlloc(Cronet_BufferPtr self, uint64_t size);
+CRONET_EXPORT
+uint64_t Cronet_Buffer_GetSize(Cronet_BufferPtr self);
+CRONET_EXPORT
+RawDataPtr Cronet_Buffer_GetData(Cronet_BufferPtr self);
+// Concrete interface Cronet_Buffer is implemented by Cronet.
+// The app can implement these for testing / mocking.
+typedef void (*Cronet_Buffer_InitWithDataAndCallbackFunc)(
+    Cronet_BufferPtr self,
+    RawDataPtr data,
+    uint64_t size,
+    Cronet_BufferCallbackPtr callback);
+typedef void (*Cronet_Buffer_InitWithAllocFunc)(Cronet_BufferPtr self,
+                                                uint64_t size);
+typedef uint64_t (*Cronet_Buffer_GetSizeFunc)(Cronet_BufferPtr self);
+typedef RawDataPtr (*Cronet_Buffer_GetDataFunc)(Cronet_BufferPtr self);
+// Concrete interface Cronet_Buffer is implemented by Cronet.
+// The app can use this for testing / mocking.
+CRONET_EXPORT Cronet_BufferPtr Cronet_Buffer_CreateStub(
+    Cronet_Buffer_InitWithDataAndCallbackFunc InitWithDataAndCallbackFunc,
+    Cronet_Buffer_InitWithAllocFunc InitWithAllocFunc,
+    Cronet_Buffer_GetSizeFunc GetSizeFunc,
+    Cronet_Buffer_GetDataFunc GetDataFunc);
+
+///////////////////////
 // Abstract interface Cronet_BufferCallback is implemented by the app.
 
 // There is no method to create a concrete implementation.
 
 // Destroy an instance of Cronet_BufferCallback.
-void Cronet_BufferCallback_Destroy(Cronet_BufferCallbackPtr self);
+CRONET_EXPORT void Cronet_BufferCallback_Destroy(Cronet_BufferCallbackPtr self);
 // Set and get app-specific Cronet_BufferCallbackContext.
-void Cronet_BufferCallback_SetContext(Cronet_BufferCallbackPtr self,
-                                      Cronet_BufferCallbackContext);
-Cronet_BufferCallbackContext Cronet_BufferCallback_GetContext(
-    Cronet_BufferCallbackPtr self);
+CRONET_EXPORT void Cronet_BufferCallback_SetContext(
+    Cronet_BufferCallbackPtr self,
+    Cronet_BufferCallbackContext);
+CRONET_EXPORT Cronet_BufferCallbackContext
+Cronet_BufferCallback_GetContext(Cronet_BufferCallbackPtr self);
 // Abstract interface Cronet_BufferCallback is implemented by the app.
 // The following concrete methods forward call to app implementation.
 // The app doesn't normally call them.
+CRONET_EXPORT
 void Cronet_BufferCallback_OnDestroy(Cronet_BufferCallbackPtr self,
                                      Cronet_BufferPtr buffer);
 // The app implements abstract interface Cronet_BufferCallback by defining
@@ -138,7 +186,7 @@
     Cronet_BufferPtr buffer);
 // The app creates an instance of Cronet_BufferCallback by providing custom
 // functions for each method.
-Cronet_BufferCallbackPtr Cronet_BufferCallback_CreateStub(
+CRONET_EXPORT Cronet_BufferCallbackPtr Cronet_BufferCallback_CreateStub(
     Cronet_BufferCallback_OnDestroyFunc OnDestroyFunc);
 
 ///////////////////////
@@ -147,21 +195,24 @@
 // There is no method to create a concrete implementation.
 
 // Destroy an instance of Cronet_Runnable.
-void Cronet_Runnable_Destroy(Cronet_RunnablePtr self);
+CRONET_EXPORT void Cronet_Runnable_Destroy(Cronet_RunnablePtr self);
 // Set and get app-specific Cronet_RunnableContext.
-void Cronet_Runnable_SetContext(Cronet_RunnablePtr self,
-                                Cronet_RunnableContext);
-Cronet_RunnableContext Cronet_Runnable_GetContext(Cronet_RunnablePtr self);
+CRONET_EXPORT void Cronet_Runnable_SetContext(Cronet_RunnablePtr self,
+                                              Cronet_RunnableContext);
+CRONET_EXPORT Cronet_RunnableContext
+Cronet_Runnable_GetContext(Cronet_RunnablePtr self);
 // Abstract interface Cronet_Runnable is implemented by the app.
 // The following concrete methods forward call to app implementation.
 // The app doesn't normally call them.
+CRONET_EXPORT
 void Cronet_Runnable_Run(Cronet_RunnablePtr self);
 // The app implements abstract interface Cronet_Runnable by defining custom
 // functions for each method.
 typedef void (*Cronet_Runnable_RunFunc)(Cronet_RunnablePtr self);
 // The app creates an instance of Cronet_Runnable by providing custom functions
 // for each method.
-Cronet_RunnablePtr Cronet_Runnable_CreateStub(Cronet_Runnable_RunFunc RunFunc);
+CRONET_EXPORT Cronet_RunnablePtr
+Cronet_Runnable_CreateStub(Cronet_Runnable_RunFunc RunFunc);
 
 ///////////////////////
 // Abstract interface Cronet_Executor is implemented by the app.
@@ -169,14 +220,16 @@
 // There is no method to create a concrete implementation.
 
 // Destroy an instance of Cronet_Executor.
-void Cronet_Executor_Destroy(Cronet_ExecutorPtr self);
+CRONET_EXPORT void Cronet_Executor_Destroy(Cronet_ExecutorPtr self);
 // Set and get app-specific Cronet_ExecutorContext.
-void Cronet_Executor_SetContext(Cronet_ExecutorPtr self,
-                                Cronet_ExecutorContext);
-Cronet_ExecutorContext Cronet_Executor_GetContext(Cronet_ExecutorPtr self);
+CRONET_EXPORT void Cronet_Executor_SetContext(Cronet_ExecutorPtr self,
+                                              Cronet_ExecutorContext);
+CRONET_EXPORT Cronet_ExecutorContext
+Cronet_Executor_GetContext(Cronet_ExecutorPtr self);
 // Abstract interface Cronet_Executor is implemented by the app.
 // The following concrete methods forward call to app implementation.
 // The app doesn't normally call them.
+CRONET_EXPORT
 void Cronet_Executor_Execute(Cronet_ExecutorPtr self,
                              Cronet_RunnablePtr command);
 // The app implements abstract interface Cronet_Executor by defining custom
@@ -185,28 +238,35 @@
                                             Cronet_RunnablePtr command);
 // The app creates an instance of Cronet_Executor by providing custom functions
 // for each method.
-Cronet_ExecutorPtr Cronet_Executor_CreateStub(
-    Cronet_Executor_ExecuteFunc ExecuteFunc);
+CRONET_EXPORT Cronet_ExecutorPtr
+Cronet_Executor_CreateStub(Cronet_Executor_ExecuteFunc ExecuteFunc);
 
 ///////////////////////
 // Concrete interface Cronet_Engine.
 
 // Create an instance of Cronet_Engine.
-Cronet_EnginePtr Cronet_Engine_Create();
+CRONET_EXPORT Cronet_EnginePtr Cronet_Engine_Create();
 // Destroy an instance of Cronet_Engine.
-void Cronet_Engine_Destroy(Cronet_EnginePtr self);
+CRONET_EXPORT void Cronet_Engine_Destroy(Cronet_EnginePtr self);
 // Set and get app-specific Cronet_EngineContext.
-void Cronet_Engine_SetContext(Cronet_EnginePtr self, Cronet_EngineContext);
-Cronet_EngineContext Cronet_Engine_GetContext(Cronet_EnginePtr self);
+CRONET_EXPORT void Cronet_Engine_SetContext(Cronet_EnginePtr self,
+                                            Cronet_EngineContext);
+CRONET_EXPORT Cronet_EngineContext
+Cronet_Engine_GetContext(Cronet_EnginePtr self);
 // Concrete methods of Cronet_Engine implemented by Cronet.
 // The app calls them to manipulate Cronet_Engine.
+CRONET_EXPORT
 void Cronet_Engine_StartWithParams(Cronet_EnginePtr self,
                                    Cronet_EngineParamsPtr params);
+CRONET_EXPORT
 void Cronet_Engine_StartNetLogToFile(Cronet_EnginePtr self,
                                      CharString fileName,
                                      bool logAll);
+CRONET_EXPORT
 void Cronet_Engine_StopNetLog(Cronet_EnginePtr self);
+CRONET_EXPORT
 CharString Cronet_Engine_GetVersionString(Cronet_EnginePtr self);
+CRONET_EXPORT
 CharString Cronet_Engine_GetDefaultUserAgent(Cronet_EnginePtr self);
 // Concrete interface Cronet_Engine is implemented by Cronet.
 // The app can implement these for testing / mocking.
@@ -222,7 +282,7 @@
     Cronet_EnginePtr self);
 // Concrete interface Cronet_Engine is implemented by Cronet.
 // The app can use this for testing / mocking.
-Cronet_EnginePtr Cronet_Engine_CreateStub(
+CRONET_EXPORT Cronet_EnginePtr Cronet_Engine_CreateStub(
     Cronet_Engine_StartWithParamsFunc StartWithParamsFunc,
     Cronet_Engine_StartNetLogToFileFunc StartNetLogToFileFunc,
     Cronet_Engine_StopNetLogFunc StopNetLogFunc,
@@ -235,18 +295,19 @@
 // There is no method to create a concrete implementation.
 
 // Destroy an instance of Cronet_UrlRequestStatusListener.
-void Cronet_UrlRequestStatusListener_Destroy(
+CRONET_EXPORT void Cronet_UrlRequestStatusListener_Destroy(
     Cronet_UrlRequestStatusListenerPtr self);
 // Set and get app-specific Cronet_UrlRequestStatusListenerContext.
-void Cronet_UrlRequestStatusListener_SetContext(
+CRONET_EXPORT void Cronet_UrlRequestStatusListener_SetContext(
     Cronet_UrlRequestStatusListenerPtr self,
     Cronet_UrlRequestStatusListenerContext);
-Cronet_UrlRequestStatusListenerContext
+CRONET_EXPORT Cronet_UrlRequestStatusListenerContext
 Cronet_UrlRequestStatusListener_GetContext(
     Cronet_UrlRequestStatusListenerPtr self);
 // Abstract interface Cronet_UrlRequestStatusListener is implemented by the app.
 // The following concrete methods forward call to app implementation.
 // The app doesn't normally call them.
+CRONET_EXPORT
 void Cronet_UrlRequestStatusListener_OnStatus(
     Cronet_UrlRequestStatusListenerPtr self,
     Cronet_UrlRequestStatusListener_Status status);
@@ -257,7 +318,8 @@
     Cronet_UrlRequestStatusListener_Status status);
 // The app creates an instance of Cronet_UrlRequestStatusListener by providing
 // custom functions for each method.
-Cronet_UrlRequestStatusListenerPtr Cronet_UrlRequestStatusListener_CreateStub(
+CRONET_EXPORT Cronet_UrlRequestStatusListenerPtr
+Cronet_UrlRequestStatusListener_CreateStub(
     Cronet_UrlRequestStatusListener_OnStatusFunc OnStatusFunc);
 
 ///////////////////////
@@ -266,36 +328,44 @@
 // There is no method to create a concrete implementation.
 
 // Destroy an instance of Cronet_UrlRequestCallback.
-void Cronet_UrlRequestCallback_Destroy(Cronet_UrlRequestCallbackPtr self);
-// Set and get app-specific Cronet_UrlRequestCallbackContext.
-void Cronet_UrlRequestCallback_SetContext(Cronet_UrlRequestCallbackPtr self,
-                                          Cronet_UrlRequestCallbackContext);
-Cronet_UrlRequestCallbackContext Cronet_UrlRequestCallback_GetContext(
+CRONET_EXPORT void Cronet_UrlRequestCallback_Destroy(
     Cronet_UrlRequestCallbackPtr self);
+// Set and get app-specific Cronet_UrlRequestCallbackContext.
+CRONET_EXPORT void Cronet_UrlRequestCallback_SetContext(
+    Cronet_UrlRequestCallbackPtr self,
+    Cronet_UrlRequestCallbackContext);
+CRONET_EXPORT Cronet_UrlRequestCallbackContext
+Cronet_UrlRequestCallback_GetContext(Cronet_UrlRequestCallbackPtr self);
 // Abstract interface Cronet_UrlRequestCallback is implemented by the app.
 // The following concrete methods forward call to app implementation.
 // The app doesn't normally call them.
+CRONET_EXPORT
 void Cronet_UrlRequestCallback_OnRedirectReceived(
     Cronet_UrlRequestCallbackPtr self,
     Cronet_UrlRequestPtr request,
     Cronet_UrlResponseInfoPtr info,
     CharString newLocationUrl);
+CRONET_EXPORT
 void Cronet_UrlRequestCallback_OnResponseStarted(
     Cronet_UrlRequestCallbackPtr self,
     Cronet_UrlRequestPtr request,
     Cronet_UrlResponseInfoPtr info);
+CRONET_EXPORT
 void Cronet_UrlRequestCallback_OnReadCompleted(
     Cronet_UrlRequestCallbackPtr self,
     Cronet_UrlRequestPtr request,
     Cronet_UrlResponseInfoPtr info,
     Cronet_BufferPtr buffer);
+CRONET_EXPORT
 void Cronet_UrlRequestCallback_OnSucceeded(Cronet_UrlRequestCallbackPtr self,
                                            Cronet_UrlRequestPtr request,
                                            Cronet_UrlResponseInfoPtr info);
+CRONET_EXPORT
 void Cronet_UrlRequestCallback_OnFailed(Cronet_UrlRequestCallbackPtr self,
                                         Cronet_UrlRequestPtr request,
                                         Cronet_UrlResponseInfoPtr info,
                                         Cronet_ExceptionPtr error);
+CRONET_EXPORT
 void Cronet_UrlRequestCallback_OnCanceled(Cronet_UrlRequestCallbackPtr self,
                                           Cronet_UrlRequestPtr request,
                                           Cronet_UrlResponseInfoPtr info);
@@ -330,7 +400,7 @@
     Cronet_UrlResponseInfoPtr info);
 // The app creates an instance of Cronet_UrlRequestCallback by providing custom
 // functions for each method.
-Cronet_UrlRequestCallbackPtr Cronet_UrlRequestCallback_CreateStub(
+CRONET_EXPORT Cronet_UrlRequestCallbackPtr Cronet_UrlRequestCallback_CreateStub(
     Cronet_UrlRequestCallback_OnRedirectReceivedFunc OnRedirectReceivedFunc,
     Cronet_UrlRequestCallback_OnResponseStartedFunc OnResponseStartedFunc,
     Cronet_UrlRequestCallback_OnReadCompletedFunc OnReadCompletedFunc,
@@ -342,21 +412,26 @@
 // Concrete interface Cronet_UploadDataSink.
 
 // Create an instance of Cronet_UploadDataSink.
-Cronet_UploadDataSinkPtr Cronet_UploadDataSink_Create();
+CRONET_EXPORT Cronet_UploadDataSinkPtr Cronet_UploadDataSink_Create();
 // Destroy an instance of Cronet_UploadDataSink.
-void Cronet_UploadDataSink_Destroy(Cronet_UploadDataSinkPtr self);
+CRONET_EXPORT void Cronet_UploadDataSink_Destroy(Cronet_UploadDataSinkPtr self);
 // Set and get app-specific Cronet_UploadDataSinkContext.
-void Cronet_UploadDataSink_SetContext(Cronet_UploadDataSinkPtr self,
-                                      Cronet_UploadDataSinkContext);
-Cronet_UploadDataSinkContext Cronet_UploadDataSink_GetContext(
-    Cronet_UploadDataSinkPtr self);
+CRONET_EXPORT void Cronet_UploadDataSink_SetContext(
+    Cronet_UploadDataSinkPtr self,
+    Cronet_UploadDataSinkContext);
+CRONET_EXPORT Cronet_UploadDataSinkContext
+Cronet_UploadDataSink_GetContext(Cronet_UploadDataSinkPtr self);
 // Concrete methods of Cronet_UploadDataSink implemented by Cronet.
 // The app calls them to manipulate Cronet_UploadDataSink.
+CRONET_EXPORT
 void Cronet_UploadDataSink_OnReadSucceeded(Cronet_UploadDataSinkPtr self,
                                            bool finalChunk);
+CRONET_EXPORT
 void Cronet_UploadDataSink_OnReadError(Cronet_UploadDataSinkPtr self,
                                        Cronet_ExceptionPtr error);
+CRONET_EXPORT
 void Cronet_UploadDataSink_OnRewindSucceded(Cronet_UploadDataSinkPtr self);
+CRONET_EXPORT
 void Cronet_UploadDataSink_OnRewindError(Cronet_UploadDataSinkPtr self,
                                          Cronet_ExceptionPtr error);
 // Concrete interface Cronet_UploadDataSink is implemented by Cronet.
@@ -374,7 +449,7 @@
     Cronet_ExceptionPtr error);
 // Concrete interface Cronet_UploadDataSink is implemented by Cronet.
 // The app can use this for testing / mocking.
-Cronet_UploadDataSinkPtr Cronet_UploadDataSink_CreateStub(
+CRONET_EXPORT Cronet_UploadDataSinkPtr Cronet_UploadDataSink_CreateStub(
     Cronet_UploadDataSink_OnReadSucceededFunc OnReadSucceededFunc,
     Cronet_UploadDataSink_OnReadErrorFunc OnReadErrorFunc,
     Cronet_UploadDataSink_OnRewindSuccededFunc OnRewindSuccededFunc,
@@ -386,21 +461,27 @@
 // There is no method to create a concrete implementation.
 
 // Destroy an instance of Cronet_UploadDataProvider.
-void Cronet_UploadDataProvider_Destroy(Cronet_UploadDataProviderPtr self);
-// Set and get app-specific Cronet_UploadDataProviderContext.
-void Cronet_UploadDataProvider_SetContext(Cronet_UploadDataProviderPtr self,
-                                          Cronet_UploadDataProviderContext);
-Cronet_UploadDataProviderContext Cronet_UploadDataProvider_GetContext(
+CRONET_EXPORT void Cronet_UploadDataProvider_Destroy(
     Cronet_UploadDataProviderPtr self);
+// Set and get app-specific Cronet_UploadDataProviderContext.
+CRONET_EXPORT void Cronet_UploadDataProvider_SetContext(
+    Cronet_UploadDataProviderPtr self,
+    Cronet_UploadDataProviderContext);
+CRONET_EXPORT Cronet_UploadDataProviderContext
+Cronet_UploadDataProvider_GetContext(Cronet_UploadDataProviderPtr self);
 // Abstract interface Cronet_UploadDataProvider is implemented by the app.
 // The following concrete methods forward call to app implementation.
 // The app doesn't normally call them.
+CRONET_EXPORT
 int64_t Cronet_UploadDataProvider_GetLength(Cronet_UploadDataProviderPtr self);
+CRONET_EXPORT
 void Cronet_UploadDataProvider_Read(Cronet_UploadDataProviderPtr self,
                                     Cronet_UploadDataSinkPtr uploadDataSink,
                                     Cronet_BufferPtr buffer);
+CRONET_EXPORT
 void Cronet_UploadDataProvider_Rewind(Cronet_UploadDataProviderPtr self,
                                       Cronet_UploadDataSinkPtr uploadDataSink);
+CRONET_EXPORT
 void Cronet_UploadDataProvider_Close(Cronet_UploadDataProviderPtr self);
 // The app implements abstract interface Cronet_UploadDataProvider by defining
 // custom functions for each method.
@@ -417,7 +498,7 @@
     Cronet_UploadDataProviderPtr self);
 // The app creates an instance of Cronet_UploadDataProvider by providing custom
 // functions for each method.
-Cronet_UploadDataProviderPtr Cronet_UploadDataProvider_CreateStub(
+CRONET_EXPORT Cronet_UploadDataProviderPtr Cronet_UploadDataProvider_CreateStub(
     Cronet_UploadDataProvider_GetLengthFunc GetLengthFunc,
     Cronet_UploadDataProvider_ReadFunc ReadFunc,
     Cronet_UploadDataProvider_RewindFunc RewindFunc,
@@ -427,27 +508,34 @@
 // Concrete interface Cronet_UrlRequest.
 
 // Create an instance of Cronet_UrlRequest.
-Cronet_UrlRequestPtr Cronet_UrlRequest_Create();
+CRONET_EXPORT Cronet_UrlRequestPtr Cronet_UrlRequest_Create();
 // Destroy an instance of Cronet_UrlRequest.
-void Cronet_UrlRequest_Destroy(Cronet_UrlRequestPtr self);
+CRONET_EXPORT void Cronet_UrlRequest_Destroy(Cronet_UrlRequestPtr self);
 // Set and get app-specific Cronet_UrlRequestContext.
-void Cronet_UrlRequest_SetContext(Cronet_UrlRequestPtr self,
-                                  Cronet_UrlRequestContext);
-Cronet_UrlRequestContext Cronet_UrlRequest_GetContext(
-    Cronet_UrlRequestPtr self);
+CRONET_EXPORT void Cronet_UrlRequest_SetContext(Cronet_UrlRequestPtr self,
+                                                Cronet_UrlRequestContext);
+CRONET_EXPORT Cronet_UrlRequestContext
+Cronet_UrlRequest_GetContext(Cronet_UrlRequestPtr self);
 // Concrete methods of Cronet_UrlRequest implemented by Cronet.
 // The app calls them to manipulate Cronet_UrlRequest.
+CRONET_EXPORT
 void Cronet_UrlRequest_InitWithParams(Cronet_UrlRequestPtr self,
                                       Cronet_EnginePtr engine,
                                       CharString url,
                                       Cronet_UrlRequestParamsPtr params,
                                       Cronet_UrlRequestCallbackPtr callback,
                                       Cronet_ExecutorPtr executor);
+CRONET_EXPORT
 void Cronet_UrlRequest_Start(Cronet_UrlRequestPtr self);
+CRONET_EXPORT
 void Cronet_UrlRequest_FollowRedirect(Cronet_UrlRequestPtr self);
+CRONET_EXPORT
 void Cronet_UrlRequest_Read(Cronet_UrlRequestPtr self, Cronet_BufferPtr buffer);
+CRONET_EXPORT
 void Cronet_UrlRequest_Cancel(Cronet_UrlRequestPtr self);
+CRONET_EXPORT
 bool Cronet_UrlRequest_IsDone(Cronet_UrlRequestPtr self);
+CRONET_EXPORT
 void Cronet_UrlRequest_GetStatus(Cronet_UrlRequestPtr self,
                                  Cronet_UrlRequestStatusListenerPtr listener);
 // Concrete interface Cronet_UrlRequest is implemented by Cronet.
@@ -470,7 +558,7 @@
     Cronet_UrlRequestStatusListenerPtr listener);
 // Concrete interface Cronet_UrlRequest is implemented by Cronet.
 // The app can use this for testing / mocking.
-Cronet_UrlRequestPtr Cronet_UrlRequest_CreateStub(
+CRONET_EXPORT Cronet_UrlRequestPtr Cronet_UrlRequest_CreateStub(
     Cronet_UrlRequest_InitWithParamsFunc InitWithParamsFunc,
     Cronet_UrlRequest_StartFunc StartFunc,
     Cronet_UrlRequest_FollowRedirectFunc FollowRedirectFunc,
@@ -480,229 +568,291 @@
     Cronet_UrlRequest_GetStatusFunc GetStatusFunc);
 
 ///////////////////////
-// Struct Cronet_Buffer.
-Cronet_BufferPtr Cronet_Buffer_Create();
-void Cronet_Buffer_Destroy(Cronet_BufferPtr self);
-// Cronet_Buffer setters.
-void Cronet_Buffer_set_size(Cronet_BufferPtr self, int32_t size);
-void Cronet_Buffer_set_limit(Cronet_BufferPtr self, int32_t limit);
-void Cronet_Buffer_set_position(Cronet_BufferPtr self, int32_t position);
-void Cronet_Buffer_set_data(Cronet_BufferPtr self, RawDataPtr data);
-void Cronet_Buffer_set_callback(Cronet_BufferPtr self,
-                                Cronet_BufferCallbackPtr callback);
-// Cronet_Buffer getters.
-int32_t Cronet_Buffer_get_size(Cronet_BufferPtr self);
-int32_t Cronet_Buffer_get_limit(Cronet_BufferPtr self);
-int32_t Cronet_Buffer_get_position(Cronet_BufferPtr self);
-RawDataPtr Cronet_Buffer_get_data(Cronet_BufferPtr self);
-Cronet_BufferCallbackPtr Cronet_Buffer_get_callback(Cronet_BufferPtr self);
-
-///////////////////////
 // Struct Cronet_Exception.
-Cronet_ExceptionPtr Cronet_Exception_Create();
-void Cronet_Exception_Destroy(Cronet_ExceptionPtr self);
+CRONET_EXPORT Cronet_ExceptionPtr Cronet_Exception_Create();
+CRONET_EXPORT void Cronet_Exception_Destroy(Cronet_ExceptionPtr self);
 // Cronet_Exception setters.
+CRONET_EXPORT
 void Cronet_Exception_set_error_code(Cronet_ExceptionPtr self,
                                      Cronet_Exception_ERROR_CODE error_code);
+CRONET_EXPORT
 void Cronet_Exception_set_internal_error_code(Cronet_ExceptionPtr self,
                                               int32_t internal_error_code);
+CRONET_EXPORT
 void Cronet_Exception_set_immediately_retryable(Cronet_ExceptionPtr self,
                                                 bool immediately_retryable);
+CRONET_EXPORT
 void Cronet_Exception_set_quic_detailed_error_code(
     Cronet_ExceptionPtr self,
     int32_t quic_detailed_error_code);
 // Cronet_Exception getters.
+CRONET_EXPORT
 Cronet_Exception_ERROR_CODE Cronet_Exception_get_error_code(
     Cronet_ExceptionPtr self);
+CRONET_EXPORT
 int32_t Cronet_Exception_get_internal_error_code(Cronet_ExceptionPtr self);
+CRONET_EXPORT
 bool Cronet_Exception_get_immediately_retryable(Cronet_ExceptionPtr self);
+CRONET_EXPORT
 int32_t Cronet_Exception_get_quic_detailed_error_code(Cronet_ExceptionPtr self);
 
 ///////////////////////
 // Struct Cronet_QuicHint.
-Cronet_QuicHintPtr Cronet_QuicHint_Create();
-void Cronet_QuicHint_Destroy(Cronet_QuicHintPtr self);
+CRONET_EXPORT Cronet_QuicHintPtr Cronet_QuicHint_Create();
+CRONET_EXPORT void Cronet_QuicHint_Destroy(Cronet_QuicHintPtr self);
 // Cronet_QuicHint setters.
+CRONET_EXPORT
 void Cronet_QuicHint_set_host(Cronet_QuicHintPtr self, CharString host);
+CRONET_EXPORT
 void Cronet_QuicHint_set_port(Cronet_QuicHintPtr self, int32_t port);
+CRONET_EXPORT
 void Cronet_QuicHint_set_alternatePort(Cronet_QuicHintPtr self,
                                        int32_t alternatePort);
 // Cronet_QuicHint getters.
+CRONET_EXPORT
 CharString Cronet_QuicHint_get_host(Cronet_QuicHintPtr self);
+CRONET_EXPORT
 int32_t Cronet_QuicHint_get_port(Cronet_QuicHintPtr self);
+CRONET_EXPORT
 int32_t Cronet_QuicHint_get_alternatePort(Cronet_QuicHintPtr self);
 
 ///////////////////////
 // Struct Cronet_PublicKeyPins.
-Cronet_PublicKeyPinsPtr Cronet_PublicKeyPins_Create();
-void Cronet_PublicKeyPins_Destroy(Cronet_PublicKeyPinsPtr self);
+CRONET_EXPORT Cronet_PublicKeyPinsPtr Cronet_PublicKeyPins_Create();
+CRONET_EXPORT void Cronet_PublicKeyPins_Destroy(Cronet_PublicKeyPinsPtr self);
 // Cronet_PublicKeyPins setters.
+CRONET_EXPORT
 void Cronet_PublicKeyPins_set_host(Cronet_PublicKeyPinsPtr self,
                                    CharString host);
+CRONET_EXPORT
 void Cronet_PublicKeyPins_add_pinsSha256(Cronet_PublicKeyPinsPtr self,
                                          RawDataPtr pinsSha256);
+CRONET_EXPORT
 void Cronet_PublicKeyPins_set_includeSubdomains(Cronet_PublicKeyPinsPtr self,
                                                 bool includeSubdomains);
 // Cronet_PublicKeyPins getters.
+CRONET_EXPORT
 CharString Cronet_PublicKeyPins_get_host(Cronet_PublicKeyPinsPtr self);
+CRONET_EXPORT
 uint32_t Cronet_PublicKeyPins_get_pinsSha256Size(Cronet_PublicKeyPinsPtr self);
 RawDataPtr Cronet_PublicKeyPins_get_pinsSha256AtIndex(
     Cronet_PublicKeyPinsPtr self,
     uint32_t index);
+CRONET_EXPORT
 bool Cronet_PublicKeyPins_get_includeSubdomains(Cronet_PublicKeyPinsPtr self);
 
 ///////////////////////
 // Struct Cronet_EngineParams.
-Cronet_EngineParamsPtr Cronet_EngineParams_Create();
-void Cronet_EngineParams_Destroy(Cronet_EngineParamsPtr self);
+CRONET_EXPORT Cronet_EngineParamsPtr Cronet_EngineParams_Create();
+CRONET_EXPORT void Cronet_EngineParams_Destroy(Cronet_EngineParamsPtr self);
 // Cronet_EngineParams setters.
+CRONET_EXPORT
 void Cronet_EngineParams_set_userAgent(Cronet_EngineParamsPtr self,
                                        CharString userAgent);
+CRONET_EXPORT
 void Cronet_EngineParams_set_storagePath(Cronet_EngineParamsPtr self,
                                          CharString storagePath);
+CRONET_EXPORT
 void Cronet_EngineParams_set_enableQuic(Cronet_EngineParamsPtr self,
                                         bool enableQuic);
+CRONET_EXPORT
 void Cronet_EngineParams_set_enableHttp2(Cronet_EngineParamsPtr self,
                                          bool enableHttp2);
+CRONET_EXPORT
 void Cronet_EngineParams_set_enableBrotli(Cronet_EngineParamsPtr self,
                                           bool enableBrotli);
+CRONET_EXPORT
 void Cronet_EngineParams_set_httpCacheMode(
     Cronet_EngineParamsPtr self,
     Cronet_EngineParams_HTTP_CACHE_MODE httpCacheMode);
+CRONET_EXPORT
 void Cronet_EngineParams_set_httpCacheMaxSize(Cronet_EngineParamsPtr self,
                                               int64_t httpCacheMaxSize);
+CRONET_EXPORT
 void Cronet_EngineParams_add_quicHints(Cronet_EngineParamsPtr self,
                                        Cronet_QuicHintPtr quicHints);
+CRONET_EXPORT
 void Cronet_EngineParams_add_publicKeyPins(
     Cronet_EngineParamsPtr self,
     Cronet_PublicKeyPinsPtr publicKeyPins);
+CRONET_EXPORT
 void Cronet_EngineParams_set_enablePublicKeyPinningBypassForLocalTrustAnchors(
     Cronet_EngineParamsPtr self,
     bool enablePublicKeyPinningBypassForLocalTrustAnchors);
 // Cronet_EngineParams getters.
+CRONET_EXPORT
 CharString Cronet_EngineParams_get_userAgent(Cronet_EngineParamsPtr self);
+CRONET_EXPORT
 CharString Cronet_EngineParams_get_storagePath(Cronet_EngineParamsPtr self);
+CRONET_EXPORT
 bool Cronet_EngineParams_get_enableQuic(Cronet_EngineParamsPtr self);
+CRONET_EXPORT
 bool Cronet_EngineParams_get_enableHttp2(Cronet_EngineParamsPtr self);
+CRONET_EXPORT
 bool Cronet_EngineParams_get_enableBrotli(Cronet_EngineParamsPtr self);
+CRONET_EXPORT
 Cronet_EngineParams_HTTP_CACHE_MODE Cronet_EngineParams_get_httpCacheMode(
     Cronet_EngineParamsPtr self);
+CRONET_EXPORT
 int64_t Cronet_EngineParams_get_httpCacheMaxSize(Cronet_EngineParamsPtr self);
+CRONET_EXPORT
 uint32_t Cronet_EngineParams_get_quicHintsSize(Cronet_EngineParamsPtr self);
 Cronet_QuicHintPtr Cronet_EngineParams_get_quicHintsAtIndex(
     Cronet_EngineParamsPtr self,
     uint32_t index);
+CRONET_EXPORT
 uint32_t Cronet_EngineParams_get_publicKeyPinsSize(Cronet_EngineParamsPtr self);
 Cronet_PublicKeyPinsPtr Cronet_EngineParams_get_publicKeyPinsAtIndex(
     Cronet_EngineParamsPtr self,
     uint32_t index);
+CRONET_EXPORT
 bool Cronet_EngineParams_get_enablePublicKeyPinningBypassForLocalTrustAnchors(
     Cronet_EngineParamsPtr self);
 
 ///////////////////////
 // Struct Cronet_HttpHeader.
-Cronet_HttpHeaderPtr Cronet_HttpHeader_Create();
-void Cronet_HttpHeader_Destroy(Cronet_HttpHeaderPtr self);
+CRONET_EXPORT Cronet_HttpHeaderPtr Cronet_HttpHeader_Create();
+CRONET_EXPORT void Cronet_HttpHeader_Destroy(Cronet_HttpHeaderPtr self);
 // Cronet_HttpHeader setters.
+CRONET_EXPORT
 void Cronet_HttpHeader_set_name(Cronet_HttpHeaderPtr self, CharString name);
+CRONET_EXPORT
 void Cronet_HttpHeader_set_value(Cronet_HttpHeaderPtr self, CharString value);
 // Cronet_HttpHeader getters.
+CRONET_EXPORT
 CharString Cronet_HttpHeader_get_name(Cronet_HttpHeaderPtr self);
+CRONET_EXPORT
 CharString Cronet_HttpHeader_get_value(Cronet_HttpHeaderPtr self);
 
 ///////////////////////
 // Struct Cronet_UrlResponseInfo.
-Cronet_UrlResponseInfoPtr Cronet_UrlResponseInfo_Create();
-void Cronet_UrlResponseInfo_Destroy(Cronet_UrlResponseInfoPtr self);
+CRONET_EXPORT Cronet_UrlResponseInfoPtr Cronet_UrlResponseInfo_Create();
+CRONET_EXPORT void Cronet_UrlResponseInfo_Destroy(
+    Cronet_UrlResponseInfoPtr self);
 // Cronet_UrlResponseInfo setters.
+CRONET_EXPORT
 void Cronet_UrlResponseInfo_set_url(Cronet_UrlResponseInfoPtr self,
                                     CharString url);
+CRONET_EXPORT
 void Cronet_UrlResponseInfo_add_urlChain(Cronet_UrlResponseInfoPtr self,
                                          CharString urlChain);
+CRONET_EXPORT
 void Cronet_UrlResponseInfo_set_httpStatusCode(Cronet_UrlResponseInfoPtr self,
                                                int32_t httpStatusCode);
+CRONET_EXPORT
 void Cronet_UrlResponseInfo_set_httpStatusText(Cronet_UrlResponseInfoPtr self,
                                                CharString httpStatusText);
+CRONET_EXPORT
 void Cronet_UrlResponseInfo_add_allHeadersList(
     Cronet_UrlResponseInfoPtr self,
     Cronet_HttpHeaderPtr allHeadersList);
+CRONET_EXPORT
 void Cronet_UrlResponseInfo_set_wasCached(Cronet_UrlResponseInfoPtr self,
                                           bool wasCached);
+CRONET_EXPORT
 void Cronet_UrlResponseInfo_set_negotiatedProtocol(
     Cronet_UrlResponseInfoPtr self,
     CharString negotiatedProtocol);
+CRONET_EXPORT
 void Cronet_UrlResponseInfo_set_proxyServer(Cronet_UrlResponseInfoPtr self,
                                             CharString proxyServer);
+CRONET_EXPORT
 void Cronet_UrlResponseInfo_set_receivedByteCount(
     Cronet_UrlResponseInfoPtr self,
     int64_t receivedByteCount);
 // Cronet_UrlResponseInfo getters.
+CRONET_EXPORT
 CharString Cronet_UrlResponseInfo_get_url(Cronet_UrlResponseInfoPtr self);
+CRONET_EXPORT
 uint32_t Cronet_UrlResponseInfo_get_urlChainSize(
     Cronet_UrlResponseInfoPtr self);
 CharString Cronet_UrlResponseInfo_get_urlChainAtIndex(
     Cronet_UrlResponseInfoPtr self,
     uint32_t index);
+CRONET_EXPORT
 int32_t Cronet_UrlResponseInfo_get_httpStatusCode(
     Cronet_UrlResponseInfoPtr self);
+CRONET_EXPORT
 CharString Cronet_UrlResponseInfo_get_httpStatusText(
     Cronet_UrlResponseInfoPtr self);
+CRONET_EXPORT
 uint32_t Cronet_UrlResponseInfo_get_allHeadersListSize(
     Cronet_UrlResponseInfoPtr self);
 Cronet_HttpHeaderPtr Cronet_UrlResponseInfo_get_allHeadersListAtIndex(
     Cronet_UrlResponseInfoPtr self,
     uint32_t index);
+CRONET_EXPORT
 bool Cronet_UrlResponseInfo_get_wasCached(Cronet_UrlResponseInfoPtr self);
+CRONET_EXPORT
 CharString Cronet_UrlResponseInfo_get_negotiatedProtocol(
     Cronet_UrlResponseInfoPtr self);
+CRONET_EXPORT
 CharString Cronet_UrlResponseInfo_get_proxyServer(
     Cronet_UrlResponseInfoPtr self);
+CRONET_EXPORT
 int64_t Cronet_UrlResponseInfo_get_receivedByteCount(
     Cronet_UrlResponseInfoPtr self);
 
 ///////////////////////
 // Struct Cronet_UrlRequestParams.
-Cronet_UrlRequestParamsPtr Cronet_UrlRequestParams_Create();
-void Cronet_UrlRequestParams_Destroy(Cronet_UrlRequestParamsPtr self);
+CRONET_EXPORT Cronet_UrlRequestParamsPtr Cronet_UrlRequestParams_Create();
+CRONET_EXPORT void Cronet_UrlRequestParams_Destroy(
+    Cronet_UrlRequestParamsPtr self);
 // Cronet_UrlRequestParams setters.
+CRONET_EXPORT
 void Cronet_UrlRequestParams_set_httpMethod(Cronet_UrlRequestParamsPtr self,
                                             CharString httpMethod);
+CRONET_EXPORT
 void Cronet_UrlRequestParams_add_requestHeaders(
     Cronet_UrlRequestParamsPtr self,
     Cronet_HttpHeaderPtr requestHeaders);
+CRONET_EXPORT
 void Cronet_UrlRequestParams_set_disableCache(Cronet_UrlRequestParamsPtr self,
                                               bool disableCache);
+CRONET_EXPORT
 void Cronet_UrlRequestParams_set_priority(
     Cronet_UrlRequestParamsPtr self,
     Cronet_UrlRequestParams_REQUEST_PRIORITY priority);
+CRONET_EXPORT
 void Cronet_UrlRequestParams_set_uploadDataProvider(
     Cronet_UrlRequestParamsPtr self,
     Cronet_UploadDataProviderPtr uploadDataProvider);
+CRONET_EXPORT
 void Cronet_UrlRequestParams_set_uploadDataProviderExecutor(
     Cronet_UrlRequestParamsPtr self,
     Cronet_ExecutorPtr uploadDataProviderExecutor);
+CRONET_EXPORT
 void Cronet_UrlRequestParams_set_allowDirectExecutor(
     Cronet_UrlRequestParamsPtr self,
     bool allowDirectExecutor);
+CRONET_EXPORT
 void Cronet_UrlRequestParams_add_annotations(Cronet_UrlRequestParamsPtr self,
                                              RawDataPtr annotations);
 // Cronet_UrlRequestParams getters.
+CRONET_EXPORT
 CharString Cronet_UrlRequestParams_get_httpMethod(
     Cronet_UrlRequestParamsPtr self);
+CRONET_EXPORT
 uint32_t Cronet_UrlRequestParams_get_requestHeadersSize(
     Cronet_UrlRequestParamsPtr self);
 Cronet_HttpHeaderPtr Cronet_UrlRequestParams_get_requestHeadersAtIndex(
     Cronet_UrlRequestParamsPtr self,
     uint32_t index);
+CRONET_EXPORT
 bool Cronet_UrlRequestParams_get_disableCache(Cronet_UrlRequestParamsPtr self);
+CRONET_EXPORT
 Cronet_UrlRequestParams_REQUEST_PRIORITY Cronet_UrlRequestParams_get_priority(
     Cronet_UrlRequestParamsPtr self);
+CRONET_EXPORT
 Cronet_UploadDataProviderPtr Cronet_UrlRequestParams_get_uploadDataProvider(
     Cronet_UrlRequestParamsPtr self);
+CRONET_EXPORT
 Cronet_ExecutorPtr Cronet_UrlRequestParams_get_uploadDataProviderExecutor(
     Cronet_UrlRequestParamsPtr self);
+CRONET_EXPORT
 bool Cronet_UrlRequestParams_get_allowDirectExecutor(
     Cronet_UrlRequestParamsPtr self);
+CRONET_EXPORT
 uint32_t Cronet_UrlRequestParams_get_annotationsSize(
     Cronet_UrlRequestParamsPtr self);
 RawDataPtr Cronet_UrlRequestParams_get_annotationsAtIndex(
diff --git a/components/cronet/native/generated/cronet.idl_impl_interface.cc b/components/cronet/native/generated/cronet.idl_impl_interface.cc
index a780fb9..04ac221c 100644
--- a/components/cronet/native/generated/cronet.idl_impl_interface.cc
+++ b/components/cronet/native/generated/cronet.idl_impl_interface.cc
@@ -8,6 +8,98 @@
 
 #include "base/logging.h"
 
+// C functions of Cronet_Buffer that forward calls to C++ implementation.
+void Cronet_Buffer_Destroy(Cronet_BufferPtr self) {
+  DCHECK(self);
+  return delete self;
+}
+
+void Cronet_Buffer_SetContext(Cronet_BufferPtr self,
+                              Cronet_BufferContext context) {
+  DCHECK(self);
+  return self->SetContext(context);
+}
+
+Cronet_BufferContext Cronet_Buffer_GetContext(Cronet_BufferPtr self) {
+  DCHECK(self);
+  return self->GetContext();
+}
+
+void Cronet_Buffer_InitWithDataAndCallback(Cronet_BufferPtr self,
+                                           RawDataPtr data,
+                                           uint64_t size,
+                                           Cronet_BufferCallbackPtr callback) {
+  DCHECK(self);
+  self->InitWithDataAndCallback(data, size, callback);
+}
+
+void Cronet_Buffer_InitWithAlloc(Cronet_BufferPtr self, uint64_t size) {
+  DCHECK(self);
+  self->InitWithAlloc(size);
+}
+
+uint64_t Cronet_Buffer_GetSize(Cronet_BufferPtr self) {
+  DCHECK(self);
+  return self->GetSize();
+}
+
+RawDataPtr Cronet_Buffer_GetData(Cronet_BufferPtr self) {
+  DCHECK(self);
+  return self->GetData();
+}
+
+// Implementation of Cronet_Buffer that forwards calls to C functions
+// implemented by the app.
+class Cronet_BufferStub : public Cronet_Buffer {
+ public:
+  Cronet_BufferStub(
+      Cronet_Buffer_InitWithDataAndCallbackFunc InitWithDataAndCallbackFunc,
+      Cronet_Buffer_InitWithAllocFunc InitWithAllocFunc,
+      Cronet_Buffer_GetSizeFunc GetSizeFunc,
+      Cronet_Buffer_GetDataFunc GetDataFunc)
+      : InitWithDataAndCallbackFunc_(InitWithDataAndCallbackFunc),
+        InitWithAllocFunc_(InitWithAllocFunc),
+        GetSizeFunc_(GetSizeFunc),
+        GetDataFunc_(GetDataFunc) {}
+
+  ~Cronet_BufferStub() override {}
+
+  void SetContext(Cronet_BufferContext context) override { context_ = context; }
+
+  Cronet_BufferContext GetContext() override { return context_; }
+
+ protected:
+  void InitWithDataAndCallback(RawDataPtr data,
+                               uint64_t size,
+                               Cronet_BufferCallbackPtr callback) override {
+    InitWithDataAndCallbackFunc_(this, data, size, callback);
+  }
+
+  void InitWithAlloc(uint64_t size) override { InitWithAllocFunc_(this, size); }
+
+  uint64_t GetSize() override { return GetSizeFunc_(this); }
+
+  RawDataPtr GetData() override { return GetDataFunc_(this); }
+
+ private:
+  Cronet_BufferContext context_ = nullptr;
+  const Cronet_Buffer_InitWithDataAndCallbackFunc InitWithDataAndCallbackFunc_;
+  const Cronet_Buffer_InitWithAllocFunc InitWithAllocFunc_;
+  const Cronet_Buffer_GetSizeFunc GetSizeFunc_;
+  const Cronet_Buffer_GetDataFunc GetDataFunc_;
+
+  DISALLOW_COPY_AND_ASSIGN(Cronet_BufferStub);
+};
+
+Cronet_BufferPtr Cronet_Buffer_CreateStub(
+    Cronet_Buffer_InitWithDataAndCallbackFunc InitWithDataAndCallbackFunc,
+    Cronet_Buffer_InitWithAllocFunc InitWithAllocFunc,
+    Cronet_Buffer_GetSizeFunc GetSizeFunc,
+    Cronet_Buffer_GetDataFunc GetDataFunc) {
+  return new Cronet_BufferStub(InitWithDataAndCallbackFunc, InitWithAllocFunc,
+                               GetSizeFunc, GetDataFunc);
+}
+
 // C functions of Cronet_BufferCallback that forward calls to C++
 // implementation.
 void Cronet_BufferCallback_Destroy(Cronet_BufferCallbackPtr self) {
@@ -37,7 +129,8 @@
 // implemented by the app.
 class Cronet_BufferCallbackStub : public Cronet_BufferCallback {
  public:
-  Cronet_BufferCallbackStub(Cronet_BufferCallback_OnDestroyFunc OnDestroyFunc)
+  explicit Cronet_BufferCallbackStub(
+      Cronet_BufferCallback_OnDestroyFunc OnDestroyFunc)
       : OnDestroyFunc_(OnDestroyFunc) {}
 
   ~Cronet_BufferCallbackStub() override {}
@@ -55,7 +148,7 @@
 
  private:
   Cronet_BufferCallbackContext context_ = nullptr;
-  Cronet_BufferCallback_OnDestroyFunc OnDestroyFunc_;
+  const Cronet_BufferCallback_OnDestroyFunc OnDestroyFunc_;
 
   DISALLOW_COPY_AND_ASSIGN(Cronet_BufferCallbackStub);
 };
@@ -91,7 +184,8 @@
 // implemented by the app.
 class Cronet_RunnableStub : public Cronet_Runnable {
  public:
-  Cronet_RunnableStub(Cronet_Runnable_RunFunc RunFunc) : RunFunc_(RunFunc) {}
+  explicit Cronet_RunnableStub(Cronet_Runnable_RunFunc RunFunc)
+      : RunFunc_(RunFunc) {}
 
   ~Cronet_RunnableStub() override {}
 
@@ -106,7 +200,7 @@
 
  private:
   Cronet_RunnableContext context_ = nullptr;
-  Cronet_Runnable_RunFunc RunFunc_;
+  const Cronet_Runnable_RunFunc RunFunc_;
 
   DISALLOW_COPY_AND_ASSIGN(Cronet_RunnableStub);
 };
@@ -142,7 +236,7 @@
 // implemented by the app.
 class Cronet_ExecutorStub : public Cronet_Executor {
  public:
-  Cronet_ExecutorStub(Cronet_Executor_ExecuteFunc ExecuteFunc)
+  explicit Cronet_ExecutorStub(Cronet_Executor_ExecuteFunc ExecuteFunc)
       : ExecuteFunc_(ExecuteFunc) {}
 
   ~Cronet_ExecutorStub() override {}
@@ -160,7 +254,7 @@
 
  private:
   Cronet_ExecutorContext context_ = nullptr;
-  Cronet_Executor_ExecuteFunc ExecuteFunc_;
+  const Cronet_Executor_ExecuteFunc ExecuteFunc_;
 
   DISALLOW_COPY_AND_ASSIGN(Cronet_ExecutorStub);
 };
@@ -256,11 +350,11 @@
 
  private:
   Cronet_EngineContext context_ = nullptr;
-  Cronet_Engine_StartWithParamsFunc StartWithParamsFunc_;
-  Cronet_Engine_StartNetLogToFileFunc StartNetLogToFileFunc_;
-  Cronet_Engine_StopNetLogFunc StopNetLogFunc_;
-  Cronet_Engine_GetVersionStringFunc GetVersionStringFunc_;
-  Cronet_Engine_GetDefaultUserAgentFunc GetDefaultUserAgentFunc_;
+  const Cronet_Engine_StartWithParamsFunc StartWithParamsFunc_;
+  const Cronet_Engine_StartNetLogToFileFunc StartNetLogToFileFunc_;
+  const Cronet_Engine_StopNetLogFunc StopNetLogFunc_;
+  const Cronet_Engine_GetVersionStringFunc GetVersionStringFunc_;
+  const Cronet_Engine_GetDefaultUserAgentFunc GetDefaultUserAgentFunc_;
 
   DISALLOW_COPY_AND_ASSIGN(Cronet_EngineStub);
 };
@@ -310,7 +404,7 @@
 class Cronet_UrlRequestStatusListenerStub
     : public Cronet_UrlRequestStatusListener {
  public:
-  Cronet_UrlRequestStatusListenerStub(
+  explicit Cronet_UrlRequestStatusListenerStub(
       Cronet_UrlRequestStatusListener_OnStatusFunc OnStatusFunc)
       : OnStatusFunc_(OnStatusFunc) {}
 
@@ -331,7 +425,7 @@
 
  private:
   Cronet_UrlRequestStatusListenerContext context_ = nullptr;
-  Cronet_UrlRequestStatusListener_OnStatusFunc OnStatusFunc_;
+  const Cronet_UrlRequestStatusListener_OnStatusFunc OnStatusFunc_;
 
   DISALLOW_COPY_AND_ASSIGN(Cronet_UrlRequestStatusListenerStub);
 };
@@ -471,12 +565,13 @@
 
  private:
   Cronet_UrlRequestCallbackContext context_ = nullptr;
-  Cronet_UrlRequestCallback_OnRedirectReceivedFunc OnRedirectReceivedFunc_;
-  Cronet_UrlRequestCallback_OnResponseStartedFunc OnResponseStartedFunc_;
-  Cronet_UrlRequestCallback_OnReadCompletedFunc OnReadCompletedFunc_;
-  Cronet_UrlRequestCallback_OnSucceededFunc OnSucceededFunc_;
-  Cronet_UrlRequestCallback_OnFailedFunc OnFailedFunc_;
-  Cronet_UrlRequestCallback_OnCanceledFunc OnCanceledFunc_;
+  const Cronet_UrlRequestCallback_OnRedirectReceivedFunc
+      OnRedirectReceivedFunc_;
+  const Cronet_UrlRequestCallback_OnResponseStartedFunc OnResponseStartedFunc_;
+  const Cronet_UrlRequestCallback_OnReadCompletedFunc OnReadCompletedFunc_;
+  const Cronet_UrlRequestCallback_OnSucceededFunc OnSucceededFunc_;
+  const Cronet_UrlRequestCallback_OnFailedFunc OnFailedFunc_;
+  const Cronet_UrlRequestCallback_OnCanceledFunc OnCanceledFunc_;
 
   DISALLOW_COPY_AND_ASSIGN(Cronet_UrlRequestCallbackStub);
 };
@@ -574,10 +669,10 @@
 
  private:
   Cronet_UploadDataSinkContext context_ = nullptr;
-  Cronet_UploadDataSink_OnReadSucceededFunc OnReadSucceededFunc_;
-  Cronet_UploadDataSink_OnReadErrorFunc OnReadErrorFunc_;
-  Cronet_UploadDataSink_OnRewindSuccededFunc OnRewindSuccededFunc_;
-  Cronet_UploadDataSink_OnRewindErrorFunc OnRewindErrorFunc_;
+  const Cronet_UploadDataSink_OnReadSucceededFunc OnReadSucceededFunc_;
+  const Cronet_UploadDataSink_OnReadErrorFunc OnReadErrorFunc_;
+  const Cronet_UploadDataSink_OnRewindSuccededFunc OnRewindSuccededFunc_;
+  const Cronet_UploadDataSink_OnRewindErrorFunc OnRewindErrorFunc_;
 
   DISALLOW_COPY_AND_ASSIGN(Cronet_UploadDataSinkStub);
 };
@@ -672,10 +767,10 @@
 
  private:
   Cronet_UploadDataProviderContext context_ = nullptr;
-  Cronet_UploadDataProvider_GetLengthFunc GetLengthFunc_;
-  Cronet_UploadDataProvider_ReadFunc ReadFunc_;
-  Cronet_UploadDataProvider_RewindFunc RewindFunc_;
-  Cronet_UploadDataProvider_CloseFunc CloseFunc_;
+  const Cronet_UploadDataProvider_GetLengthFunc GetLengthFunc_;
+  const Cronet_UploadDataProvider_ReadFunc ReadFunc_;
+  const Cronet_UploadDataProvider_RewindFunc RewindFunc_;
+  const Cronet_UploadDataProvider_CloseFunc CloseFunc_;
 
   DISALLOW_COPY_AND_ASSIGN(Cronet_UploadDataProviderStub);
 };
@@ -801,13 +896,13 @@
 
  private:
   Cronet_UrlRequestContext context_ = nullptr;
-  Cronet_UrlRequest_InitWithParamsFunc InitWithParamsFunc_;
-  Cronet_UrlRequest_StartFunc StartFunc_;
-  Cronet_UrlRequest_FollowRedirectFunc FollowRedirectFunc_;
-  Cronet_UrlRequest_ReadFunc ReadFunc_;
-  Cronet_UrlRequest_CancelFunc CancelFunc_;
-  Cronet_UrlRequest_IsDoneFunc IsDoneFunc_;
-  Cronet_UrlRequest_GetStatusFunc GetStatusFunc_;
+  const Cronet_UrlRequest_InitWithParamsFunc InitWithParamsFunc_;
+  const Cronet_UrlRequest_StartFunc StartFunc_;
+  const Cronet_UrlRequest_FollowRedirectFunc FollowRedirectFunc_;
+  const Cronet_UrlRequest_ReadFunc ReadFunc_;
+  const Cronet_UrlRequest_CancelFunc CancelFunc_;
+  const Cronet_UrlRequest_IsDoneFunc IsDoneFunc_;
+  const Cronet_UrlRequest_GetStatusFunc GetStatusFunc_;
 
   DISALLOW_COPY_AND_ASSIGN(Cronet_UrlRequestStub);
 };
diff --git a/components/cronet/native/generated/cronet.idl_impl_interface.h b/components/cronet/native/generated/cronet.idl_impl_interface.h
index 1db330a..7cf09d9 100644
--- a/components/cronet/native/generated/cronet.idl_impl_interface.h
+++ b/components/cronet/native/generated/cronet.idl_impl_interface.h
@@ -13,6 +13,24 @@
 #include "base/macros.h"
 #include "components/cronet/native/generated/cronet.idl_c.h"
 
+struct Cronet_Buffer {
+  Cronet_Buffer() = default;
+  virtual ~Cronet_Buffer() = default;
+
+  virtual void SetContext(Cronet_BufferContext context) = 0;
+  virtual Cronet_BufferContext GetContext() = 0;
+
+  virtual void InitWithDataAndCallback(RawDataPtr data,
+                                       uint64_t size,
+                                       Cronet_BufferCallbackPtr callback) = 0;
+  virtual void InitWithAlloc(uint64_t size) = 0;
+  virtual uint64_t GetSize() = 0;
+  virtual RawDataPtr GetData() = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Cronet_Buffer);
+};
+
 struct Cronet_BufferCallback {
   Cronet_BufferCallback() = default;
   virtual ~Cronet_BufferCallback() = default;
diff --git a/components/cronet/native/generated/cronet.idl_impl_interface_unittest.cc b/components/cronet/native/generated/cronet.idl_impl_interface_unittest.cc
index 5072eb37..09c3c95 100644
--- a/components/cronet/native/generated/cronet.idl_impl_interface_unittest.cc
+++ b/components/cronet/native/generated/cronet.idl_impl_interface_unittest.cc
@@ -10,6 +10,84 @@
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+// Test of Cronet_Buffer interface.
+class Cronet_BufferTest : public ::testing::Test {
+ protected:
+  void SetUp() override {}
+
+  void TearDown() override {}
+
+  Cronet_BufferTest() {}
+  ~Cronet_BufferTest() override {}
+
+ public:
+  bool InitWithDataAndCallback_called_ = false;
+  bool InitWithAlloc_called_ = false;
+  bool GetSize_called_ = false;
+  bool GetData_called_ = false;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Cronet_BufferTest);
+};
+
+namespace {
+// Implementation of Cronet_Buffer methods for testing.
+void TestCronet_Buffer_InitWithDataAndCallback(
+    Cronet_BufferPtr self,
+    RawDataPtr data,
+    uint64_t size,
+    Cronet_BufferCallbackPtr callback) {
+  CHECK(self);
+  Cronet_BufferContext context = Cronet_Buffer_GetContext(self);
+  Cronet_BufferTest* test = static_cast<Cronet_BufferTest*>(context);
+  CHECK(test);
+  test->InitWithDataAndCallback_called_ = true;
+}
+void TestCronet_Buffer_InitWithAlloc(Cronet_BufferPtr self, uint64_t size) {
+  CHECK(self);
+  Cronet_BufferContext context = Cronet_Buffer_GetContext(self);
+  Cronet_BufferTest* test = static_cast<Cronet_BufferTest*>(context);
+  CHECK(test);
+  test->InitWithAlloc_called_ = true;
+}
+uint64_t TestCronet_Buffer_GetSize(Cronet_BufferPtr self) {
+  CHECK(self);
+  Cronet_BufferContext context = Cronet_Buffer_GetContext(self);
+  Cronet_BufferTest* test = static_cast<Cronet_BufferTest*>(context);
+  CHECK(test);
+  test->GetSize_called_ = true;
+
+  return static_cast<uint64_t>(0);
+}
+RawDataPtr TestCronet_Buffer_GetData(Cronet_BufferPtr self) {
+  CHECK(self);
+  Cronet_BufferContext context = Cronet_Buffer_GetContext(self);
+  Cronet_BufferTest* test = static_cast<Cronet_BufferTest*>(context);
+  CHECK(test);
+  test->GetData_called_ = true;
+
+  return static_cast<RawDataPtr>(0);
+}
+}  // namespace
+
+// Test that Cronet_Buffer stub forwards function calls as expected.
+TEST_F(Cronet_BufferTest, TestCreate) {
+  Cronet_BufferPtr test = Cronet_Buffer_CreateStub(
+      TestCronet_Buffer_InitWithDataAndCallback,
+      TestCronet_Buffer_InitWithAlloc, TestCronet_Buffer_GetSize,
+      TestCronet_Buffer_GetData);
+  CHECK(test);
+  Cronet_Buffer_SetContext(test, this);
+  CHECK(!InitWithDataAndCallback_called_);
+  CHECK(!InitWithAlloc_called_);
+  Cronet_Buffer_GetSize(test);
+  CHECK(GetSize_called_);
+  Cronet_Buffer_GetData(test);
+  CHECK(GetData_called_);
+
+  Cronet_Buffer_Destroy(test);
+}
+
 // Test of Cronet_BufferCallback interface.
 class Cronet_BufferCallbackTest : public ::testing::Test {
  protected:
diff --git a/components/cronet/native/generated/cronet.idl_impl_struct.cc b/components/cronet/native/generated/cronet.idl_impl_struct.cc
index 3edfa0c..34e3cbe50 100644
--- a/components/cronet/native/generated/cronet.idl_impl_struct.cc
+++ b/components/cronet/native/generated/cronet.idl_impl_struct.cc
@@ -10,72 +10,6 @@
 
 #include "base/logging.h"
 
-// Struct Cronet_Buffer.
-Cronet_Buffer::Cronet_Buffer() {}
-
-Cronet_Buffer::~Cronet_Buffer() {}
-
-Cronet_BufferPtr Cronet_Buffer_Create() {
-  return new Cronet_Buffer();
-}
-
-void Cronet_Buffer_Destroy(Cronet_BufferPtr self) {
-  delete self;
-}
-
-// Struct Cronet_Buffer setters.
-void Cronet_Buffer_set_size(Cronet_BufferPtr self, int32_t size) {
-  DCHECK(self);
-  self->size = size;
-}
-
-void Cronet_Buffer_set_limit(Cronet_BufferPtr self, int32_t limit) {
-  DCHECK(self);
-  self->limit = limit;
-}
-
-void Cronet_Buffer_set_position(Cronet_BufferPtr self, int32_t position) {
-  DCHECK(self);
-  self->position = position;
-}
-
-void Cronet_Buffer_set_data(Cronet_BufferPtr self, RawDataPtr data) {
-  DCHECK(self);
-  self->data = data;
-}
-
-void Cronet_Buffer_set_callback(Cronet_BufferPtr self,
-                                Cronet_BufferCallbackPtr callback) {
-  DCHECK(self);
-  self->callback = callback;
-}
-
-// Struct Cronet_Buffer getters.
-int32_t Cronet_Buffer_get_size(Cronet_BufferPtr self) {
-  DCHECK(self);
-  return self->size;
-}
-
-int32_t Cronet_Buffer_get_limit(Cronet_BufferPtr self) {
-  DCHECK(self);
-  return self->limit;
-}
-
-int32_t Cronet_Buffer_get_position(Cronet_BufferPtr self) {
-  DCHECK(self);
-  return self->position;
-}
-
-RawDataPtr Cronet_Buffer_get_data(Cronet_BufferPtr self) {
-  DCHECK(self);
-  return self->data;
-}
-
-Cronet_BufferCallbackPtr Cronet_Buffer_get_callback(Cronet_BufferPtr self) {
-  DCHECK(self);
-  return self->callback;
-}
-
 // Struct Cronet_Exception.
 Cronet_Exception::Cronet_Exception() {}
 
diff --git a/components/cronet/native/generated/cronet.idl_impl_struct.h b/components/cronet/native/generated/cronet.idl_impl_struct.h
index 24c780fb..6107156d 100644
--- a/components/cronet/native/generated/cronet.idl_impl_struct.h
+++ b/components/cronet/native/generated/cronet.idl_impl_struct.h
@@ -15,22 +15,6 @@
 
 #include "base/macros.h"
 
-// Struct Cronet_Buffer.
-struct Cronet_Buffer {
- public:
-  Cronet_Buffer();
-  ~Cronet_Buffer();
-
-  int32_t size = 0;
-  int32_t limit = 0;
-  int32_t position = 0;
-  RawDataPtr data;
-  Cronet_BufferCallbackPtr callback;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Cronet_Buffer);
-};
-
 // Struct Cronet_Exception.
 struct Cronet_Exception {
  public:
diff --git a/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc b/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc
index f9485366..e2027e3 100644
--- a/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc
+++ b/components/cronet/native/generated/cronet.idl_impl_struct_unittest.cc
@@ -23,28 +23,6 @@
   DISALLOW_COPY_AND_ASSIGN(CronetStructTest);
 };
 
-// Test Struct Cronet_Buffer setters and getters.
-TEST_F(CronetStructTest, TestCronet_Buffer) {
-  Cronet_BufferPtr first = Cronet_Buffer_Create();
-  Cronet_BufferPtr second = Cronet_Buffer_Create();
-
-  // Copy values from |first| to |second|.
-  Cronet_Buffer_set_size(second, Cronet_Buffer_get_size(first));
-  EXPECT_EQ(Cronet_Buffer_get_size(first), Cronet_Buffer_get_size(second));
-  Cronet_Buffer_set_limit(second, Cronet_Buffer_get_limit(first));
-  EXPECT_EQ(Cronet_Buffer_get_limit(first), Cronet_Buffer_get_limit(second));
-  Cronet_Buffer_set_position(second, Cronet_Buffer_get_position(first));
-  EXPECT_EQ(Cronet_Buffer_get_position(first),
-            Cronet_Buffer_get_position(second));
-  Cronet_Buffer_set_data(second, Cronet_Buffer_get_data(first));
-  EXPECT_EQ(Cronet_Buffer_get_data(first), Cronet_Buffer_get_data(second));
-  Cronet_Buffer_set_callback(second, Cronet_Buffer_get_callback(first));
-  EXPECT_EQ(Cronet_Buffer_get_callback(first),
-            Cronet_Buffer_get_callback(second));
-  Cronet_Buffer_Destroy(first);
-  Cronet_Buffer_Destroy(second);
-}
-
 // Test Struct Cronet_Exception setters and getters.
 TEST_F(CronetStructTest, TestCronet_Exception) {
   Cronet_ExceptionPtr first = Cronet_Exception_Create();
diff --git a/components/cronet/native/include/DEPS b/components/cronet/native/include/DEPS
new file mode 100644
index 0000000..0223c4a
--- /dev/null
+++ b/components/cronet/native/include/DEPS
@@ -0,0 +1,8 @@
+# Files in this directory are copied externally and can't have any dependencies
+include_rules = [
+  # TODO(mef): There doesn't appear to be a way to specify that no includes
+  # are allowed, so currently we just don't allow a dependency on //base, which
+  # should disqualify most code. It would be nice to be able to actual prevent
+  # all dependencies in the future.
+  "-base",
+]
\ No newline at end of file
diff --git a/components/cronet/native/include/cronet_c.h b/components/cronet/native/include/cronet_c.h
new file mode 100644
index 0000000..792473d
--- /dev/null
+++ b/components/cronet/native/include/cronet_c.h
@@ -0,0 +1,23 @@
+// 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_CRONET_NATIVE_INCLUDE_CRONET_C_H_
+#define COMPONENTS_CRONET_NATIVE_INCLUDE_CRONET_C_H_
+
+#include "cronet_export.h"
+
+// Cronet public C API is generated from cronet.idl and
+#include "cronet.idl_c.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// TODO(mef): Remove this file if it is not needed.
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // COMPONENTS_CRONET_NATIVE_INCLUDE_CRONET_C_H_
diff --git a/components/cronet/native/include/cronet_export.h b/components/cronet/native/include/cronet_export.h
new file mode 100644
index 0000000..0a29976
--- /dev/null
+++ b/components/cronet/native/include/cronet_export.h
@@ -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.
+
+#ifndef COMPONENTS_CRONET_NATIVE_INCLUDE_CRONET_EXPORT_H_
+#define COMPONENTS_CRONET_NATIVE_INCLUDE_CRONET_EXPORT_H_
+
+#if defined(WIN32)
+#define CRONET_EXPORT
+#else
+#define CRONET_EXPORT __attribute__((visibility("default")))
+#endif
+
+#endif  // COMPONENTS_CRONET_NATIVE_INCLUDE_CRONET_EXPORT_H_
diff --git a/components/cronet/native/include/headers.gni b/components/cronet/native/include/headers.gni
new file mode 100644
index 0000000..506db3a
--- /dev/null
+++ b/components/cronet/native/include/headers.gni
@@ -0,0 +1,5 @@
+cronet_native_public_headers = [
+  "//components/cronet/native/generated/cronet.idl_c.h",
+  "//components/cronet/native/include/cronet_c.h",
+  "//components/cronet/native/include/cronet_export.h",
+]
diff --git a/components/cronet/native/runnables.cc b/components/cronet/native/runnables.cc
new file mode 100644
index 0000000..668c5f4f
--- /dev/null
+++ b/components/cronet/native/runnables.cc
@@ -0,0 +1,28 @@
+// 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/cronet/native/runnables.h"
+
+#include <utility>
+
+namespace cronet {
+
+void BaseCronet_Runnable::SetContext(Cronet_RunnableContext context) {
+  context_ = context;
+}
+
+Cronet_RunnableContext BaseCronet_Runnable::GetContext() {
+  return context_;
+}
+
+OnceClosureRunnable::OnceClosureRunnable(base::OnceClosure task)
+    : task_(std::move(task)) {}
+
+OnceClosureRunnable::~OnceClosureRunnable() = default;
+
+void OnceClosureRunnable::Run() {
+  std::move(task_).Run();
+}
+
+}  // namespace cronet
diff --git a/components/cronet/native/runnables.h b/components/cronet/native/runnables.h
new file mode 100644
index 0000000..692a6a14f
--- /dev/null
+++ b/components/cronet/native/runnables.h
@@ -0,0 +1,49 @@
+// 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_CRONET_NATIVE_RUNNABLES_H_
+#define COMPONENTS_CRONET_NATIVE_RUNNABLES_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "components/cronet/native/generated/cronet.idl_impl_interface.h"
+
+namespace cronet {
+
+// Base implementation of CronetRunnable that keeps Cronet_RunnableContext but
+// doesn't implement Run() method.
+class BaseCronet_Runnable : public Cronet_Runnable {
+ public:
+  BaseCronet_Runnable() = default;
+  ~BaseCronet_Runnable() override = default;
+
+  void SetContext(Cronet_RunnableContext context) override;
+
+  Cronet_RunnableContext GetContext() override;
+
+ private:
+  // Runnable context.
+  Cronet_RunnableContext context_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(BaseCronet_Runnable);
+};
+
+// Implementation of CronetRunnable that runs arbitrary base::OnceClosure.
+class OnceClosureRunnable : public BaseCronet_Runnable {
+ public:
+  explicit OnceClosureRunnable(base::OnceClosure task);
+  ~OnceClosureRunnable() override;
+
+  void Run() override;
+
+ private:
+  // Closure to run.
+  base::OnceClosure task_;
+
+  DISALLOW_COPY_AND_ASSIGN(OnceClosureRunnable);
+};
+
+};  // namespace cronet
+
+#endif  // COMPONENTS_CRONET_NATIVE_RUNNABLES_H_
diff --git a/components/cronet/native/runnables_unittest.cc b/components/cronet/native/runnables_unittest.cc
new file mode 100644
index 0000000..67e80cd
--- /dev/null
+++ b/components/cronet/native/runnables_unittest.cc
@@ -0,0 +1,193 @@
+// 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/cronet/native/runnables.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/cronet/native/include/cronet_c.h"
+#include "components/cronet/native/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class RunnablesTest : public ::testing::Test {
+ public:
+  RunnablesTest() = default;
+  ~RunnablesTest() override {}
+
+ protected:
+  static void UrlRequestCallback_OnRedirectReceived(
+      Cronet_UrlRequestCallbackPtr self,
+      Cronet_UrlRequestPtr request,
+      Cronet_UrlResponseInfoPtr info,
+      CharString newLocationUrl);
+  static void UrlRequestCallback_OnResponseStarted(
+      Cronet_UrlRequestCallbackPtr self,
+      Cronet_UrlRequestPtr request,
+      Cronet_UrlResponseInfoPtr info);
+  static void UrlRequestCallback_OnReadCompleted(
+      Cronet_UrlRequestCallbackPtr self,
+      Cronet_UrlRequestPtr request,
+      Cronet_UrlResponseInfoPtr info,
+      Cronet_BufferPtr buffer);
+
+  bool callback_called() const { return callback_called_; }
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ private:
+  bool callback_called_ = false;
+  DISALLOW_COPY_AND_ASSIGN(RunnablesTest);
+};
+
+class OnRedirectReceived_Runnable : public cronet::BaseCronet_Runnable {
+ public:
+  OnRedirectReceived_Runnable(Cronet_UrlRequestCallbackPtr callback,
+                              CharString new_location_url)
+      : callback_(callback), new_location_url_(new_location_url) {}
+
+  ~OnRedirectReceived_Runnable() override = default;
+
+  void Run() override {
+    Cronet_UrlRequestCallback_OnRedirectReceived(
+        callback_, /* request = */ nullptr, /* response_info = */ nullptr,
+        new_location_url_.c_str());
+  }
+
+ private:
+  // Callback provided by the application.
+  Cronet_UrlRequestCallbackPtr callback_;
+  // New location to redirect to.
+  std::string new_location_url_;
+};
+
+// Implementation of Cronet_UrlRequestCallback methods for testing.
+
+// static
+void RunnablesTest::UrlRequestCallback_OnRedirectReceived(
+    Cronet_UrlRequestCallbackPtr self,
+    Cronet_UrlRequestPtr request,
+    Cronet_UrlResponseInfoPtr info,
+    CharString newLocationUrl) {
+  CHECK(self);
+  Cronet_UrlRequestCallbackContext context =
+      Cronet_UrlRequestCallback_GetContext(self);
+  RunnablesTest* test = static_cast<RunnablesTest*>(context);
+  CHECK(test);
+  test->callback_called_ = true;
+  ASSERT_STREQ(newLocationUrl, "newUrl");
+}
+
+// static
+void RunnablesTest::UrlRequestCallback_OnResponseStarted(
+    Cronet_UrlRequestCallbackPtr self,
+    Cronet_UrlRequestPtr request,
+    Cronet_UrlResponseInfoPtr info) {
+  CHECK(self);
+  Cronet_UrlRequestCallbackContext context =
+      Cronet_UrlRequestCallback_GetContext(self);
+  RunnablesTest* test = static_cast<RunnablesTest*>(context);
+  CHECK(test);
+  test->callback_called_ = true;
+}
+
+// static
+void RunnablesTest::UrlRequestCallback_OnReadCompleted(
+    Cronet_UrlRequestCallbackPtr self,
+    Cronet_UrlRequestPtr request,
+    Cronet_UrlResponseInfoPtr info,
+    Cronet_BufferPtr buffer) {
+  CHECK(self);
+  CHECK(buffer);
+  // Destroy the |buffer|.
+  Cronet_Buffer_Destroy(buffer);
+  Cronet_UrlRequestCallbackContext context =
+      Cronet_UrlRequestCallback_GetContext(self);
+  RunnablesTest* test = static_cast<RunnablesTest*>(context);
+  CHECK(test);
+  test->callback_called_ = true;
+}
+
+// Example of posting application callback to the executor.
+TEST_F(RunnablesTest, TestRunCallbackOnExecutor) {
+  // Executor provided by the application.
+  Cronet_ExecutorPtr executor = cronet::test::CreateTestExecutor();
+  // Callback provided by the application.
+  Cronet_UrlRequestCallbackPtr callback = Cronet_UrlRequestCallback_CreateStub(
+      RunnablesTest::UrlRequestCallback_OnRedirectReceived,
+      /* OnResponseStartedFunc = */ nullptr,
+      /* OnReadCompletedFunc = */ nullptr,
+      /* OnSucceededFunc = */ nullptr,
+      /* OnFailedFunc = */ nullptr,
+      /* OnCanceledFunc = */ nullptr);
+  // New location to redirect to.
+  CharString new_location_url = "newUrl";
+  // Invoke Cronet_UrlRequestCallback_OnRedirectReceived
+  Cronet_RunnablePtr runnable =
+      new OnRedirectReceived_Runnable(callback, new_location_url);
+  new_location_url = "bad";
+  Cronet_UrlRequestCallback_SetContext(callback, this);
+  Cronet_Executor_Execute(executor, runnable);
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_TRUE(callback_called());
+  Cronet_Executor_Destroy(executor);
+}
+
+// Example of posting application callback to the executor using OneClosure.
+TEST_F(RunnablesTest, TestRunOnceClosureOnExecutor) {
+  // Executor provided by the application.
+  Cronet_ExecutorPtr executor = cronet::test::CreateTestExecutor();
+  // Callback provided by the application.
+  Cronet_UrlRequestCallbackPtr callback = Cronet_UrlRequestCallback_CreateStub(
+      RunnablesTest::UrlRequestCallback_OnRedirectReceived,
+      RunnablesTest::UrlRequestCallback_OnResponseStarted,
+      /* OnReadCompletedFunc = */ nullptr,
+      /* OnSucceededFunc = */ nullptr,
+      /* OnFailedFunc = */ nullptr,
+      /* OnCanceledFunc = */ nullptr);
+  // Invoke Cronet_UrlRequestCallback_OnResponseStarted using OnceClosure
+  Cronet_RunnablePtr runnable = new cronet::OnceClosureRunnable(
+      base::BindOnce(Cronet_UrlRequestCallback_OnResponseStarted, callback,
+                     /* request = */ nullptr, /* response_info = */ nullptr));
+  Cronet_UrlRequestCallback_SetContext(callback, this);
+  Cronet_Executor_Execute(executor, runnable);
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_TRUE(callback_called());
+  Cronet_Executor_Destroy(executor);
+}
+
+// Example of posting application callback to the executor and passing
+// Cronet_Buffer to it.
+TEST_F(RunnablesTest, TestCronetBuffer) {
+  // Executor provided by the application.
+  Cronet_ExecutorPtr executor = cronet::test::CreateTestExecutor();
+  // Callback provided by the application.
+  Cronet_UrlRequestCallbackPtr callback = Cronet_UrlRequestCallback_CreateStub(
+      RunnablesTest::UrlRequestCallback_OnRedirectReceived,
+      RunnablesTest::UrlRequestCallback_OnResponseStarted,
+      RunnablesTest::UrlRequestCallback_OnReadCompleted,
+      /* OnSucceededFunc = */ nullptr,
+      /* OnFailedFunc = */ nullptr,
+      /* OnCanceledFunc = */ nullptr);
+  // Create Cronet buffer and allocate buffer data.
+  Cronet_BufferPtr buffer = Cronet_Buffer_Create();
+  Cronet_Buffer_InitWithAlloc(buffer, 20);
+  // Invoke Cronet_UrlRequestCallback_OnReadCompleted using OnceClosure.
+  Cronet_RunnablePtr runnable = new cronet::OnceClosureRunnable(base::BindOnce(
+      RunnablesTest::UrlRequestCallback_OnReadCompleted, callback,
+      /* request = */ nullptr,
+      /* response_info = */ nullptr, buffer));
+  Cronet_UrlRequestCallback_SetContext(callback, this);
+  Cronet_Executor_Execute(executor, runnable);
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_TRUE(callback_called());
+  Cronet_Executor_Destroy(executor);
+}
+
+}  // namespace
diff --git a/components/cronet/native/test_util.cc b/components/cronet/native/test_util.cc
new file mode 100644
index 0000000..6e56cd5
--- /dev/null
+++ b/components/cronet/native/test_util.cc
@@ -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.
+
+#include "components/cronet/native/test_util.h"
+
+#include "base/bind.h"
+#include "base/task_scheduler/post_task.h"
+
+namespace {
+// Implementation of PostTaskExecutor methods.
+void TestExecutor_Execute(Cronet_ExecutorPtr self, Cronet_RunnablePtr command) {
+  CHECK(self);
+  DVLOG(1) << "Post Task";
+  base::PostTask(FROM_HERE, base::BindOnce(
+                                [](Cronet_RunnablePtr command) {
+                                  Cronet_Runnable_Run(command);
+                                  Cronet_Runnable_Destroy(command);
+                                },
+                                command));
+}
+}  // namespace
+
+namespace cronet {
+namespace test {
+
+Cronet_ExecutorPtr CreateTestExecutor() {
+  return Cronet_Executor_CreateStub(TestExecutor_Execute);
+}
+
+}  // namespace test
+}  // namespace cronet
diff --git a/components/cronet/native/test_util.h b/components/cronet/native/test_util.h
new file mode 100644
index 0000000..c674781e
--- /dev/null
+++ b/components/cronet/native/test_util.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_CRONET_NATIVE_TEST_UTIL_H_
+#define COMPONENTS_CRONET_NATIVE_TEST_UTIL_H_
+
+#include "base/macros.h"
+#include "cronet_c.h"
+
+namespace cronet {
+// Various test utility functions for testing Cronet.
+namespace test {
+
+// Create an executor that runs tasks on different background thread.
+Cronet_ExecutorPtr CreateTestExecutor();
+
+}  // namespace test
+}  // namespace cronet
+
+#endif  // COMPONENTS_CRONET_NATIVE_TEST_UTIL_H_
diff --git a/components/cronet/tools/generators/c_templates/module_c.h.tmpl b/components/cronet/tools/generators/c_templates/module_c.h.tmpl
index eccff687..a66b4e20 100644
--- a/components/cronet/tools/generators/c_templates/module_c.h.tmpl
+++ b/components/cronet/tools/generators/c_templates/module_c.h.tmpl
@@ -19,6 +19,10 @@
 #ifndef {{header_guard}}
 #define {{header_guard}}
 
+{#-- TODO(mef): Derive EXPORT_MACRO from module name --#}
+{%- set export_macro = "CRONET_EXPORT" %}
+#include "cronet_export.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -72,13 +76,13 @@
 // Concrete interface {{interface_name}}.
 
 // Create an instance of {{interface_name}}.
-{{interface_name}}Ptr {{interface_name}}_Create();
+{{export_macro}} {{interface_name}}Ptr {{interface_name}}_Create();
 {%-   endif %}
 // Destroy an instance of {{interface_name}}.
-void {{interface_name}}_Destroy({{interface_name}}Ptr self);
+{{export_macro}} void {{interface_name}}_Destroy({{interface_name}}Ptr self);
 // Set and get app-specific {{interface_name}}Context.
-void {{interface_name}}_SetContext({{interface_name}}Ptr self, {{interface_name}}Context);
-{{interface_name}}Context {{interface_name}}_GetContext({{interface_name}}Ptr self);
+{{export_macro}} void {{interface_name}}_SetContext({{interface_name}}Ptr self, {{interface_name}}Context);
+{{export_macro}} {{interface_name}}Context {{interface_name}}_GetContext({{interface_name}}Ptr self);
 {%-  if interface|is_abstract %}
 // Abstract interface {{interface_name}} is implemented by the app.
 // The following concrete methods forward call to app implementation.
@@ -88,6 +92,7 @@
 // The app calls them to manipulate {{interface_name}}.
 {%-   endif %}
 {%- for method in interface.methods %}
+{{export_macro}}
 {%-  if method.response_parameters and method.sync %}
 {%-   for param in method.response_parameters %}
 {{param.kind|c_wrapper_type}}
@@ -127,7 +132,7 @@
 // Concrete interface {{interface_name}} is implemented by Cronet.
 // The app can use this for testing / mocking.
 {%-   endif %}
-{{interface_name}}Ptr {{interface_name}}_CreateStub(
+{{export_macro}} {{interface_name}}Ptr {{interface_name}}_CreateStub(
 {%- for method in interface.methods -%}
   {{interface_name}}_{{method.name}}Func {{method.name}}Func
 {%- if not loop.last %}, {% endif %}
@@ -139,10 +144,11 @@
 {% set struct_name = struct|get_name_for_kind %}
 ///////////////////////
 // Struct {{struct_name}}.
-{{struct_name}}Ptr {{struct_name}}_Create();
-void {{struct_name}}_Destroy({{struct_name}}Ptr self);
+{{export_macro}} {{struct_name}}Ptr {{struct_name}}_Create();
+{{export_macro}} void {{struct_name}}_Destroy({{struct_name}}Ptr self);
 // {{struct_name}} setters.
 {%- for packed_field in struct.packed.packed_fields_in_ordinal_order %}
+{{export_macro}}
 {%-  set kind = packed_field.field.kind %}
 {%-  if kind|is_array_kind %}
 void {{struct_name}}_add_{{packed_field.field.name}}({{struct_name}}Ptr self, {{kind.kind|c_wrapper_type}} {{packed_field.field.name}});
@@ -152,6 +158,7 @@
 {%- endfor %}
 // {{struct_name}} getters.
 {%- for packed_field in struct.packed.packed_fields_in_ordinal_order %}
+{{export_macro}}
 {%-  set kind = packed_field.field.kind %}
 {%-  if kind|is_array_kind %}
 uint32_t {{struct_name}}_get_{{packed_field.field.name}}Size({{struct_name}}Ptr self);
diff --git a/components/cronet/tools/generators/c_templates/module_impl_interface.cc.tmpl b/components/cronet/tools/generators/c_templates/module_impl_interface.cc.tmpl
index 052d828..98406459 100644
--- a/components/cronet/tools/generators/c_templates/module_impl_interface.cc.tmpl
+++ b/components/cronet/tools/generators/c_templates/module_impl_interface.cc.tmpl
@@ -58,7 +58,10 @@
 // Implementation of {{interface_name}} that forwards calls to C functions implemented by the app.
 class {{interface_name}}Stub : public {{interface_name}} {
  public:
-  {{interface_name}}Stub(
+{%-  if interface.methods|count == 1 -%}
+  explicit
+{%-   endif %}
+   {{interface_name}}Stub(
 {%- for method in interface.methods -%}
   {{interface_name}}_{{method.name}}Func {{method.name}}Func
 {%- if not loop.last %}, {% endif %}
@@ -92,7 +95,7 @@
  private:
   {{interface_name}}Context context_ = nullptr;
 {%- for method in interface.methods -%}
-  {{interface_name}}_{{method.name}}Func {{method.name}}Func_;
+  const {{interface_name}}_{{method.name}}Func {{method.name}}Func_;
 {%-   endfor %}
 
   DISALLOW_COPY_AND_ASSIGN({{interface_name}}Stub);
diff --git a/components/gcm_driver/gcm_channel_status_syncer.cc b/components/gcm_driver/gcm_channel_status_syncer.cc
index cbe1ba2f..6ef1f13 100644
--- a/components/gcm_driver/gcm_channel_status_syncer.cc
+++ b/components/gcm_driver/gcm_channel_status_syncer.cc
@@ -197,6 +197,9 @@
 void GCMChannelStatusSyncer::StartRequest() {
   DCHECK(!request_);
 
+  if (channel_status_request_url_.empty())
+    return;
+
   request_.reset(new GCMChannelStatusRequest(
       request_context_,
       channel_status_request_url_,
diff --git a/components/grpc_support/PRESUBMIT.py b/components/grpc_support/PRESUBMIT.py
new file mode 100644
index 0000000..1cc5e91
--- /dev/null
+++ b/components/grpc_support/PRESUBMIT.py
@@ -0,0 +1,23 @@
+# 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.
+
+"""Presubmit script for components/grpc_support/.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+def PostUploadHook(cl, change, output_api):
+  """git cl upload will call this hook after the issue is created/modified.
+
+  This hook adds an extra line to the CL description in order to run Cronet
+  tests in addition to CQ bots.
+  """
+
+  # TODO(https://crbug.com/712733): Remove this once Cronet bots are deployed on CQ.
+  try_bots = ['master.tryserver.chromium.android:android_cronet_tester',
+              'master.tryserver.chromium.mac:ios-simulator-cronet']
+
+  return output_api.EnsureCQIncludeTrybotsAreAdded(
+    cl, try_bots, 'Automatically added Cronet trybots to run tests on CQ.')
diff --git a/components/history/core/browser/browsing_history_service_unittest.cc b/components/history/core/browser/browsing_history_service_unittest.cc
index cfb147c..fb33ef4 100644
--- a/components/history/core/browser/browsing_history_service_unittest.cc
+++ b/components/history/core/browser/browsing_history_service_unittest.cc
@@ -124,9 +124,7 @@
 class TestWebHistoryService : public FakeWebHistoryService {
  public:
   TestWebHistoryService()
-      : FakeWebHistoryService(nullptr,
-                              nullptr,
-                              scoped_refptr<net::URLRequestContextGetter>()) {}
+      : FakeWebHistoryService(scoped_refptr<net::URLRequestContextGetter>()) {}
 
   void TriggerOnWebHistoryDeleted() {
     TestRequest request;
diff --git a/components/history/core/test/fake_web_history_service.cc b/components/history/core/test/fake_web_history_service.cc
index ac42270..3bafb03 100644
--- a/components/history/core/test/fake_web_history_service.cc
+++ b/components/history/core/test/fake_web_history_service.cc
@@ -178,12 +178,13 @@
 // FakeWebHistoryService -------------------------------------------------------
 
 FakeWebHistoryService::FakeWebHistoryService(
-    OAuth2TokenService* token_service,
-    SigninManagerBase* signin_manager,
     const scoped_refptr<net::URLRequestContextGetter>& request_context)
-    : history::WebHistoryService(token_service,
-                                 signin_manager,
-                                 request_context),
+    // NOTE: Simply pass null ojects for
+    // SigninManager/OAuth2TokenService. WebHistoryService's only
+    // usage of those objects is to fetch access tokens via RequestImpl,
+    // and FakeWebHistoryService deliberately replaces this flow with
+    // FakeWebHistoryService::FakeRequest.
+    : history::WebHistoryService(nullptr, nullptr, request_context),
       emulate_success_(true),
       emulate_response_code_(net::HTTP_OK),
       web_and_app_activity_enabled_(false),
diff --git a/components/history/core/test/fake_web_history_service.h b/components/history/core/test/fake_web_history_service.h
index ae527650..2b29cf7 100644
--- a/components/history/core/test/fake_web_history_service.h
+++ b/components/history/core/test/fake_web_history_service.h
@@ -14,9 +14,6 @@
 #include "components/history/core/browser/web_history_service.h"
 #include "url/gurl.h"
 
-class OAuth2TokenService;
-class SigninManagerBase;
-
 namespace history {
 
 // A fake WebHistoryService for testing.
@@ -33,8 +30,6 @@
 class FakeWebHistoryService : public WebHistoryService {
  public:
   FakeWebHistoryService(
-      OAuth2TokenService* token_service,
-      SigninManagerBase* signin_manager,
       const scoped_refptr<net::URLRequestContextGetter>& request_context);
   ~FakeWebHistoryService() override;
 
diff --git a/components/nacl/broker/nacl_broker_manifest.json b/components/nacl/broker/nacl_broker_manifest.json
index 8a56b79..1dc1c44 100644
--- a/components/nacl/broker/nacl_broker_manifest.json
+++ b/components/nacl/broker/nacl_broker_manifest.json
@@ -5,7 +5,15 @@
     "service_manager:connector": {
       "provides": {
         "browser": [
-          "IPC::mojom::ChannelBootstrap"
+          "IPC::mojom::ChannelBootstrap",
+
+          // NOTE: The interfaces below are not implemented in the nacl_loader
+          // service, but they are requested from all child processes by common
+          // browser-side code. We list them here to make the Service Manager
+          // happy.
+          "content::mojom::Child",
+          "content::mojom::ChildControl",
+          "content::mojom::ChildHistogramFetcherFactory"
         ]
       }
     }
diff --git a/components/nacl/common/nacl_service.cc b/components/nacl/common/nacl_service.cc
index 8f3289c..72e917f 100644
--- a/components/nacl/common/nacl_service.cc
+++ b/components/nacl/common/nacl_service.cc
@@ -15,6 +15,7 @@
 #include "mojo/edk/embedder/incoming_broker_client_invitation.h"
 #include "mojo/edk/embedder/scoped_ipc_support.h"
 #include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/cpp/service_context.h"
@@ -56,11 +57,6 @@
   return service_manager::mojom::ServiceRequest(std::move(parent_handle));
 }
 
-void ConnectBootstrapChannel(IPC::mojom::ChannelBootstrapPtrInfo ptr,
-                             IPC::mojom::ChannelBootstrapRequest request) {
-  mojo::FuseInterface(std::move(request), std::move(ptr));
-}
-
 class NaClService : public service_manager::Service {
  public:
   NaClService(IPC::mojom::ChannelBootstrapPtrInfo bootstrap,
@@ -76,17 +72,13 @@
   IPC::mojom::ChannelBootstrapPtrInfo ipc_channel_bootstrap_;
   std::unique_ptr<mojo::edk::ScopedIPCSupport> ipc_support_;
   bool connected_ = false;
-  service_manager::BinderRegistry registry_;
 };
 
 NaClService::NaClService(
     IPC::mojom::ChannelBootstrapPtrInfo bootstrap,
     std::unique_ptr<mojo::edk::ScopedIPCSupport> ipc_support)
     : ipc_channel_bootstrap_(std::move(bootstrap)),
-      ipc_support_(std::move(ipc_support)) {
-  registry_.AddInterface(base::Bind(&ConnectBootstrapChannel,
-                                    base::Passed(&ipc_channel_bootstrap_)));
-}
+      ipc_support_(std::move(ipc_support)) {}
 
 NaClService::~NaClService() = default;
 
@@ -95,9 +87,13 @@
     const std::string& interface_name,
     mojo::ScopedMessagePipeHandle interface_pipe) {
   if (source_info.identity.name() == content::mojom::kBrowserServiceName &&
-      !connected_) {
+      interface_name == IPC::mojom::ChannelBootstrap::Name_ && !connected_) {
     connected_ = true;
-    registry_.BindInterface(interface_name, std::move(interface_pipe));
+    mojo::FuseInterface(
+        IPC::mojom::ChannelBootstrapRequest(std::move(interface_pipe)),
+        std::move(ipc_channel_bootstrap_));
+  } else {
+    DVLOG(1) << "Ignoring request for unknown interface " << interface_name;
   }
 }
 
diff --git a/components/nacl/loader/nacl_loader_manifest.json b/components/nacl/loader/nacl_loader_manifest.json
index 7598054..dc2f9bf 100644
--- a/components/nacl/loader/nacl_loader_manifest.json
+++ b/components/nacl/loader/nacl_loader_manifest.json
@@ -5,7 +5,15 @@
     "service_manager:connector": {
       "provides": {
         "browser": [
-          "IPC::mojom::ChannelBootstrap"
+          "IPC::mojom::ChannelBootstrap",
+
+          // NOTE: The interfaces below are not implemented in the nacl_loader
+          // service, but they are requested from all child processes by common
+          // browser-side code. We list them here to make the Service Manager
+          // happy.
+          "content::mojom::Child",
+          "content::mojom::ChildControl",
+          "content::mojom::ChildHistogramFetcherFactory"
         ]
       }
     }
diff --git a/components/offline_pages/core/BUILD.gn b/components/offline_pages/core/BUILD.gn
index dfb760a..a64ec1f2 100644
--- a/components/offline_pages/core/BUILD.gn
+++ b/components/offline_pages/core/BUILD.gn
@@ -25,6 +25,8 @@
     "model/clear_legacy_temporary_pages_task.h",
     "model/clear_storage_task.cc",
     "model/clear_storage_task.h",
+    "model/complete_offline_page_upgrade_task.cc",
+    "model/complete_offline_page_upgrade_task.h",
     "model/create_archive_task.cc",
     "model/create_archive_task.h",
     "model/delete_page_task.cc",
@@ -147,6 +149,7 @@
     "model/clear_digest_task_unittest.cc",
     "model/clear_legacy_temporary_pages_task_unittest.cc",
     "model/clear_storage_task_unittest.cc",
+    "model/complete_offline_page_upgrade_task_unittest.cc",
     "model/create_archive_task_unittest.cc",
     "model/delete_page_task_unittest.cc",
     "model/get_pages_task_unittest.cc",
diff --git a/components/offline_pages/core/model/complete_offline_page_upgrade_task.cc b/components/offline_pages/core/model/complete_offline_page_upgrade_task.cc
new file mode 100644
index 0000000..9085b5cd
--- /dev/null
+++ b/components/offline_pages/core/model/complete_offline_page_upgrade_task.cc
@@ -0,0 +1,128 @@
+// 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/offline_pages/core/model/complete_offline_page_upgrade_task.h"
+
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/sys_info.h"
+#include "components/offline_pages/core/offline_page_metadata_store_sql.h"
+#include "components/offline_pages/core/offline_store_utils.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+#include "sql/transaction.h"
+
+namespace offline_pages {
+
+namespace {
+
+CompleteUpgradeStatus CompleteOfflinePageUpgradeSync(
+    int64_t offline_id,
+    const base::FilePath& temporary_file_path,
+    const base::FilePath& target_file_path,
+    const std::string& digest,
+    int64_t file_size,
+    sql::Connection* db) {
+  if (!db)
+    return CompleteUpgradeStatus::DB_ERROR;
+
+  sql::Transaction transaction(db);
+  if (!transaction.Begin())
+    return CompleteUpgradeStatus::DB_ERROR;
+
+  // We need to remember the old file path, so that we can remove that file
+  // later on.
+  const char kSql[] =
+      "SELECT file_path FROM offlinepages_v1 WHERE offline_id = ?";
+  sql::Statement select_statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
+  select_statement.BindInt64(0, offline_id);
+  if (!select_statement.Step()) {
+    return select_statement.Succeeded() ? CompleteUpgradeStatus::ITEM_MISSING
+                                        : CompleteUpgradeStatus::DB_ERROR;
+  }
+
+  base::FilePath old_file_path =
+      store_utils::FromDatabaseFilePath(select_statement.ColumnString(0));
+
+  // TODO(fgorski): Verify the digest and size of the temporary file.
+  // That requires moving ComputeDigest function to component and this is
+  // already in progress.
+
+  // Verify that the temporary file is there.
+  if (!base::PathExists(temporary_file_path))
+    return CompleteUpgradeStatus::TEMPORARY_FILE_MISSING;
+
+  // Verify that the target file name is not in use.
+  if (base::PathExists(target_file_path))
+    return CompleteUpgradeStatus::TARGET_FILE_NAME_IN_USE;
+
+  if (!base::Move(temporary_file_path, target_file_path))
+    return CompleteUpgradeStatus::RENAMING_FAILED;
+
+  // Conditions for upgrade are met here.
+  // Update remaining attempts in DB and complete task.
+  const char kUpdateSql[] =
+      "UPDATE offlinepages_v1"
+      " SET upgrade_attempt = 0, file_path = ?, file_size = ?, digest = ?"
+      " WHERE offline_id = ?";
+  sql::Statement update_statement(
+      db->GetCachedStatement(SQL_FROM_HERE, kUpdateSql));
+  update_statement.BindString(
+      0, store_utils::ToDatabaseFilePath(target_file_path));
+  update_statement.BindInt64(1, file_size);
+  update_statement.BindString(2, digest);
+  update_statement.BindInt64(3, offline_id);
+
+  // This status might require special handling/reporting as the new file was
+  // renamed to its final name, but store item was not updated accordingly.
+  if (!update_statement.Run() || !transaction.Commit())
+    return CompleteUpgradeStatus::DB_ERROR_POST_FILE_RENAME;
+
+  // Make a best effort to delete the old file (will be cleaned up by
+  // consistency check otherwise).
+  base::DeleteFile(old_file_path, false /* recursive */);
+
+  return CompleteUpgradeStatus::SUCCESS;
+}
+
+}  // namespace
+
+CompleteOfflinePageUpgradeTask::CompleteOfflinePageUpgradeTask(
+    OfflinePageMetadataStoreSQL* store,
+    int64_t offline_id,
+    const base::FilePath& temporary_file_path,
+    const base::FilePath& target_file_path,
+    const std::string& digest,
+    int64_t file_size,
+    CompleteUpgradeCallback callback)
+    : store_(store),
+      offline_id_(offline_id),
+      temporary_file_path_(temporary_file_path),
+      target_file_path_(target_file_path),
+      digest_(digest),
+      file_size_(file_size),
+      callback_(std::move(callback)),
+      weak_ptr_factory_(this) {
+  DCHECK(store_);
+  DCHECK(!callback_.is_null());
+}
+
+CompleteOfflinePageUpgradeTask::~CompleteOfflinePageUpgradeTask() {}
+
+void CompleteOfflinePageUpgradeTask::Run() {
+  store_->Execute(
+      base::BindOnce(&CompleteOfflinePageUpgradeSync, offline_id_,
+                     temporary_file_path_, target_file_path_, digest_,
+                     file_size_),
+      base::BindOnce(&CompleteOfflinePageUpgradeTask::InformUpgradeAttemptDone,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CompleteOfflinePageUpgradeTask::InformUpgradeAttemptDone(
+    CompleteUpgradeStatus result) {
+  std::move(callback_).Run(result);
+  TaskComplete();
+}
+
+}  // namespace offline_pages
diff --git a/components/offline_pages/core/model/complete_offline_page_upgrade_task.h b/components/offline_pages/core/model/complete_offline_page_upgrade_task.h
new file mode 100644
index 0000000..049755bb
--- /dev/null
+++ b/components/offline_pages/core/model/complete_offline_page_upgrade_task.h
@@ -0,0 +1,68 @@
+// 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_OFFLINE_PAGES_CORE_MODEL_COMPLETE_OFFLINE_PAGE_UPRGRADE_TASK_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_COMPLETE_OFFLINE_PAGE_UPRGRADE_TASK_H_
+
+#include <stdint.h>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/offline_pages/core/model/offline_page_upgrade_types.h"
+#include "components/offline_pages/core/task.h"
+
+namespace offline_pages {
+
+class OfflinePageMetadataStoreSQL;
+
+// This task is responsible for completing the upgrade process for an offline
+// page.
+class CompleteOfflinePageUpgradeTask : public Task {
+ public:
+  CompleteOfflinePageUpgradeTask(OfflinePageMetadataStoreSQL* store,
+                                 int64_t offline_id,
+                                 const base::FilePath& temporary_file_path,
+                                 const base::FilePath& target_file_path,
+                                 const std::string& digest,
+                                 int64_t file_size,
+                                 CompleteUpgradeCallback callback);
+  ~CompleteOfflinePageUpgradeTask() override;
+
+  // Task implementation.
+  void Run() override;
+
+ private:
+  void InformUpgradeAttemptDone(CompleteUpgradeStatus result);
+
+  // The store containing the pages to be cleared. Not owned.
+  OfflinePageMetadataStoreSQL* store_;
+
+  // ID of the item that needs to be updated.
+  int64_t offline_id_;
+
+  // Name of the temporary file. This file is already upgraded and needs to
+  // replace the old file in the DB.
+  base::FilePath temporary_file_path_;
+
+  // Final name that the archive should have in the public location.
+  base::FilePath target_file_path_;
+
+  // Digest of the temporary file.
+  std::string digest_;
+
+  // Expected file size of the temporary file, which is double checked in
+  // archive verification step.
+  int64_t file_size_;
+
+  // Callback to return the result of starting the upgrade process.
+  CompleteUpgradeCallback callback_;
+
+  base::WeakPtrFactory<CompleteOfflinePageUpgradeTask> weak_ptr_factory_;
+  DISALLOW_COPY_AND_ASSIGN(CompleteOfflinePageUpgradeTask);
+};
+
+}  // namespace offline_pages
+
+#endif  // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_COMPLETE_OFFLINE_PAGE_UPRGRADE_TASK_H_
diff --git a/components/offline_pages/core/model/complete_offline_page_upgrade_task_unittest.cc b/components/offline_pages/core/model/complete_offline_page_upgrade_task_unittest.cc
new file mode 100644
index 0000000..f8015a5
--- /dev/null
+++ b/components/offline_pages/core/model/complete_offline_page_upgrade_task_unittest.cc
@@ -0,0 +1,200 @@
+// 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/offline_pages/core/model/complete_offline_page_upgrade_task.h"
+
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ptr_util.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/offline_pages/core/model/offline_page_item_generator.h"
+#include "components/offline_pages/core/offline_page_metadata_store_test_util.h"
+#include "components/offline_pages/core/test_task_runner.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace offline_pages {
+
+namespace {
+const char kContentsOfTempFile[] = "Sample content of temp file.";
+const char kTargetFileName[] = "target_file_name.mhtml";
+// TODO(fgorski): Replace test with actually computed digest.
+const char kDummyDigest[] = "TestDigest==";
+
+base::FilePath PrepareTemporaryFile(const base::FilePath& temp_dir) {
+  base::FilePath temporary_file_path;
+  EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir, &temporary_file_path));
+  EXPECT_TRUE(
+      base::AppendToFile(temporary_file_path,
+                         reinterpret_cast<const char*>(&kContentsOfTempFile[0]),
+                         sizeof(kContentsOfTempFile)));
+  return temporary_file_path;
+}
+
+}  // namespace
+
+class CompleteOfflinePageUpgradeTaskTest : public testing::Test {
+ public:
+  CompleteOfflinePageUpgradeTaskTest();
+  ~CompleteOfflinePageUpgradeTaskTest() override;
+
+  void SetUp() override;
+  void TearDown() override;
+  OfflinePageItem CreateOfflinePage();
+
+  void CompleteUpgradeDone(CompleteUpgradeStatus result);
+
+  OfflinePageMetadataStoreSQL* store() { return store_test_util_.store(); }
+  OfflinePageMetadataStoreTestUtil* store_test_util() {
+    return &store_test_util_;
+  }
+  OfflinePageItemGenerator* generator() { return &generator_; }
+  TestTaskRunner* runner() { return &runner_; }
+
+  CompleteUpgradeCallback callback() {
+    return base::BindOnce(
+        &CompleteOfflinePageUpgradeTaskTest::CompleteUpgradeDone,
+        base::Unretained(this));
+  }
+
+  const base::FilePath& temp_dir_path() const { return temp_dir_.GetPath(); }
+  const base::FilePath& temporary_file_path() const {
+    return temporary_file_path_;
+  }
+  const base::FilePath& target_file_path() const { return target_file_path_; }
+
+  CompleteUpgradeStatus last_status() const { return last_status_; }
+
+ private:
+  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
+  base::ThreadTaskRunnerHandle task_runner_handle_;
+  OfflinePageMetadataStoreTestUtil store_test_util_;
+  OfflinePageItemGenerator generator_;
+  TestTaskRunner runner_;
+  CompleteUpgradeStatus last_status_;
+  base::ScopedTempDir temp_dir_;
+  base::FilePath temporary_file_path_;
+  base::FilePath target_file_path_;
+};
+
+CompleteOfflinePageUpgradeTaskTest::CompleteOfflinePageUpgradeTaskTest()
+    : task_runner_(new base::TestMockTimeTaskRunner()),
+      task_runner_handle_(task_runner_),
+      store_test_util_(task_runner_),
+      runner_(task_runner_),
+      last_status_(CompleteUpgradeStatus::DB_ERROR) {}
+
+CompleteOfflinePageUpgradeTaskTest::~CompleteOfflinePageUpgradeTaskTest() {}
+
+void CompleteOfflinePageUpgradeTaskTest::SetUp() {
+  store_test_util_.BuildStoreInMemory();
+  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+  generator()->SetArchiveDirectory(temp_dir_path());
+
+  temporary_file_path_ = PrepareTemporaryFile(temp_dir_path());
+  target_file_path_ = temp_dir_path().AppendASCII(kTargetFileName);
+}
+
+void CompleteOfflinePageUpgradeTaskTest::TearDown() {
+  store_test_util_.DeleteStore();
+}
+
+OfflinePageItem CompleteOfflinePageUpgradeTaskTest::CreateOfflinePage() {
+  OfflinePageItem page = generator()->CreateItemWithTempFile();
+  page.upgrade_attempt = 3;
+  store_test_util()->InsertItem(page);
+  return page;
+}
+
+void CompleteOfflinePageUpgradeTaskTest::CompleteUpgradeDone(
+    CompleteUpgradeStatus result) {
+  last_status_ = result;
+}
+
+TEST_F(CompleteOfflinePageUpgradeTaskTest, Success) {
+  OfflinePageItem original_page = CreateOfflinePage();
+
+  auto task = base::MakeUnique<CompleteOfflinePageUpgradeTask>(
+      store(), original_page.offline_id, temporary_file_path(),
+      target_file_path(), kDummyDigest, sizeof(kContentsOfTempFile),
+      callback());
+  runner()->RunTask(std::move(task));
+
+  EXPECT_EQ(CompleteUpgradeStatus::SUCCESS, last_status());
+
+  auto upgraded_page =
+      store_test_util()->GetPageByOfflineId(original_page.offline_id);
+  ASSERT_TRUE(upgraded_page);
+  EXPECT_EQ(0, upgraded_page->upgrade_attempt);
+  EXPECT_EQ(target_file_path(), upgraded_page->file_path);
+  EXPECT_EQ(static_cast<int64_t>(sizeof(kContentsOfTempFile)),
+            upgraded_page->file_size);
+  EXPECT_EQ(kDummyDigest, upgraded_page->digest);
+
+  EXPECT_FALSE(base::PathExists(temporary_file_path()));
+  EXPECT_TRUE(base::PathExists(target_file_path()));
+  EXPECT_FALSE(base::PathExists(original_page.file_path));
+}
+
+TEST_F(CompleteOfflinePageUpgradeTaskTest, ItemMissing) {
+  auto task = base::MakeUnique<CompleteOfflinePageUpgradeTask>(
+      store(), 42, temporary_file_path(), target_file_path(), kDummyDigest,
+      sizeof(kContentsOfTempFile), callback());
+  runner()->RunTask(std::move(task));
+
+  EXPECT_EQ(CompleteUpgradeStatus::ITEM_MISSING, last_status());
+
+  EXPECT_TRUE(base::PathExists(temporary_file_path()));
+  EXPECT_FALSE(base::PathExists(target_file_path()));
+}
+
+TEST_F(CompleteOfflinePageUpgradeTaskTest, TemporaryFileMissing) {
+  OfflinePageItem original_page = CreateOfflinePage();
+
+  // This ensures the temporary file won't be there.
+  EXPECT_TRUE(base::DeleteFile(temporary_file_path(), false));
+
+  auto task = base::MakeUnique<CompleteOfflinePageUpgradeTask>(
+      store(), original_page.offline_id, temporary_file_path(),
+      target_file_path(), kDummyDigest, sizeof(kContentsOfTempFile),
+      callback());
+  runner()->RunTask(std::move(task));
+
+  EXPECT_EQ(CompleteUpgradeStatus::TEMPORARY_FILE_MISSING, last_status());
+
+  auto upgraded_page =
+      store_test_util()->GetPageByOfflineId(original_page.offline_id);
+  ASSERT_TRUE(upgraded_page);
+  EXPECT_EQ(original_page, *upgraded_page);
+
+  EXPECT_FALSE(base::PathExists(temporary_file_path()));
+  EXPECT_FALSE(base::PathExists(target_file_path()));
+  EXPECT_TRUE(base::PathExists(original_page.file_path));
+}
+
+TEST_F(CompleteOfflinePageUpgradeTaskTest, TargetFileNameInUse) {
+  OfflinePageItem original_page = CreateOfflinePage();
+
+  // This ensures target name is taken.
+  EXPECT_TRUE(base::CopyFile(temporary_file_path(), target_file_path()));
+
+  auto task = base::MakeUnique<CompleteOfflinePageUpgradeTask>(
+      store(), original_page.offline_id, temporary_file_path(),
+      target_file_path(), kDummyDigest, sizeof(kContentsOfTempFile),
+      callback());
+  runner()->RunTask(std::move(task));
+
+  EXPECT_EQ(CompleteUpgradeStatus::TARGET_FILE_NAME_IN_USE, last_status());
+
+  auto upgraded_page =
+      store_test_util()->GetPageByOfflineId(original_page.offline_id);
+  ASSERT_TRUE(upgraded_page);
+  EXPECT_EQ(original_page, *upgraded_page);
+
+  EXPECT_TRUE(base::PathExists(temporary_file_path()));
+  EXPECT_TRUE(base::PathExists(target_file_path()));
+  EXPECT_TRUE(base::PathExists(original_page.file_path));
+}
+
+}  // namespace offline_pages
diff --git a/components/offline_pages/core/model/offline_page_upgrade_types.cc b/components/offline_pages/core/model/offline_page_upgrade_types.cc
index 945c2064..fa1a5b6 100644
--- a/components/offline_pages/core/model/offline_page_upgrade_types.cc
+++ b/components/offline_pages/core/model/offline_page_upgrade_types.cc
@@ -13,10 +13,8 @@
     : status(status) {}
 
 StartUpgradeResult::StartUpgradeResult(StartUpgradeStatus status,
-                                       std::string digest,
-                                       base::FilePath file_path)
-    : status(status),
-      digest(std::move(digest)),
-      file_path(std::move(file_path)) {}
+                                       const std::string& digest,
+                                       const base::FilePath& file_path)
+    : status(status), digest(digest), file_path(file_path) {}
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/core/model/offline_page_upgrade_types.h b/components/offline_pages/core/model/offline_page_upgrade_types.h
index 420a80fe..3fd1b95 100644
--- a/components/offline_pages/core/model/offline_page_upgrade_types.h
+++ b/components/offline_pages/core/model/offline_page_upgrade_types.h
@@ -26,8 +26,8 @@
   StartUpgradeResult();
   explicit StartUpgradeResult(StartUpgradeStatus status);
   StartUpgradeResult(StartUpgradeStatus status,
-                     std::string digest,
-                     base::FilePath file_path);
+                     const std::string& digest,
+                     const base::FilePath& file_path);
 
   // Support for move semantics.
   StartUpgradeResult(StartUpgradeResult&& other) = default;
@@ -41,6 +41,21 @@
 // Callback delivering results of starting the upgrade.
 typedef base::OnceCallback<void(StartUpgradeResult)> StartUpgradeCallback;
 
+// Enumeration of possible statuses of upgrade process completion.
+enum class CompleteUpgradeStatus {
+  SUCCESS,
+  DB_ERROR,
+  ITEM_MISSING,
+  DIGEST_VERIFICATION_FAILED,
+  TEMPORARY_FILE_MISSING,
+  TARGET_FILE_NAME_IN_USE,
+  RENAMING_FAILED,
+  DB_ERROR_POST_FILE_RENAME,
+};
+
+// Callback for completing the upgrade.
+typedef base::OnceCallback<void(CompleteUpgradeStatus)> CompleteUpgradeCallback;
+
 }  // namespace offline_pages
 
 #endif  // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_UPRGRADE_TYPES_H_
diff --git a/components/offline_pages/core/model/start_offline_page_upgrade_task.cc b/components/offline_pages/core/model/start_offline_page_upgrade_task.cc
index 74e31bf..b97698f9 100644
--- a/components/offline_pages/core/model/start_offline_page_upgrade_task.cc
+++ b/components/offline_pages/core/model/start_offline_page_upgrade_task.cc
@@ -17,8 +17,6 @@
 
 namespace {
 
-const int64_t kMinFreeDiskSpaceInBytes = 10 * 1024 * 1024;  // 10 MB
-
 StartUpgradeResult StartOfflinePageUpgradeSync(
     int64_t offline_id,
     const base::FilePath& target_directory,
@@ -35,8 +33,11 @@
       " FROM offlinepages_v1 WHERE offline_id = ?";
   sql::Statement select_statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
   select_statement.BindInt64(0, offline_id);
-  if (!select_statement.Step())
-    return StartUpgradeResult(StartUpgradeStatus::ITEM_MISSING);
+  if (!select_statement.Step()) {
+    return StartUpgradeResult(select_statement.Succeeded()
+                                  ? StartUpgradeStatus::ITEM_MISSING
+                                  : StartUpgradeStatus::DB_ERROR);
+  }
 
   base::FilePath file_path =
       store_utils::FromDatabaseFilePath(select_statement.ColumnString(0));
@@ -45,8 +46,6 @@
 
   int64_t free_disk_space_on_target =
       base::SysInfo::AmountOfFreeDiskSpace(target_directory);
-  if (free_disk_space_on_target < kMinFreeDiskSpaceInBytes)
-    return StartUpgradeResult(StartUpgradeStatus::NOT_ENOUGH_STORAGE);
 
   int64_t file_size = select_statement.ColumnInt64(1);
   if (free_disk_space_on_target < 2 * file_size)
diff --git a/components/offline_pages/core/model/start_offline_page_upgrade_task_unittest.cc b/components/offline_pages/core/model/start_offline_page_upgrade_task_unittest.cc
index 4c8f9c6..ec676ba 100644
--- a/components/offline_pages/core/model/start_offline_page_upgrade_task_unittest.cc
+++ b/components/offline_pages/core/model/start_offline_page_upgrade_task_unittest.cc
@@ -79,22 +79,23 @@
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   generator()->SetArchiveDirectory(temp_dir.GetPath());
 
-  OfflinePageItem page = generator()->CreateItemWithTempFile();
-  page.upgrade_attempt = 3;
-  page.digest = kTestDigest;
-  store_test_util()->InsertItem(page);
+  OfflinePageItem original_page = generator()->CreateItemWithTempFile();
+  original_page.upgrade_attempt = 3;
+  original_page.digest = kTestDigest;
+  store_test_util()->InsertItem(original_page);
 
   auto task = base::MakeUnique<StartOfflinePageUpgradeTask>(
-      store(), page.offline_id, temp_dir.GetPath(), callback());
+      store(), original_page.offline_id, temp_dir.GetPath(), callback());
   runner()->RunTask(std::move(task));
 
   EXPECT_EQ(StartUpgradeStatus::SUCCESS, last_result()->status);
   EXPECT_EQ(kTestDigest, last_result()->digest);
-  EXPECT_EQ(page.file_path, last_result()->file_path);
+  EXPECT_EQ(original_page.file_path, last_result()->file_path);
 
-  auto offline_page = store_test_util()->GetPageByOfflineId(page.offline_id);
-  ASSERT_TRUE(offline_page);
-  EXPECT_EQ(2, offline_page->upgrade_attempt);
+  auto upgraded_page =
+      store_test_util()->GetPageByOfflineId(original_page.offline_id);
+  ASSERT_TRUE(upgraded_page);
+  EXPECT_EQ(2, upgraded_page->upgrade_attempt);
 }
 
 TEST_F(StartOfflinePageUpgradeTaskTest, StartUpgradeItemMissing) {
@@ -108,21 +109,22 @@
 }
 
 TEST_F(StartOfflinePageUpgradeTaskTest, StartUpgradeFileMissing) {
-  OfflinePageItem page = generator()->CreateItem();
-  page.upgrade_attempt = 3;
-  store_test_util()->InsertItem(page);
+  OfflinePageItem original_page = generator()->CreateItem();
+  original_page.upgrade_attempt = 3;
+  store_test_util()->InsertItem(original_page);
 
   auto task = base::MakeUnique<StartOfflinePageUpgradeTask>(
-      store(), page.offline_id, base::FilePath(), callback());
+      store(), original_page.offline_id, base::FilePath(), callback());
   runner()->RunTask(std::move(task));
 
   EXPECT_EQ(StartUpgradeStatus::FILE_MISSING, last_result()->status);
   EXPECT_TRUE(last_result()->digest.empty());
   EXPECT_TRUE(last_result()->file_path.empty());
 
-  auto offline_page = store_test_util()->GetPageByOfflineId(page.offline_id);
-  ASSERT_TRUE(offline_page);
-  EXPECT_EQ(3, offline_page->upgrade_attempt);
+  auto upgraded_page =
+      store_test_util()->GetPageByOfflineId(original_page.offline_id);
+  ASSERT_TRUE(upgraded_page);
+  EXPECT_EQ(original_page, *upgraded_page);
 }
 
 TEST_F(StartOfflinePageUpgradeTaskTest, StartUpgradeNotEnoughSpace) {
@@ -130,21 +132,22 @@
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   generator()->SetArchiveDirectory(temp_dir.GetPath());
 
-  OfflinePageItem page = generator()->CreateItemWithTempFile();
-  page.upgrade_attempt = 3;
-  store_test_util()->InsertItem(page);
+  OfflinePageItem original_page = generator()->CreateItemWithTempFile();
+  original_page.upgrade_attempt = 3;
+  store_test_util()->InsertItem(original_page);
 
   auto task = base::MakeUnique<StartOfflinePageUpgradeTask>(
-      store(), page.offline_id, base::FilePath(), callback());
+      store(), original_page.offline_id, base::FilePath(), callback());
   runner()->RunTask(std::move(task));
 
   EXPECT_EQ(StartUpgradeStatus::NOT_ENOUGH_STORAGE, last_result()->status);
   EXPECT_TRUE(last_result()->digest.empty());
   EXPECT_TRUE(last_result()->file_path.empty());
 
-  auto offline_page = store_test_util()->GetPageByOfflineId(page.offline_id);
-  ASSERT_TRUE(offline_page);
-  EXPECT_EQ(3, offline_page->upgrade_attempt);
+  auto upgraded_page =
+      store_test_util()->GetPageByOfflineId(original_page.offline_id);
+  ASSERT_TRUE(upgraded_page);
+  EXPECT_EQ(original_page, *upgraded_page);
 }
 
 }  // namespace offline_pages
diff --git a/components/omnibox/browser/autocomplete_input.cc b/components/omnibox/browser/autocomplete_input.cc
index 8c80cc1..75ab139 100644
--- a/components/omnibox/browser/autocomplete_input.cc
+++ b/components/omnibox/browser/autocomplete_input.cc
@@ -306,10 +306,16 @@
   // many other characters (perhaps for weird intranet machines), it's extremely
   // unlikely that a user would be trying to type those in for anything other
   // than a search query.
+  //
+  // Per https://tools.ietf.org/html/rfc6761, the .invalid TLD is considered
+  // non-navigable and thus is treated like a non-compliant hostname. (Though
+  // just the word "invalid" is not a hostname).
   const base::string16 original_host(
       text.substr(parts->host.begin, parts->host.len));
-  if ((host_info.family == url::CanonHostInfo::NEUTRAL) &&
-      !net::IsCanonicalizedHostCompliant(canonicalized_url->host())) {
+  if (text != base::ASCIIToUTF16("invalid") &&
+      (host_info.family == url::CanonHostInfo::NEUTRAL) &&
+      (!net::IsCanonicalizedHostCompliant(canonicalized_url->host()) ||
+       canonicalized_url->DomainIs("invalid"))) {
     // Invalid hostname.  There are several possible cases:
     // * The user is typing a multi-word query.  If we see a space anywhere in
     //   the input host we assume this is a search and return QUERY.  (We check
@@ -435,10 +441,16 @@
   if (canonicalized_url->has_username() && desired_tld.empty())
     return metrics::OmniboxInputType::UNKNOWN;
 
-  // If the host has a known TLD or a port, it's probably a URL.  Note that we
-  // special-case "localhost" as a known hostname.
-  if (has_known_tld || (canonicalized_url->host() == "localhost") ||
-      canonicalized_url->has_port())
+  // If the host has a known TLD or a port, it's probably a URL.  The .example,
+  // .test and .localhost TLDs are special-cased as known TLDs due to
+  // https://tools.ietf.org/html/rfc6761. Note that DomainIs also covers the
+  // host, e.g. just the word localhost, that is not desired for "example" or
+  // "test".
+  if (text != base::ASCIIToUTF16("example") &&
+      text != base::ASCIIToUTF16("test") &&
+      (has_known_tld || canonicalized_url->DomainIs("example") ||
+       canonicalized_url->DomainIs("localhost") ||
+       canonicalized_url->DomainIs("test") || canonicalized_url->has_port()))
     return metrics::OmniboxInputType::URL;
 
   // No scheme, username, port, and no known TLD on the host.
diff --git a/components/omnibox/browser/autocomplete_input_unittest.cc b/components/omnibox/browser/autocomplete_input_unittest.cc
index 5dc67926..c2870d3 100644
--- a/components/omnibox/browser/autocomplete_input_unittest.cc
+++ b/components/omnibox/browser/autocomplete_input_unittest.cc
@@ -174,6 +174,20 @@
     {ASCIIToUTF16("://w"), metrics::OmniboxInputType::UNKNOWN},
     {ASCIIToUTF16(":w"), metrics::OmniboxInputType::UNKNOWN},
     {base::WideToUTF16(L".\u062A"), metrics::OmniboxInputType::UNKNOWN},
+    // These tests are for https://tools.ietf.org/html/rfc6761.
+    {ASCIIToUTF16("foo.example"), metrics::OmniboxInputType::URL},
+    {ASCIIToUTF16("foo example"), metrics::OmniboxInputType::QUERY},
+    {ASCIIToUTF16("example"), metrics::OmniboxInputType::UNKNOWN},
+    {ASCIIToUTF16("http://foo.invalid"), metrics::OmniboxInputType::UNKNOWN},
+    {ASCIIToUTF16("foo.invalid/"), metrics::OmniboxInputType::QUERY},
+    {ASCIIToUTF16("foo.invalid"), metrics::OmniboxInputType::QUERY},
+    {ASCIIToUTF16("foo invalid"), metrics::OmniboxInputType::QUERY},
+    {ASCIIToUTF16("invalid"), metrics::OmniboxInputType::UNKNOWN},
+    {ASCIIToUTF16("foo.localhost"), metrics::OmniboxInputType::URL},
+    {ASCIIToUTF16("foo localhost"), metrics::OmniboxInputType::QUERY},
+    {ASCIIToUTF16("foo.test"), metrics::OmniboxInputType::URL},
+    {ASCIIToUTF16("foo test"), metrics::OmniboxInputType::QUERY},
+    {ASCIIToUTF16("test"), metrics::OmniboxInputType::UNKNOWN},
   };
 
   for (size_t i = 0; i < arraysize(input_cases); ++i) {
diff --git a/components/onc/docs/onc_spec.md b/components/onc/docs/onc_spec.md
index b451ba6..46a3d77 100644
--- a/components/onc/docs/onc_spec.md
+++ b/components/onc/docs/onc_spec.md
@@ -881,6 +881,10 @@
     * If set, only allow connections to server hosts with X509 name or common
       name equal to this string.
 
+* **TLSVersionMin**
+    * (optional) - **string**
+    * If set, specifies the minimum TLS protocol version used by OpenVPN.
+
 * **UserAuthenticationType**
     * (optional, defaults to *None*) - **string**
     * Allowed values are:
diff --git a/components/onc/onc_constants.cc b/components/onc/onc_constants.cc
index 077a35ff..41d3142 100644
--- a/components/onc/onc_constants.cc
+++ b/components/onc/onc_constants.cc
@@ -389,6 +389,7 @@
 const char kStaticChallenge[] = "StaticChallenge";
 const char kTLSAuthContents[] = "TLSAuthContents";
 const char kTLSRemote[] = "TLSRemote";
+const char kTLSVersionMin[] = "TLSVersionMin";
 const char kUserAuthenticationType[] = "UserAuthenticationType";
 const char kVerb[] = "Verb";
 const char kVerifyHash[] = "VerifyHash";
diff --git a/components/onc/onc_constants.h b/components/onc/onc_constants.h
index a1d9a1f..9b16a55 100644
--- a/components/onc/onc_constants.h
+++ b/components/onc/onc_constants.h
@@ -402,6 +402,7 @@
 ONC_EXPORT extern const char kStaticChallenge[];
 ONC_EXPORT extern const char kTLSAuthContents[];
 ONC_EXPORT extern const char kTLSRemote[];
+ONC_EXPORT extern const char kTLSVersionMin[];
 ONC_EXPORT extern const char kUserAuthenticationType[];
 ONC_EXPORT extern const char kVerb[];
 ONC_EXPORT extern const char kVerifyHash[];
diff --git a/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc b/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc
index 3a67e27..b9564d08 100644
--- a/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc
+++ b/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc
@@ -12,7 +12,6 @@
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/storage_monitor/removable_device_constants.h"
-#include "device/media_transfer_protocol/mtp_storage_info.pb.h"
 
 namespace storage_monitor {
 
@@ -41,20 +40,21 @@
 }
 
 // Returns a unique device id from the given |storage_info|.
-std::string GetDeviceIdFromStorageInfo(const MtpStorageInfo& storage_info) {
+std::string GetDeviceIdFromStorageInfo(
+    const device::mojom::MtpStorageInfo& storage_info) {
   const std::string storage_id =
-      GetStorageIdFromStorageName(storage_info.storage_name());
+      GetStorageIdFromStorageName(storage_info.storage_name);
   if (storage_id.empty())
     return std::string();
 
   // Some devices have multiple data stores. Therefore, include storage id as
   // part of unique id along with vendor, model and volume information.
-  const std::string vendor_id = base::UintToString(storage_info.vendor_id());
-  const std::string model_id = base::UintToString(storage_info.product_id());
+  const std::string vendor_id = base::UintToString(storage_info.vendor_id);
+  const std::string model_id = base::UintToString(storage_info.product_id);
   return StorageInfo::MakeDeviceId(
       StorageInfo::MTP_OR_PTP,
       kVendorModelVolumeStoragePrefix + vendor_id + ":" + model_id + ":" +
-          storage_info.volume_identifier() + ":" + storage_id);
+          storage_info.volume_identifier + ":" + storage_id);
 }
 
 // Returns the |data_store_id| string in the required format.
@@ -65,12 +65,12 @@
 
 // Helper function to get device label from storage information.
 base::string16 GetDeviceLabelFromStorageInfo(
-    const MtpStorageInfo& storage_info) {
+    const device::mojom::MtpStorageInfo& storage_info) {
   std::string device_label;
-  const std::string& vendor_name = storage_info.vendor();
+  const std::string& vendor_name = storage_info.vendor;
   device_label = vendor_name;
 
-  const std::string& product_name = storage_info.product();
+  const std::string& product_name = storage_info.product;
   if (!product_name.empty()) {
     if (!device_label.empty())
       device_label += " ";
@@ -79,12 +79,12 @@
 
   // Add the data store id to the device label.
   if (!device_label.empty()) {
-    const std::string& volume_id = storage_info.volume_identifier();
+    const std::string& volume_id = storage_info.volume_identifier;
     if (!volume_id.empty()) {
       device_label += GetFormattedIdString(volume_id);
     } else {
       const std::string data_store_id =
-          GetStorageIdFromStorageName(storage_info.storage_name());
+          GetStorageIdFromStorageName(storage_info.storage_name);
       if (!data_store_id.empty())
         device_label += GetFormattedIdString(data_store_id);
     }
@@ -103,7 +103,7 @@
                     base::string16* vendor_name,
                     base::string16* product_name) {
   DCHECK(!storage_name.empty());
-  const MtpStorageInfo* storage_info =
+  const device::mojom::MtpStorageInfo* storage_info =
       mtp_manager->GetStorageInfo(storage_name);
 
   if (!storage_info)
@@ -112,8 +112,8 @@
   *id = GetDeviceIdFromStorageInfo(*storage_info);
   *label = GetDeviceLabelFromStorageInfo(*storage_info);
   *location = GetDeviceLocationFromStorageName(storage_name);
-  *vendor_name = base::UTF8ToUTF16(storage_info->vendor());
-  *product_name = base::UTF8ToUTF16(storage_info->product());
+  *vendor_name = base::UTF8ToUTF16(storage_info->vendor);
+  *product_name = base::UTF8ToUTF16(storage_info->product);
 }
 
 }  // namespace
diff --git a/components/storage_monitor/storage_info.cc b/components/storage_monitor/storage_info.cc
index 7725c7a..73bf072 100644
--- a/components/storage_monitor/storage_info.cc
+++ b/components/storage_monitor/storage_info.cc
@@ -109,6 +109,16 @@
   } else if (prefix == kMacImageCapturePrefix) {
     found_type = MAC_IMAGE_CAPTURE;
   } else {
+#if DCHECK_IS_ON()
+    // Users may have legacy device IDs in their profiles.
+    static const char kLegacyIPhotoPrefix[] = "iphoto:";
+    static const char kLegacyITunesPrefix[] = "itunes:";
+    static const char kLegacyPicasaPrefix[] = "picasa:";
+    if (prefix == kLegacyIPhotoPrefix || prefix == kLegacyITunesPrefix ||
+        prefix == kLegacyPicasaPrefix) {
+      return false;
+    }
+#endif
     NOTREACHED();
     return false;
   }
diff --git a/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
index 5431aa55..16c5f5a 100644
--- a/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
+++ b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
@@ -4,9 +4,6 @@
 
 #include "components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h"
 
-#include "device/media_transfer_protocol/mtp_file_entry.pb.h"
-#include "device/media_transfer_protocol/mtp_storage_info.pb.h"
-
 namespace storage_monitor {
 
 TestMediaTransferProtocolManagerChromeOS::
@@ -25,7 +22,8 @@
 TestMediaTransferProtocolManagerChromeOS::GetStorages() const {
   return std::vector<std::string>();
 }
-const MtpStorageInfo* TestMediaTransferProtocolManagerChromeOS::GetStorageInfo(
+const device::mojom::MtpStorageInfo*
+TestMediaTransferProtocolManagerChromeOS::GetStorageInfo(
     const std::string& storage_name) const {
   return NULL;
 }
@@ -33,7 +31,7 @@
 void TestMediaTransferProtocolManagerChromeOS::GetStorageInfoFromDevice(
     const std::string& storage_name,
     const GetStorageInfoFromDeviceCallback& callback) {
-  MtpStorageInfo mtp_storage_info;
+  device::mojom::MtpStorageInfo mtp_storage_info;
   callback.Run(mtp_storage_info, true /* error */);
 }
 
diff --git a/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h
index 403e350f..25e826f 100644
--- a/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h
+++ b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h
@@ -25,7 +25,7 @@
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
   const std::vector<std::string> GetStorages() const override;
-  const MtpStorageInfo* GetStorageInfo(
+  const device::mojom::MtpStorageInfo* GetStorageInfo(
       const std::string& storage_name) const override;
   void GetStorageInfoFromDevice(
       const std::string& storage_name,
diff --git a/components/ukm/content/source_url_recorder.cc b/components/ukm/content/source_url_recorder.cc
index 2e683b1..fb8dc18b 100644
--- a/components/ukm/content/source_url_recorder.cc
+++ b/components/ukm/content/source_url_recorder.cc
@@ -16,7 +16,9 @@
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "url/gurl.h"
 
-namespace {
+namespace ukm {
+
+namespace internal {
 
 // SourceUrlRecorderWebContentsObserver is responsible for recording UKM source
 // URLs, for all (any only) main frame navigations in a given WebContents.
@@ -139,21 +141,22 @@
   }
 }
 
-}  // namespace
-
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(SourceUrlRecorderWebContentsObserver);
-
-namespace ukm {
+}  // namespace internal
 
 void InitializeSourceUrlRecorderForWebContents(
     content::WebContents* web_contents) {
-  SourceUrlRecorderWebContentsObserver::CreateForWebContents(web_contents);
+  internal::SourceUrlRecorderWebContentsObserver::CreateForWebContents(
+      web_contents);
 }
 
 SourceId GetSourceIdForWebContentsDocument(content::WebContents* web_contents) {
-  SourceUrlRecorderWebContentsObserver* obs =
-      SourceUrlRecorderWebContentsObserver::FromWebContents(web_contents);
+  internal::SourceUrlRecorderWebContentsObserver* obs =
+      internal::SourceUrlRecorderWebContentsObserver::FromWebContents(
+          web_contents);
   return obs ? obs->GetLastCommittedSourceId() : kInvalidSourceId;
 }
 
 }  // namespace ukm
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(
+    ukm::internal::SourceUrlRecorderWebContentsObserver);
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn
index aad08ee..edf82432 100644
--- a/components/variations/BUILD.gn
+++ b/components/variations/BUILD.gn
@@ -78,7 +78,7 @@
   deps = [
     "proto",
     "//base",
-    "//components/crash/core/common",
+    "//components/crash/core/common:crash_key",
     "//components/prefs",
     "//crypto",
     "//third_party/mt19937ar",
diff --git a/components/variations/variations_util.cc b/components/variations/variations_util.cc
index f2a2633..e0ef0552 100644
--- a/components/variations/variations_util.cc
+++ b/components/variations/variations_util.cc
@@ -6,18 +6,37 @@
 
 #include <vector>
 
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
-#include "components/crash/core/common/crash_keys.h"
+#include "components/crash/core/common/crash_key.h"
 #include "components/variations/active_field_trials.h"
 
 namespace variations {
 
 void SetVariationListCrashKeys() {
-  std::vector<std::string> experiment_strings;
-  GetFieldTrialActiveGroupIdsAsStrings(base::StringPiece(),
-                                       &experiment_strings);
-  GetSyntheticTrialGroupIdsAsString(&experiment_strings);
-  crash_keys::SetVariationsList(experiment_strings);
+  std::vector<std::string> variations;
+  GetFieldTrialActiveGroupIdsAsStrings(base::StringPiece(), &variations);
+  GetSyntheticTrialGroupIdsAsString(&variations);
+
+  static crash_reporter::CrashKeyString<8> num_variations_key(
+      "num-experiments");
+  num_variations_key.Set(base::NumberToString(variations.size()));
+
+  static constexpr size_t kVariationsKeySize = 2048;
+  static crash_reporter::CrashKeyString<kVariationsKeySize> crash_key(
+      "variations");
+
+  std::string variations_string;
+  variations_string.reserve(kVariationsKeySize);
+
+  for (const auto& variation : variations) {
+    // Do not truncate an individual experiment.
+    if (variations_string.size() + variation.size() >= kVariationsKeySize)
+      break;
+    variations_string += variation;
+    variations_string += ",";
+  }
+  crash_key.Set(variations_string);
 }
 
 }  // namespace variations
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index aac91bf0b..b7e972d 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -157,7 +157,6 @@
     "//gpu",
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/client:gles2_interface",
-    "//gpu/command_buffer/common:gles2_utils",
     "//gpu/command_buffer/service",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings:skia_bindings",
diff --git a/components/viz/common/gl_helper_benchmark.cc b/components/viz/common/gl_helper_benchmark.cc
index 2f77caf..3cbaf04 100644
--- a/components/viz/common/gl_helper_benchmark.cc
+++ b/components/viz/common/gl_helper_benchmark.cc
@@ -54,7 +54,7 @@
 class GLHelperBenchmark : public testing::Test {
  protected:
   void SetUp() override {
-    gpu::gles2::ContextCreationAttribHelper attributes;
+    gpu::ContextCreationAttribs attributes;
     attributes.alpha_size = 8;
     attributes.depth_size = 24;
     attributes.red_size = 8;
diff --git a/components/viz/common/gl_helper_unittest.cc b/components/viz/common/gl_helper_unittest.cc
index 6c184d1..23214ca4 100644
--- a/components/viz/common/gl_helper_unittest.cc
+++ b/components/viz/common/gl_helper_unittest.cc
@@ -49,7 +49,7 @@
 class GLHelperTest : public testing::Test {
  protected:
   void SetUp() override {
-    gpu::gles2::ContextCreationAttribHelper attributes;
+    gpu::ContextCreationAttribs attributes;
     attributes.alpha_size = 8;
     attributes.depth_size = 24;
     attributes.red_size = 8;
diff --git a/components/viz/common/gpu/in_process_context_provider.cc b/components/viz/common/gpu/in_process_context_provider.cc
index a4fa4eb9..7fceb9b 100644
--- a/components/viz/common/gpu/in_process_context_provider.cc
+++ b/components/viz/common/gpu/in_process_context_provider.cc
@@ -15,7 +15,7 @@
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/raster_implementation_gles.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/service/framebuffer_completeness_cache.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
@@ -36,8 +36,8 @@
 
 namespace {
 
-gpu::gles2::ContextCreationAttribHelper CreateAttributes() {
-  gpu::gles2::ContextCreationAttribHelper attributes;
+gpu::ContextCreationAttribs CreateAttributes() {
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = -1;
   attributes.depth_size = 0;
   attributes.stencil_size = 8;
diff --git a/components/viz/common/gpu/in_process_context_provider.h b/components/viz/common/gpu/in_process_context_provider.h
index 3218727e7..37c39be 100644
--- a/components/viz/common/gpu/in_process_context_provider.h
+++ b/components/viz/common/gpu/in_process_context_provider.h
@@ -14,7 +14,7 @@
 #include "components/viz/common/gpu/context_cache_controller.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/viz_common_export.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/ipc/in_process_command_buffer.h"
 #include "ui/gfx/native_widget_types.h"
 
@@ -84,7 +84,7 @@
   ~InProcessContextProvider() override;
 
  private:
-  const gpu::gles2::ContextCreationAttribHelper attributes_;
+  const gpu::ContextCreationAttribs attributes_;
 
   base::Lock context_lock_;
   std::unique_ptr<gpu::GLInProcessContext> context_;
diff --git a/components/viz/common/yuv_readback_unittest.cc b/components/viz/common/yuv_readback_unittest.cc
index 4f625e8..d75228ac 100644
--- a/components/viz/common/yuv_readback_unittest.cc
+++ b/components/viz/common/yuv_readback_unittest.cc
@@ -30,7 +30,7 @@
 class YUVReadbackTest : public testing::Test {
  protected:
   void SetUp() override {
-    gpu::gles2::ContextCreationAttribHelper attributes;
+    gpu::ContextCreationAttribs attributes;
     attributes.alpha_size = 8;
     attributes.depth_size = 24;
     attributes.red_size = 8;
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index a604c1e..e9cdb90c 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -60,6 +60,8 @@
     "display/overlay_strategy_underlay_cast.h",
     "display/program_binding.cc",
     "display/program_binding.h",
+    "display/scoped_render_pass_texture.cc",
+    "display/scoped_render_pass_texture.h",
     "display/shader.cc",
     "display/shader.h",
     "display/skia_renderer.cc",
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
index 36e299cc..4300b7d 100644
--- a/components/viz/service/display/gl_renderer.cc
+++ b/components/viz/service/display/gl_renderer.cc
@@ -33,7 +33,6 @@
 #include "cc/paint/render_surface_filters.h"
 #include "cc/raster/scoped_gpu_raster.h"
 #include "cc/resources/resource_pool.h"
-#include "cc/resources/scoped_resource.h"
 #include "components/viz/common/display/renderer_settings.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/gpu/context_provider.h"
@@ -43,6 +42,7 @@
 #include "components/viz/common/quads/render_pass.h"
 #include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/resources/platform_color.h"
 #include "components/viz/common/resources/resource.h"
 #include "components/viz/common/resources/resource_fence.h"
 #include "components/viz/service/display/draw_polygon.h"
@@ -50,6 +50,7 @@
 #include "components/viz/service/display/layer_quad.h"
 #include "components/viz/service/display/output_surface.h"
 #include "components/viz/service/display/output_surface_frame.h"
+#include "components/viz/service/display/scoped_render_pass_texture.h"
 #include "components/viz/service/display/static_geometry_binding.h"
 #include "components/viz/service/display/texture_deleter.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -189,7 +190,8 @@
 
   // Required Inputs.
   const RenderPassDrawQuad* quad = nullptr;
-  const cc::Resource* contents_texture = nullptr;
+  const cc::Resource* bypass_quad_texture = nullptr;
+  ScopedRenderPassTexture* contents_texture = nullptr;
   const gfx::QuadF* clip_region = nullptr;
   bool flip_texture = false;
   gfx::Transform window_matrix;
@@ -221,7 +223,7 @@
 
   // The original contents, bound for sampling.
   std::unique_ptr<cc::DisplayResourceProvider::ScopedSamplerGL>
-      contents_resource_lock;
+      bypass_quad_resource_lock;
 
   // A mask to be applied when drawing the RPDQ.
   std::unique_ptr<cc::DisplayResourceProvider::ScopedSamplerGL>
@@ -251,8 +253,8 @@
   gfx::RectF tex_coord_rect;
 
   // The color space of the texture bound for sampling (from filter_image or
-  // contents_resource_lock, depending on the path taken).
-  gfx::ColorSpace contents_color_space;
+  // bypass_quad_resource_lock, depending on the path taken).
+  gfx::ColorSpace contents_and_bypass_color_space;
 };
 
 static GLint GetActiveTextureUnit(GLES2Interface* gl) {
@@ -477,7 +479,7 @@
   if (!use_discard_framebuffer_)
     return;
   bool using_default_framebuffer =
-      !current_framebuffer_lock_ &&
+      !current_framebuffer_texture_ &&
       output_surface_->capabilities().uses_default_gl_framebuffer;
   GLenum attachments[] = {static_cast<GLenum>(
       using_default_framebuffer ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0_EXT)};
@@ -907,10 +909,10 @@
   // texture. Otherwise, we use the format of the default framebuffer. But
   // whatever the format is, convert it to a valid format for CopyTexSubImage2D.
   GLenum format;
-  if (!current_framebuffer_lock_)
+  if (!current_framebuffer_texture_)
     format = output_surface_->GetFramebufferCopyTextureFormat();
   else
-    format = GLCopyTextureInternalFormat(current_framebuffer_format_);
+    format = GLCopyTextureInternalFormat(BackbufferFormat());
   // Verify the format is valid for GLES2's glCopyTexSubImage2D.
   DCHECK(format == GL_ALPHA || format == GL_LUMINANCE ||
          format == GL_LUMINANCE_ALPHA || format == GL_RGB || format == GL_RGBA)
@@ -1098,19 +1100,18 @@
     // inputs are oriented opposite to framebuffer outputs, don't flip via
     // texture coords and let the projection matrix naturallyd o it.
     params.flip_texture = false;
-    params.contents_texture = &tile_resource;
+    params.bypass_quad_texture = &tile_resource;
     DrawRenderPassQuadInternal(&params);
   } else {
-    cc::ScopedResource* contents_texture =
-        render_pass_textures_[quad->render_pass_id].get();
-    DCHECK(contents_texture);
-    DCHECK(contents_texture->id());
+    auto contents_texture_it = render_pass_textures_.find(quad->render_pass_id);
+    DCHECK(contents_texture_it->second.id());
     // See above comments about texture flipping.  When the input is a
     // render pass, it needs to an extra flip to be oriented correctly.
     params.flip_texture = true;
-    params.contents_texture = contents_texture;
+    params.contents_texture = &contents_texture_it->second;
     DrawRenderPassQuadInternal(&params);
   }
+
   if (params.background_texture) {
     gl_->DeleteTextures(1, &params.background_texture);
     params.background_texture = 0;
@@ -1280,8 +1281,11 @@
   // Apply filters to the contents texture.
   if (params->filters) {
     DCHECK(!params->filters->IsEmpty());
+    gfx::Size size = params->contents_texture
+                         ? params->contents_texture->size()
+                         : params->bypass_quad_texture->size();
     auto paint_filter = cc::RenderSurfaceFilters::BuildImageFilter(
-        *params->filters, gfx::SizeF(params->contents_texture->size()));
+        *params->filters, gfx::SizeF(size));
     auto filter = paint_filter ? paint_filter->cached_sk_filter_ : nullptr;
     if (filter) {
       SkColorFilter* colorfilter_rawptr = nullptr;
@@ -1312,19 +1316,30 @@
         SkIPoint offset;
         SkIRect subset;
         gfx::RectF src_rect(quad->rect);
+        if (params->contents_texture) {
+          params->contents_and_bypass_color_space =
+              params->contents_texture->color_space();
+          params->filter_image = ApplyImageFilter(
+              ScopedUseGrContext::Create(this), src_rect, params->dst_rect,
+              quad->filters_scale, std::move(filter),
+              params->contents_texture->id(), GL_TEXTURE_2D,
+              params->contents_texture->size(), &offset, &subset,
+              params->flip_texture, quad->filters_origin);
+        } else {
+          cc::DisplayResourceProvider::ScopedReadLockGL
+              prefilter_bypass_quad_texture_lock(
+                  resource_provider_, params->bypass_quad_texture->id());
+          params->contents_and_bypass_color_space =
+              prefilter_bypass_quad_texture_lock.color_space();
+          params->filter_image = ApplyImageFilter(
+              ScopedUseGrContext::Create(this), src_rect, params->dst_rect,
+              quad->filters_scale, std::move(filter),
+              prefilter_bypass_quad_texture_lock.texture_id(),
+              prefilter_bypass_quad_texture_lock.target(),
+              prefilter_bypass_quad_texture_lock.size(), &offset, &subset,
+              params->flip_texture, quad->filters_origin);
+        }
 
-        cc::DisplayResourceProvider::ScopedReadLockGL
-            prefilter_contents_texture_lock(resource_provider_,
-                                            params->contents_texture->id());
-        params->contents_color_space =
-            prefilter_contents_texture_lock.color_space();
-        params->filter_image = ApplyImageFilter(
-            ScopedUseGrContext::Create(this), src_rect, params->dst_rect,
-            quad->filters_scale, std::move(filter),
-            prefilter_contents_texture_lock.texture_id(),
-            prefilter_contents_texture_lock.target(),
-            prefilter_contents_texture_lock.size(), &offset, &subset,
-            params->flip_texture, quad->filters_origin);
         if (!params->filter_image)
           return false;
         params->dst_rect =
@@ -1360,17 +1375,22 @@
     gl_->BindTexture(GL_TEXTURE_2D, filter_image_id);
     gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    // |params->contents_color_space| was populated when |params->filter_image|
-    // was populated.
+    // |params->contents_and_bypass_color_space| was populated when
+    // |params->filter_image| was populated.
     params->source_needs_flip = kBottomLeft_GrSurfaceOrigin == origin;
+  } else if (params->contents_texture) {
+    gl_->BindTexture(GL_TEXTURE_2D, params->contents_texture->id());
+    params->contents_and_bypass_color_space =
+        params->contents_texture->color_space();
+    params->source_needs_flip = params->flip_texture;
   } else {
-    params->contents_resource_lock =
+    params->bypass_quad_resource_lock =
         base::MakeUnique<cc::DisplayResourceProvider::ScopedSamplerGL>(
-            resource_provider_, params->contents_texture->id(), GL_LINEAR);
+            resource_provider_, params->bypass_quad_texture->id(), GL_LINEAR);
     DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
-              params->contents_resource_lock->target());
-    params->contents_color_space =
-        params->contents_resource_lock->color_space();
+              params->bypass_quad_resource_lock->target());
+    params->contents_and_bypass_color_space =
+        params->bypass_quad_resource_lock->color_space();
     params->source_needs_flip = params->flip_texture;
   }
 }
@@ -1411,7 +1431,7 @@
                     tex_coord_precision, sampler_type, shader_blend_mode,
                     params->use_aa ? USE_AA : NO_AA, mask_mode,
                     mask_for_background, params->use_color_matrix),
-                params->contents_color_space, target_color_space);
+                params->contents_and_bypass_color_space, target_color_space);
 }
 
 void GLRenderer::UpdateRPDQUniforms(DrawRenderPassDrawQuadParams* params) {
@@ -1421,9 +1441,12 @@
   if (params->filter_image) {
     texture_size.set_width(params->filter_image->width());
     texture_size.set_height(params->filter_image->height());
-  } else {
+  } else if (params->contents_texture) {
     texture_size = params->contents_texture->size();
+  } else {
+    texture_size = params->bypass_quad_texture->size();
   }
+
   tex_rect.Scale(1.0f / texture_size.width(), 1.0f / texture_size.height());
 
   DCHECK(current_program_->vertex_tex_transform_location() != -1 ||
@@ -2601,7 +2624,7 @@
 
   copier_.FreeUnusedCachedResources();
 
-  current_framebuffer_lock_ = nullptr;
+  current_framebuffer_texture_ = nullptr;
 
   gl_->Disable(GL_BLEND);
   blend_shadow_ = false;
@@ -2619,8 +2642,7 @@
 }
 
 void GLRenderer::GenerateMipmap() {
-  DCHECK(current_framebuffer_lock_);
-  current_framebuffer_lock_->set_generate_mipmap();
+  DCHECK(current_framebuffer_texture_);
 }
 
 void GLRenderer::SetEnableDCLayers(bool enable) {
@@ -2667,9 +2689,9 @@
 
   GLuint framebuffer_texture = 0;
   gfx::Size framebuffer_texture_size;
-  if (current_framebuffer_lock_) {
-    framebuffer_texture = current_framebuffer_lock_->GetTexture();
-    framebuffer_texture_size = current_framebuffer_lock_->size();
+  if (current_framebuffer_texture_) {
+    framebuffer_texture = current_framebuffer_texture_->id();
+    framebuffer_texture_size = current_framebuffer_texture_->size();
   }
   copier_.CopyFromTextureOrFramebuffer(
       std::move(request), current_frame()->current_render_pass->output_rect,
@@ -2864,7 +2886,7 @@
 }
 
 void GLRenderer::BindFramebufferToOutputSurface() {
-  current_framebuffer_lock_ = nullptr;
+  current_framebuffer_texture_ = nullptr;
   output_surface_->BindFramebuffer();
 
   if (overdraw_feedback_) {
@@ -2882,33 +2904,27 @@
 }
 
 void GLRenderer::BindFramebufferToTexture(const RenderPassId render_pass_id) {
-  cc::ScopedResource* texture = render_pass_textures_[render_pass_id].get();
-  DCHECK(texture);
-  DCHECK(texture->id());
-
-  // Explicitly release lock, otherwise we can crash when try to lock
-  // same texture again.
-  current_framebuffer_lock_ = nullptr;
-
   gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_);
-  current_framebuffer_lock_ =
-      base::MakeUnique<cc::ResourceProvider::ScopedWriteLockGL>(
-          resource_provider_, texture->id());
-  current_framebuffer_format_ = texture->format();
-  GLuint texture_id = current_framebuffer_lock_->GetTexture();
+
+  auto contents_texture_it = render_pass_textures_.find(render_pass_id);
+  current_framebuffer_texture_ = &contents_texture_it->second;
+  GLuint texture_id = current_framebuffer_texture_->id();
+  DCHECK(texture_id);
   gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                             texture_id, 0);
   if (overdraw_feedback_) {
     if (!offscreen_stencil_renderbuffer_id_)
       gl_->GenRenderbuffers(1, &offscreen_stencil_renderbuffer_id_);
-    if (texture->size() != offscreen_stencil_renderbuffer_size_) {
+    if (current_framebuffer_texture_->size() !=
+        offscreen_stencil_renderbuffer_size_) {
       gl_->BindRenderbuffer(GL_RENDERBUFFER,
                             offscreen_stencil_renderbuffer_id_);
       gl_->RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
-                               texture->size().width(),
-                               texture->size().height());
+                               current_framebuffer_texture_->size().width(),
+                               current_framebuffer_texture_->size().height());
       gl_->BindRenderbuffer(GL_RENDERBUFFER, 0);
-      offscreen_stencil_renderbuffer_size_ = texture->size();
+      offscreen_stencil_renderbuffer_size_ =
+          current_framebuffer_texture_->size();
     }
     gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                                  GL_RENDERBUFFER,
@@ -3291,17 +3307,16 @@
     gfx::RectF* new_bounds) {
   // Don't carry over any GL state from previous RenderPass draw operations.
   ReinitializeGLState();
-
-  cc::ScopedResource* contents_texture =
-      render_pass_textures_[ca_layer_overlay->rpdq->render_pass_id].get();
-  DCHECK(contents_texture);
+  auto contents_texture_it =
+      render_pass_textures_.find(ca_layer_overlay->rpdq->render_pass_id);
+  DCHECK(contents_texture_it != render_pass_textures_.end());
 
   // Configure parameters as if drawing to a framebuffer the size of the
   // screen.
   DrawRenderPassDrawQuadParams params;
   params.quad = ca_layer_overlay->rpdq;
   params.flip_texture = true;
-  params.contents_texture = contents_texture;
+  params.contents_texture = &contents_texture_it->second;
   params.quad_to_target_transform =
       params.quad->shared_quad_state->quad_to_target_transform;
   params.tex_coord_rect = params.quad->tex_coord_rect;
@@ -3422,7 +3437,7 @@
   if (!overlay_resource_pool_) {
     DCHECK(current_task_runner_);
     overlay_resource_pool_ = cc::ResourcePool::Create(
-        resource_provider_, current_task_runner_.get(),
+        resource_provider_, true, current_task_runner_.get(),
         ResourceTextureHint::kOverlay, base::TimeDelta::FromSeconds(3),
         settings_->disallow_non_exact_resource_reuse);
   }
@@ -3586,6 +3601,7 @@
     const RenderPassList& render_passes_in_draw_order,
     const base::flat_map<RenderPassId, RenderPassRequirements>&
         render_passes_in_frame) {
+  // Collect RenderPass textures that should be deleted.
   std::vector<RenderPassId> passes_to_delete;
   for (const auto& pair : render_pass_textures_) {
     auto render_pass_it = render_passes_in_frame.find(pair.first);
@@ -3593,66 +3609,62 @@
       passes_to_delete.push_back(pair.first);
       continue;
     }
-
     gfx::Size required_size = render_pass_it->second.size;
     ResourceTextureHint required_hint = render_pass_it->second.hint;
-    cc::ScopedResource* texture = pair.second.get();
-    DCHECK(texture);
-
-    bool size_appropriate = texture->size().width() >= required_size.width() &&
-                            texture->size().height() >= required_size.height();
-    bool hint_appropriate = (texture->hint() & required_hint) == required_hint;
-    if (texture->id() && (!size_appropriate || !hint_appropriate))
-      texture->Free();
+    const ScopedRenderPassTexture& texture = pair.second;
+    bool size_appropriate = texture.size().width() >= required_size.width() &&
+                            texture.size().height() >= required_size.height();
+    bool hint_appropriate = (texture.hint() & required_hint) == required_hint;
+    if (!size_appropriate || !hint_appropriate)
+      passes_to_delete.push_back(pair.first);
   }
-
   // Delete RenderPass textures from the previous frame that will not be used
   // again.
   for (size_t i = 0; i < passes_to_delete.size(); ++i)
     render_pass_textures_.erase(passes_to_delete[i]);
 }
 
+ResourceFormat GLRenderer::BackbufferFormat() const {
+  const auto& caps = output_surface_->context_provider()->ContextCapabilities();
+  if (current_frame()->current_render_pass->color_space.IsHDR()) {
+    // If a platform does not support half-float renderbuffers then it should
+    // not should request HDR rendering.
+    DCHECK(caps.texture_half_float_linear);
+    DCHECK(caps.color_buffer_half_float_rgba);
+    return RGBA_F16;
+  }
+  return PlatformColor::BestSupportedTextureFormat(
+      caps.texture_format_bgra8888);
+}
+
 void GLRenderer::AllocateRenderPassResourceIfNeeded(
     const RenderPassId& render_pass_id,
     const gfx::Size& enlarged_size,
     ResourceTextureHint texturehint) {
-  auto& resource = render_pass_textures_[render_pass_id];
-  if (resource && resource->id())
+  const auto& caps = output_surface_->context_provider()->ContextCapabilities();
+  auto contents_texture_it = render_pass_textures_.find(render_pass_id);
+  if (contents_texture_it != render_pass_textures_.end())
     return;
 
-  if (!resource)
-    resource = std::make_unique<cc::ScopedResource>(resource_provider_);
-
-  ResourceFormat backbuffer_format;
-  if (current_frame()->current_render_pass->color_space.IsHDR()) {
-    // If a platform does not support half-float renderbuffers then it should
-    // not should request HDR rendering.
-    DCHECK(resource_provider_->IsRenderBufferFormatSupported(RGBA_F16));
-    backbuffer_format = RGBA_F16;
-  } else {
-    backbuffer_format = resource_provider_->best_texture_format();
-  }
-
-  resource->Allocate(enlarged_size, texturehint, backbuffer_format,
-                     current_frame()->current_render_pass->color_space);
+  ScopedRenderPassTexture contents_texture(
+      output_surface_->context_provider()->ContextGL(), enlarged_size,
+      texturehint, BackbufferFormat(),
+      current_frame()->current_render_pass->color_space, caps.texture_usage,
+      caps.texture_storage, caps.texture_npot);
+  render_pass_textures_[render_pass_id] = std::move(contents_texture);
 }
 
 bool GLRenderer::IsRenderPassResourceAllocated(
     const RenderPassId& render_pass_id) const {
   auto texture_it = render_pass_textures_.find(render_pass_id);
-  if (texture_it == render_pass_textures_.end())
-    return false;
-
-  cc::ScopedResource* texture = texture_it->second.get();
-  DCHECK(texture);
-  return texture->id() != 0;
+  return texture_it != render_pass_textures_.end();
 }
 
 gfx::Size GLRenderer::GetRenderPassTextureSize(
     const RenderPassId& render_pass_id) {
-  cc::ScopedResource* texture = render_pass_textures_[render_pass_id].get();
-  DCHECK(texture);
-  return texture->size();
+  auto texture_it = render_pass_textures_.find(render_pass_id);
+  DCHECK(texture_it != render_pass_textures_.end());
+  return texture_it->second.size();
 }
 
 }  // namespace viz
diff --git a/components/viz/service/display/gl_renderer.h b/components/viz/service/display/gl_renderer.h
index d1332aef..0bc25ce 100644
--- a/components/viz/service/display/gl_renderer.h
+++ b/components/viz/service/display/gl_renderer.h
@@ -36,7 +36,6 @@
 class OutputSurface;
 class Resource;
 class ResourcePool;
-class ScopedResource;
 class StreamVideoDrawQuad;
 }  // namespace cc
 
@@ -49,6 +48,7 @@
 namespace viz {
 
 class DynamicGeometryBinding;
+class ScopedRenderPassTexture;
 class StaticGeometryBinding;
 class TextureDrawQuad;
 struct DrawRenderPassDrawQuadParams;
@@ -288,9 +288,10 @@
                                unsigned query,
                                int multiplier);
 
+  ResourceFormat BackbufferFormat() const;
+
   // A map from RenderPass id to the texture used to draw the RenderPass from.
-  base::flat_map<RenderPassId, std::unique_ptr<cc::ScopedResource>>
-      render_pass_textures_;
+  base::flat_map<RenderPassId, ScopedRenderPassTexture> render_pass_textures_;
 
   using OverlayResourceLock =
       std::unique_ptr<cc::DisplayResourceProvider::ScopedReadLockGL>;
@@ -342,10 +343,7 @@
   TexturedQuadDrawCache draw_cache_;
   int highp_threshold_cache_ = 0;
 
-  std::unique_ptr<cc::ResourceProvider::ScopedWriteLockGL>
-      current_framebuffer_lock_;
-  // This is valid when current_framebuffer_lock_ is not null.
-  ResourceFormat current_framebuffer_format_;
+  ScopedRenderPassTexture* current_framebuffer_texture_;
 
   class SyncQuery;
   base::circular_deque<std::unique_ptr<SyncQuery>> pending_sync_queries_;
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc
index 547b578..cabcd4e 100644
--- a/components/viz/service/display/gl_renderer_unittest.cc
+++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -1559,7 +1559,7 @@
   int root_pass_id = 1;
   RenderPass* root_pass;
 
-  ResourceId mask = resource_provider_->CreateResource(
+  ResourceId mask = resource_provider_->CreateGpuTextureResource(
       gfx::Size(20, 12), ResourceTextureHint::kDefault,
       resource_provider_->best_texture_format(), gfx::ColorSpace());
   resource_provider_->AllocateForTesting(mask);
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index eed90ad5..5a629c8 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -116,6 +116,7 @@
 }
 
 void CreateTestTwoColoredTextureDrawQuad(
+    bool gpu_resource,
     const gfx::Rect& rect,
     SkColor texel_color,
     SkColor texel_stripe_color,
@@ -143,8 +144,16 @@
       pixels[i * rect.width() + k] = pixel_stripe_color;
     }
   }
-  ResourceId resource = resource_provider->CreateResource(
-      rect.size(), ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+
+  ResourceId resource;
+  if (gpu_resource) {
+    resource = resource_provider->CreateGpuTextureResource(
+        rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
+        gfx::ColorSpace());
+  } else {
+    resource =
+        resource_provider->CreateBitmapResource(rect.size(), gfx::ColorSpace());
+  }
   resource_provider->CopyToResource(
       resource, reinterpret_cast<uint8_t*>(&pixels.front()), rect.size());
 
@@ -161,7 +170,8 @@
                false);
 }
 
-void CreateTestTextureDrawQuad(const gfx::Rect& rect,
+void CreateTestTextureDrawQuad(bool gpu_resource,
+                               const gfx::Rect& rect,
                                SkColor texel_color,
                                float vertex_opacity[4],
                                SkColor background_color,
@@ -178,8 +188,15 @@
   size_t num_pixels = static_cast<size_t>(rect.width()) * rect.height();
   std::vector<uint32_t> pixels(num_pixels, pixel_color);
 
-  ResourceId resource = resource_provider->CreateResource(
-      rect.size(), ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+  ResourceId resource;
+  if (gpu_resource) {
+    resource = resource_provider->CreateGpuTextureResource(
+        rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
+        gfx::ColorSpace());
+  } else {
+    resource =
+        resource_provider->CreateBitmapResource(rect.size(), gfx::ColorSpace());
+  }
   resource_provider->CopyToResource(
       resource, reinterpret_cast<uint8_t*>(&pixels.front()), rect.size());
 
@@ -195,7 +212,8 @@
                false);
 }
 
-void CreateTestTextureDrawQuad(const gfx::Rect& rect,
+void CreateTestTextureDrawQuad(bool gpu_resource,
+                               const gfx::Rect& rect,
                                SkColor texel_color,
                                SkColor background_color,
                                bool premultiplied_alpha,
@@ -203,8 +221,8 @@
                                cc::ResourceProvider* resource_provider,
                                RenderPass* render_pass) {
   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
-  CreateTestTextureDrawQuad(rect, texel_color, vertex_opacity, background_color,
-                            premultiplied_alpha, shared_state,
+  CreateTestTextureDrawQuad(gpu_resource, rect, texel_color, vertex_opacity,
+                            background_color, premultiplied_alpha, shared_state,
                             resource_provider, render_pass);
 }
 
@@ -611,10 +629,10 @@
   const gfx::Size uv_tex_size = media::VideoFrame::PlaneSize(
       media::PIXEL_FORMAT_NV12, media::VideoFrame::kUVPlane, rect.size());
 
-  ResourceId y_resource = resource_provider->CreateResource(
+  ResourceId y_resource = resource_provider->CreateGpuTextureResource(
       rect.size(), ResourceTextureHint::kDefault,
       resource_provider->YuvResourceFormat(8), gfx_color_space);
-  ResourceId u_resource = resource_provider->CreateResource(
+  ResourceId u_resource = resource_provider->CreateGpuTextureResource(
       uv_tex_size, ResourceTextureHint::kDefault, RGBA_8888, gfx_color_space);
   ResourceId v_resource = u_resource;
   ResourceId a_resource = 0;
@@ -816,12 +834,12 @@
   SharedQuadState* shared_state =
       CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 
-  CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
-                            SkColorSetARGB(128, 0, 255, 0),  // Texel color.
-                            SK_ColorTRANSPARENT,  // Background color.
-                            true,                 // Premultiplied alpha.
-                            shared_state, this->resource_provider_.get(),
-                            pass.get());
+  CreateTestTextureDrawQuad(
+      this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+      SkColorSetARGB(128, 0, 255, 0),  // Texel color.
+      SK_ColorTRANSPARENT,             // Background color.
+      true,                            // Premultiplied alpha.
+      shared_state, this->resource_provider_.get(), pass.get());
 
   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
@@ -844,12 +862,12 @@
       CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
   texture_quad_state->opacity = 0.8f;
 
-  CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
-                            SkColorSetARGB(204, 120, 255, 120),  // Texel color.
-                            SK_ColorGREEN,  // Background color.
-                            true,           // Premultiplied alpha.
-                            texture_quad_state, this->resource_provider_.get(),
-                            pass.get());
+  CreateTestTextureDrawQuad(
+      this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+      SkColorSetARGB(204, 120, 255, 120),  // Texel color.
+      SK_ColorGREEN,                       // Background color.
+      true,                                // Premultiplied alpha.
+      texture_quad_state, this->resource_provider_.get(), pass.get());
 
   SharedQuadState* color_quad_state =
       CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
@@ -975,13 +993,13 @@
   texture_quad_state->opacity = 0.8f;
 
   float vertex_opacity[4] = {1.f, 1.f, 0.f, 0.f};
-  CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
-                            SkColorSetARGB(204, 120, 255, 120),  // Texel color.
-                            vertex_opacity,
-                            SK_ColorGREEN,  // Background color.
-                            true,           // Premultiplied alpha.
-                            texture_quad_state, this->resource_provider_.get(),
-                            pass.get());
+  CreateTestTextureDrawQuad(
+      this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+      SkColorSetARGB(204, 120, 255, 120),  // Texel color.
+      vertex_opacity,
+      SK_ColorGREEN,  // Background color.
+      true,           // Premultiplied alpha.
+      texture_quad_state, this->resource_provider_.get(), pass.get());
 
   SharedQuadState* color_quad_state =
       CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
@@ -1129,12 +1147,14 @@
 TYPED_TEST(IntersectingQuadPixelTest, TexturedQuads) {
   this->SetupQuadStateAndRenderPass();
   CreateTestTwoColoredTextureDrawQuad(
-      this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
+      this->use_gpu(), this->quad_rect_,
+      GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
       GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT,
       true, this->front_quad_state_, this->resource_provider_.get(),
       this->render_pass_.get());
   CreateTestTwoColoredTextureDrawQuad(
-      this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
+      this->use_gpu(), this->quad_rect_,
+      GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
       GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT,
       true, this->back_quad_state_, this->resource_provider_.get(),
       this->render_pass_.get());
@@ -1214,12 +1234,14 @@
       gfx::Transform(), this->quad_rect_, child_pass2.get());
 
   CreateTestTwoColoredTextureDrawQuad(
-      this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
+      this->use_gpu(), this->quad_rect_,
+      GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
       GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT,
       true, child1_quad_state, this->resource_provider_.get(),
       child_pass1.get());
   CreateTestTwoColoredTextureDrawQuad(
-      this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
+      this->use_gpu(), this->quad_rect_,
+      GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
       GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT,
       true, child2_quad_state, this->resource_provider_.get(),
       child_pass2.get());
@@ -1301,12 +1323,12 @@
   SharedQuadState* shared_state =
       CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 
-  CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
-                            SkColorSetARGB(128, 0, 255, 0),  // Texel color.
-                            SK_ColorTRANSPARENT,  // Background color.
-                            false,                // Premultiplied alpha.
-                            shared_state, this->resource_provider_.get(),
-                            pass.get());
+  CreateTestTextureDrawQuad(
+      this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+      SkColorSetARGB(128, 0, 255, 0),  // Texel color.
+      SK_ColorTRANSPARENT,             // Background color.
+      false,                           // Premultiplied alpha.
+      shared_state, this->resource_provider_.get(), pass.get());
 
   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
   color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
@@ -1330,12 +1352,12 @@
       CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
   texture_quad_state->opacity = 0.8f;
 
-  CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
-                            SkColorSetARGB(204, 120, 255, 120),  // Texel color.
-                            SK_ColorGREEN,  // Background color.
-                            false,          // Premultiplied alpha.
-                            texture_quad_state, this->resource_provider_.get(),
-                            pass.get());
+  CreateTestTextureDrawQuad(
+      this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+      SkColorSetARGB(204, 120, 255, 120),  // Texel color.
+      SK_ColorGREEN,                       // Background color.
+      false,                               // Premultiplied alpha.
+      texture_quad_state, this->resource_provider_.get(), pass.get());
 
   SharedQuadState* color_quad_state =
       CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
@@ -2156,9 +2178,15 @@
     rect.Inset(6, 6, 4, 4);
   }
 
-  ResourceId mask_resource_id = this->resource_provider_->CreateResource(
-      mask_rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
-      gfx::ColorSpace());
+  ResourceId mask_resource_id;
+  if (this->use_gpu()) {
+    mask_resource_id = this->resource_provider_->CreateGpuTextureResource(
+        mask_rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
+        gfx::ColorSpace());
+  } else {
+    mask_resource_id = this->resource_provider_->CreateBitmapResource(
+        mask_rect.size(), gfx::ColorSpace());
+  }
 
   this->resource_provider_->CopyToResource(
       mask_resource_id, reinterpret_cast<uint8_t*>(bitmap.getPixels()),
@@ -2242,9 +2270,15 @@
     rect.Inset(6, 6, 4, 4);
   }
 
-  ResourceId mask_resource_id = this->resource_provider_->CreateResource(
-      mask_rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
-      gfx::ColorSpace());
+  ResourceId mask_resource_id;
+  if (this->use_gpu()) {
+    mask_resource_id = this->resource_provider_->CreateGpuTextureResource(
+        mask_rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
+        gfx::ColorSpace());
+  } else {
+    mask_resource_id = this->resource_provider_->CreateBitmapResource(
+        mask_rect.size(), gfx::ColorSpace());
+  }
 
   this->resource_provider_->CopyToResource(
       mask_resource_id, reinterpret_cast<uint8_t*>(bitmap.getPixels()),
@@ -2715,8 +2749,14 @@
   canvas.clear(SK_ColorTRANSPARENT);
 
   gfx::Size tile_size(32, 32);
-  ResourceId resource = this->resource_provider_->CreateResource(
-      tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+  ResourceId resource;
+  if (this->use_gpu()) {
+    resource = this->resource_provider_->CreateGpuTextureResource(
+        tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+  } else {
+    resource = this->resource_provider_->CreateBitmapResource(
+        tile_size, gfx::ColorSpace());
+  }
 
   this->resource_provider_->CopyToResource(
       resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
@@ -3135,8 +3175,14 @@
   draw_point_color(&canvas, 1, 1, SK_ColorGREEN);
 
   gfx::Size tile_size(2, 2);
-  ResourceId resource = this->resource_provider_->CreateResource(
-      tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+  ResourceId resource;
+  if (this->use_gpu()) {
+    resource = this->resource_provider_->CreateGpuTextureResource(
+        tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+  } else {
+    resource = this->resource_provider_->CreateBitmapResource(
+        tile_size, gfx::ColorSpace());
+  }
 
   this->resource_provider_->CopyToResource(
       resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
@@ -3180,8 +3226,8 @@
   draw_point_color(&canvas, 1, 1, SK_ColorGREEN);
 
   gfx::Size tile_size(2, 2);
-  ResourceId resource = this->resource_provider_->CreateResource(
-      tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+  ResourceId resource = this->resource_provider_->CreateBitmapResource(
+      tile_size, gfx::ColorSpace());
 
   this->resource_provider_->CopyToResource(
       resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
@@ -3228,8 +3274,8 @@
   }
 
   gfx::Size tile_size(2, 2);
-  ResourceId resource = this->resource_provider_->CreateResource(
-      tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+  ResourceId resource = this->resource_provider_->CreateBitmapResource(
+      tile_size, gfx::ColorSpace());
 
   this->resource_provider_->CopyToResource(
       resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
@@ -3567,7 +3613,7 @@
     inset_rect.Inset(6, 6, 4, 4);
   }
 
-  ResourceId resource = this->resource_provider_->CreateResource(
+  ResourceId resource = this->resource_provider_->CreateGpuTextureResource(
       mask_rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
       gfx::ColorSpace());
 
@@ -3741,7 +3787,7 @@
     SharedQuadState* shared_state =
         CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 
-    ResourceId resource = resource_provider_->CreateResource(
+    ResourceId resource = resource_provider_->CreateGpuTextureResource(
         rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
         src_color_space_);
     resource_provider_->CopyToResource(resource, input_colors.data(),
diff --git a/components/viz/service/display/scoped_render_pass_texture.cc b/components/viz/service/display/scoped_render_pass_texture.cc
new file mode 100644
index 0000000..004025b8
--- /dev/null
+++ b/components/viz/service/display/scoped_render_pass_texture.cc
@@ -0,0 +1,93 @@
+// 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/viz/service/display/scoped_render_pass_texture.h"
+
+#include "base/bits.h"
+#include "base/logging.h"
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/GLES2/gl2extchromium.h"
+
+namespace viz {
+
+ScopedRenderPassTexture::ScopedRenderPassTexture(
+    gpu::gles2::GLES2Interface* gl,
+    const gfx::Size& size,
+    ResourceTextureHint hint,
+    ResourceFormat format,
+    const gfx::ColorSpace& color_space,
+    bool use_texture_usage_hint,
+    bool use_texture_storage,
+    bool use_texture_npot)
+    : gl_(gl), size_(size), hint_(hint), color_space_(color_space) {
+  DCHECK(gl_);
+  gl_->GenTextures(1, &gl_id_);
+
+  // Create and set texture properties.
+  gl_->BindTexture(GL_TEXTURE_2D, gl_id_);
+  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  if (use_texture_usage_hint && (hint_ & ResourceTextureHint::kFramebuffer)) {
+    gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE,
+                       GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+  }
+
+  if (use_texture_storage) {
+    GLint levels = 1;
+    if (use_texture_npot && (hint_ & ResourceTextureHint::kMipmap))
+      levels += base::bits::Log2Floor(std::max(size_.width(), size_.height()));
+
+    gl_->TexStorage2DEXT(GL_TEXTURE_2D, levels, TextureStorageFormat(format),
+                         size_.width(), size_.height());
+  } else {
+    gl_->TexImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), size_.width(),
+                    size_.height(), 0, GLDataFormat(format), GLDataType(format),
+                    nullptr);
+  }
+}
+
+ScopedRenderPassTexture::ScopedRenderPassTexture() = default;
+
+ScopedRenderPassTexture::ScopedRenderPassTexture(
+    ScopedRenderPassTexture&& other) {
+  gl_ = other.gl_;
+  size_ = other.size_;
+  hint_ = other.hint_;
+  color_space_ = other.color_space_;
+  gl_id_ = other.gl_id_;
+
+  // When being moved, other will no longer hold this gl_id_.
+  other.gl_id_ = 0;
+}
+
+ScopedRenderPassTexture::~ScopedRenderPassTexture() {
+  Free();
+}
+
+ScopedRenderPassTexture& ScopedRenderPassTexture::operator=(
+    ScopedRenderPassTexture&& other) {
+  if (this != &other) {
+    Free();
+    gl_ = other.gl_;
+    size_ = other.size_;
+    hint_ = other.hint_;
+    color_space_ = other.color_space_;
+    gl_id_ = other.gl_id_;
+
+    // When being moved, other will no longer hold this gl_id_.
+    other.gl_id_ = 0;
+  }
+  return *this;
+}
+
+void ScopedRenderPassTexture::Free() {
+  if (!gl_id_)
+    return;
+  gl_->DeleteTextures(1, &gl_id_);
+  gl_id_ = 0;
+}
+
+}  // namespace viz
diff --git a/components/viz/service/display/scoped_render_pass_texture.h b/components/viz/service/display/scoped_render_pass_texture.h
new file mode 100644
index 0000000..b8bd90b
--- /dev/null
+++ b/components/viz/service/display/scoped_render_pass_texture.h
@@ -0,0 +1,61 @@
+// 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_VIZ_SERVICE_DISPLAY_SCOPED_RENDER_PASS_TEXTURE_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_SCOPED_RENDER_PASS_TEXTURE_H_
+
+#include "base/macros.h"
+#include "components/viz/common/resources/resource_format.h"
+#include "components/viz/common/resources/resource_texture_hint.h"
+#include "components/viz/service/viz_service_export.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "ui/gfx/color_space.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace viz {
+
+// ScopedRenderPassTexture is resource used inside the same GL context and will
+// not being sent into another process. So no need to create fence and mailbox
+// for these resources.
+class VIZ_SERVICE_EXPORT ScopedRenderPassTexture {
+ public:
+  explicit ScopedRenderPassTexture(gpu::gles2::GLES2Interface* gl,
+                                   const gfx::Size& size,
+                                   ResourceTextureHint hint,
+                                   ResourceFormat format,
+                                   const gfx::ColorSpace& color_space,
+                                   bool use_texture_usage_hint,
+                                   bool use_texture_storage,
+                                   bool use_texture_npot);
+
+  ScopedRenderPassTexture();
+  ScopedRenderPassTexture(ScopedRenderPassTexture&& other);
+  ScopedRenderPassTexture& operator=(ScopedRenderPassTexture&& other);
+  ~ScopedRenderPassTexture();
+
+  GLuint id() const { return gl_id_; }
+  const gfx::Size& size() const { return size_; }
+  ResourceTextureHint hint() const { return hint_; }
+  const gfx::ColorSpace& color_space() const { return color_space_; }
+
+ private:
+  void Free();
+
+  gpu::gles2::GLES2Interface* gl_;
+  // The GL texture id.
+  GLuint gl_id_ = 0;
+  // Size of the resource in pixels.
+  gfx::Size size_;
+  // A hint for texture-backed resources about how the resource will be used,
+  // that dictates how it should be allocated/used.
+  ResourceTextureHint hint_;
+  // TODO(xing.xu): Remove this and set the color space when we draw the
+  // RenderPassDrawQuad.
+  gfx::ColorSpace color_space_;
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_SCOPED_RENDER_PASS_TEXTURE_H_
diff --git a/components/viz/service/display/software_renderer_unittest.cc b/components/viz/service/display/software_renderer_unittest.cc
index dac30cb7..cfc8803 100644
--- a/components/viz/service/display/software_renderer_unittest.cc
+++ b/components/viz/service/display/software_renderer_unittest.cc
@@ -147,10 +147,10 @@
   bool needs_blending = false;
   InitializeRenderer(std::make_unique<SoftwareOutputDevice>());
 
-  ResourceId resource_yellow = resource_provider()->CreateResource(
-      outer_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
-  ResourceId resource_cyan = resource_provider()->CreateResource(
-      inner_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+  ResourceId resource_yellow =
+      resource_provider()->CreateBitmapResource(outer_size, gfx::ColorSpace());
+  ResourceId resource_cyan =
+      resource_provider()->CreateBitmapResource(inner_size, gfx::ColorSpace());
 
   SkBitmap yellow_tile;
   yellow_tile.allocN32Pixels(outer_size.width(), outer_size.height());
@@ -211,8 +211,8 @@
   visible_rect.Inset(1, 2, 3, 4);
   InitializeRenderer(std::make_unique<SoftwareOutputDevice>());
 
-  ResourceId resource_cyan = resource_provider()->CreateResource(
-      tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+  ResourceId resource_cyan =
+      resource_provider()->CreateBitmapResource(tile_size, gfx::ColorSpace());
 
   SkBitmap cyan_tile;  // The lowest five rows are yellow.
   cyan_tile.allocN32Pixels(tile_size.width(), tile_size.height());
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 5c31a236..1c736fef 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -33,9 +33,9 @@
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_sync_channel.h"
 #include "ipc/ipc_sync_message_filter.h"
+#include "media/gpu/gpu_video_accelerator_util.h"
 #include "media/gpu/gpu_video_encode_accelerator_factory.h"
 #include "media/gpu/ipc/service/gpu_video_decode_accelerator.h"
-#include "media/gpu/ipc/service/gpu_video_encode_accelerator.h"
 #include "media/gpu/ipc/service/media_gpu_channel_manager.h"
 #include "media/mojo/services/mojo_jpeg_decode_accelerator_service.h"
 #include "media/mojo/services/mojo_video_encode_accelerator_provider.h"
@@ -157,7 +157,9 @@
       media::GpuVideoDecodeAccelerator::GetCapabilities(gpu_preferences_,
                                                         gpu_workarounds);
   gpu_info_.video_encode_accelerator_supported_profiles =
-      media::GpuVideoEncodeAccelerator::GetSupportedProfiles(gpu_preferences_);
+      media::GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(
+          media::GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(
+              gpu_preferences_));
   gpu_info_.jpeg_decode_accelerator_supported = media::
       GpuJpegDecodeAcceleratorFactory::IsAcceleratedJpegDecodeSupported();
   // Record initialization only after collecting the GPU info because that can
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 2bb9ee3c..0f8103dc 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -956,8 +956,6 @@
     "keyboard_lock/keyboard_lock_service_impl.h",
     "leveldb_wrapper_impl.cc",
     "leveldb_wrapper_impl.h",
-    "loader/async_resource_handler.cc",
-    "loader/async_resource_handler.h",
     "loader/cross_site_document_resource_handler.cc",
     "loader/cross_site_document_resource_handler.h",
     "loader/detachable_resource_handler.cc",
@@ -1003,8 +1001,6 @@
     "loader/resource_loader.cc",
     "loader/resource_loader.h",
     "loader/resource_loader_delegate.h",
-    "loader/resource_message_delegate.cc",
-    "loader/resource_message_delegate.h",
     "loader/resource_message_filter.cc",
     "loader/resource_message_filter.h",
     "loader/resource_request_info_impl.cc",
@@ -1019,8 +1015,6 @@
     "loader/stream_resource_handler.h",
     "loader/stream_writer.cc",
     "loader/stream_writer.h",
-    "loader/sync_resource_handler.cc",
-    "loader/sync_resource_handler.h",
     "loader/temporary_file_stream.cc",
     "loader/temporary_file_stream.h",
     "loader/throttling_resource_handler.cc",
@@ -1660,13 +1654,6 @@
     "web_contents/web_drag_source_mac.mm",
     "web_contents/web_drag_utils_win.cc",
     "web_contents/web_drag_utils_win.h",
-    "webauth/cbor/cbor_binary.h",
-    "webauth/cbor/cbor_reader.cc",
-    "webauth/cbor/cbor_reader.h",
-    "webauth/cbor/cbor_values.cc",
-    "webauth/cbor/cbor_values.h",
-    "webauth/cbor/cbor_writer.cc",
-    "webauth/cbor/cbor_writer.h",
     "websockets/websocket_handshake_request_info_impl.cc",
     "websockets/websocket_handshake_request_info_impl.h",
     "websockets/websocket_impl.cc",
@@ -2185,7 +2172,10 @@
       "webauth/register_response_data.cc",
       "webauth/register_response_data.h",
     ]
-    deps += [ "//third_party/flac" ]
+    deps += [
+      "//components/cbor",
+      "//third_party/flac",
+    ]
   }
 
   if (is_mac) {
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 3c69e7d..b1fa91a 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -19,6 +19,7 @@
   "+components/ukm",
   "+components/url_formatter",
   "+components/viz",
+  "+components/cbor",
 
   "+content/app/strings/grit",  # For generated headers
   "+content/public/browser",
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index dd45e718..b2c4170 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -96,8 +96,10 @@
     case ui::AX_ATTR_HIERARCHICAL_LEVEL:
     case ui::AX_ATTR_IN_PAGE_LINK_TARGET_ID:
     case ui::AX_ATTR_MEMBER_OF_ID:
+    case ui::AX_ATTR_NEXT_FOCUS_ID:
     case ui::AX_ATTR_NEXT_ON_LINE_ID:
     case ui::AX_ATTR_POS_IN_SET:
+    case ui::AX_ATTR_PREVIOUS_FOCUS_ID:
     case ui::AX_ATTR_PREVIOUS_ON_LINE_ID:
     case ui::AX_ATTR_SCROLL_X:
     case ui::AX_ATTR_SCROLL_X_MAX:
diff --git a/content/browser/accessibility/browser_accessibility_mac_unittest.mm b/content/browser/accessibility/browser_accessibility_mac_unittest.mm
index 45bec90..f62219f 100644
--- a/content/browser/accessibility/browser_accessibility_mac_unittest.mm
+++ b/content/browser/accessibility/browser_accessibility_mac_unittest.mm
@@ -19,7 +19,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "ui/accessibility/ax_tree_update.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace content {
 
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index 1464e6f..1c2190d 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -6,6 +6,7 @@
 
 #include "content/browser/accessibility/browser_accessibility_auralinux.h"
 #include "content/common/accessibility_messages.h"
+#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
 
 namespace content {
 
@@ -51,7 +52,10 @@
 void BrowserAccessibilityManagerAuraLinux::FireFocusEvent(
     BrowserAccessibility* node) {
   BrowserAccessibilityManager::FireFocusEvent(node);
-  // Need to implement.
+  if (node->IsNative()) {
+    ToBrowserAccessibilityAuraLinux(node)->GetNode()->NotifyAccessibilityEvent(
+        ui::AX_EVENT_FOCUS);
+  }
 }
 
 void BrowserAccessibilityManagerAuraLinux::FireBlinkEvent(
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index 5fa9271..c23fb4f 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -363,8 +363,12 @@
 
 void BrowserChildProcessHostImpl::OnBadMessageReceived(
     const IPC::Message& message) {
-  std::string log_message =
-      base::StringPrintf("Bad message received of type: %u", message.type());
+  std::string log_message = "Bad message received of type: ";
+  if (message.IsValid()) {
+    log_message += std::to_string(message.type());
+  } else {
+    log_message += "unknown";
+  }
   TerminateOnBadMessageReceived(log_message);
 }
 
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index 87fa72b..e27f75b 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -1114,7 +1114,7 @@
   // not use these things either (except for alpha when using mus for
   // non-opaque ui that overlaps the system's window borders or stencil bits
   // for overdraw feedback), so we can request only that when needed.
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = need_alpha_channel ? 8 : -1;
   attributes.depth_size = 0;
   attributes.stencil_size = need_stencil_bits ? 8 : 0;
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
index 5178bd5b7..44f6ff0 100644
--- a/content/browser/compositor/viz_process_transport_factory.cc
+++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -52,7 +52,7 @@
     ui::command_buffer_metrics::ContextType type) {
   constexpr bool kAutomaticFlushes = false;
 
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = -1;
   attributes.depth_size = 0;
   attributes.stencil_size = 0;
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 2570e13..711af6a 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -1316,16 +1316,14 @@
   return interceptor && interceptor->ShouldCancelNavigation(global_request_id);
 }
 
-void NetworkHandler::AppendDevToolsHeaders(net::HttpRequestHeaders* headers) {
+void NetworkHandler::WillSendNavigationRequest(net::HttpRequestHeaders* headers,
+                                               bool* skip_service_worker) {
   headers->SetHeader(kDevToolsEmulateNetworkConditionsClientId, host_id_);
   if (!user_agent_.empty())
     headers->SetHeader(net::HttpRequestHeaders::kUserAgent, user_agent_);
   for (auto& entry : extra_headers_)
     headers->SetHeader(entry.first, entry.second);
-}
-
-bool NetworkHandler::ShouldBypassServiceWorker() const {
-  return bypass_service_worker_;
+  *skip_service_worker |= bypass_service_worker_;
 }
 
 namespace {
diff --git a/content/browser/devtools/protocol/network_handler.h b/content/browser/devtools/protocol/network_handler.h
index 76a06e5..01bb4b2 100644
--- a/content/browser/devtools/protocol/network_handler.h
+++ b/content/browser/devtools/protocol/network_handler.h
@@ -139,8 +139,8 @@
   std::unique_ptr<NavigationThrottle> CreateThrottleForNavigation(
       NavigationHandle* navigation_handle);
   bool ShouldCancelNavigation(const GlobalRequestID& global_request_id);
-  void AppendDevToolsHeaders(net::HttpRequestHeaders* headers);
-  bool ShouldBypassServiceWorker() const;
+  void WillSendNavigationRequest(net::HttpRequestHeaders* headers,
+                                 bool* skip_service_worker);
 
  private:
   void RequestIntercepted(std::unique_ptr<InterceptedRequestInfo> request_info);
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc
index 5552688..a4d405f83 100644
--- a/content/browser/devtools/protocol/target_handler.cc
+++ b/content/browser/devtools/protocol/target_handler.cc
@@ -48,6 +48,8 @@
   const char* GetNameForLogging() override;
 
  private:
+  void CleanupPointers();
+
   base::WeakPtr<protocol::TargetHandler> target_handler_;
   scoped_refptr<DevToolsAgentHost> agent_host_;
 
@@ -143,8 +145,19 @@
 }
 
 TargetHandler::Throttle::~Throttle() {
-  if (target_handler_)
+  CleanupPointers();
+}
+
+void TargetHandler::Throttle::CleanupPointers() {
+  if (target_handler_ && agent_host_) {
+    auto it = target_handler_->auto_attached_sessions_.find(agent_host_.get());
+    if (it != target_handler_->auto_attached_sessions_.end())
+      it->second->SetThrottle(nullptr);
+  }
+  if (target_handler_) {
     target_handler_->throttles_.erase(this);
+    target_handler_ = nullptr;
+  }
 }
 
 NavigationThrottle::ThrottleCheckResult
@@ -165,18 +178,11 @@
 }
 
 void TargetHandler::Throttle::Clear() {
-  bool deferred = agent_host_.get();
-  if (target_handler_ && deferred) {
-    auto it = target_handler_->auto_attached_sessions_.find(agent_host_.get());
-    if (it != target_handler_->auto_attached_sessions_.end())
-      it->second->SetThrottle(nullptr);
-  }
-  agent_host_ = nullptr;
-  if (target_handler_)
-    target_handler_->throttles_.erase(this);
-  target_handler_.reset();
-  if (deferred)
+  CleanupPointers();
+  if (agent_host_) {
+    agent_host_ = nullptr;
     Resume();
+  }
 }
 
 TargetHandler::TargetHandler()
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index 0e931230..848871c 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -49,6 +49,7 @@
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/content_features.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
+#include "net/http/http_request_headers.h"
 #include "third_party/WebKit/common/associated_interfaces/associated_interface_provider.h"
 
 #if defined(OS_ANDROID)
@@ -487,6 +488,27 @@
 }
 
 // static
+void RenderFrameDevToolsAgentHost::OnWillSendNavigationRequest(
+    FrameTreeNode* frame_tree_node,
+    mojom::BeginNavigationParams* begin_params,
+    bool* report_raw_headers) {
+  frame_tree_node = GetFrameTreeNodeAncestor(frame_tree_node);
+  RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
+  if (!agent_host)
+    return;
+  net::HttpRequestHeaders headers;
+  headers.AddHeadersFromString(begin_params->headers);
+  for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) {
+    if (!network->enabled())
+      continue;
+    *report_raw_headers = true;
+    network->WillSendNavigationRequest(&headers,
+                                       &begin_params->skip_service_worker);
+  }
+  begin_params->headers = headers.ToString();
+}
+
+// static
 bool RenderFrameDevToolsAgentHost::IsNetworkHandlerEnabled(
     FrameTreeNode* frame_tree_node) {
   frame_tree_node = GetFrameTreeNodeAncestor(frame_tree_node);
@@ -501,32 +523,6 @@
 }
 
 // static
-void RenderFrameDevToolsAgentHost::AppendDevToolsHeaders(
-    FrameTreeNode* frame_tree_node,
-    net::HttpRequestHeaders* headers) {
-  frame_tree_node = GetFrameTreeNodeAncestor(frame_tree_node);
-  RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
-  if (!agent_host)
-    return;
-  for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host))
-    network->AppendDevToolsHeaders(headers);
-}
-
-// static
-bool RenderFrameDevToolsAgentHost::ShouldBypassServiceWorker(
-    FrameTreeNode* frame_tree_node) {
-  frame_tree_node = GetFrameTreeNodeAncestor(frame_tree_node);
-  RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
-  if (!agent_host)
-    return false;
-  for (auto* network : protocol::NetworkHandler::ForAgentHost(agent_host)) {
-    if (network->ShouldBypassServiceWorker())
-      return true;
-  }
-  return false;
-}
-
-// static
 void RenderFrameDevToolsAgentHost::WebContentsCreated(
     WebContents* web_contents) {
   if (ShouldForceCreation()) {
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h
index 17300dc..809c965 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -16,6 +16,7 @@
 #include "content/browser/devtools/devtools_agent_host_impl.h"
 #include "content/common/content_export.h"
 #include "content/common/devtools.mojom.h"
+#include "content/common/navigation_params.mojom.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "net/base/net_errors.h"
 
@@ -24,10 +25,6 @@
 #include "ui/android/view_android.h"
 #endif  // OS_ANDROID
 
-namespace net {
-class HttpRequestHeaders;
-}
-
 namespace viz {
 class CompositorFrameMetadata;
 }
@@ -57,6 +54,11 @@
   static scoped_refptr<DevToolsAgentHost> GetOrCreateForDangling(
       FrameTreeNode* frame_tree_node);
 
+  static void OnWillSendNavigationRequest(
+      FrameTreeNode* frame_tree_node,
+      mojom::BeginNavigationParams* begin_params,
+      bool* report_raw_headers);
+
   static void OnCancelPendingNavigation(RenderFrameHost* pending,
                                         RenderFrameHost* current);
   static void OnBeforeNavigation(RenderFrameHost* current,
@@ -66,9 +68,6 @@
   static std::vector<std::unique_ptr<NavigationThrottle>>
   CreateNavigationThrottles(NavigationHandle* navigation_handle);
   static bool IsNetworkHandlerEnabled(FrameTreeNode* frame_tree_node);
-  static void AppendDevToolsHeaders(FrameTreeNode* frame_tree_node,
-                                    net::HttpRequestHeaders* headers);
-  static bool ShouldBypassServiceWorker(FrameTreeNode* frame_tree_node);
   static void WebContentsCreated(WebContents* web_contents);
 
   static void SignalSynchronousSwapCompositorFrame(
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index 8d42586..641aff90 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -931,7 +931,8 @@
   // they aren't owned by the download system.
   const bool is_complete = GetState() == DownloadItem::COMPLETE;
   return (!IsDone() || is_complete) && !IsTemporary() &&
-         !file_externally_removed_;
+         !file_externally_removed_ &&
+         delegate_->IsMostRecentDownloadItemAtFilePath(this);
 }
 
 bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() {
diff --git a/content/browser/download/download_item_impl_delegate.cc b/content/browser/download/download_item_impl_delegate.cc
index 7619c32b8..73424b5f 100644
--- a/content/browser/download/download_item_impl_delegate.cc
+++ b/content/browser/download/download_item_impl_delegate.cc
@@ -72,6 +72,11 @@
 
 void DownloadItemImplDelegate::OpenDownload(DownloadItemImpl* download) {}
 
+bool DownloadItemImplDelegate::IsMostRecentDownloadItemAtFilePath(
+    DownloadItemImpl* download) {
+  return true;
+}
+
 void DownloadItemImplDelegate::ShowDownloadInShell(DownloadItemImpl* download) {
 }
 
diff --git a/content/browser/download/download_item_impl_delegate.h b/content/browser/download/download_item_impl_delegate.h
index fd193ac4..9e6fe97 100644
--- a/content/browser/download/download_item_impl_delegate.h
+++ b/content/browser/download/download_item_impl_delegate.h
@@ -85,6 +85,10 @@
   // Opens the file associated with this download.
   virtual void OpenDownload(DownloadItemImpl* download);
 
+  // Returns whether this is the most recent download in the rare event where
+  // multiple downloads are associated with the same file path.
+  virtual bool IsMostRecentDownloadItemAtFilePath(DownloadItemImpl* download);
+
   // Shows the download via the OS shell.
   virtual void ShowDownloadInShell(DownloadItemImpl* download);
 
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 0f5c706..89174b48 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -974,6 +974,12 @@
     delegate_->OpenDownload(download);
 }
 
+bool DownloadManagerImpl::IsMostRecentDownloadItemAtFilePath(
+    DownloadItemImpl* download) {
+  return delegate_ ? delegate_->IsMostRecentDownloadItemAtFilePath(download)
+                   : false;
+}
+
 void DownloadManagerImpl::ShowDownloadInShell(DownloadItemImpl* download) {
   if (delegate_)
     delegate_->ShowDownloadInShell(download);
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index 6007ada..1891d7af 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -206,6 +206,7 @@
       std::unique_ptr<content::DownloadUrlParameters> params,
       uint32_t id) override;
   void OpenDownload(DownloadItemImpl* download) override;
+  bool IsMostRecentDownloadItemAtFilePath(DownloadItemImpl* download) override;
   void ShowDownloadInShell(DownloadItemImpl* download) override;
   void DownloadRemoved(DownloadItemImpl* download) override;
 
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index cf198bf..a294da6 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -174,10 +174,6 @@
                                   ? GetContentClient()->GetUserAgent()
                                   : user_agent_override);
 
-  // Check whether DevTools wants to override user agent for this request
-  // after setting the default user agent, or append throttling control header.
-  RenderFrameDevToolsAgentHost::AppendDevToolsHeaders(frame_tree_node, headers);
-
   // Next, set the HTTP Origin if needed.
   if (!NeedsHTTPOrigin(headers, method))
     return;
@@ -424,10 +420,6 @@
     }
   }
   begin_params_->headers = headers.ToString();
-
-  // Check whether DevTools wants to skip the service worker.
-  if (RenderFrameDevToolsAgentHost::ShouldBypassServiceWorker(frame_tree_node))
-    begin_params_->skip_service_worker = true;
 }
 
 NavigationRequest::~NavigationRequest() {
@@ -1073,8 +1065,11 @@
       navigation_handle_->GetStartingSiteInstance()->GetSiteURL().
           SchemeIs(kGuestScheme);
 
-  bool report_raw_headers =
-      RenderFrameDevToolsAgentHost::IsNetworkHandlerEnabled(frame_tree_node_);
+  // Give DevTools a chance to override begin params (headers, skip SW)
+  // before actually loading resource.
+  bool report_raw_headers = false;
+  RenderFrameDevToolsAgentHost::OnWillSendNavigationRequest(
+      frame_tree_node_, begin_params_.get(), &report_raw_headers);
 
   loader_ = NavigationURLLoader::Create(
       browser_context->GetResourceContext(), partition,
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h
index 004fd46..9374609 100644
--- a/content/browser/frame_host/navigator.h
+++ b/content/browser/frame_host/navigator.h
@@ -141,7 +141,6 @@
       scoped_refptr<ResourceRequestBody> post_body,
       const std::string& extra_headers) {}
 
-  // PlzNavigate
   // Called after receiving a BeforeUnloadACK IPC from the renderer. If
   // |frame_tree_node| has a NavigationRequest waiting for the renderer
   // response, then the request is either started or canceled, depending on the
@@ -150,18 +149,15 @@
                                  bool proceed,
                                  const base::TimeTicks& proceed_time) {}
 
-  // PlzNavigate
   // Used to start a new renderer-initiated navigation, following a
   // BeginNavigation IPC from the renderer.
   virtual void OnBeginNavigation(FrameTreeNode* frame_tree_node,
                                  const CommonNavigationParams& common_params,
                                  mojom::BeginNavigationParamsPtr begin_params);
 
-  // PlzNavigate
   // Used to abort an ongoing renderer-initiated navigation.
   virtual void OnAbortNavigation(FrameTreeNode* frame_tree_node) {}
 
-  // PlzNavigate
   // Cancel a NavigationRequest for |frame_tree_node|. If the request is
   // renderer-initiated and |inform_renderer| is true, an IPC will be sent to
   // the renderer process to inform it that the navigation it requested was
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 4fc67e8..71d4d55 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -39,7 +39,6 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/stream_handle.h"
 #include "content/public/common/bindings_policy.h"
-#include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/resource_response.h"
@@ -166,6 +165,8 @@
   return controller_;
 }
 
+// TODO(clamy): See if we can remove this function now that PlzNavigate has
+// shipped.
 void NavigatorImpl::DidStartProvisionalLoad(
     RenderFrameHostImpl* render_frame_host,
     const GURL& url,
@@ -191,49 +192,6 @@
                                 render_frame_host->GetSiteInstance(),
                                 render_frame_host->navigation_handle());
   }
-
-  if (is_error_page || IsBrowserSideNavigationEnabled())
-    return;
-
-  if (render_frame_host->navigation_handle()) {
-    if (render_frame_host->navigation_handle()->is_transferring()) {
-      // If the navigation is completing a transfer, this
-      // DidStartProvisionalLoad should not correspond to a new navigation.
-      DCHECK_EQ(url, render_frame_host->navigation_handle()->GetURL());
-      render_frame_host->navigation_handle()->set_is_transferring(false);
-      return;
-    }
-
-    // This ensures that notifications about the end of the previous
-    // navigation are sent before notifications about the start of the
-    // new navigation.
-    render_frame_host->SetNavigationHandle(
-        std::unique_ptr<NavigationHandleImpl>());
-  }
-
-  // It is safer to assume navigations are renderer-initiated unless shown
-  // otherwise. Browser navigations generally have more privileges, and they
-  // should always have a pending NavigationEntry to distinguish them.
-  bool is_renderer_initiated = true;
-  int pending_nav_entry_id = 0;
-  bool started_from_context_menu = false;
-  NavigationEntryImpl* pending_entry = controller_->GetPendingEntry();
-  if (pending_entry) {
-    is_renderer_initiated = pending_entry->is_renderer_initiated();
-    pending_nav_entry_id = pending_entry->GetUniqueID();
-    started_from_context_menu = pending_entry->has_started_from_context_menu();
-  }
-
-  std::vector<GURL> validated_redirect_chain = redirect_chain;
-  for (size_t i = 0; i < validated_redirect_chain.size(); ++i)
-    render_process_host->FilterURL(false, &validated_redirect_chain[i]);
-  render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create(
-      validated_url, validated_redirect_chain,
-      render_frame_host->frame_tree_node(), is_renderer_initiated,
-      false,  // is_same_document
-      navigation_start, pending_nav_entry_id, started_from_context_menu,
-      CSPDisposition::CHECK,  // should_check_main_world_csp
-      false));                // is_form_submission
 }
 
 void NavigatorImpl::DidFailProvisionalLoadWithError(
@@ -378,8 +336,6 @@
       previews_state, is_same_document_history_load,
       is_history_navigation_in_new_child, post_body, navigation_start);
   if (frame_tree_node->IsMainFrame() && frame_tree_node->navigation_request()) {
-    // TODO(carlosk): extend these traces to support subframes and
-    // non-PlzNavigate navigations.
     // For the trace below we're using the navigation handle as the async
     // trace id, |navigation_start| as the timestamp and reporting the
     // FrameTreeNode id as a parameter. For navigations where no network
@@ -826,11 +782,9 @@
                   false, false, post_body);
 }
 
-// PlzNavigate
 void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node,
                                       bool proceed,
                                       const base::TimeTicks& proceed_time) {
-  CHECK(IsBrowserSideNavigationEnabled());
   DCHECK(frame_tree_node);
 
   NavigationRequest* navigation_request = frame_tree_node->navigation_request();
@@ -875,7 +829,6 @@
   // See https://crbug.com/770157.
 }
 
-// PlzNavigate
 void NavigatorImpl::OnBeginNavigation(
     FrameTreeNode* frame_tree_node,
     const CommonNavigationParams& common_params,
@@ -883,7 +836,6 @@
   // TODO(clamy): the url sent by the renderer should be validated with
   // FilterURL.
   // This is a renderer-initiated navigation.
-  CHECK(IsBrowserSideNavigationEnabled());
   DCHECK(frame_tree_node);
 
   NavigationRequest* ongoing_navigation_request =
@@ -959,10 +911,8 @@
   CancelNavigation(frame_tree_node, false);
 }
 
-// PlzNavigate
 void NavigatorImpl::CancelNavigation(FrameTreeNode* frame_tree_node,
                                      bool inform_renderer) {
-  CHECK(IsBrowserSideNavigationEnabled());
   if (frame_tree_node->navigation_request() &&
       frame_tree_node->navigation_request()->navigation_handle()) {
     frame_tree_node->navigation_request()
@@ -1036,7 +986,6 @@
   }
 }
 
-// PlzNavigate
 void NavigatorImpl::RequestNavigation(
     FrameTreeNode* frame_tree_node,
     const GURL& dest_url,
@@ -1049,7 +998,6 @@
     bool is_history_navigation_in_new_child,
     const scoped_refptr<ResourceRequestBody>& post_body,
     base::TimeTicks navigation_start) {
-  CHECK(IsBrowserSideNavigationEnabled());
   DCHECK(frame_tree_node);
 
   // This value must be set here because creating a NavigationRequest might
@@ -1184,7 +1132,6 @@
   bool has_browser_initiated_pending_entry =
       pending_entry && !pending_entry->is_renderer_initiated();
 
-  // PlzNavigate
   // A pending navigation entry is created in OnBeginNavigation(). The renderer
   // sends a provisional load notification after that. We don't want to create
   // a duplicate navigation entry here.
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h
index 7401d57..4c198a2 100644
--- a/content/browser/frame_host/navigator_impl.h
+++ b/content/browser/frame_host/navigator_impl.h
@@ -121,9 +121,8 @@
                        bool is_pending_entry,
                        const scoped_refptr<ResourceRequestBody>& post_body);
 
-  // PlzNavigate: if needed, sends a BeforeUnload IPC to the renderer to ask it
-  // to execute the beforeUnload event. Otherwise, the navigation request will
-  // be started.
+  // If needed, sends a BeforeUnload IPC to the renderer to ask it to execute
+  // the beforeUnload event. Otherwise, the navigation request will be started.
   void RequestNavigation(FrameTreeNode* frame_tree_node,
                          const GURL& dest_url,
                          const Referrer& dest_referrer,
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index e68dfa3b..ebbeb0a 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -24,6 +24,7 @@
 #include "base/version.h"
 #include "build/build_config.h"
 #include "cc/base/switches.h"
+#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
 #include "content/browser/gpu/gpu_process_host.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/gpu_data_manager_observer.h"
@@ -756,6 +757,18 @@
 void GpuDataManagerImplPrivate::UpdateGpuPreferences(
     gpu::GpuPreferences* gpu_preferences) const {
   DCHECK(gpu_preferences);
+
+  BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
+      BrowserGpuMemoryBufferManager::current();
+  // For performance reasons, discourage storing VideoFrames in a biplanar
+  // GpuMemoryBuffer if this is not native, see https://crbug.com/791676.
+  if (gpu_memory_buffer_manager) {
+    gpu_preferences->disable_biplanar_gpu_memory_buffers_for_video_frames =
+        !gpu_memory_buffer_manager->IsNativeGpuMemoryBufferConfiguration(
+            gfx::BufferFormat::YUV_420_BIPLANAR,
+            gfx::BufferUsage::GPU_READ_CPU_READ_WRITE);
+  }
+
   gpu_preferences->gpu_program_cache_size =
       gpu::ShaderDiskCache::CacheSizeBytes();
 }
diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc
index 8bd2721..789e709 100644
--- a/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -33,7 +33,7 @@
       content::BrowserMainLoop::GetInstance()->gpu_channel_establish_factory();
   // This is for an offscreen context, so the default framebuffer doesn't need
   // any alpha, depth, stencil, antialiasing.
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = -1;
   attributes.depth_size = 0;
   attributes.stencil_size = 0;
@@ -355,7 +355,7 @@
 
   // This is for an offscreen context, so the default framebuffer doesn't need
   // any alpha, depth, stencil, antialiasing.
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = -1;
   attributes.depth_size = 0;
   attributes.stencil_size = 0;
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc
deleted file mode 100644
index aeea9dc4..0000000
--- a/content/browser/loader/async_resource_handler.cc
+++ /dev/null
@@ -1,440 +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.
-
-#include "content/browser/loader/async_resource_handler.h"
-
-#include <algorithm>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/debug/alias.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/time/time.h"
-#include "content/browser/loader/resource_buffer.h"
-#include "content/browser/loader/resource_controller.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_message_filter.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/common/resource_messages.h"
-#include "content/common/view_messages.h"
-#include "content/network/upload_progress_tracker.h"
-#include "content/public/common/resource_response.h"
-#include "ipc/ipc_message_macros.h"
-#include "net/base/io_buffer.h"
-#include "net/base/load_flags.h"
-#include "net/base/upload_progress.h"
-#include "net/url_request/redirect_info.h"
-#include "services/network/public/cpp/url_loader_completion_status.h"
-
-using base::TimeDelta;
-using base::TimeTicks;
-
-namespace content {
-namespace {
-
-static int g_async_loader_buffer_size = 1024 * 512;
-static int g_async_loader_min_buffer_allocation_size = 1024 * 4;
-static int g_async_loader_max_buffer_allocation_size = 1024 * 32;
-
-}  // namespace
-
-// Used to write into an existing IOBuffer at a given offset. This is
-// very similar to DependentIOBufferForRedirectToFile and
-// DependentIOBufferForMimeSniffing but not identical.
-class DependentIOBufferForAsyncLoading : public net::WrappedIOBuffer {
- public:
-  DependentIOBufferForAsyncLoading(ResourceBuffer* backing, char* memory)
-      : net::WrappedIOBuffer(memory), backing_(backing) {}
-
- private:
-  ~DependentIOBufferForAsyncLoading() override {}
-  scoped_refptr<ResourceBuffer> backing_;
-};
-
-AsyncResourceHandler::AsyncResourceHandler(net::URLRequest* request,
-                                           ResourceDispatcherHostImpl* rdh)
-    : ResourceHandler(request),
-      ResourceMessageDelegate(request),
-      rdh_(rdh),
-      pending_data_count_(0),
-      allocation_size_(0),
-      total_read_body_bytes_(0),
-      has_checked_for_sufficient_resources_(false),
-      sent_received_response_msg_(false),
-      sent_data_buffer_msg_(false),
-      reported_transfer_size_(0) {
-  DCHECK(GetRequestInfo()->requester_info()->IsRenderer());
-  InitializeResourceBufferConstants();
-}
-
-AsyncResourceHandler::~AsyncResourceHandler() {
-  if (has_checked_for_sufficient_resources_)
-    rdh_->FinishedWithResourcesForRequest(request());
-}
-
-void AsyncResourceHandler::InitializeResourceBufferConstants() {
-  static bool did_init = false;
-  if (did_init)
-    return;
-  did_init = true;
-
-  GetNumericArg("resource-buffer-size", &g_async_loader_buffer_size);
-  GetNumericArg("resource-buffer-min-allocation-size",
-                &g_async_loader_min_buffer_allocation_size);
-  GetNumericArg("resource-buffer-max-allocation-size",
-                &g_async_loader_max_buffer_allocation_size);
-}
-
-bool AsyncResourceHandler::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(AsyncResourceHandler, message)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_FollowRedirect, OnFollowRedirect)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_DataReceived_ACK, OnDataReceivedACK)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_UploadProgress_ACK, OnUploadProgressACK)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-void AsyncResourceHandler::OnFollowRedirect(int request_id) {
-  if (!request()->status().is_success()) {
-    DVLOG(1) << "OnFollowRedirect for invalid request";
-    return;
-  }
-
-  ResumeIfDeferred();
-}
-
-void AsyncResourceHandler::OnDataReceivedACK(int request_id) {
-  if (pending_data_count_) {
-    --pending_data_count_;
-
-    buffer_->RecycleLeastRecentlyAllocated();
-    if (buffer_->CanAllocate())
-      ResumeIfDeferred();
-  }
-}
-
-void AsyncResourceHandler::OnUploadProgressACK(int request_id) {
-  if (upload_progress_tracker_)
-    upload_progress_tracker_->OnAckReceived();
-}
-
-void AsyncResourceHandler::OnRequestRedirected(
-    const net::RedirectInfo& redirect_info,
-    ResourceResponse* response,
-    std::unique_ptr<ResourceController> controller) {
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Cancel();
-    return;
-  }
-
-  response->head.encoded_data_length = request()->GetTotalReceivedBytes();
-  reported_transfer_size_ = 0;
-  response->head.request_start = request()->creation_time();
-  response->head.response_start = TimeTicks::Now();
-  // TODO(davidben): Is it necessary to pass the new first party URL for
-  // cookies? The only case where it can change is top-level navigation requests
-  // and hopefully those will eventually all be owned by the browser. It's
-  // possible this is still needed while renderer-owned ones exist.
-  if (filter->Send(new ResourceMsg_ReceivedRedirect(
-          GetRequestID(), redirect_info, response->head))) {
-    OnDefer(std::move(controller));
-  } else {
-    controller->Cancel();
-  }
-}
-
-void AsyncResourceHandler::OnResponseStarted(
-    ResourceResponse* response,
-    std::unique_ptr<ResourceController> controller) {
-  // For changes to the main frame, inform the renderer of the new URL's
-  // per-host settings before the request actually commits.  This way the
-  // renderer will be able to set these precisely at the time the
-  // request commits, avoiding the possibility of e.g. zooming the old content
-  // or of having to layout the new content twice.
-  DCHECK(!has_controller());
-
-  response_started_ticks_ = base::TimeTicks::Now();
-
-  // We want to send a final upload progress message prior to sending the
-  // response complete message even if we're waiting for an ack to to a
-  // previous upload progress message.
-  if (upload_progress_tracker_) {
-    upload_progress_tracker_->OnUploadCompleted();
-    upload_progress_tracker_ = nullptr;
-  }
-
-  const ResourceRequestInfoImpl* info = GetRequestInfo();
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Cancel();
-    return;
-  }
-
-  response->head.encoded_data_length = request()->raw_header_size();
-
-  // If the parent handler downloaded the resource to a file, grant the child
-  // read permissions on it.
-  if (!response->head.download_file_path.empty()) {
-    rdh_->RegisterDownloadedTempFile(
-        info->GetChildID(), info->GetRequestID(),
-        response->head.download_file_path);
-  }
-
-  response->head.request_start = request()->creation_time();
-  response->head.response_start = TimeTicks::Now();
-  filter->Send(
-      new ResourceMsg_ReceivedResponse(GetRequestID(), response->head));
-  sent_received_response_msg_ = true;
-
-  if (request()->response_info().metadata.get()) {
-    std::vector<uint8_t> copy(request()->response_info().metadata->data(),
-                              request()->response_info().metadata->data() +
-                                  request()->response_info().metadata->size());
-    filter->Send(new ResourceMsg_ReceivedCachedMetadata(GetRequestID(), copy));
-  }
-
-  controller->Resume();
-}
-
-void AsyncResourceHandler::OnWillStart(
-    const GURL& url,
-    std::unique_ptr<ResourceController> controller) {
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Cancel();
-    return;
-  }
-
-  if (GetRequestInfo()->is_upload_progress_enabled() &&
-      request()->has_upload()) {
-    upload_progress_tracker_ = std::make_unique<UploadProgressTracker>(
-        FROM_HERE,
-        base::BindRepeating(&AsyncResourceHandler::SendUploadProgress,
-                            base::Unretained(this)),
-        request());
-  }
-  controller->Resume();
-}
-
-void AsyncResourceHandler::OnWillRead(
-    scoped_refptr<net::IOBuffer>* buf,
-    int* buf_size,
-    std::unique_ptr<ResourceController> controller) {
-  DCHECK(!has_controller());
-
-  if (!CheckForSufficientResource()) {
-    controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
-    return;
-  }
-
-  if (!EnsureResourceBufferIsInitialized()) {
-    controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
-    return;
-  }
-
-  DCHECK(buffer_->CanAllocate());
-  char* memory = buffer_->Allocate(&allocation_size_);
-  CHECK(memory);
-
-  *buf = new DependentIOBufferForAsyncLoading(buffer_.get(), memory);
-  *buf_size = allocation_size_;
-
-  controller->Resume();
-}
-
-void AsyncResourceHandler::OnReadCompleted(
-    int bytes_read,
-    std::unique_ptr<ResourceController> controller) {
-  DCHECK(!has_controller());
-  DCHECK_GE(bytes_read, 0);
-
-  if (!bytes_read) {
-    controller->Resume();
-    return;
-  }
-
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Cancel();
-    return;
-  }
-
-  int encoded_data_length = CalculateEncodedDataLengthToReport();
-  if (!first_chunk_read_)
-    encoded_data_length -= request()->raw_header_size();
-
-  first_chunk_read_ = true;
-
-  buffer_->ShrinkLastAllocation(bytes_read);
-
-  total_read_body_bytes_ += bytes_read;
-
-  if (!sent_data_buffer_msg_) {
-    base::SharedMemoryHandle handle = base::SharedMemory::DuplicateHandle(
-        buffer_->GetSharedMemory().handle());
-    if (!base::SharedMemory::IsHandleValid(handle)) {
-      controller->Cancel();
-      return;
-    }
-    filter->Send(new ResourceMsg_SetDataBuffer(
-        GetRequestID(), handle, buffer_->GetSharedMemory().mapped_size()));
-    sent_data_buffer_msg_ = true;
-  }
-
-  int data_offset = buffer_->GetLastAllocationOffset();
-
-  filter->Send(new ResourceMsg_DataReceived(GetRequestID(), data_offset,
-                                            bytes_read, encoded_data_length));
-  ++pending_data_count_;
-
-  if (!buffer_->CanAllocate()) {
-    OnDefer(std::move(controller));
-  } else {
-    controller->Resume();
-  }
-}
-
-void AsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
-  int encoded_data_length = CalculateEncodedDataLengthToReport();
-
-  ResourceMessageFilter* filter = GetFilter();
-  if (filter) {
-    filter->Send(new ResourceMsg_DataDownloaded(
-        GetRequestID(), bytes_downloaded, encoded_data_length));
-  }
-}
-
-void AsyncResourceHandler::OnResponseCompleted(
-    const net::URLRequestStatus& request_status,
-    std::unique_ptr<ResourceController> controller) {
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter) {
-    controller->Resume();
-    return;
-  }
-
-  // Ensure sending the final upload progress message here, since
-  // OnResponseCompleted can be called without OnResponseStarted on cancellation
-  // or error cases.
-  if (upload_progress_tracker_) {
-    upload_progress_tracker_->OnUploadCompleted();
-    upload_progress_tracker_ = nullptr;
-  }
-
-  // If we crash here, figure out what URL the renderer was requesting.
-  // http://crbug.com/107692
-  char url_buf[128];
-  base::strlcpy(url_buf, request()->url().spec().c_str(), arraysize(url_buf));
-  base::debug::Alias(url_buf);
-
-  // TODO(gavinp): Remove this CHECK when we figure out the cause of
-  // http://crbug.com/124680 . This check mirrors closely check in
-  // WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore
-  // ResourceHandleInternal which asserts on its state and crashes. By crashing
-  // when the message is sent, we should get better crash reports.
-  CHECK(request_status.status() != net::URLRequestStatus::SUCCESS ||
-        sent_received_response_msg_);
-
-  int error_code = request_status.error();
-
-  DCHECK(request_status.status() != net::URLRequestStatus::IO_PENDING);
-
-  network::URLLoaderCompletionStatus loader_status;
-  loader_status.error_code = error_code;
-  loader_status.exists_in_cache = request()->response_info().was_cached;
-  loader_status.completion_time = TimeTicks::Now();
-  loader_status.encoded_data_length = request()->GetTotalReceivedBytes();
-  loader_status.encoded_body_length = request()->GetRawBodyBytes();
-  loader_status.decoded_body_length = total_read_body_bytes_;
-  filter->Send(new ResourceMsg_RequestComplete(GetRequestID(), loader_status));
-
-  if (request_status.is_success())
-    RecordHistogram();
-  controller->Resume();
-}
-
-bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() {
-  DCHECK(has_checked_for_sufficient_resources_);
-
-  if (buffer_.get() && buffer_->IsInitialized())
-    return true;
-
-  buffer_ = new ResourceBuffer();
-  return buffer_->Initialize(g_async_loader_buffer_size,
-                             g_async_loader_min_buffer_allocation_size,
-                             g_async_loader_max_buffer_allocation_size);
-}
-
-void AsyncResourceHandler::ResumeIfDeferred() {
-  if (has_controller()) {
-    request()->LogUnblocked();
-    Resume();
-  }
-}
-
-void AsyncResourceHandler::OnDefer(
-    std::unique_ptr<ResourceController> controller) {
-  HoldController(std::move(controller));
-  request()->LogBlockedBy("AsyncResourceHandler");
-}
-
-bool AsyncResourceHandler::CheckForSufficientResource() {
-  if (has_checked_for_sufficient_resources_)
-    return true;
-  has_checked_for_sufficient_resources_ = true;
-
-  if (rdh_->HasSufficientResourcesForRequest(request()))
-    return true;
-
-  return false;
-}
-
-int AsyncResourceHandler::CalculateEncodedDataLengthToReport() {
-  const auto transfer_size = request()->GetTotalReceivedBytes();
-  const auto difference =  transfer_size - reported_transfer_size_;
-  reported_transfer_size_ = transfer_size;
-  return difference;
-}
-
-void AsyncResourceHandler::RecordHistogram() {
-  int64_t elapsed_time =
-      (base::TimeTicks::Now() - response_started_ticks_).InMicroseconds();
-  int64_t encoded_length = request()->GetTotalReceivedBytes();
-  if (encoded_length < 2 * 1024) {
-    // The resource was smaller than the smallest required buffer size.
-    UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ResourceLoader.ResponseStartToEnd.LT_2kB",
-                                elapsed_time, 1, 100000, 100);
-  } else if (encoded_length < 32 * 1024) {
-    // The resource was smaller than single chunk.
-    UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ResourceLoader.ResponseStartToEnd.LT_32kB",
-                                elapsed_time, 1, 100000, 100);
-  } else if (encoded_length < 512 * 1024) {
-    // The resource was smaller than single chunk.
-    UMA_HISTOGRAM_CUSTOM_COUNTS(
-        "Net.ResourceLoader.ResponseStartToEnd.LT_512kB",
-        elapsed_time, 1, 100000, 100);
-  } else {
-    UMA_HISTOGRAM_CUSTOM_COUNTS(
-        "Net.ResourceLoader.ResponseStartToEnd.Over_512kB",
-        elapsed_time, 1, 100000, 100);
-  }
-}
-
-void AsyncResourceHandler::SendUploadProgress(
-    const net::UploadProgress& progress) {
-  ResourceMessageFilter* filter = GetFilter();
-  if (!filter)
-    return;
-  filter->Send(new ResourceMsg_UploadProgress(
-      GetRequestID(), progress.position(), progress.size()));
-}
-
-}  // namespace content
diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h
deleted file mode 100644
index 1ddccd83..0000000
--- a/content/browser/loader/async_resource_handler.h
+++ /dev/null
@@ -1,109 +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.
-
-#ifndef CONTENT_BROWSER_LOADER_ASYNC_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_ASYNC_RESOURCE_HANDLER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/browser/loader/resource_handler.h"
-#include "content/browser/loader/resource_message_delegate.h"
-#include "content/common/content_export.h"
-#include "net/base/io_buffer.h"
-#include "url/gurl.h"
-
-namespace net {
-class URLRequest;
-class UploadProgress;
-}
-
-namespace content {
-class ResourceBuffer;
-class ResourceController;
-class ResourceDispatcherHostImpl;
-class UploadProgressTracker;
-
-// Used to complete an asynchronous resource request in response to resource
-// load events from the resource dispatcher host.
-class CONTENT_EXPORT AsyncResourceHandler : public ResourceHandler,
-                                            public ResourceMessageDelegate {
- public:
-  AsyncResourceHandler(net::URLRequest* request,
-                       ResourceDispatcherHostImpl* rdh);
-  ~AsyncResourceHandler() override;
-
-  bool OnMessageReceived(const IPC::Message& message) override;
-
-  // ResourceHandler implementation:
-  void OnRequestRedirected(
-      const net::RedirectInfo& redirect_info,
-      ResourceResponse* response,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnResponseStarted(
-      ResourceResponse* response,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnWillStart(const GURL& url,
-                   std::unique_ptr<ResourceController> controller) override;
-  void OnWillRead(scoped_refptr<net::IOBuffer>* buf,
-                  int* buf_size,
-                  std::unique_ptr<ResourceController> controller) override;
-  void OnReadCompleted(int bytes_read,
-                       std::unique_ptr<ResourceController> controller) override;
-  void OnResponseCompleted(
-      const net::URLRequestStatus& status,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnDataDownloaded(int bytes_downloaded) override;
-
- private:
-  // IPC message handlers:
-  void OnFollowRedirect(int request_id);
-  void OnDataReceivedACK(int request_id);
-  void OnUploadProgressACK(int request_id);
-
-  bool EnsureResourceBufferIsInitialized();
-  void ResumeIfDeferred();
-  void OnDefer(std::unique_ptr<ResourceController> controller);
-  bool CheckForSufficientResource();
-  int CalculateEncodedDataLengthToReport();
-  int CalculateEncodedBodyLengthToReport();
-  void RecordHistogram();
-  void SendUploadProgress(const net::UploadProgress& progress);
-  static void InitializeResourceBufferConstants();
-
-  scoped_refptr<ResourceBuffer> buffer_;
-  ResourceDispatcherHostImpl* rdh_;
-
-  // Number of messages we've sent to the renderer that we haven't gotten an
-  // ACK for. This allows us to avoid having too many messages in flight.
-  int pending_data_count_;
-
-  int allocation_size_;
-
-  // Size of received body. Used for comparison with expected content size,
-  // which is reported to UMA.
-  int64_t total_read_body_bytes_;
-
-  bool first_chunk_read_ = false;
-
-  bool has_checked_for_sufficient_resources_;
-  bool sent_received_response_msg_;
-  bool sent_data_buffer_msg_;
-
-  base::TimeTicks response_started_ticks_;
-
-  std::unique_ptr<UploadProgressTracker> upload_progress_tracker_;
-
-  int64_t reported_transfer_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(AsyncResourceHandler);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_LOADER_ASYNC_RESOURCE_HANDLER_H_
diff --git a/content/browser/loader/async_resource_handler_browsertest.cc b/content/browser/loader/async_resource_handler_browsertest.cc
deleted file mode 100644
index 4dae1a2..0000000
--- a/content/browser/loader/async_resource_handler_browsertest.cc
+++ /dev/null
@@ -1,111 +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 "content/browser/loader/async_resource_handler.h"
-
-#include <stddef.h>
-#include <string>
-#include <utility>
-
-#include "base/format_macros.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "build/build_config.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/public/test/content_browser_test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/embedded_test_server/http_request.h"
-#include "net/test/embedded_test_server/http_response.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-const char kPostPath[] = "/post";
-const char kRedirectPostPath[] = "/redirect";
-
-// ThreadSanitizer is too slow to perform the full upload, so tests
-// using that build get an easier test which might not show two distinct
-// progress events. See crbug.com/526985. In addition, OSX buildbots have
-// experienced slowdowns on this test (crbug.com/548819), give them the easier
-// test too.
-#if defined(THREAD_SANITIZER) || defined(OS_MACOSX)
-const size_t kPayloadSize = 1062882;  // 2*3^12
-#else
-const size_t kPayloadSize = 28697814;  // 2*3^15
-#endif
-
-std::unique_ptr<net::test_server::HttpResponse> HandlePostAndRedirectURLs(
-    const std::string& request_path,
-    const net::test_server::HttpRequest& request) {
-  std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
-      new net::test_server::BasicHttpResponse());
-  if (base::StartsWith(request.relative_url, kRedirectPostPath,
-                       base::CompareCase::SENSITIVE)) {
-    http_response->set_code(net::HTTP_TEMPORARY_REDIRECT);
-    http_response->AddCustomHeader("Location", kPostPath);
-    EXPECT_EQ(request.content.length(), kPayloadSize);
-    return std::move(http_response);
-  } else if (base::StartsWith(request.relative_url, kPostPath,
-                              base::CompareCase::SENSITIVE)) {
-    http_response->set_content("hello");
-    http_response->set_content_type("text/plain");
-    EXPECT_EQ(request.content.length(), kPayloadSize);
-    return std::move(http_response);
-  } else {
-    return std::unique_ptr<net::test_server::HttpResponse>();
-  }
-}
-
-}  // namespace
-
-// https://crbug.com/788748
-#if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
-#define MAYBE_AsyncResourceHandlerBrowserTest \
-  DISABLED_AsyncResourceHandlerBrowserTest
-#else
-#define MAYBE_AsyncResourceHandlerBrowserTest AsyncResourceHandlerBrowserTest
-#endif  // defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
-class MAYBE_AsyncResourceHandlerBrowserTest : public ContentBrowserTest {};
-
-IN_PROC_BROWSER_TEST_F(MAYBE_AsyncResourceHandlerBrowserTest, UploadProgress) {
-  net::EmbeddedTestServer* test_server = embedded_test_server();
-  test_server->RegisterRequestHandler(
-      base::Bind(&HandlePostAndRedirectURLs, kPostPath));
-  ASSERT_TRUE(test_server->Start());
-
-  NavigateToURL(shell(),
-                test_server->GetURL("/loader/async_resource_handler.html"));
-
-  std::string js_result;
-  EXPECT_TRUE(ExecuteScriptAndExtractString(
-      shell(), base::StringPrintf("WaitForAsyncXHR('%s', %" PRIuS ")",
-                                  kPostPath, kPayloadSize),
-      &js_result));
-  EXPECT_EQ(js_result, "success");
-}
-
-IN_PROC_BROWSER_TEST_F(MAYBE_AsyncResourceHandlerBrowserTest,
-                       UploadProgressRedirect) {
-  net::EmbeddedTestServer* test_server = embedded_test_server();
-  test_server->RegisterRequestHandler(
-      base::Bind(&HandlePostAndRedirectURLs, kRedirectPostPath));
-  ASSERT_TRUE(test_server->Start());
-
-  NavigateToURL(shell(),
-                test_server->GetURL("/loader/async_resource_handler.html"));
-
-  std::string js_result;
-  EXPECT_TRUE(ExecuteScriptAndExtractString(
-      shell(), base::StringPrintf("WaitForAsyncXHR('%s', %" PRIuS ")",
-                                  kRedirectPostPath, kPayloadSize),
-      &js_result));
-  EXPECT_EQ(js_result, "success");
-}
-
-}  // namespace content
diff --git a/content/browser/loader/async_resource_handler_unittest.cc b/content/browser/loader/async_resource_handler_unittest.cc
deleted file mode 100644
index ef8d97c..0000000
--- a/content/browser/loader/async_resource_handler_unittest.cc
+++ /dev/null
@@ -1,311 +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 "content/browser/loader/async_resource_handler.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <memory>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/process/process.h"
-#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/scoped_feature_list.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_loader.h"
-#include "content/browser/loader/resource_loader_delegate.h"
-#include "content/browser/loader/resource_message_filter.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/common/resource_messages.h"
-#include "content/public/browser/resource_context.h"
-#include "content/public/browser/resource_request_info.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/previews_state.h"
-#include "content/public/common/resource_request.h"
-#include "content/public/common/resource_type.h"
-#include "content/public/test/mock_resource_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_message_macros.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "net/ssl/client_cert_store.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_job.h"
-#include "net/url_request/url_request_job_factory_impl.h"
-#include "net/url_request/url_request_test_job.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/common/page/page_visibility_state.mojom.h"
-#include "ui/base/page_transition_types.h"
-#include "url/gurl.h"
-
-namespace content {
-
-namespace {
-
-std::string GenerateHeader(size_t response_data_size) {
-  return base::StringPrintf(
-      "HTTP/1.1 200 OK\n"
-      "Content-type: text/html\n"
-      "Content-Length: %" PRIuS "\n",
-      response_data_size);
-}
-
-int64_t TotalReceivedBytes(size_t response_data_size) {
-  return response_data_size + GenerateHeader(response_data_size).size();
-}
-
-std::string GenerateData(size_t response_data_size) {
-  return std::string(response_data_size, 'a');
-}
-
-class TestProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
- public:
-  TestProtocolHandler(size_t response_data_size)
-      : response_data_size_(response_data_size) {}
-
-  net::URLRequestJob* MaybeCreateJob(
-      net::URLRequest* request,
-      net::NetworkDelegate* network_delegate) const override {
-    return new net::URLRequestTestJob(request, network_delegate,
-                                      GenerateHeader(response_data_size_),
-                                      GenerateData(response_data_size_), true);
-  }
-
- private:
-  size_t response_data_size_;
-};
-
-// A subclass of ResourceMessageFilter that records IPC messages that are sent.
-class RecordingResourceMessageFilter : public ResourceMessageFilter {
- public:
-  RecordingResourceMessageFilter(ResourceContext* resource_context,
-                                 net::URLRequestContext* request_context)
-      : ResourceMessageFilter(
-            0,
-            nullptr,
-            nullptr,
-            nullptr,
-            nullptr,
-            base::Bind(&RecordingResourceMessageFilter::GetContexts,
-                       base::Unretained(this)),
-            BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
-        resource_context_(resource_context),
-        request_context_(request_context) {
-    InitializeForTest();
-    set_peer_process_for_testing(base::Process::Current());
-  }
-
-  const std::vector<std::unique_ptr<IPC::Message>>& messages() const {
-    return messages_;
-  }
-
-  // IPC::Sender implementation:
-  bool Send(IPC::Message* message) override {
-    // Unpickle the base::SharedMemoryHandle to avoid warnings about
-    // "MessageAttachmentSet destroyed with unconsumed descriptors".
-    if (message->type() == ResourceMsg_SetDataBuffer::ID) {
-      ResourceMsg_SetDataBuffer::Param params;
-      ResourceMsg_SetDataBuffer::Read(message, &params);
-    }
-    messages_.push_back(base::WrapUnique(message));
-    return true;
-  }
-
- private:
-  ~RecordingResourceMessageFilter() override {}
-
-  void GetContexts(ResourceType resource_type,
-                   ResourceContext** resource_context,
-                   net::URLRequestContext** request_context) {
-    *resource_context = resource_context_;
-    *request_context = request_context_;
-  }
-
-  ResourceContext* const resource_context_;
-  net::URLRequestContext* const request_context_;
-  std::vector<std::unique_ptr<IPC::Message>> messages_;
-};
-
-class AsyncResourceHandlerTest : public ::testing::Test,
-                                 public ResourceLoaderDelegate {
- protected:
-  AsyncResourceHandlerTest()
-      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), context_(true) {}
-
-  void TearDown() override {
-    if (filter_)
-      filter_->OnChannelClosing();
-    // Prevent memory leaks.
-    filter_ = nullptr;
-    rdh_.Shutdown();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void CreateRequestWithResponseDataSize(size_t response_data_size) {
-    test_job_factory_.SetProtocolHandler(
-        "test", std::make_unique<TestProtocolHandler>(response_data_size));
-    context_.set_job_factory(&test_job_factory_);
-    context_.Init();
-    std::unique_ptr<net::URLRequest> request =
-        context_.CreateRequest(GURL("test:test"), net::DEFAULT_PRIORITY,
-                               nullptr, TRAFFIC_ANNOTATION_FOR_TESTS);
-    resource_context_ = std::make_unique<MockResourceContext>(&context_);
-    filter_ =
-        new RecordingResourceMessageFilter(resource_context_.get(), &context_);
-    ResourceRequestInfoImpl* info = new ResourceRequestInfoImpl(
-        filter_->requester_info_for_test(),
-        0,                                 // route_id
-        -1,                                // frame_tree_node_id
-        0,                                 // origin_pid
-        0,                                 // request_id
-        0,                                 // render_frame_id
-        false,                             // is_main_frame
-        RESOURCE_TYPE_IMAGE,               // resource_type
-        ui::PAGE_TRANSITION_LINK,          // transition_type
-        false,                             // should_replace_current_entry
-        false,                             // is_download
-        false,                             // is_stream
-        false,                             // allow_download
-        false,                             // has_user_gesture
-        false,                             // enable load timing
-        false,                             // enable upload progress
-        false,                             // do_not_prompt_for_login
-        false,                             // keep_alive
-        blink::kWebReferrerPolicyDefault,  // referrer_policy
-        blink::mojom::PageVisibilityState::kVisible,  // visibility_state
-        resource_context_.get(),                      // context
-        false,                                        // report_raw_headers
-        true,                                         // is_async
-        PREVIEWS_OFF,                                 // previews_state
-        nullptr,                                      // body
-        false);  // initiated_in_secure_context
-    info->AssociateWithRequest(request.get());
-    std::unique_ptr<AsyncResourceHandler> handler =
-        std::make_unique<AsyncResourceHandler>(request.get(), &rdh_);
-    loader_ = std::make_unique<ResourceLoader>(std::move(request),
-                                               std::move(handler), this);
-  }
-
-  void StartRequestAndWaitWithResponseDataSize(size_t response_data_size) {
-    CreateRequestWithResponseDataSize(response_data_size);
-    loader_->StartRequest();
-    finish_waiter_.reset(new base::RunLoop);
-    finish_waiter_->Run();
-  }
-
-  scoped_refptr<RecordingResourceMessageFilter> filter_;
-
- private:
-  // ResourceLoaderDelegate implementation:
-  ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
-      ResourceLoader* loader,
-      net::AuthChallengeInfo* auth_info) override {
-    return nullptr;
-  }
-
-  bool HandleExternalProtocol(ResourceLoader* loader,
-                              const GURL& url) override {
-    return false;
-  }
-  void DidStartRequest(ResourceLoader* loader) override {}
-  void DidReceiveRedirect(ResourceLoader* loader,
-                          const GURL& new_url,
-                          ResourceResponse* response) override {}
-  void DidReceiveResponse(ResourceLoader* loader,
-                          ResourceResponse* response) override {}
-  void DidFinishLoading(ResourceLoader* loader) override {
-    loader_.reset();
-    finish_waiter_->Quit();
-  }
-  std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
-      ResourceLoader* loader) override {
-    return nullptr;
-  }
-
-  TestBrowserThreadBundle thread_bundle_;
-  ResourceDispatcherHostImpl rdh_;
-  net::TestURLRequestContext context_;
-  net::URLRequestJobFactoryImpl test_job_factory_;
-  std::unique_ptr<MockResourceContext> resource_context_;
-  std::unique_ptr<ResourceLoader> loader_;
-  std::unique_ptr<base::RunLoop> finish_waiter_;
-};
-
-TEST_F(AsyncResourceHandlerTest, Construct) {
-  CreateRequestWithResponseDataSize(1);
-}
-
-TEST_F(AsyncResourceHandlerTest, OneChunkLengths) {
-  // Larger than kInlinedLeadingChunkSize and smaller than
-  // kMaxAllocationSize.
-  constexpr auto kDataSize = 4096;
-  StartRequestAndWaitWithResponseDataSize(kDataSize);
-  const auto& messages = filter_->messages();
-  ASSERT_EQ(4u, messages.size());
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_DataReceived::ID),
-            messages[2]->type());
-  ResourceMsg_DataReceived::Param params;
-  ResourceMsg_DataReceived::Read(messages[2].get(), &params);
-
-  int encoded_data_length = std::get<3>(params);
-  EXPECT_EQ(kDataSize, encoded_data_length);
-
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_RequestComplete::ID),
-            messages[3]->type());
-  ResourceMsg_RequestComplete::Param completion_params;
-  ResourceMsg_RequestComplete::Read(messages[3].get(), &completion_params);
-  network::URLLoaderCompletionStatus status = std::get<1>(completion_params);
-
-  EXPECT_EQ(TotalReceivedBytes(kDataSize), status.encoded_data_length);
-  EXPECT_EQ(kDataSize, status.encoded_body_length);
-}
-
-TEST_F(AsyncResourceHandlerTest, TwoChunksLengths) {
-  // Larger than kMaxAllocationSize.
-  constexpr auto kDataSize = 64 * 1024;
-  StartRequestAndWaitWithResponseDataSize(kDataSize);
-  const auto& messages = filter_->messages();
-  ASSERT_EQ(5u, messages.size());
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_DataReceived::ID),
-            messages[2]->type());
-  ResourceMsg_DataReceived::Param params;
-  ResourceMsg_DataReceived::Read(messages[2].get(), &params);
-
-  int encoded_data_length = std::get<3>(params);
-  EXPECT_EQ(32768, encoded_data_length);
-
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_DataReceived::ID),
-            messages[3]->type());
-  ResourceMsg_DataReceived::Read(messages[3].get(), &params);
-
-  encoded_data_length = std::get<3>(params);
-  EXPECT_EQ(32768, encoded_data_length);
-
-  ASSERT_EQ(static_cast<uint32_t>(ResourceMsg_RequestComplete::ID),
-            messages[4]->type());
-  ResourceMsg_RequestComplete::Param completion_params;
-  ResourceMsg_RequestComplete::Read(messages[4].get(), &completion_params);
-  network::URLLoaderCompletionStatus status = std::get<1>(completion_params);
-  EXPECT_EQ(TotalReceivedBytes(kDataSize), status.encoded_data_length);
-  EXPECT_EQ(kDataSize, status.encoded_body_length);
-}
-
-}  // namespace
-
-}  // namespace content
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 466969f..17a1d67b 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -43,7 +43,6 @@
 #include "content/browser/browsing_data/clear_site_data_throttle.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/frame_host/navigation_request_info.h"
-#include "content/browser/loader/async_resource_handler.h"
 #include "content/browser/loader/cross_site_document_resource_handler.h"
 #include "content/browser/loader/detachable_resource_handler.h"
 #include "content/browser/loader/intercepting_resource_handler.h"
@@ -60,7 +59,6 @@
 #include "content/browser/loader/resource_requester_info.h"
 #include "content/browser/loader/resource_scheduler.h"
 #include "content/browser/loader/stream_resource_handler.h"
-#include "content/browser/loader/sync_resource_handler.h"
 #include "content/browser/loader/throttling_resource_handler.h"
 #include "content/browser/loader/upload_data_stream_builder.h"
 #include "content/browser/loader/wake_lock_resource_throttle.h"
@@ -74,7 +72,6 @@
 #include "content/browser/streams/stream_registry.h"
 #include "content/common/loader_util.h"
 #include "content/common/net/url_request_service_worker_data.h"
-#include "content/common/resource_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/browser_child_process_host.h"
 #include "content/public/browser/browser_thread.h"
@@ -94,8 +91,6 @@
 #include "content/public/common/origin_util.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/resource_request_body.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_message_start.h"
 #include "net/base/auth.h"
 #include "net/base/load_flags.h"
 #include "net/base/mime_util.h"
@@ -133,8 +128,6 @@
 using base::TimeDelta;
 using base::TimeTicks;
 using storage::ShareableFileReference;
-using SyncLoadResultCallback =
-    content::ResourceDispatcherHostImpl::SyncLoadResultCallback;
 
 // ----------------------------------------------------------------------------
 
@@ -177,14 +170,8 @@
 // Aborts a request before an URLRequest has actually been created.
 void AbortRequestBeforeItStarts(
     IPC::Sender* sender,
-    const SyncLoadResultCallback& sync_result_handler,
     int request_id,
     mojom::URLLoaderClientPtr url_loader_client) {
-  if (sync_result_handler) {
-    SyncLoadResult result;
-    result.error_code = net::ERR_ABORTED;
-    sync_result_handler.Run(&result);
-  } else {
     // Tell the renderer that this request was disallowed.
     network::URLLoaderCompletionStatus status;
     status.error_code = net::ERR_ABORTED;
@@ -193,12 +180,7 @@
     status.completion_time = base::TimeTicks();
     status.encoded_data_length = 0;
     status.encoded_body_length = 0;
-    if (url_loader_client) {
-      url_loader_client->OnComplete(status);
-    } else {
-      sender->Send(new ResourceMsg_RequestComplete(request_id, status));
-    }
-  }
+    url_loader_client->OnComplete(status);
 }
 
 void RemoveDownloadFileFromChildSecurityPolicy(int child_id,
@@ -238,22 +220,6 @@
   return previews_state;
 }
 
-// Sends back the result of a synchronous loading result to the renderer through
-// Chrome IPC.
-void HandleSyncLoadResult(base::WeakPtr<ResourceMessageFilter> filter,
-                          std::unique_ptr<IPC::Message> sync_result,
-                          const SyncLoadResult* result) {
-  if (!filter)
-    return;
-
-  if (result) {
-    ResourceHostMsg_SyncLoad::WriteReplyParams(sync_result.get(), *result);
-  } else {
-    sync_result->set_reply_error();
-  }
-  filter->Send(sync_result.release());
-}
-
 bool ValidatePluginChildId(int plugin_child_id) {
   if (plugin_child_id == ChildProcessHost::kInvalidUniqueID)
     return true;
@@ -754,60 +720,6 @@
   scheduler_.reset();
 }
 
-bool ResourceDispatcherHostImpl::OnMessageReceived(
-    const IPC::Message& message,
-    ResourceRequesterInfo* requester_info) {
-  DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
-
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ResourceDispatcherHostImpl, message,
-                                   requester_info)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource)
-    IPC_MESSAGE_HANDLER_WITH_PARAM_DELAY_REPLY(ResourceHostMsg_SyncLoad,
-                                               OnSyncLoad)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_ReleaseDownloadedFile,
-                        OnReleaseDownloadedFile)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_CancelRequest, OnCancelRequest)
-    IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, OnDidChangePriority)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-
-  if (!handled && IPC_MESSAGE_ID_CLASS(message.type()) == ResourceMsgStart) {
-    base::PickleIterator iter(message);
-    int request_id = -1;
-    bool ok = iter.ReadInt(&request_id);
-    DCHECK(ok);
-    GlobalRequestID id(requester_info->child_id(), request_id);
-    DelegateMap::iterator it = delegate_map_.find(id);
-    if (it != delegate_map_.end()) {
-      for (auto& delegate : *it->second) {
-        if (delegate.OnMessageReceived(message)) {
-          handled = true;
-          break;
-        }
-      }
-    }
-
-    // As the unhandled resource message effectively has no consumer, mark it as
-    // handled to prevent needless propagation through the filter pipeline.
-    handled = true;
-  }
-
-  return handled;
-}
-
-void ResourceDispatcherHostImpl::OnRequestResource(
-    ResourceRequesterInfo* requester_info,
-    int routing_id,
-    int request_id,
-    const ResourceRequest& request_data,
-    net::MutableNetworkTrafficAnnotationTag traffic_annotation) {
-  OnRequestResourceInternal(
-      requester_info, routing_id, request_id, false /* is_sync_load */,
-      request_data, nullptr, nullptr,
-      net::NetworkTrafficAnnotationTag(traffic_annotation));
-}
-
 void ResourceDispatcherHostImpl::OnRequestResourceInternal(
     ResourceRequesterInfo* requester_info,
     int routing_id,
@@ -819,31 +731,10 @@
     const net::NetworkTrafficAnnotationTag& traffic_annotation) {
   DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
   BeginRequest(requester_info, request_id, request_data, is_sync_load,
-               SyncLoadResultCallback(), routing_id, std::move(mojo_request),
+               routing_id, std::move(mojo_request),
                std::move(url_loader_client), traffic_annotation);
 }
 
-// Begins a resource request with the given params on behalf of the specified
-// child process.  Responses will be dispatched through the given receiver. The
-// process ID is used to lookup WebContentsImpl from routing_id's in the case of
-// a request from a renderer.  request_context is the cookie/cache context to be
-// used for this request.
-//
-// If sync_result is non-null, then a SyncLoad reply will be generated, else
-// a normal asynchronous set of response messages will be generated.
-void ResourceDispatcherHostImpl::OnSyncLoad(
-    ResourceRequesterInfo* requester_info,
-    int request_id,
-    const ResourceRequest& request_data,
-    IPC::Message* sync_result) {
-  SyncLoadResultCallback callback =
-      base::Bind(&HandleSyncLoadResult, requester_info->filter()->GetWeakPtr(),
-                 base::Passed(WrapUnique(sync_result)));
-  BeginRequest(requester_info, request_id, request_data,
-               true /* is_sync_load */, callback, sync_result->routing_id(),
-               nullptr, nullptr, GetTrafficAnnotation());
-}
-
 bool ResourceDispatcherHostImpl::IsRequestIDInUse(
     const GlobalRequestID& id) const {
   if (pending_loaders_.find(id) != pending_loaders_.end())
@@ -911,17 +802,6 @@
       blocked_loaders_map_.erase(old_routing_id);
     }
   }
-  if (old_request_id != new_request_id) {
-    DelegateMap::iterator it = delegate_map_.find(old_request_id);
-    if (it != delegate_map_.end()) {
-      // Tell each delegate that the request ID has changed.
-      for (auto& delegate : *it->second)
-        delegate.set_request_id(new_request_id);
-      // Now store the observer list under the new request ID.
-      delegate_map_[new_request_id] = delegate_map_[old_request_id];
-      delegate_map_.erase(old_request_id);
-    }
-  }
 
   AppCacheInterceptor::CompleteCrossSiteTransfer(
       loader_ptr->request(), child_id, request_data.appcache_host_id,
@@ -999,7 +879,6 @@
     int request_id,
     const ResourceRequest& request_data,
     bool is_sync_load,
-    const SyncLoadResultCallback& sync_result_handler,  // only valid for sync
     int route_id,
     mojom::URLLoaderRequest mojo_request,
     mojom::URLLoaderClientPtr url_loader_client,
@@ -1066,8 +945,8 @@
   if (is_shutdown_ ||
       !ShouldServiceRequest(child_id, request_data, request_data.headers,
                             requester_info, resource_context)) {
-    AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler,
-                               request_id, std::move(url_loader_client));
+    AbortRequestBeforeItStarts(requester_info->filter(), request_id,
+                               std::move(url_loader_client));
     return;
   }
 
@@ -1086,8 +965,7 @@
         // will be used in UploadDataStream and ServiceWorkerURLRequestJob.
         if (!GetBodyBlobDataHandles(request_data.request_body.get(),
                                     resource_context, &blob_handles)) {
-          AbortRequestBeforeItStarts(requester_info->filter(),
-                                     sync_result_handler, request_id,
+          AbortRequestBeforeItStarts(requester_info->filter(), request_id,
                                      std::move(url_loader_client));
           return;
         }
@@ -1117,9 +995,8 @@
               base::Bind(
                   &ResourceDispatcherHostImpl::ContinuePendingBeginRequest,
                   base::Unretained(this), base::WrapRefCounted(requester_info),
-                  request_id, request_data, is_sync_load, sync_result_handler,
-                  route_id, request_data.headers,
-                  base::Passed(std::move(mojo_request)),
+                  request_id, request_data, is_sync_load, route_id,
+                  request_data.headers, base::Passed(std::move(mojo_request)),
                   base::Passed(std::move(url_loader_client)),
                   base::Passed(std::move(blob_handles)), traffic_annotation));
           return;
@@ -1127,12 +1004,11 @@
       }
     }
   }
-  ContinuePendingBeginRequest(requester_info, request_id, request_data,
-                              is_sync_load, sync_result_handler, route_id,
-                              request_data.headers, std::move(mojo_request),
-                              std::move(url_loader_client),
-                              std::move(blob_handles), traffic_annotation,
-                              HeaderInterceptorResult::CONTINUE);
+  ContinuePendingBeginRequest(
+      requester_info, request_id, request_data, is_sync_load, route_id,
+      request_data.headers, std::move(mojo_request),
+      std::move(url_loader_client), std::move(blob_handles), traffic_annotation,
+      HeaderInterceptorResult::CONTINUE);
 }
 
 void ResourceDispatcherHostImpl::ContinuePendingBeginRequest(
@@ -1140,7 +1016,6 @@
     int request_id,
     const ResourceRequest& request_data,
     bool is_sync_load,
-    const SyncLoadResultCallback& sync_result_handler,  // only valid for sync
     int route_id,
     const net::HttpRequestHeaders& headers,
     mojom::URLLoaderRequest mojo_request,
@@ -1149,7 +1024,6 @@
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     HeaderInterceptorResult interceptor_result) {
   DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
-  DCHECK(!sync_result_handler || is_sync_load);
   if (interceptor_result != HeaderInterceptorResult::CONTINUE) {
     if (requester_info->IsRenderer() &&
         interceptor_result == HeaderInterceptorResult::KILL) {
@@ -1159,8 +1033,8 @@
       bad_message::ReceivedBadMessage(requester_info->filter(),
                                       bad_message::RDH_ILLEGAL_ORIGIN);
     }
-    AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler,
-                               request_id, std::move(url_loader_client));
+    AbortRequestBeforeItStarts(requester_info->filter(), request_id,
+                               std::move(url_loader_client));
     return;
   }
   int child_id = requester_info->child_id();
@@ -1183,8 +1057,8 @@
                                                   request_data.url,
                                                   request_data.resource_type,
                                                   resource_context)) {
-    AbortRequestBeforeItStarts(requester_info->filter(), sync_result_handler,
-                               request_id, std::move(url_loader_client));
+    AbortRequestBeforeItStarts(requester_info->filter(), request_id,
+                               std::move(url_loader_client));
     return;
   }
 
@@ -1386,10 +1260,10 @@
         new_request.get(), requester_info->appcache_service(), child_id,
         request_data.appcache_host_id, request_data.resource_type,
         request_data.should_reset_appcache);
-    handler = CreateResourceHandler(
-        requester_info.get(), new_request.get(), request_data,
-        sync_result_handler, route_id, child_id, resource_context,
-        std::move(mojo_request), std::move(url_loader_client));
+    handler = CreateResourceHandler(requester_info.get(), new_request.get(),
+                                    request_data, route_id, child_id,
+                                    resource_context, std::move(mojo_request),
+                                    std::move(url_loader_client));
   }
   if (handler)
     BeginRequestInternal(std::move(new_request), std::move(handler));
@@ -1400,7 +1274,6 @@
     ResourceRequesterInfo* requester_info,
     net::URLRequest* request,
     const ResourceRequest& request_data,
-    const SyncLoadResultCallback& sync_result_handler,
     int route_id,
     int child_id,
     ResourceContext* resource_context,
@@ -1409,36 +1282,21 @@
   DCHECK(requester_info->IsRenderer() || requester_info->IsNavigationPreload());
   // Construct the IPC resource handler.
   std::unique_ptr<ResourceHandler> handler;
-  if (sync_result_handler) {
-    // download_to_file is not supported for synchronous requests.
-    if (request_data.download_to_file) {
-      DCHECK(requester_info->IsRenderer());
-      bad_message::ReceivedBadMessage(requester_info->filter(),
-                                      bad_message::RDH_BAD_DOWNLOAD);
-      return std::unique_ptr<ResourceHandler>();
-    }
+  handler = CreateBaseResourceHandler(request, std::move(mojo_request),
+                                      std::move(url_loader_client),
+                                      request_data.resource_type);
 
-    DCHECK(!mojo_request.is_pending());
-    DCHECK(!url_loader_client);
-    handler.reset(new SyncResourceHandler(request, sync_result_handler, this));
-  } else {
-    handler = CreateBaseResourceHandler(request, std::move(mojo_request),
-                                        std::move(url_loader_client),
-                                        request_data.resource_type);
-
-    // The RedirectToFileResourceHandler depends on being next in the chain.
-    if (request_data.download_to_file) {
-      handler.reset(
-          new RedirectToFileResourceHandler(std::move(handler), request));
-    }
+  // The RedirectToFileResourceHandler depends on being next in the chain.
+  if (request_data.download_to_file) {
+    handler.reset(
+        new RedirectToFileResourceHandler(std::move(handler), request));
   }
 
   bool start_detached = request_data.download_to_network_cache_only;
 
   // Prefetches and <a ping> requests outlive their child process.
-  if (!sync_result_handler &&
-      (start_detached || request_data.resource_type == RESOURCE_TYPE_PREFETCH ||
-       request_data.keepalive)) {
+  if (start_detached || request_data.resource_type == RESOURCE_TYPE_PREFETCH ||
+      request_data.keepalive) {
     auto timeout =
         base::TimeDelta::FromMilliseconds(kDefaultDetachableCancelDelayMs);
     int timeout_set_by_finch_in_sec = base::GetFieldTrialParamByFeatureAsInt(
@@ -1472,14 +1330,10 @@
     mojom::URLLoaderClientPtr url_loader_client,
     ResourceType resource_type) {
   std::unique_ptr<ResourceHandler> handler;
-  if (mojo_request.is_pending()) {
-    handler.reset(new MojoAsyncResourceHandler(
-        request, this, std::move(mojo_request), std::move(url_loader_client),
-        resource_type,
-        false));  // defer_on_response_started.
-  } else {
-    handler.reset(new AsyncResourceHandler(request, this));
-  }
+  handler.reset(
+      new MojoAsyncResourceHandler(request, this, std::move(mojo_request),
+                                   std::move(url_loader_client), resource_type,
+                                   false));  // defer_on_response_started.
   return handler;
 }
 
@@ -1593,27 +1447,6 @@
   return handler;
 }
 
-void ResourceDispatcherHostImpl::OnReleaseDownloadedFile(
-    ResourceRequesterInfo* requester_info,
-    int request_id) {
-  UnregisterDownloadedTempFile(requester_info->child_id(), request_id);
-}
-
-void ResourceDispatcherHostImpl::OnDidChangePriority(
-    ResourceRequesterInfo* requester_info,
-    int request_id,
-    net::RequestPriority new_priority,
-    int intra_priority_value) {
-  ResourceLoader* loader = GetLoader(requester_info->child_id(), request_id);
-  // The request may go away before processing this message, so |loader| can
-  // legitimately be null.
-  if (!loader)
-    return;
-
-  scheduler_->ReprioritizeRequest(loader->request(), new_priority,
-                                  intra_priority_value);
-}
-
 void ResourceDispatcherHostImpl::RegisterDownloadedTempFile(
     int child_id, int request_id, const base::FilePath& file_path) {
   scoped_refptr<ShareableFileReference> reference =
@@ -1650,18 +1483,6 @@
   // when all file refs are deleted (see RegisterDownloadedTempFile).
 }
 
-bool ResourceDispatcherHostImpl::Send(IPC::Message* message) {
-  delete message;
-  return false;
-}
-
-void ResourceDispatcherHostImpl::OnCancelRequest(
-    ResourceRequesterInfo* requester_info,
-    int request_id) {
-  CancelRequestFromRenderer(
-      GlobalRequestID(requester_info->child_id(), request_id));
-}
-
 ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
     int child_id,
     int render_view_route_id,
@@ -2631,31 +2452,6 @@
   return GetLoader(GlobalRequestID(child_id, request_id));
 }
 
-void ResourceDispatcherHostImpl::RegisterResourceMessageDelegate(
-    const GlobalRequestID& id, ResourceMessageDelegate* delegate) {
-  DelegateMap::iterator it = delegate_map_.find(id);
-  if (it == delegate_map_.end()) {
-    it = delegate_map_.insert(
-                           std::make_pair(
-                               id,
-                               new base::ObserverList<ResourceMessageDelegate>))
-             .first;
-  }
-  it->second->AddObserver(delegate);
-}
-
-void ResourceDispatcherHostImpl::UnregisterResourceMessageDelegate(
-    const GlobalRequestID& id, ResourceMessageDelegate* delegate) {
-  DCHECK(base::ContainsKey(delegate_map_, id));
-  DelegateMap::iterator it = delegate_map_.find(id);
-  DCHECK(it->second->HasObserver(delegate));
-  it->second->RemoveObserver(delegate);
-  if (!it->second->might_have_observers()) {
-    delete it->second;
-    delegate_map_.erase(it);
-  }
-}
-
 bool ResourceDispatcherHostImpl::ShouldServiceRequest(
     int child_id,
     const ResourceRequest& request_data,
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h
index 19b8912..d92a4e3 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -38,7 +38,6 @@
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_type.h"
 #include "content/public/common/url_loader.mojom.h"
-#include "ipc/ipc_message.h"
 #include "net/base/load_states.h"
 #include "net/base/request_priority.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -87,11 +86,6 @@
     : public ResourceDispatcherHost,
       public ResourceLoaderDelegate {
  public:
-  // Used to handle the result of SyncLoad IPC. |result| is null if it's
-  // unavailable due to an error.
-  using SyncLoadResultCallback =
-      base::Callback<void(const SyncLoadResult* result)>;
-
   // This constructor should be used if we want downloads to work correctly.
   // TODO(ananta)
   // Work on moving creation of download handlers out of
@@ -126,10 +120,6 @@
   // for it are dead.
   void CancelRequestsForContext(ResourceContext* context);
 
-  // Returns true if the message was a resource message that was processed.
-  bool OnMessageReceived(const IPC::Message& message,
-                         ResourceRequesterInfo* requester_info);
-
   // Cancels the given request if it still exists.
   void CancelRequest(int child_id, int request_id);
 
@@ -208,9 +198,6 @@
       const base::FilePath& file_path);
   void UnregisterDownloadedTempFile(int child_id, int request_id);
 
-  // Needed for the sync IPC message dispatcher macros.
-  bool Send(IPC::Message* message);
-
   // Indicates whether third-party sub-content can pop-up HTTP basic auth
   // dialog boxes.
   bool allow_cross_origin_auth_prompt();
@@ -535,13 +522,6 @@
       const GlobalFrameRoutingId& global_routing_id,
       bool cancel_requests);
 
-  void OnRequestResource(
-      ResourceRequesterInfo* requester_info,
-      int routing_id,
-      int request_id,
-      const ResourceRequest& request_data,
-      net::MutableNetworkTrafficAnnotationTag traffic_annotation);
-
   void OnRequestResourceInternal(
       ResourceRequesterInfo* requester_info,
       int routing_id,
@@ -552,11 +532,6 @@
       mojom::URLLoaderClientPtr url_loader_client,
       const net::NetworkTrafficAnnotationTag& traffic_annotation);
 
-  void OnSyncLoad(ResourceRequesterInfo* requester_info,
-                  int request_id,
-                  const ResourceRequest& request_data,
-                  IPC::Message* sync_result);
-
   bool IsRequestIDInUse(const GlobalRequestID& id) const;
 
   // Update the ResourceRequestInfo and internal maps when a request is
@@ -583,7 +558,6 @@
       int request_id,
       const ResourceRequest& request_data,
       bool is_sync_load,
-      const SyncLoadResultCallback& sync_result_handler,  // only valid for sync
       int route_id,
       mojom::URLLoaderRequest mojo_request,
       mojom::URLLoaderClientPtr url_loader_client,
@@ -602,7 +576,6 @@
       int request_id,
       const ResourceRequest& request_data,
       bool is_sync_load,
-      const SyncLoadResultCallback& sync_result_handler,  // only valid for sync
       int route_id,
       const net::HttpRequestHeaders& headers,
       mojom::URLLoaderRequest mojo_request,
@@ -617,7 +590,6 @@
       ResourceRequesterInfo* requester_info,
       net::URLRequest* request,
       const ResourceRequest& request_data,
-      const SyncLoadResultCallback& sync_result_handler,
       int route_id,
       int child_id,
       ResourceContext* resource_context,
@@ -651,14 +623,6 @@
       NavigationURLLoaderImplCore* navigation_loader_core,
       std::unique_ptr<StreamHandle> stream_handle);
 
-  void OnCancelRequest(ResourceRequesterInfo* requester_info, int request_id);
-  void OnReleaseDownloadedFile(ResourceRequesterInfo* requester_info,
-                               int request_id);
-  void OnDidChangePriority(ResourceRequesterInfo* requester_info,
-                           int request_id,
-                           net::RequestPriority new_priority,
-                           int intra_priority_value);
-
   // Creates ResourceRequestInfoImpl for a download or page save.
   // |download| should be true if the request is a file download.
   ResourceRequestInfoImpl* CreateRequestInfo(
@@ -691,13 +655,6 @@
   ResourceLoader* GetLoader(const GlobalRequestID& id) const;
   ResourceLoader* GetLoader(int child_id, int request_id) const;
 
-  // Registers |delegate| to receive resource IPC messages targeted to the
-  // specified |id|.
-  void RegisterResourceMessageDelegate(const GlobalRequestID& id,
-                                       ResourceMessageDelegate* delegate);
-  void UnregisterResourceMessageDelegate(const GlobalRequestID& id,
-                                         ResourceMessageDelegate* delegate);
-
   // Consults the RendererSecurity policy to determine whether the
   // ResourceDispatcherHostImpl should service this request.  A request might
   // be disallowed if the renderer is not authorized to retrieve the request
@@ -828,10 +785,6 @@
 
   bool allow_cross_origin_auth_prompt_;
 
-  typedef std::map<GlobalRequestID,
-                   base::ObserverList<ResourceMessageDelegate>*> DelegateMap;
-  DelegateMap delegate_map_;
-
   std::unique_ptr<ResourceScheduler> scheduler_;
 
   // Used to invoke an interceptor for the HTTP header.
diff --git a/content/browser/loader/resource_loader_unittest.cc b/content/browser/loader/resource_loader_unittest.cc
index f8f3b77..3c27727 100644
--- a/content/browser/loader/resource_loader_unittest.cc
+++ b/content/browser/loader/resource_loader_unittest.cc
@@ -33,7 +33,6 @@
 #include "content/public/test/test_renderer_host.h"
 #include "content/test/test_content_browser_client.h"
 #include "content/test/test_web_contents.h"
-#include "ipc/ipc_message.h"
 #include "net/base/chunked_upload_data_stream.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
diff --git a/content/browser/loader/resource_message_delegate.cc b/content/browser/loader/resource_message_delegate.cc
deleted file mode 100644
index 01d3595..0000000
--- a/content/browser/loader/resource_message_delegate.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2013 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/loader/resource_message_delegate.h"
-
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "net/url_request/url_request.h"
-
-namespace content {
-
-ResourceMessageDelegate::ResourceMessageDelegate(const net::URLRequest* request)
-    : id_(ResourceRequestInfoImpl::ForRequest(request)->GetGlobalRequestID()) {
-  ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
-  rdh->RegisterResourceMessageDelegate(id_, this);
-}
-
-ResourceMessageDelegate::~ResourceMessageDelegate() {
-  ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
-  rdh->UnregisterResourceMessageDelegate(id_, this);
-}
-
-}  // namespace content
diff --git a/content/browser/loader/resource_message_delegate.h b/content/browser/loader/resource_message_delegate.h
deleted file mode 100644
index f007f1c..0000000
--- a/content/browser/loader/resource_message_delegate.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 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_LOADER_RESOURCE_MESSAGE_DELEGATE_H_
-#define CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_DELEGATE_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/global_request_id.h"
-
-namespace IPC {
-class Message;
-}
-
-namespace net {
-class URLRequest;
-}
-
-namespace content {
-
-// A ResourceMessageDelegate receives IPC ResourceMsg_* messages for a specified
-// URLRequest. The delegate should implement its own IPC handler. It will
-// receive the message _after_ the ResourceDispatcherHost has handled it.
-class CONTENT_EXPORT ResourceMessageDelegate {
- public:
-  ResourceMessageDelegate(const net::URLRequest* request);
-  virtual ~ResourceMessageDelegate();
-
-  // Called when the ResourceDispatcherHostImpl receives a message specifically
-  // for this delegate.
-  virtual bool OnMessageReceived(const IPC::Message& message) = 0;
-
-  void set_request_id(const GlobalRequestID& new_request_id) {
-    id_ = new_request_id;
-  }
-
- private:
-  GlobalRequestID id_;
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceMessageDelegate);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_DELEGATE_H_
diff --git a/content/browser/loader/resource_message_filter.cc b/content/browser/loader/resource_message_filter.cc
index 88f35647..99d348a 100644
--- a/content/browser/loader/resource_message_filter.cc
+++ b/content/browser/loader/resource_message_filter.cc
@@ -72,10 +72,7 @@
 
 bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
   DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
-  // Check if InitializeOnIOThread() has been called.
-  DCHECK_EQ(this, requester_info_->filter());
-  return ResourceDispatcherHostImpl::Get()->OnMessageReceived(
-      message, requester_info_.get());
+  return false;
 }
 
 void ResourceMessageFilter::OnDestruct() const {
diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc
deleted file mode 100644
index e65d9e5..0000000
--- a/content/browser/loader/sync_resource_handler.cc
+++ /dev/null
@@ -1,132 +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.
-
-#include "content/browser/loader/sync_resource_handler.h"
-
-#include "base/callback_helpers.h"
-#include "base/logging.h"
-#include "content/browser/loader/resource_controller.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/common/resource_messages.h"
-#include "content/public/browser/resource_dispatcher_host_delegate.h"
-#include "content/public/browser/resource_request_info.h"
-#include "net/base/io_buffer.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/redirect_info.h"
-
-namespace content {
-
-SyncResourceHandler::SyncResourceHandler(
-    net::URLRequest* request,
-    const SyncLoadResultCallback& result_handler,
-    ResourceDispatcherHostImpl* resource_dispatcher_host)
-    : ResourceHandler(request),
-      read_buffer_(new net::IOBuffer(kReadBufSize)),
-      result_handler_(result_handler),
-      rdh_(resource_dispatcher_host),
-      total_transfer_size_(0) {
-  result_.final_url = request->url();
-}
-
-SyncResourceHandler::~SyncResourceHandler() {
-  if (result_handler_)
-    result_handler_.Run(nullptr);
-}
-
-void SyncResourceHandler::OnRequestRedirected(
-    const net::RedirectInfo& redirect_info,
-    ResourceResponse* response,
-    std::unique_ptr<ResourceController> controller) {
-  if (rdh_->delegate()) {
-    rdh_->delegate()->OnRequestRedirected(
-        redirect_info.new_url, request(), GetRequestInfo()->GetContext(),
-        response);
-  }
-
-  // TODO(darin): It would be much better if this could live in WebCore, but
-  // doing so requires API changes at all levels.  Similar code exists in
-  // WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
-  if (redirect_info.new_url.GetOrigin() != result_.final_url.GetOrigin()) {
-    LOG(ERROR) << "Cross origin redirect denied";
-    controller->Cancel();
-    return;
-  }
-  result_.final_url = redirect_info.new_url;
-
-  total_transfer_size_ += request()->GetTotalReceivedBytes();
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnResponseStarted(
-    ResourceResponse* response,
-    std::unique_ptr<ResourceController> controller) {
-  ResourceRequestInfoImpl* info = GetRequestInfo();
-  DCHECK(info->requester_info()->IsRenderer());
-  if (!info->requester_info()->filter()) {
-    controller->Cancel();
-    return;
-  }
-
-  if (rdh_->delegate()) {
-    rdh_->delegate()->OnResponseStarted(request(), info->GetContext(),
-                                        response);
-  }
-
-  // We don't care about copying the status here.
-  result_.headers = response->head.headers;
-  result_.mime_type = response->head.mime_type;
-  result_.charset = response->head.charset;
-  result_.download_file_path = response->head.download_file_path;
-  result_.request_time = response->head.request_time;
-  result_.response_time = response->head.response_time;
-  result_.load_timing = response->head.load_timing;
-  result_.devtools_info = response->head.devtools_info;
-  result_.socket_address = response->head.socket_address;
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnWillStart(
-    const GURL& url,
-    std::unique_ptr<ResourceController> controller) {
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnWillRead(
-    scoped_refptr<net::IOBuffer>* buf,
-    int* buf_size,
-    std::unique_ptr<ResourceController> controller) {
-  *buf = read_buffer_.get();
-  *buf_size = kReadBufSize;
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnReadCompleted(
-    int bytes_read,
-    std::unique_ptr<ResourceController> controller) {
-  if (bytes_read)
-    result_.data.append(read_buffer_->data(), bytes_read);
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnResponseCompleted(
-    const net::URLRequestStatus& status,
-    std::unique_ptr<ResourceController> controller) {
-  result_.error_code = status.error();
-
-  int total_transfer_size = request()->GetTotalReceivedBytes();
-  result_.encoded_data_length = total_transfer_size_ + total_transfer_size;
-  result_.encoded_body_length = request()->GetRawBodyBytes();
-
-  base::ResetAndReturn(&result_handler_).Run(&result_);
-
-  controller->Resume();
-}
-
-void SyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
-  // Sync requests don't involve ResourceMsg_DataDownloaded messages
-  // being sent back to renderers as progress is made.
-}
-
-}  // namespace content
diff --git a/content/browser/loader/sync_resource_handler.h b/content/browser/loader/sync_resource_handler.h
deleted file mode 100644
index 881be7f..0000000
--- a/content/browser/loader/sync_resource_handler.h
+++ /dev/null
@@ -1,68 +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.
-
-#ifndef CONTENT_BROWSER_LOADER_SYNC_RESOURCE_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_SYNC_RESOURCE_HANDLER_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/loader/resource_handler.h"
-#include "content/public/common/resource_response.h"
-
-namespace net {
-class IOBuffer;
-class URLRequest;
-}
-
-namespace content {
-class ResourceController;
-
-// Used to complete a synchronous resource request in response to resource load
-// events from the resource dispatcher host.
-class SyncResourceHandler : public ResourceHandler {
- public:
-  using SyncLoadResultCallback =
-      ResourceDispatcherHostImpl::SyncLoadResultCallback;
-
-  SyncResourceHandler(net::URLRequest* request,
-                      const SyncLoadResultCallback& sync_result_handler,
-                      ResourceDispatcherHostImpl* resource_dispatcher_host);
-  ~SyncResourceHandler() override;
-
-  void OnRequestRedirected(
-      const net::RedirectInfo& redirect_info,
-      ResourceResponse* response,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnResponseStarted(
-      ResourceResponse* response,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnWillStart(const GURL& url,
-                   std::unique_ptr<ResourceController> controller) override;
-  void OnWillRead(scoped_refptr<net::IOBuffer>* buf,
-                  int* buf_size,
-                  std::unique_ptr<ResourceController> controller) override;
-  void OnReadCompleted(int bytes_read,
-                       std::unique_ptr<ResourceController> controller) override;
-  void OnResponseCompleted(
-      const net::URLRequestStatus& status,
-      std::unique_ptr<ResourceController> controller) override;
-  void OnDataDownloaded(int bytes_downloaded) override;
-
- private:
-  enum { kReadBufSize = 3840 };
-
-  scoped_refptr<net::IOBuffer> read_buffer_;
-
-  SyncLoadResult result_;
-  SyncLoadResultCallback result_handler_;
-  ResourceDispatcherHostImpl* rdh_;
-  int64_t total_transfer_size_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_LOADER_SYNC_RESOURCE_HANDLER_H_
diff --git a/content/browser/media/capture/cursor_renderer_mac_unittest.mm b/content/browser/media/capture/cursor_renderer_mac_unittest.mm
index 24b1840..a2d35fd 100644
--- a/content/browser/media/capture/cursor_renderer_mac_unittest.mm
+++ b/content/browser/media/capture/cursor_renderer_mac_unittest.mm
@@ -12,8 +12,8 @@
 #include "base/time/time.h"
 #include "media/base/video_frame.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/test/cocoa_helper.h"
 #include "ui/gfx/mac/coordinate_conversion.h"
-#include "ui/gfx/test/ui_cocoa_test_helper.h"
 
 namespace content {
 
diff --git a/content/browser/media/cdm_registry_impl_unittest.cc b/content/browser/media/cdm_registry_impl_unittest.cc
index 607792c1..37bec476 100644
--- a/content/browser/media/cdm_registry_impl_unittest.cc
+++ b/content/browser/media/cdm_registry_impl_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/version.h"
 #include "content/public/common/cdm_info.h"
+#include "media/base/video_codecs.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
@@ -24,8 +25,6 @@
 const char kTestPath[] = "/aa/bb";
 const char kVersion1[] = "1.1.1.1";
 const char kVersion2[] = "1.1.1.2";
-const char kTestCodecs[] = "vp9,avc1";
-const char kCodecDelimiter[] = ",";
 const char kTestKeySystem[] = "com.example.somesystem";
 const char kTestFileSystemId[] = "file_system_id";
 
@@ -40,18 +39,15 @@
   void Register(const std::string& name,
                 const std::string& version,
                 const std::string& path,
-                const std::string& supported_codecs,
+                const std::vector<media::VideoCodec>& supported_video_codecs,
                 bool supports_persistent_license,
                 std::string supported_key_system,
                 bool supports_sub_key_systems = false) {
-    const std::vector<std::string> codecs =
-        base::SplitString(supported_codecs, kCodecDelimiter,
-                          base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
     cdm_registry_.RegisterCdm(
         CdmInfo(name, kTestCdmGuid, base::Version(version),
-                base::FilePath::FromUTF8Unsafe(path), kTestFileSystemId, codecs,
-                supports_persistent_license, supported_key_system,
-                supports_sub_key_systems));
+                base::FilePath::FromUTF8Unsafe(path), kTestFileSystemId,
+                supported_video_codecs, supports_persistent_license,
+                supported_key_system, supports_sub_key_systems));
   }
 
   bool IsRegistered(const std::string& name, const std::string& version) {
@@ -76,8 +72,8 @@
 };
 
 TEST_F(CdmRegistryImplTest, Register) {
-  Register(kTestCdmName, kVersion1, kTestPath, kTestCodecs, true,
-           kTestKeySystem, true);
+  Register(kTestCdmName, kVersion1, kTestPath,
+           {media::kCodecVP8, media::kCodecVP9}, true, kTestKeySystem, true);
   std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
   ASSERT_EQ(1u, cdms.size());
   CdmInfo cdm = cdms[0];
@@ -85,36 +81,33 @@
   EXPECT_EQ(kVersion1, cdm.version.GetString());
   EXPECT_EQ(kTestPath, cdm.path.MaybeAsASCII());
   EXPECT_EQ(kTestFileSystemId, cdm.file_system_id);
-  EXPECT_EQ(2u, cdm.supported_codecs.size());
-  EXPECT_EQ("vp9", cdm.supported_codecs[0]);
-  EXPECT_EQ("avc1", cdm.supported_codecs[1]);
+  EXPECT_EQ(2u, cdm.supported_video_codecs.size());
+  EXPECT_EQ(media::kCodecVP8, cdm.supported_video_codecs[0]);
+  EXPECT_EQ(media::kCodecVP9, cdm.supported_video_codecs[1]);
   EXPECT_TRUE(cdm.supports_persistent_license);
   EXPECT_EQ(kTestKeySystem, cdm.supported_key_system);
   EXPECT_TRUE(cdm.supports_sub_key_systems);
 }
 
 TEST_F(CdmRegistryImplTest, ReRegister) {
-  Register(kTestCdmName, kVersion1, "/bb/cc", "unknown", false, kTestKeySystem);
+  Register(kTestCdmName, kVersion1, "/bb/cc", {}, false, kTestKeySystem);
   EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
 
   // Now register same key system with different values.
-  Register(kTestCdmName, kVersion1, kTestPath, kTestCodecs, false,
-           kTestKeySystem);
+  Register(kTestCdmName, kVersion1, kTestPath, {}, false, kTestKeySystem);
   EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
 }
 
 TEST_F(CdmRegistryImplTest, MultipleVersions) {
-  Register(kTestCdmName, kVersion1, kTestPath, kTestCodecs, false,
-           kTestKeySystem);
-  Register(kTestCdmName, kVersion2, "/bb/cc", "unknown", false, kTestKeySystem);
+  Register(kTestCdmName, kVersion1, kTestPath, {}, false, kTestKeySystem);
+  Register(kTestCdmName, kVersion2, "/bb/cc", {}, false, kTestKeySystem);
   EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
   EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion2));
 }
 
 TEST_F(CdmRegistryImplTest, NewVersionInsertedFirst) {
-  Register(kTestCdmName, kVersion1, kTestPath, kTestCodecs, false,
-           kTestKeySystem);
-  Register(kTestCdmName, kVersion2, "/bb/cc", "unknown", false, kTestKeySystem);
+  Register(kTestCdmName, kVersion1, kTestPath, {}, false, kTestKeySystem);
+  Register(kTestCdmName, kVersion2, "/bb/cc", {}, false, kTestKeySystem);
 
   const std::vector<std::string> versions = GetVersions(kTestCdmGuid);
   EXPECT_EQ(2u, versions.size());
diff --git a/content/browser/media/media_interface_proxy.cc b/content/browser/media/media_interface_proxy.cc
index 0584b24..9a04a8f 100644
--- a/content/browser/media/media_interface_proxy.cc
+++ b/content/browser/media/media_interface_proxy.cc
@@ -16,6 +16,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/service_manager_connection.h"
 #include "media/mojo/interfaces/constants.mojom.h"
+#include "media/mojo/interfaces/media_service.mojom.h"
 #include "media/mojo/services/media_interface_provider.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -41,9 +42,9 @@
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
 #if defined(OS_MACOSX)
-#include "media/mojo/interfaces/media_service_mac.mojom.h"
+#include "media/mojo/interfaces/cdm_service_mac.mojom.h"
 #else
-#include "media/mojo/interfaces/media_service.mojom.h"
+#include "media/mojo/interfaces/cdm_service.mojom.h"
 #endif  // defined(OS_MACOSX)
 
 namespace content {
@@ -326,8 +327,8 @@
   service_manager::Connector* connector =
       ServiceManagerConnection::GetForProcess()->GetConnector();
 
-  media::mojom::MediaServicePtr media_service;
-  connector->BindInterface(identity, &media_service);
+  media::mojom::CdmServicePtr cdm_service;
+  connector->BindInterface(identity, &cdm_service);
 
 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
 #if defined(OS_MACOSX)
@@ -337,15 +338,15 @@
       std::make_unique<SeatbeltExtensionTokenProviderImpl>(cdm_path),
       mojo::MakeRequest(&token_provider_ptr));
 
-  media_service->LoadCdm(cdm_path, std::move(token_provider_ptr));
+  cdm_service->LoadCdm(cdm_path, std::move(token_provider_ptr));
 #else
-  media_service->LoadCdm(cdm_path);
+  cdm_service->LoadCdm(cdm_path);
 #endif  // defined(OS_MACOSX)
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
   InterfaceFactoryPtr interface_factory_ptr;
-  media_service->CreateInterfaceFactory(MakeRequest(&interface_factory_ptr),
-                                        GetFrameServices(cdm_file_system_id));
+  cdm_service->CreateInterfaceFactory(MakeRequest(&interface_factory_ptr),
+                                      GetFrameServices(cdm_file_system_id));
   interface_factory_ptr.set_connection_error_handler(
       base::BindOnce(&MediaInterfaceProxy::OnCdmServiceConnectionError,
                      base::Unretained(this), cdm_guid));
diff --git a/content/browser/plugin_service_impl.cc b/content/browser/plugin_service_impl.cc
index 0378ab3..130f4d8e 100644
--- a/content/browser/plugin_service_impl.cc
+++ b/content/browser/plugin_service_impl.cc
@@ -60,7 +60,11 @@
   DCHECK(sequence_checker->CalledOnValidSequence());
 }
 
-void RecordBrokerUsage(int render_process_id, int render_frame_id) {
+}  // namespace
+
+// static
+void PluginServiceImpl::RecordBrokerUsage(int render_process_id,
+                                          int render_frame_id) {
   ukm::UkmRecorder* recorder = ukm::UkmRecorder::Get();
   ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
   WebContents* web_contents = WebContents::FromRenderFrameHost(
@@ -71,8 +75,6 @@
   }
 }
 
-}  // namespace
-
 // static
 PluginService* PluginService::GetInstance() {
   return PluginServiceImpl::GetInstance();
@@ -230,9 +232,9 @@
     int render_frame_id,
     const base::FilePath& path,
     PpapiPluginProcessHost::BrokerClient* client) {
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&RecordBrokerUsage, render_process_id, render_frame_id));
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::BindOnce(&PluginServiceImpl::RecordBrokerUsage,
+                                         render_process_id, render_frame_id));
 
   PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(
       render_process_id, path);
diff --git a/content/browser/plugin_service_impl.h b/content/browser/plugin_service_impl.h
index fb9226fd..e6de4ca 100644
--- a/content/browser/plugin_service_impl.h
+++ b/content/browser/plugin_service_impl.h
@@ -116,6 +116,9 @@
  private:
   friend struct base::DefaultSingletonTraits<PluginServiceImpl>;
 
+  // Helper for recording URLs to UKM.
+  static void RecordBrokerUsage(int render_process_id, int render_frame_id);
+
   // Creates the PluginServiceImpl object, but doesn't actually build the plugin
   // list yet.  It's generated lazily.
   PluginServiceImpl();
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm
index c21fe756..dc7eb8d 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -515,6 +515,15 @@
 gfx::Size BrowserCompositorMac::DelegatedFrameHostDesiredSizeInDIP() const {
   gfx::Size dip_size;
   GetViewProperties(&dip_size, nullptr, nullptr);
+  if (enable_viz_) {
+    if (recyclable_compositor_) {
+      const gfx::Size& pixel_size =
+          recyclable_compositor_->compositor()->size();
+      float scale_factor =
+          recyclable_compositor_->compositor()->device_scale_factor();
+      dip_size = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
+    }
+  }
   return dip_size;
 }
 
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 66547bf..439d41c 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -172,7 +172,7 @@
   return limits;
 }
 
-gpu::gles2::ContextCreationAttribHelper GetCompositorContextAttributes(
+gpu::ContextCreationAttribs GetCompositorContextAttributes(
     const gfx::ColorSpace& display_color_space,
     bool requires_alpha_channel) {
   // This is used for the browser compositor (offscreen) and for the display
@@ -181,7 +181,7 @@
   // not need alpha, stencil, depth, antialiasing. The display compositor does
   // not use these things either, except for alpha when it has a transparent
   // background.
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = -1;
   attributes.stencil_size = 0;
   attributes.depth_size = 0;
@@ -189,11 +189,11 @@
   attributes.sample_buffers = 0;
   attributes.bind_generates_resource = false;
   if (display_color_space == gfx::ColorSpace::CreateSRGB()) {
-    attributes.color_space = gpu::gles2::COLOR_SPACE_SRGB;
+    attributes.color_space = gpu::COLOR_SPACE_SRGB;
   } else if (display_color_space == gfx::ColorSpace::CreateDisplayP3D65()) {
-    attributes.color_space = gpu::gles2::COLOR_SPACE_DISPLAY_P3;
+    attributes.color_space = gpu::COLOR_SPACE_DISPLAY_P3;
   } else {
-    attributes.color_space = gpu::gles2::COLOR_SPACE_UNSPECIFIED;
+    attributes.color_space = gpu::COLOR_SPACE_UNSPECIFIED;
     DLOG(ERROR) << "Android color space is neither sRGB nor P3, output color "
                    "will be incorrect.";
   }
@@ -227,7 +227,7 @@
 
 void CreateContextProviderAfterGpuChannelEstablished(
     gpu::SurfaceHandle handle,
-    gpu::gles2::ContextCreationAttribHelper attributes,
+    gpu::ContextCreationAttribs attributes,
     gpu::SharedMemoryLimits shared_memory_limits,
     Compositor::ContextProviderCallback callback,
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
@@ -441,7 +441,7 @@
 // static
 void Compositor::CreateContextProvider(
     gpu::SurfaceHandle handle,
-    gpu::gles2::ContextCreationAttribHelper attributes,
+    gpu::ContextCreationAttribs attributes,
     gpu::SharedMemoryLimits shared_memory_limits,
     ContextProviderCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
index 588cdd4..6337629 100644
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -301,11 +301,13 @@
 void DelegatedFrameHost::WasResized() {
   const viz::SurfaceId* primary_surface_id =
       client_->DelegatedFrameHostGetLayer()->GetPrimarySurfaceId();
+  gfx::Size new_size_in_dip = client_->DelegatedFrameHostDesiredSizeInDIP();
+
   if (enable_surface_synchronization_ &&
       client_->DelegatedFrameHostIsVisible() &&
       (!primary_surface_id || primary_surface_id->local_surface_id() !=
                                   client_->GetLocalSurfaceId())) {
-    current_frame_size_in_dip_ = client_->DelegatedFrameHostDesiredSizeInDIP();
+    current_frame_size_in_dip_ = new_size_in_dip;
 
     viz::SurfaceId surface_id(frame_sink_id_, client_->GetLocalSurfaceId());
     client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
@@ -317,8 +319,7 @@
     return;
   }
 
-  if (client_->DelegatedFrameHostDesiredSizeInDIP() !=
-          current_frame_size_in_dip_ &&
+  if (new_size_in_dip != current_frame_size_in_dip_ &&
       !client_->DelegatedFrameHostIsVisible()) {
     EvictDelegatedFrame();
   }
@@ -345,14 +346,13 @@
     return;
   }
 
-  if (current_frame_size_in_dip_.width() <
-      client_->DelegatedFrameHostDesiredSizeInDIP().width()) {
+  gfx::Size size_in_dip = client_->DelegatedFrameHostDesiredSizeInDIP();
+  if (current_frame_size_in_dip_.width() < size_in_dip.width()) {
     right_gutter_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
     right_gutter_->SetColor(GetGutterColor());
-    int width = client_->DelegatedFrameHostDesiredSizeInDIP().width() -
-                current_frame_size_in_dip_.width();
+    int width = size_in_dip.width() - current_frame_size_in_dip_.width();
     // The right gutter also includes the bottom-right corner, if necessary.
-    int height = client_->DelegatedFrameHostDesiredSizeInDIP().height();
+    int height = size_in_dip.height();
     right_gutter_->SetBounds(
         gfx::Rect(current_frame_size_in_dip_.width(), 0, width, height));
 
@@ -361,13 +361,11 @@
     right_gutter_.reset();
   }
 
-  if (current_frame_size_in_dip_.height() <
-      client_->DelegatedFrameHostDesiredSizeInDIP().height()) {
+  if (current_frame_size_in_dip_.height() < size_in_dip.height()) {
     bottom_gutter_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
     bottom_gutter_->SetColor(GetGutterColor());
     int width = current_frame_size_in_dip_.width();
-    int height = client_->DelegatedFrameHostDesiredSizeInDIP().height() -
-                 current_frame_size_in_dip_.height();
+    int height = size_in_dip.height() - current_frame_size_in_dip_.height();
     bottom_gutter_->SetBounds(
         gfx::Rect(0, current_frame_size_in_dip_.height(), width, height));
     client_->DelegatedFrameHostGetLayer()->Add(bottom_gutter_.get());
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
index ad3a7446..acfab25 100644
--- a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
+++ b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -7,7 +7,9 @@
 #include <memory>
 #include <utility>
 
+#include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "components/viz/common/switches.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "components/viz/service/surfaces/surface_manager.h"
@@ -78,12 +80,22 @@
 
 void OffscreenCanvasSurfaceImpl::Require(const viz::SurfaceId& surface_id,
                                          const viz::SurfaceSequence& sequence) {
+  // TODO(kylechar): This is a hacky workaround for https://crbug.com/796700
+  // to unblock video with surfaces work. Remove before M65 branch.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableViz))
+    return;
+
   auto* surface_manager = GetFrameSinkManager()->surface_manager();
   if (!surface_manager->using_surface_references())
     surface_manager->RequireSequence(surface_id, sequence);
 }
 
 void OffscreenCanvasSurfaceImpl::Satisfy(const viz::SurfaceSequence& sequence) {
+  // TODO(kylechar): This is a hacky workaround for https://crbug.com/796700
+  // to unblock video with surfaces work. Remove before M65 branch.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableViz))
+    return;
+
   auto* surface_manager = GetFrameSinkManager()->surface_manager();
   if (!surface_manager->using_surface_references())
     surface_manager->SatisfySequence(sequence);
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc
index 6bc3f0f1..0c0a0211 100644
--- a/content/browser/renderer_host/overscroll_controller.cc
+++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -45,8 +45,6 @@
 bool OverscrollController::ShouldProcessEvent(
     const blink::WebInputEvent& event) {
   switch (event.GetType()) {
-    case blink::WebInputEvent::kMouseWheel:
-      return false;
     case blink::WebInputEvent::kGestureScrollBegin:
     case blink::WebInputEvent::kGestureScrollUpdate:
     case blink::WebInputEvent::kGestureScrollEnd: {
@@ -90,6 +88,11 @@
   if (!ShouldProcessEvent(event))
     return false;
 
+  // TODO(mohsen): Consider filtering mouse-wheel events during overscroll. See
+  // https://crbug.com/772106.
+  if (event.GetType() == blink::WebInputEvent::kMouseWheel)
+    return false;
+
   if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin ||
       event.GetType() == blink::WebInputEvent::kGestureScrollEnd) {
     // Will handle events when processing ACKs to ensure the correct order.
@@ -97,8 +100,8 @@
   }
 
   bool reset_scroll_state = false;
-  if (scroll_state_ != STATE_UNKNOWN ||
-      overscroll_delta_x_ || overscroll_delta_y_) {
+  if (scroll_state_ != ScrollState::NONE || overscroll_delta_x_ ||
+      overscroll_delta_y_) {
     switch (event.GetType()) {
       case blink::WebInputEvent::kGestureFlingStart:
         reset_scroll_state = true;
@@ -140,7 +143,7 @@
 
   // In overscrolling state, consume scroll-update and fling-start events when
   // they do not contribute to overscroll in order to prevent content scroll.
-  return scroll_state_ == STATE_OVERSCROLLING &&
+  return scroll_state_ == ScrollState::OVERSCROLLING &&
          (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
           event.GetType() == blink::WebInputEvent::kGestureFlingStart);
 }
@@ -154,18 +157,25 @@
     // If a scroll event is consumed by the page, i.e. some content on the page
     // has been scrolled, then there is not going to be an overscroll gesture,
     // until the current scroll ends, and a new scroll gesture starts.
-    if (scroll_state_ == STATE_UNKNOWN &&
-        event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) {
-      scroll_state_ = STATE_CONTENT_SCROLLING;
+    // Similarly, if a mouse-wheel event is consumed, probably the page has
+    // implemented its own scroll-like behavior and no overscroll should happen.
+    if (scroll_state_ == ScrollState::NONE &&
+        (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate ||
+         event.GetType() == blink::WebInputEvent::kMouseWheel)) {
+      scroll_state_ = ScrollState::CONTENT_CONSUMING;
     }
     // In overscrolling state, only return if we are in an overscroll mode;
     // otherwise, we would want to ProcessEventForOverscroll to let it start a
     // new overscroll mode.
-    if (scroll_state_ != STATE_OVERSCROLLING ||
+    if (scroll_state_ != ScrollState::OVERSCROLLING ||
         overscroll_mode_ != OVERSCROLL_NONE) {
       return;
     }
   }
+
+  if (event.GetType() == blink::WebInputEvent::kMouseWheel)
+    return;
+
   ProcessEventForOverscroll(event);
 }
 
@@ -358,10 +368,11 @@
 bool OverscrollController::ProcessOverscroll(float delta_x,
                                              float delta_y,
                                              bool is_touchpad) {
-  if (scroll_state_ != STATE_CONTENT_SCROLLING) {
-    overscroll_delta_x_ += delta_x;
-    overscroll_delta_y_ += delta_y;
-  }
+  if (scroll_state_ == ScrollState::CONTENT_CONSUMING)
+    return false;
+
+  overscroll_delta_x_ += delta_x;
+  overscroll_delta_y_ += delta_y;
 
   const float start_threshold = GetOverscrollConfig(
       is_touchpad ? OverscrollConfig::THRESHOLD_START_TOUCHPAD
@@ -477,7 +488,7 @@
   if (overscroll_mode_ == OVERSCROLL_NONE) {
     overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
   } else {
-    scroll_state_ = STATE_OVERSCROLLING;
+    scroll_state_ = ScrollState::OVERSCROLLING;
     locked_mode_ = overscroll_mode_;
   }
   if (delegate_)
@@ -485,7 +496,7 @@
 }
 
 void OverscrollController::ResetScrollState() {
-  scroll_state_ = STATE_UNKNOWN;
+  scroll_state_ = ScrollState::NONE;
   locked_mode_ = OVERSCROLL_NONE;
 }
 
diff --git a/content/browser/renderer_host/overscroll_controller.h b/content/browser/renderer_host/overscroll_controller.h
index 104865bd..64fdf23 100644
--- a/content/browser/renderer_host/overscroll_controller.h
+++ b/content/browser/renderer_host/overscroll_controller.h
@@ -13,8 +13,9 @@
 
 namespace content {
 
-class RenderWidgetHostViewAuraOverscrollTest;
 class OverscrollControllerDelegate;
+class OverscrollControllerTest;
+class RenderWidgetHostViewAuraOverscrollTest;
 
 // Indicates the direction that the scroll is heading in relative to the screen,
 // with the top being NORTH.
@@ -37,11 +38,9 @@
 // overscroll gesture. This controller receives the events that are dispatched
 // to the renderer, and the ACKs of events, and updates the overscroll gesture
 // status accordingly.
+// Exported for testing.
 class CONTENT_EXPORT OverscrollController {
  public:
-  // Exported for testing.
-  // TODO(mcnee): Tests needing CONTENT_EXPORT are BrowserPlugin specific.
-  // Remove after removing BrowserPlugin (crbug.com/533069).
   OverscrollController();
   virtual ~OverscrollController();
 
@@ -53,9 +52,7 @@
 
   // This must be called when the ACK for any event comes in. This updates the
   // overscroll gesture status as appropriate.
-  // Virtual and exported for testing.
-  // TODO(mcnee): Tests needing CONTENT_EXPORT and virtual are BrowserPlugin
-  // specific. Remove after removing BrowserPlugin (crbug.com/533069).
+  // Virtual for testing.
   virtual void ReceivedEventACK(const blink::WebInputEvent& event,
                                 bool processed);
 
@@ -73,14 +70,22 @@
   void Cancel();
 
  private:
+  friend class OverscrollControllerTest;
   friend class RenderWidgetHostViewAuraOverscrollTest;
 
   // Different scrolling states.
-  enum ScrollState {
-    STATE_UNKNOWN,
-    STATE_PENDING,
-    STATE_CONTENT_SCROLLING,
-    STATE_OVERSCROLLING,
+  enum class ScrollState {
+    NONE,
+
+    // Either a mouse-wheel or a gesture-scroll-update event is consumed by the
+    // renderer in which case no overscroll should be initiated until the end of
+    // the user interaction.
+    CONTENT_CONSUMING,
+
+    // Overscroll controller has initiated overscrolling and will consume all
+    // subsequent gesture-scroll-update events, preventing them from being
+    // forwarded to the renderer.
+    OVERSCROLLING,
   };
 
   // Returns true if the event indicates that the in-progress overscroll gesture
@@ -128,12 +133,8 @@
   // Source of the current overscroll gesture.
   OverscrollSource overscroll_source_ = OverscrollSource::NONE;
 
-  // Used to keep track of the scrolling state.
-  // If scrolling starts, and some scroll events are consumed at the beginning
-  // of the scroll (i.e. some content on the web-page was scrolled), then do not
-  // process any of the subsequent scroll events for generating overscroll
-  // gestures.
-  ScrollState scroll_state_ = STATE_UNKNOWN;
+  // Current scrolling state.
+  ScrollState scroll_state_ = ScrollState::NONE;
 
   // The amount of overscroll in progress. These values are invalid when
   // |overscroll_mode_| is set to OVERSCROLL_NONE.
diff --git a/content/browser/renderer_host/overscroll_controller_unittest.cc b/content/browser/renderer_host/overscroll_controller_unittest.cc
new file mode 100644
index 0000000..db2f3d4
--- /dev/null
+++ b/content/browser/renderer_host/overscroll_controller_unittest.cc
@@ -0,0 +1,123 @@
+// 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/overscroll_controller.h"
+
+#include <memory>
+
+#include "base/containers/queue.h"
+#include "content/browser/renderer_host/overscroll_controller_delegate.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/test/test_overscroll_delegate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class OverscrollControllerTest : public ::testing::Test {
+ protected:
+  OverscrollControllerTest() {}
+  ~OverscrollControllerTest() override {}
+
+  void SetUp() override {
+    delegate_ = std::make_unique<TestOverscrollDelegate>(gfx::Size(400, 300));
+    controller_ = std::make_unique<OverscrollController>();
+    controller_->set_delegate(delegate_.get());
+  }
+
+  void TearDown() override {
+    controller_ = nullptr;
+    delegate_ = nullptr;
+  }
+
+  // Creates and sends a mouse-wheel event to the overscroll controller. Returns
+  // |true| if the event is consumed by the overscroll controller.
+  bool SimulateMouseWheel(float dx, float dy) {
+    DCHECK(!current_event_);
+    current_event_ = std::make_unique<blink::WebMouseWheelEvent>(
+        SyntheticWebMouseWheelEventBuilder::Build(0, 0, dx, dy, 0, true));
+    return controller_->WillHandleEvent(*current_event_);
+  }
+
+  // Creates and sends a gesture-scroll-update event to the overscroll
+  // controller. Returns |true| if the event is consumed by the overscroll
+  // controller.
+  bool SimulateGestureScrollUpdate(float dx,
+                                   float dy,
+                                   blink::WebGestureDevice device) {
+    DCHECK(!current_event_);
+    current_event_ = std::make_unique<blink::WebGestureEvent>(
+        SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0, device));
+    return controller_->WillHandleEvent(*current_event_);
+  }
+
+  // Notifies the overscroll controller that the current event is ACKed.
+  void SimulateAck(bool processed) {
+    DCHECK(current_event_);
+    controller_->ReceivedEventACK(*current_event_, processed);
+    current_event_ = nullptr;
+  }
+
+  TestOverscrollDelegate* delegate() const { return delegate_.get(); }
+
+  OverscrollMode controller_mode() const {
+    return controller_->overscroll_mode_;
+  }
+
+  OverscrollSource controller_source() const {
+    return controller_->overscroll_source_;
+  }
+
+ private:
+  std::unique_ptr<TestOverscrollDelegate> delegate_;
+  std::unique_ptr<OverscrollController> controller_;
+
+  // Keeps track of the last event that has been processed by the overscroll
+  // controller which is not yet ACKed. Will be null if no event is processed or
+  // the last event is ACKed.
+  std::unique_ptr<blink::WebInputEvent> current_event_;
+
+  DISALLOW_COPY_AND_ASSIGN(OverscrollControllerTest);
+};
+
+// Tests that if a mouse-wheel is consumed by content before overscroll is
+// initiated, overscroll will not initiate anymore.
+TEST_F(OverscrollControllerTest, MouseWheelConsumedPreventsOverscroll) {
+  // Simulate a mouse-wheel, ACK it as not processed, simulate the corresponding
+  // gesture scroll-update event, and ACK it is not processed. Since it is not
+  // passing the start threshold, no overscroll should happen.
+  EXPECT_FALSE(SimulateMouseWheel(10, 0));
+  SimulateAck(false);
+  EXPECT_FALSE(
+      SimulateGestureScrollUpdate(10, 0, blink::kWebGestureDeviceTouchpad));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a mouse-wheel and ACK it as processed. No gesture scroll-update
+  // needs to be simulated. Still no overscroll.
+  EXPECT_FALSE(SimulateMouseWheel(10, 0));
+  SimulateAck(true);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+
+  // Simulate a mouse-wheel and the corresponding gesture scroll-update both
+  // ACKed as not processed. Although the scroll passes overscroll start
+  // threshold, no overscroll should happen since the previous mouse-wheel was
+  // marked as processed.
+  EXPECT_FALSE(SimulateMouseWheel(100, 0));
+  SimulateAck(false);
+  EXPECT_FALSE(
+      SimulateGestureScrollUpdate(100, 0, blink::kWebGestureDeviceTouchpad));
+  SimulateAck(false);
+  EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
+  EXPECT_EQ(OverscrollSource::NONE, controller_source());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->current_mode());
+  EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index faf91a9..c8038a7 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -177,7 +177,7 @@
 #include "device/gamepad/gamepad_monitor.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gpu_switches.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/ipc/host/gpu_memory_buffer_support.h"
 #include "ipc/ipc.mojom.h"
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 1506a36..9293ecf 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -760,6 +760,8 @@
     resize_params->browser_controls_shrink_blink_size =
         view_->DoBrowserControlsShrinkBlinkSize();
     resize_params->visible_viewport_size = view_->GetVisibleViewportSize();
+    // TODO(ccameron): GetLocalSurfaceId is not synchronized with the device
+    // scale factor of the surface. Fix this.
     viz::LocalSurfaceId local_surface_id = view_->GetLocalSurfaceId();
     if (local_surface_id.is_valid())
       resize_params->local_surface_id = local_surface_id;
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index f8f3250..2b812822 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -170,24 +170,87 @@
 
 RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget(
     RenderWidgetHostViewBase* root_view,
+    const blink::WebMouseEvent& event,
+    gfx::PointF* transformed_point) const {
+  RenderWidgetHostViewBase* target = nullptr;
+  bool needs_transform_point = true;
+  if (root_view->IsMouseLocked()) {
+    target = root_view->GetRenderWidgetHostImpl()
+                 ->delegate()
+                 ->GetMouseLockWidget()
+                 ->GetView();
+  }
+
+  constexpr int mouse_button_modifiers =
+      blink::WebInputEvent::kLeftButtonDown |
+      blink::WebInputEvent::kMiddleButtonDown |
+      blink::WebInputEvent::kRightButtonDown |
+      blink::WebInputEvent::kBackButtonDown |
+      blink::WebInputEvent::kForwardButtonDown;
+  if (!target && mouse_capture_target_.target &&
+      event.GetType() != blink::WebInputEvent::kMouseDown &&
+      (event.GetType() == blink::WebInputEvent::kMouseUp ||
+       event.GetModifiers() & mouse_button_modifiers)) {
+    target = mouse_capture_target_.target;
+  }
+
+  if (!target) {
+    target = FindViewAtLocation(root_view, event.PositionInWidget(),
+                                event.PositionInScreen(),
+                                viz::EventSource::MOUSE, transformed_point);
+    // |transformed_point| is already transformed.
+    needs_transform_point = false;
+  }
+
+  if (target && target->IsRenderWidgetHostViewGuest()) {
+    RenderWidgetHostViewBase* owner_view =
+        static_cast<RenderWidgetHostViewGuest*>(target)
+            ->GetOwnerRenderWidgetHostView();
+    // In case there is nested RenderWidgetHostViewGuests (i.e., PDF inside
+    // <webview>), we will need the owner view of the top-most guest for input
+    // routing.
+    while (owner_view->IsRenderWidgetHostViewGuest()) {
+      owner_view = static_cast<RenderWidgetHostViewGuest*>(owner_view)
+                       ->GetOwnerRenderWidgetHostView();
+    }
+
+    if (owner_view != root_view) {
+      needs_transform_point = true;
+    } else {
+      needs_transform_point = false;
+      *transformed_point = event.PositionInWidget();
+    }
+    target = owner_view;
+  }
+
+  if (needs_transform_point) {
+    if (!root_view->TransformPointToCoordSpaceForView(
+            event.PositionInWidget(), target, transformed_point))
+      return nullptr;
+  }
+  return target;
+}
+
+RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindViewAtLocation(
+    RenderWidgetHostViewBase* root_view,
     const gfx::Point& point,
     const gfx::Point& point_in_screen,
     viz::EventSource source,
-    gfx::Point* transformed_point) {
+    gfx::Point* transformed_point) const {
   gfx::PointF temp_point(*transformed_point);
   RenderWidgetHostViewBase* view =
-      FindEventTarget(root_view, gfx::PointF(point),
-                      gfx::PointF(point_in_screen), source, &temp_point);
+      FindViewAtLocation(root_view, gfx::PointF(point),
+                         gfx::PointF(point_in_screen), source, &temp_point);
   *transformed_point = gfx::ToFlooredPoint(temp_point);
   return view;
 }
 
-RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget(
+RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindViewAtLocation(
     RenderWidgetHostViewBase* root_view,
     const gfx::PointF& point,
     const gfx::PointF& point_in_screen,
     viz::EventSource source,
-    gfx::PointF* transformed_point) {
+    gfx::PointF* transformed_point) const {
   viz::FrameSinkId frame_sink_id;
 
   if (enable_viz_) {
@@ -236,96 +299,28 @@
 
   // TODO(kenrb): There should be a better way to handle hit tests to surfaces
   // that are no longer valid for hit testing. See https://crbug.com/790044.
-  const FrameSinkIdOwnerMap::iterator iter = owner_map_.find(frame_sink_id);
+  auto iter = owner_map_.find(frame_sink_id);
   // If the point hit a Surface whose namspace is no longer in the map, then
   // it likely means the RenderWidgetHostView has been destroyed but its
   // parent frame has not sent a new compositor frame since that happened.
-  if (iter == owner_map_.end())
-    return root_view;
-
-  return iter->second;
+  return (iter == owner_map_.end()) ? root_view : iter->second;
 }
 
 void RenderWidgetHostInputEventRouter::RouteMouseEvent(
     RenderWidgetHostViewBase* root_view,
     blink::WebMouseEvent* event,
     const ui::LatencyInfo& latency) {
-  RenderWidgetHostViewBase* target = nullptr;
   gfx::PointF transformed_point;
-
-  // When the mouse is locked, directly route the events to the widget that
-  // holds the lock and return.
-  if (root_view->IsMouseLocked()) {
-    target = root_view->GetRenderWidgetHostImpl()
-                 ->delegate()
-                 ->GetMouseLockWidget()
-                 ->GetView();
-    if (!root_view->TransformPointToCoordSpaceForView(
-            event->PositionInWidget(), target, &transformed_point))
-      return;
-
-    event->SetPositionInWidget(transformed_point.x(), transformed_point.y());
-    target->ProcessMouseEvent(*event, latency);
-    return;
-  }
-
-  const int mouse_button_modifiers = blink::WebInputEvent::kLeftButtonDown |
-                                     blink::WebInputEvent::kMiddleButtonDown |
-                                     blink::WebInputEvent::kRightButtonDown |
-                                     blink::WebInputEvent::kBackButtonDown |
-                                     blink::WebInputEvent::kForwardButtonDown;
-  if (mouse_capture_target_.target &&
-      event->GetType() != blink::WebInputEvent::kMouseDown &&
-      (event->GetType() == blink::WebInputEvent::kMouseUp ||
-       event->GetModifiers() & mouse_button_modifiers)) {
-    target = mouse_capture_target_.target;
-    if (!root_view->TransformPointToCoordSpaceForView(
-            event->PositionInWidget(), target, &transformed_point))
-      return;
-    if (event->GetType() == blink::WebInputEvent::kMouseUp)
-      mouse_capture_target_.target = nullptr;
-  } else {
-    target = FindEventTarget(root_view, event->PositionInWidget(),
-                             event->PositionInScreen(), viz::EventSource::MOUSE,
-                             &transformed_point);
-  }
-
-  // RenderWidgetHostViewGuest does not properly handle direct routing of mouse
-  // events, so they have to go by the double-hop forwarding path through
-  // the embedding renderer and then BrowserPluginGuest.
-  if (target && target->IsRenderWidgetHostViewGuest()) {
-    ui::LatencyInfo latency_info;
-    RenderWidgetHostViewBase* owner_view =
-        static_cast<RenderWidgetHostViewGuest*>(target)
-            ->GetOwnerRenderWidgetHostView();
-    // In case there is nested RenderWidgetHostViewGuests (i.e., PDF inside
-    // <webview>), we will need the owner view of the top-most guest for input
-    // routing.
-    while (owner_view->IsRenderWidgetHostViewGuest()) {
-      owner_view = static_cast<RenderWidgetHostViewGuest*>(owner_view)
-                       ->GetOwnerRenderWidgetHostView();
-    }
-
-    if (owner_view != root_view) {
-      // This happens when the view is embedded inside a cross-process frame
-      // (i.e., owner view is a RenderWidgetHostViewChildFrame).
-      gfx::PointF owner_point;
-      if (!root_view->TransformPointToCoordSpaceForView(
-              event->PositionInWidget(), owner_view, &owner_point)) {
-        return;
-      }
-      event->SetPositionInWidget(owner_point.x(), owner_point.y());
-    }
-    owner_view->ProcessMouseEvent(*event, latency_info);
-    return;
-  }
-
-  if (event->GetType() == blink::WebInputEvent::kMouseDown)
-    mouse_capture_target_.target = target;
-
+  RenderWidgetHostViewBase* const target =
+      FindEventTarget(root_view, *event, &transformed_point);
   if (!target)
     return;
 
+  if (event->GetType() == blink::WebInputEvent::kMouseUp)
+    mouse_capture_target_.target = nullptr;
+  else if (event->GetType() == blink::WebInputEvent::kMouseDown)
+    mouse_capture_target_.target = target;
+
   // SendMouseEnterOrLeaveEvents is called with the original event
   // coordinates, which are transformed independently for each view that will
   // receive an event. Also, since the view under the mouse has changed,
@@ -362,7 +357,7 @@
     }
   } else if (root_view->wheel_scroll_latching_enabled()) {
     if (event->phase == blink::WebMouseWheelEvent::kPhaseBegan) {
-      wheel_target_.target = FindEventTarget(
+      wheel_target_.target = FindViewAtLocation(
           root_view, event->PositionInWidget(), event->PositionInScreen(),
           viz::EventSource::MOUSE, &transformed_point);
       wheel_target_.delta =
@@ -391,9 +386,9 @@
 
   } else {  // !root_view->IsMouseLocked() &&
     // !root_view->wheel_scroll_latching_enabled()
-    target = FindEventTarget(root_view, event->PositionInWidget(),
-                             event->PositionInScreen(), viz::EventSource::MOUSE,
-                             &transformed_point);
+    target = FindViewAtLocation(root_view, event->PositionInWidget(),
+                                event->PositionInScreen(),
+                                viz::EventSource::MOUSE, &transformed_point);
   }
 
   if (!target) {
@@ -500,9 +495,9 @@
         gfx::Point original_point_in_screen(
             event->touches[0].PositionInScreen().x,
             event->touches[0].PositionInScreen().y);
-        touch_target_.target =
-            FindEventTarget(root_view, original_point, original_point_in_screen,
-                            viz::EventSource::TOUCH, &transformed_point);
+        touch_target_.target = FindViewAtLocation(
+            root_view, original_point, original_point_in_screen,
+            viz::EventSource::TOUCH, &transformed_point);
 
         // TODO(wjmaclean): Instead of just computing a delta, we should extract
         // the complete transform. We assume it doesn't change for the duration
@@ -939,8 +934,8 @@
   // TODO(kenrb): Pass screen coordinates through this method from all the
   // callers. This will be broken with --enable-viz until then.
   return RenderWidgetHostImpl::From(
-      FindEventTarget(root_view, point, gfx::PointF(), viz::EventSource::MOUSE,
-                      transformed_point)
+      FindViewAtLocation(root_view, point, gfx::PointF(),
+                         viz::EventSource::MOUSE, transformed_point)
           ->GetRenderWidgetHost());
 }
 
@@ -1022,8 +1017,8 @@
     gfx::Point original_point(event->x, event->y);
     gfx::Point original_point_in_screen(event->global_x, event->global_y);
     touchscreen_gesture_target_.target =
-        FindEventTarget(root_view, original_point, original_point_in_screen,
-                        viz::EventSource::TOUCH, &transformed_point);
+        FindViewAtLocation(root_view, original_point, original_point_in_screen,
+                           viz::EventSource::TOUCH, &transformed_point);
     touchscreen_gesture_target_.delta = transformed_point - original_point;
   } else if (is_gesture_start) {
     touchscreen_gesture_target_ = gesture_target_it->second;
@@ -1063,8 +1058,8 @@
     gfx::Point original_point(event->x, event->y);
     gfx::Point original_point_in_screen(event->global_x, event->global_y);
     touchpad_gesture_target_.target =
-        FindEventTarget(root_view, original_point, original_point_in_screen,
-                        viz::EventSource::TOUCH, &transformed_point);
+        FindViewAtLocation(root_view, original_point, original_point_in_screen,
+                           viz::EventSource::TOUCH, &transformed_point);
     // TODO(mohsen): Instead of just computing a delta, we should extract the
     // complete transform. We assume it doesn't change for the duration of the
     // touchpad gesture sequence, though this could be wrong; a better approach
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 a5dc62b..7b8a2c8 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
@@ -131,18 +131,24 @@
   using TargetMap = std::map<uint32_t, TargetData>;
 
   void ClearAllObserverRegistrations();
+  RenderWidgetHostViewBase* FindEventTarget(
+      RenderWidgetHostViewBase* root_view,
+      const blink::WebMouseEvent& event,
+      gfx::PointF* transformed_point) const;
 
-  RenderWidgetHostViewBase* FindEventTarget(RenderWidgetHostViewBase* root_view,
-                                            const gfx::Point& point,
-                                            const gfx::Point& point_in_screen,
-                                            viz::EventSource source,
-                                            gfx::Point* transformed_point);
+  RenderWidgetHostViewBase* FindViewAtLocation(
+      RenderWidgetHostViewBase* root_view,
+      const gfx::Point& point,
+      const gfx::Point& point_in_screen,
+      viz::EventSource source,
+      gfx::Point* transformed_point) const;
 
-  RenderWidgetHostViewBase* FindEventTarget(RenderWidgetHostViewBase* root_view,
-                                            const gfx::PointF& point,
-                                            const gfx::PointF& point_in_screen,
-                                            viz::EventSource source,
-                                            gfx::PointF* transformed_point);
+  RenderWidgetHostViewBase* FindViewAtLocation(
+      RenderWidgetHostViewBase* root_view,
+      const gfx::PointF& point,
+      const gfx::PointF& point_in_screen,
+      viz::EventSource source,
+      gfx::PointF* transformed_point) const;
 
   void RouteTouchscreenGestureEvent(RenderWidgetHostViewBase* root_view,
                                     blink::WebGestureEvent* event,
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 2f28c3e..382cae4 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -201,7 +201,7 @@
 
   // This is for an offscreen context, so we don't need the default framebuffer
   // to have alpha, stencil, depth, antialiasing.
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = -1;
   attributes.stencil_size = 0;
   attributes.depth_size = 0;
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 2ec45c37..731e35a8 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
@@ -71,6 +71,7 @@
 #include "content/test/fake_renderer_compositor_frame_sink.h"
 #include "content/test/mock_render_widget_host_delegate.h"
 #include "content/test/mock_widget_impl.h"
+#include "content/test/test_overscroll_delegate.h"
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_web_contents.h"
 #include "ipc/ipc_message.h"
@@ -174,79 +175,6 @@
       ->damage_rect;
 }
 
-class TestOverscrollDelegate : public OverscrollControllerDelegate {
- public:
-  explicit TestOverscrollDelegate(RenderWidgetHostView* view)
-      : view_(view),
-        current_mode_(OVERSCROLL_NONE),
-        completed_mode_(OVERSCROLL_NONE),
-        delta_x_(0.f),
-        delta_y_(0.f) {}
-
-  ~TestOverscrollDelegate() override {}
-
-  void set_delta_cap(float delta_cap) { delta_cap_ = delta_cap; }
-
-  OverscrollMode current_mode() const { return current_mode_; }
-  OverscrollMode completed_mode() const { return completed_mode_; }
-  const std::vector<OverscrollMode>& historical_modes() const {
-    return historical_modes_;
-  }
-  float delta_x() const { return delta_x_; }
-  float delta_y() const { return delta_y_; }
-
-  void Reset() {
-    current_mode_ = OVERSCROLL_NONE;
-    completed_mode_ = OVERSCROLL_NONE;
-    historical_modes_.clear();
-    delta_x_ = delta_y_ = 0.f;
-  }
-
- private:
-  // Overridden from OverscrollControllerDelegate:
-  gfx::Size GetDisplaySize() const override {
-    return display::Screen::GetScreen()
-        ->GetDisplayNearestView(view_->GetNativeView())
-        .size();
-  }
-
-  bool OnOverscrollUpdate(float delta_x, float delta_y) override {
-    delta_x_ = delta_x;
-    delta_y_ = delta_y;
-    return true;
-  }
-
-  void OnOverscrollComplete(OverscrollMode overscroll_mode) override {
-    EXPECT_EQ(current_mode_, overscroll_mode);
-    completed_mode_ = overscroll_mode;
-    current_mode_ = OVERSCROLL_NONE;
-  }
-
-  void OnOverscrollModeChange(OverscrollMode old_mode,
-                              OverscrollMode new_mode,
-                              OverscrollSource source) override {
-    EXPECT_EQ(current_mode_, old_mode);
-    current_mode_ = new_mode;
-    historical_modes_.push_back(new_mode);
-    delta_x_ = delta_y_ = 0.f;
-  }
-
-  base::Optional<float> GetMaxOverscrollDelta() const override {
-    return delta_cap_;
-  }
-
-  RenderWidgetHostView* view_;
-  base::Optional<float> delta_cap_;
-  OverscrollMode current_mode_;
-  OverscrollMode completed_mode_;
-  std::vector<OverscrollMode> historical_modes_;
-
-  float delta_x_;
-  float delta_y_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestOverscrollDelegate);
-};
-
 // Simple observer that keeps track of changes to a window for tests.
 class TestWindowObserver : public aura::WindowObserver {
  public:
@@ -881,6 +809,8 @@
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestAuraTest);
 };
 
+// TODO(mohsen): Consider moving these tests to OverscrollControllerTest if
+// appropriate.
 class RenderWidgetHostViewAuraOverscrollTest
     : public RenderWidgetHostViewAuraTest {
  public:
@@ -947,7 +877,10 @@
     RenderWidgetHostViewAuraTest::SetUp();
 
     view_->SetOverscrollControllerEnabled(true);
-    overscroll_delegate_.reset(new TestOverscrollDelegate(view_));
+    gfx::Size display_size = display::Screen::GetScreen()
+                                 ->GetDisplayNearestView(view_->GetNativeView())
+                                 .size();
+    overscroll_delegate_.reset(new TestOverscrollDelegate(display_size));
     view_->overscroll_controller()->set_delegate(overscroll_delegate_.get());
 
     view_->InitAsChild(nullptr);
@@ -1084,16 +1017,17 @@
         velocityX, velocityY, sourceDevice));
   }
 
-  bool ScrollStateIsContentScrolling() const {
-    return scroll_state() == OverscrollController::STATE_CONTENT_SCROLLING;
+  bool ScrollStateIsContentConsuming() const {
+    return scroll_state() ==
+           OverscrollController::ScrollState::CONTENT_CONSUMING;
   }
 
   bool ScrollStateIsOverscrolling() const {
-    return scroll_state() == OverscrollController::STATE_OVERSCROLLING;
+    return scroll_state() == OverscrollController::ScrollState::OVERSCROLLING;
   }
 
   bool ScrollStateIsUnknown() const {
-    return scroll_state() == OverscrollController::STATE_UNKNOWN;
+    return scroll_state() == OverscrollController::ScrollState::NONE;
   }
 
   OverscrollController::ScrollState scroll_state() const {
@@ -1260,7 +1194,7 @@
   void WheelScrollOverscrollToggle();
   void OverscrollMouseMoveCompletion();
   void WheelScrollEventOverscrolls();
-  void WheelScrollConsumedDoNotHorizOverscroll();
+  void WheelScrollConsumedDoNotOverscroll();
   void ScrollEventsOverscrollWithFling();
   void OverscrollDirectionChangeMouseWheel();
   void OverscrollStateResetsAfterScroll();
@@ -3991,6 +3925,7 @@
   EXPECT_EQ(kY, pointer_state().GetY(0));
 }
 
+// Tests that non-precise mouse-wheel events do not initiate overscroll.
 void RenderWidgetHostViewAuraOverscrollTest::WheelNotPreciseScrollEvent() {
   SetUpOverscrollEnvironment();
 
@@ -4052,6 +3987,8 @@
   WheelNotPreciseScrollEvent();
 }
 
+// Tests that precise mouse-wheel events initiate overscroll and a mouse move
+// will cancel it.
 void RenderWidgetHostViewAuraOverscrollTest::WheelScrollEventOverscrolls() {
   SetUpOverscrollEnvironment();
 
@@ -4134,9 +4071,9 @@
 }
 
 // Tests that if some scroll events are consumed towards the start, then
-// subsequent scrolls do not horizontal overscroll.
+// subsequent scrolls do not overscroll.
 void RenderWidgetHostViewAuraOverscrollTest::
-    WheelScrollConsumedDoNotHorizOverscroll() {
+    WheelScrollConsumedDoNotOverscroll() {
   SetUpOverscrollEnvironment();
 
   // Simulate wheel events. Do not cross start threshold.
@@ -4215,16 +4152,16 @@
   EXPECT_EQ(OverscrollSource::NONE, overscroll_source());
 }
 TEST_F(RenderWidgetHostViewAuraOverscrollTest,
-       WheelScrollConsumedDoNotHorizOverscroll) {
-  WheelScrollConsumedDoNotHorizOverscroll();
+       WheelScrollConsumedDoNotOverscroll) {
+  WheelScrollConsumedDoNotOverscroll();
 }
 TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest,
-       WheelScrollConsumedDoNotHorizOverscroll) {
-  WheelScrollConsumedDoNotHorizOverscroll();
+       WheelScrollConsumedDoNotOverscroll) {
+  WheelScrollConsumedDoNotOverscroll();
 }
 TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest,
-       WheelScrollConsumedDoNotHorizOverscroll) {
-  WheelScrollConsumedDoNotHorizOverscroll();
+       WheelScrollConsumedDoNotOverscroll) {
+  WheelScrollConsumedDoNotOverscroll();
 }
 
 // Tests that wheel-scrolling correctly turns overscroll on and off.
@@ -4363,6 +4300,7 @@
   WheelScrollOverscrollToggle();
 }
 
+// Tests that a small fling after overscroll is initiated aborts the overscroll.
 void RenderWidgetHostViewAuraOverscrollTest::ScrollEventsOverscrollWithFling() {
   SetUpOverscrollEnvironment();
 
@@ -4558,14 +4496,14 @@
 }
 
 // Tests that a fling in the opposite direction of the overscroll cancels the
-// overscroll nav instead of completing it.
+// overscroll instead of completing it.
 TEST_F(RenderWidgetHostViewAuraOverscrollTest, ReverseFlingCancelsOverscroll) {
   SetUpOverscrollEnvironment();
 
   {
     // Start and end a gesture in the same direction without processing the
     // gesture events in the renderer. This should initiate and complete an
-    // overscroll navigation.
+    // overscroll.
     SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
                          blink::kWebGestureDeviceTouchscreen);
     SimulateGestureScrollUpdateEvent(300, -5, 0);
@@ -4590,8 +4528,8 @@
   {
     // Start over, except instead of ending the gesture with ScrollEnd, end it
     // with a FlingStart, with velocity in the reverse direction. This should
-    // initiate an overscroll navigation, but it should be cancelled because of
-    // the fling in the opposite direction.
+    // initiate an overscroll, but it should be cancelled because of the fling
+    // in the opposite direction.
     overscroll_delegate()->Reset();
     SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
                          blink::kWebGestureDeviceTouchscreen);
@@ -4631,7 +4569,7 @@
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
 
   // Send another gesture event and ACK as not being processed. This should
-  // initiate the navigation gesture.
+  // initiate the overscroll.
   SimulateGestureScrollUpdateEvent(55, -5, 0);
   events = GetAndResetDispatchedMessages();
   EXPECT_EQ("TouchScrollStarted GestureScrollUpdate", GetMessageNames(events));
@@ -4736,10 +4674,8 @@
 }
 
 // Tests that if the page is scrolled because of a scroll-gesture, then that
-// particular scroll sequence never generates overscroll if the scroll direction
-// is horizontal.
-TEST_F(RenderWidgetHostViewAuraOverscrollTest,
-       GestureScrollConsumedHorizontal) {
+// particular scroll sequence never generates overscroll.
+TEST_F(RenderWidgetHostViewAuraOverscrollTest, GestureScrollConsumed) {
   SetUpOverscrollEnvironment();
 
   SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
@@ -5118,6 +5054,10 @@
   EXPECT_EQ("GestureScrollEnd", GetMessageNames(events));
 }
 
+// Tests that after touchscreen overscroll is initiated, scrolling in the
+// opposite direction ends the overscroll in the original direction without
+// initiating overscroll in the opposite direction. The scroll-update events
+// should still be consumed to prevent content scroll.
 TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDirectionChange) {
   SetUpOverscrollEnvironmentWithDebounce(100);
 
@@ -5141,7 +5081,7 @@
   EXPECT_EQ(0U, events.size());
 
   // Send another update event, but in the reverse direction. Although the
-  // overscroll controller is not triggering gesture-nav, it will consume the
+  // overscroll controller is not triggering overscroll, it will consume the
   // ScrollUpdate event to prevent content scroll.
   SimulateGestureScrollUpdateEvent(-260, 0, 0);
   events = GetAndResetDispatchedMessages();
@@ -5226,6 +5166,10 @@
   EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->historical_modes().at(1));
 }
 
+// Tests that after touchpad overscroll is initiated, scrolling in the opposite
+// direction ends the overscroll in the original direction without initiating
+// overscroll in the opposite direction. The scroll-update events should still
+// be consumed to prevent content scroll.
 void RenderWidgetHostViewAuraOverscrollTest::
     OverscrollDirectionChangeMouseWheel() {
   SetUpOverscrollEnvironment();
@@ -5250,7 +5194,7 @@
   EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
 
   // Send another wheel event, but in the reverse direction. Although the
-  // overscroll controller is not triggering gesture-nav, it will consume the
+  // overscroll controller is not triggering overscroll, it will consume the
   // ScrollUpdate event to prevent content scroll.
   SimulateWheelEventPossiblyIncludingPhase(-260, 0, 0, true,
                                            WebMouseWheelEvent::kPhaseChanged);
@@ -5297,6 +5241,8 @@
   OverscrollDirectionChangeMouseWheel();
 }
 
+// Tests that mouse-move completes overscoll if it has passed activation
+// threshold and aborts it otherwise.
 void RenderWidgetHostViewAuraOverscrollTest::OverscrollMouseMoveCompletion() {
   SetUpOverscrollEnvironment();
 
@@ -5344,9 +5290,9 @@
   EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source());
   EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
 
-  // Send a mouse-move event. This should cancel the overscroll navigation
-  // (since the amount overscrolled is not above the threshold), and so the
-  // mouse-move should reach the renderer.
+  // Send a mouse-move event. This should cancel the overscroll gesture (since
+  // the amount overscrolled is not above the threshold), and so the mouse-move
+  // should reach the renderer.
   SimulateMouseMove(5, 10, 0);
   events = GetAndResetDispatchedMessages();
   EXPECT_EQ("MouseMove", GetMessageNames(events));
@@ -5437,7 +5383,7 @@
   events = ExpectGestureScrollEventsAfterMouseWheelACK(true, 1);
   SendScrollBeginAckIfNeeded(events, INPUT_EVENT_ACK_STATE_CONSUMED);
   SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_CONSUMED);
-  EXPECT_TRUE(ScrollStateIsContentScrolling());
+  EXPECT_TRUE(ScrollStateIsContentConsuming());
 
   if (wheel_scrolling_mode_ != kAsyncWheelEvents) {
     ExpectGestureScrollEndForWheelScrolling(false);
@@ -5447,7 +5393,7 @@
     events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0);
   }
   SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_CONSUMED);
-  EXPECT_TRUE(ScrollStateIsContentScrolling());
+  EXPECT_TRUE(ScrollStateIsContentConsuming());
 
   // Touchpad scroll can end with a zero-velocity fling which is not dispatched.
   SimulateGestureFlingStartEvent(0.f, 0.f, blink::kWebGestureDeviceTouchpad);
@@ -5537,6 +5483,8 @@
   OverscrollStateResetsAfterScroll();
 }
 
+// Tests that overscroll is reset when window loses focus. It should not affect
+// subsequent overscrolls.
 TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollResetsOnBlur) {
   SetUpOverscrollEnvironment();
 
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 56d4f9d..dd15337 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -311,6 +311,7 @@
   void Destroy() override;
   void SetTooltipText(const base::string16& tooltip_text) override;
   void UpdateScreenInfo(gfx::NativeView view) override;
+  gfx::Size GetRequestedRendererSize() const override;
   bool IsSurfaceAvailableForCopy() const override;
   void CopyFromSurface(const gfx::Rect& src_rect,
                        const gfx::Size& output_size,
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 0574d766..f231744 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1087,14 +1087,15 @@
 }
 
 void RenderWidgetHostViewMac::UpdateScreenInfo(gfx::NativeView view) {
-  RenderWidgetHostViewBase::UpdateScreenInfo(view);
-
-  if (!render_widget_host_ || !render_widget_host_->auto_resize_enabled())
-    return;
-
-  render_widget_host_->DidAllocateLocalSurfaceIdForAutoResize(
-      render_widget_host_->last_auto_resize_request_number());
+  // Propagate the new size to the BrowserCompositor first, so it can update the
+  // size that will be returned by GetRequestedRendererSize before the RWHImpl
+  // requests it (which will happen in RWHVBase::UpdateScreenInfo).
   browser_compositor_->WasResized();
+  RenderWidgetHostViewBase::UpdateScreenInfo(view);
+}
+
+gfx::Size RenderWidgetHostViewMac::GetRequestedRendererSize() const {
+  return browser_compositor_->DelegatedFrameHostDesiredSizeInDIP();
 }
 
 bool RenderWidgetHostViewMac::SupportsSpeech() const {
@@ -1759,19 +1760,6 @@
   display::Screen* screen = display::Screen::GetScreen();
   if (display.id() != screen->GetDisplayNearestView(cocoa_view_).id())
     return;
-
-  if (changed_metrics & DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR) {
-    RenderWidgetHostImpl* host =
-        RenderWidgetHostImpl::From(GetRenderWidgetHost());
-    if (host) {
-      if (host->auto_resize_enabled()) {
-        host->DidAllocateLocalSurfaceIdForAutoResize(
-            host->last_auto_resize_request_number());
-      }
-      host->WasResized();
-    }
-  }
-
   UpdateBackingStoreProperties();
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index f20025a..75205c44 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -46,12 +46,12 @@
 #include "testing/gtest_mac.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
 #import "third_party/ocmock/ocmock_extensions.h"
+#import "ui/base/test/cocoa_helper.h"
 #import "ui/base/test/scoped_fake_nswindow_focus.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/blink/blink_features.h"
 #include "ui/events/blink/web_input_event_traits.h"
 #include "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 #include "ui/latency/latency_info.h"
 
 // Helper class with methods used to mock -[NSEvent phase], used by
diff --git a/content/browser/speech/speech_recognition_browsertest.cc b/content/browser/speech/speech_recognition_browsertest.cc
index 3f6bfbc..fad9fdc2 100644
--- a/content/browser/speech/speech_recognition_browsertest.cc
+++ b/content/browser/speech/speech_recognition_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
 #include "content/browser/speech/speech_recognition_engine.h"
 #include "content/browser/speech/speech_recognition_manager_impl.h"
 #include "content/browser/speech/speech_recognizer_impl.h"
@@ -215,7 +216,13 @@
   EXPECT_EQ("success", GetPageFragment());
 }
 
-IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, OneShotRecognition) {
+// Flaky on mac, see https://crbug.com/794645.
+#if defined(OS_MACOSX)
+#define MAYBE_OneShotRecognition DISABLED_OneShotRecognition
+#else
+#define MAYBE_OneShotRecognition OneShotRecognition
+#endif
+IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, MAYBE_OneShotRecognition) {
   NavigateToURLBlockUntilNavigationsComplete(
       shell(), GetTestUrlFromFragment("oneshot"), 2);
 
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 2253cb71..00bef7e 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -649,6 +649,17 @@
   return url_loader_factory_for_browser_process_.get();
 }
 
+network::mojom::CookieManager*
+StoragePartitionImpl::GetCookieManagerForBrowserProcess() {
+  // Create the CookieManager as needed.
+  if (!cookie_manager_for_browser_process_ ||
+      cookie_manager_for_browser_process_.encountered_error()) {
+    GetNetworkContext()->GetCookieManager(
+        mojo::MakeRequest(&cookie_manager_for_browser_process_));
+  }
+  return cookie_manager_for_browser_process_.get();
+}
+
 storage::QuotaManager* StoragePartitionImpl::GetQuotaManager() {
   return quota_manager_.get();
 }
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index 57aaf22..449eeab 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -36,6 +36,7 @@
 #include "content/public/common/network_service.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "net/cookies/cookie_store.h"
+#include "services/network/public/interfaces/cookie_manager.mojom.h"
 #include "storage/browser/quota/special_storage_policy.h"
 
 #if !defined(OS_ANDROID)
@@ -78,6 +79,7 @@
   net::URLRequestContextGetter* GetMediaURLRequestContext() override;
   mojom::NetworkContext* GetNetworkContext() override;
   mojom::URLLoaderFactory* GetURLLoaderFactoryForBrowserProcess() override;
+  network::mojom::CookieManager* GetCookieManagerForBrowserProcess() override;
   storage::QuotaManager* GetQuotaManager() override;
   ChromeAppCacheService* GetAppCacheService() override;
   storage::FileSystemContext* GetFileSystemContext() override;
@@ -298,10 +300,12 @@
   // by |network_context_owner_|.
   mojom::NetworkContextPtr network_context_;
 
-  // URLLoaderFactory for use in the browser process only. See the method
-  // comment for StoragePartition::GetURLLoaderFactoryForBrowserProcess() for
+  // URLLoaderFactory/CookieManager for use in the browser process only.
+  // See the method comment for
+  // StoragePartition::GetURLLoaderFactoryForBrowserProcess() for
   // more details
   mojom::URLLoaderFactoryPtr url_loader_factory_for_browser_process_;
+  ::network::mojom::CookieManagerPtr cookie_manager_for_browser_process_;
 
   // When the network service is disabled, a NetworkContext is created on the IO
   // thread that wraps access to the URLRequestContext.
diff --git a/content/browser/web_contents/web_contents_view_mac_unittest.mm b/content/browser/web_contents/web_contents_view_mac_unittest.mm
index 8c009eaf..0b1dd34 100644
--- a/content/browser/web_contents/web_contents_view_mac_unittest.mm
+++ b/content/browser/web_contents/web_contents_view_mac_unittest.mm
@@ -7,7 +7,7 @@
 #include "base/mac/scoped_nsobject.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace {
 
diff --git a/content/browser/web_contents/web_drag_dest_mac_unittest.mm b/content/browser/web_contents/web_drag_dest_mac_unittest.mm
index b6a6946a..a18d7e7 100644
--- a/content/browser/web_contents/web_drag_dest_mac_unittest.mm
+++ b/content/browser/web_contents/web_drag_dest_mac_unittest.mm
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#import "content/browser/web_contents/web_drag_dest_mac.h"
+
 #include "base/mac/mac_util.h"
 #include "base/mac/scoped_nsautorelease_pool.h"
 #import "base/mac/scoped_nsobject.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#import "content/browser/web_contents/web_drag_dest_mac.h"
 #include "content/public/common/drop_data.h"
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_web_contents.h"
@@ -16,7 +17,7 @@
 #import "third_party/mozilla/NSPasteboard+Utils.h"
 #import "ui/base/clipboard/clipboard_util_mac.h"
 #import "ui/base/dragdrop/cocoa_dnd_util.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 using content::DropData;
 using content::RenderViewHostImplTestHarness;
diff --git a/content/browser/webauth/attestation_object.cc b/content/browser/webauth/attestation_object.cc
index db38b4f..4c0001c 100644
--- a/content/browser/webauth/attestation_object.cc
+++ b/content/browser/webauth/attestation_object.cc
@@ -6,8 +6,9 @@
 
 #include <utility>
 
+#include "components/cbor/cbor_values.h"
+#include "components/cbor/cbor_writer.h"
 #include "content/browser/webauth/attestation_statement.h"
-#include "content/browser/webauth/cbor/cbor_writer.h"
 
 namespace content {
 
@@ -24,14 +25,14 @@
       attestation_statement_(std::move(statement)) {}
 
 std::vector<uint8_t> AttestationObject::SerializeToCBOREncodedBytes() {
-  CBORValue::MapValue map;
-  map[CBORValue(kFormatKey)] =
-      CBORValue(attestation_statement_->format_name().c_str());
-  map[CBORValue(kAuthDataKey)] =
-      CBORValue(authenticator_data_->SerializeToByteArray());
-  map[CBORValue(kAttestationKey)] =
-      CBORValue(attestation_statement_->GetAsCBORMap());
-  auto cbor = CBORWriter::Write(CBORValue(map));
+  cbor::CBORValue::MapValue map;
+  map[cbor::CBORValue(kFormatKey)] =
+      cbor::CBORValue(attestation_statement_->format_name().c_str());
+  map[cbor::CBORValue(kAuthDataKey)] =
+      cbor::CBORValue(authenticator_data_->SerializeToByteArray());
+  map[cbor::CBORValue(kAttestationKey)] =
+      cbor::CBORValue(attestation_statement_->GetAsCBORMap());
+  auto cbor = cbor::CBORWriter::Write(cbor::CBORValue(map));
   if (cbor.has_value()) {
     return cbor.value();
   }
diff --git a/content/browser/webauth/attestation_statement.h b/content/browser/webauth/attestation_statement.h
index 6ba3720..01f22108 100644
--- a/content/browser/webauth/attestation_statement.h
+++ b/content/browser/webauth/attestation_statement.h
@@ -6,7 +6,7 @@
 #define CONTENT_BROWSER_WEBAUTH_ATTESTATION_STATEMENT_H_
 
 #include "base/macros.h"
-#include "content/browser/webauth/cbor/cbor_values.h"
+#include "components/cbor/cbor_values.h"
 
 namespace content {
 
@@ -26,7 +26,7 @@
   // https://www.w3.org/TR/2017/WD-webauthn-20170505/#defined-attestation-formats
   // This is not a CBOR-encoded byte array, but the map that will be
   // nested within another CBOR object and encoded then.
-  virtual CBORValue::MapValue GetAsCBORMap() = 0;
+  virtual cbor::CBORValue::MapValue GetAsCBORMap() = 0;
 
   const std::string& format_name() { return format_; }
 
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 0ae10bb..8fb1ff8 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -13,11 +13,11 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
+#include "components/cbor/cbor_writer.h"
 #include "content/browser/webauth/attestation_object.h"
 #include "content/browser/webauth/attested_credential_data.h"
 #include "content/browser/webauth/authenticator_data.h"
 #include "content/browser/webauth/authenticator_utils.h"
-#include "content/browser/webauth/cbor/cbor_writer.h"
 #include "content/browser/webauth/collected_client_data.h"
 #include "content/browser/webauth/ec_public_key.h"
 #include "content/browser/webauth/fido_attestation_statement.h"
@@ -577,8 +577,8 @@
   std::unique_ptr<FidoAttestationStatement> fido_attestation_statement =
       FidoAttestationStatement::CreateFromU2fRegisterResponse(
           GetTestRegisterResponse());
-  auto cbor =
-      CBORWriter::Write(CBORValue(fido_attestation_statement->GetAsCBORMap()));
+  auto cbor = cbor::CBORWriter::Write(
+      cbor::CBORValue(fido_attestation_statement->GetAsCBORMap()));
   ASSERT_TRUE(cbor.has_value());
   EXPECT_EQ(GetU2fAttestationStatementCBOR(), cbor.value());
 }
diff --git a/content/browser/webauth/ec_public_key.cc b/content/browser/webauth/ec_public_key.cc
index 9082198..62a845a 100644
--- a/content/browser/webauth/ec_public_key.cc
+++ b/content/browser/webauth/ec_public_key.cc
@@ -6,8 +6,8 @@
 
 #include <utility>
 
+#include "components/cbor/cbor_writer.h"
 #include "content/browser/webauth/authenticator_utils.h"
-#include "content/browser/webauth/cbor/cbor_writer.h"
 
 namespace content {
 
@@ -40,11 +40,11 @@
 }
 
 std::vector<uint8_t> ECPublicKey::EncodeAsCBOR() {
-  CBORValue::MapValue map;
-  map[CBORValue("alg")] = CBORValue(algorithm_.c_str());
-  map[CBORValue("x")] = CBORValue(x_coordinate_);
-  map[CBORValue("y")] = CBORValue(y_coordinate_);
-  auto cbor = CBORWriter::Write(CBORValue(map));
+  cbor::CBORValue::MapValue map;
+  map[cbor::CBORValue("alg")] = cbor::CBORValue(algorithm_.c_str());
+  map[cbor::CBORValue("x")] = cbor::CBORValue(x_coordinate_);
+  map[cbor::CBORValue("y")] = cbor::CBORValue(y_coordinate_);
+  auto cbor = cbor::CBORWriter::Write(cbor::CBORValue(map));
   DCHECK(cbor.has_value());
   return cbor.value();
 }
diff --git a/content/browser/webauth/fido_attestation_statement.cc b/content/browser/webauth/fido_attestation_statement.cc
index 4de0f6e..21333ad 100644
--- a/content/browser/webauth/fido_attestation_statement.cc
+++ b/content/browser/webauth/fido_attestation_statement.cc
@@ -6,8 +6,9 @@
 
 #include <utility>
 
+#include "base/numerics/safe_conversions.h"
+#include "components/cbor/cbor_writer.h"
 #include "content/browser/webauth/authenticator_utils.h"
-#include "content/browser/webauth/cbor/cbor_writer.h"
 #include "third_party/boringssl/src/include/openssl/bytestring.h"
 
 namespace content {
@@ -55,15 +56,17 @@
       signature_(std::move(signature)),
       x509_certificates_(std::move(x509_certificates)) {}
 
-CBORValue::MapValue FidoAttestationStatement::GetAsCBORMap() {
-  CBORValue::MapValue attstmt_map;
-  attstmt_map[CBORValue(kSignatureKey)] = CBORValue(signature_);
+cbor::CBORValue::MapValue FidoAttestationStatement::GetAsCBORMap() {
+  cbor::CBORValue::MapValue attstmt_map;
+  attstmt_map[cbor::CBORValue(kSignatureKey)] = cbor::CBORValue(signature_);
 
-  std::vector<CBORValue> array;
+  std::vector<cbor::CBORValue> array;
   for (auto cert : x509_certificates_) {
-    array.push_back(CBORValue(cert));
+    array.push_back(cbor::CBORValue(cert));
   }
-  attstmt_map[CBORValue(kX509CertKey)] = CBORValue(array);
+
+  attstmt_map[cbor::CBORValue(kX509CertKey)] = cbor::CBORValue(array);
+
   return attstmt_map;
 }
 
diff --git a/content/browser/webauth/fido_attestation_statement.h b/content/browser/webauth/fido_attestation_statement.h
index bf1b3492..07dc8b6f 100644
--- a/content/browser/webauth/fido_attestation_statement.h
+++ b/content/browser/webauth/fido_attestation_statement.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "components/cbor/cbor_values.h"
 #include "content/browser/webauth/attestation_statement.h"
 #include "content/common/content_export.h"
 
@@ -29,7 +30,7 @@
 
   // Produces a map in the following format:
   // { "x5c": [ x509_certs bytes ], "sig": signature bytes ] }
-  CBORValue::MapValue GetAsCBORMap() override;
+  cbor::CBORValue::MapValue GetAsCBORMap() override;
 
  private:
   const std::vector<uint8_t> signature_;
diff --git a/content/child/assert_matching_enums.cc b/content/child/assert_matching_enums.cc
index 1b2c0cc..75b0cc8 100644
--- a/content/child/assert_matching_enums.cc
+++ b/content/child/assert_matching_enums.cc
@@ -46,23 +46,16 @@
 // WebTextInputMode
 STATIC_ASSERT_ENUM(blink::kWebTextInputModeDefault,
                    ui::TEXT_INPUT_MODE_DEFAULT);
-STATIC_ASSERT_ENUM(blink::kWebTextInputModeVerbatim,
-                   ui::TEXT_INPUT_MODE_VERBATIM);
-STATIC_ASSERT_ENUM(blink::kWebTextInputModeLatin, ui::TEXT_INPUT_MODE_LATIN);
-STATIC_ASSERT_ENUM(blink::kWebTextInputModeLatinName,
-                   ui::TEXT_INPUT_MODE_LATIN_NAME);
-STATIC_ASSERT_ENUM(blink::kWebTextInputModeLatinProse,
-                   ui::TEXT_INPUT_MODE_LATIN_PROSE);
-STATIC_ASSERT_ENUM(blink::kWebTextInputModeFullWidthLatin,
-                   ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN);
-STATIC_ASSERT_ENUM(blink::kWebTextInputModeKana, ui::TEXT_INPUT_MODE_KANA);
-STATIC_ASSERT_ENUM(blink::kWebTextInputModeKanaName,
-                   ui::TEXT_INPUT_MODE_KANA_NAME);
-STATIC_ASSERT_ENUM(blink::kWebTextInputModeKataKana,
-                   ui::TEXT_INPUT_MODE_KATAKANA);
+STATIC_ASSERT_ENUM(blink::kWebTextInputModeNone, ui::TEXT_INPUT_MODE_NONE);
+STATIC_ASSERT_ENUM(blink::kWebTextInputModeText, ui::TEXT_INPUT_MODE_TEXT);
 STATIC_ASSERT_ENUM(blink::kWebTextInputModeTel, ui::TEXT_INPUT_MODE_TEL);
-STATIC_ASSERT_ENUM(blink::kWebTextInputModeEmail, ui::TEXT_INPUT_MODE_EMAIL);
 STATIC_ASSERT_ENUM(blink::kWebTextInputModeUrl, ui::TEXT_INPUT_MODE_URL);
+STATIC_ASSERT_ENUM(blink::kWebTextInputModeEmail, ui::TEXT_INPUT_MODE_EMAIL);
+STATIC_ASSERT_ENUM(blink::kWebTextInputModeNumeric,
+                   ui::TEXT_INPUT_MODE_NUMERIC);
+STATIC_ASSERT_ENUM(blink::kWebTextInputModeDecimal,
+                   ui::TEXT_INPUT_MODE_DECIMAL);
+STATIC_ASSERT_ENUM(blink::kWebTextInputModeSearch, ui::TEXT_INPUT_MODE_SEARCH);
 
 // WebTextInputType
 STATIC_ASSERT_ENUM(blink::kWebTextInputTypeNone, ui::TEXT_INPUT_TYPE_NONE);
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 10d0d72e2..db050efb 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -343,11 +343,8 @@
     "//device/base/synchronization",
     "//device/bluetooth",
     "//gpu",
-    "//gpu/command_buffer/client:gles2_c_lib",
-    "//gpu/command_buffer/client:gles2_cmd_helper",
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/client:gles2_interface",
-    "//gpu/command_buffer/common:gles2_utils",
     "//gpu/command_buffer/service",
     "//gpu/ipc/client",
     "//gpu/ipc/common",
diff --git a/content/common/media/cdm_info.cc b/content/common/media/cdm_info.cc
index 738e942..12b98dc 100644
--- a/content/common/media/cdm_info.cc
+++ b/content/common/media/cdm_info.cc
@@ -14,7 +14,7 @@
                  const base::Version& version,
                  const base::FilePath& path,
                  const std::string& file_system_id,
-                 const std::vector<std::string>& supported_codecs,
+                 const std::vector<media::VideoCodec>& supported_video_codecs,
                  bool supports_persistent_license,
                  const std::string& supported_key_system,
                  bool supports_sub_key_systems)
@@ -23,7 +23,7 @@
       version(version),
       path(path),
       file_system_id(file_system_id),
-      supported_codecs(supported_codecs),
+      supported_video_codecs(supported_video_codecs),
       supports_persistent_license(supports_persistent_license),
       supported_key_system(supported_key_system),
       supports_sub_key_systems(supports_sub_key_systems) {
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h
index 6a42a43..f4e8b4b 100644
--- a/content/common/resource_messages.h
+++ b/content/common/resource_messages.h
@@ -7,6 +7,7 @@
 
 // IPC messages for resource loading.
 //
+// WE ARE DEPRECATING THIS FILE. DO NOT ADD A NEW MESSAGE.
 // NOTE: All messages must send an |int request_id| as their first parameter.
 
 #include <stdint.h>
@@ -259,109 +260,4 @@
   IPC_STRUCT_TRAITS_MEMBER(ssl_info)
 IPC_STRUCT_TRAITS_END()
 
-// Resource messages sent from the browser to the renderer.
-
-// Sent when the headers are available for a resource request.
-IPC_MESSAGE_CONTROL2(ResourceMsg_ReceivedResponse,
-                     int /* request_id */,
-                     content::ResourceResponseHead)
-
-// Sent when cached metadata from a resource request is ready.
-IPC_MESSAGE_CONTROL2(ResourceMsg_ReceivedCachedMetadata,
-                     int /* request_id */,
-                     std::vector<uint8_t> /* data */)
-
-// Sent as upload progress is being made.
-IPC_MESSAGE_CONTROL3(ResourceMsg_UploadProgress,
-                     int /* request_id */,
-                     int64_t /* position */,
-                     int64_t /* size */)
-
-// Sent when the request has been redirected.  The receiver is expected to
-// respond with either a FollowRedirect message (if the redirect is to be
-// followed) or a CancelRequest message (if it should not be followed).
-IPC_MESSAGE_CONTROL3(ResourceMsg_ReceivedRedirect,
-                     int /* request_id */,
-                     net::RedirectInfo /* redirect_info */,
-                     content::ResourceResponseHead)
-
-// Sent to set the shared memory buffer to be used to transmit response data to
-// the renderer.  Subsequent DataReceived messages refer to byte ranges in the
-// shared memory buffer.  The shared memory buffer should be retained by the
-// renderer until the resource request completes.
-//
-// NOTE: The shared memory handle should already be mapped into the process
-// that receives this message.
-IPC_MESSAGE_CONTROL3(ResourceMsg_SetDataBuffer,
-                     int /* request_id */,
-                     base::SharedMemoryHandle /* shm_handle */,
-                     int /* shm_size */)
-
-// Sent when some data from a resource request is ready.  The data offset and
-// length specify a byte range into the shared memory buffer provided by the
-// SetDataBuffer message.
-IPC_MESSAGE_CONTROL4(ResourceMsg_DataReceived,
-                     int /* request_id */,
-                     int /* data_offset */,
-                     int /* data_length */,
-                     int /* encoded_data_length */)
-
-// Sent when some data from a resource request has been downloaded to
-// file. This is only called in the 'download_to_file' case and replaces
-// ResourceMsg_DataReceived in the call sequence in that case.
-IPC_MESSAGE_CONTROL3(ResourceMsg_DataDownloaded,
-                     int /* request_id */,
-                     int /* data_len */,
-                     int /* encoded_data_length */)
-
-// Sent when the request has been completed.
-IPC_MESSAGE_CONTROL2(ResourceMsg_RequestComplete,
-                     int /* request_id */,
-                     network::URLLoaderCompletionStatus)
-
-// Resource messages sent from the renderer to the browser.
-
-// Makes a resource request via the browser.
-IPC_MESSAGE_CONTROL4(
-    ResourceHostMsg_RequestResource,
-    int /* routing_id */,
-    int /* request_id */,
-    content::ResourceRequest,
-    net::MutableNetworkTrafficAnnotationTag /* network_traffic_annotation */)
-
-// Cancels a resource request with the ID given as the parameter.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_CancelRequest,
-                     int /* request_id */)
-
-// Follows a redirect that occured for the resource request with the ID given
-// as the parameter.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_FollowRedirect,
-                     int /* request_id */)
-
-// Makes a synchronous resource request via the browser.
-IPC_SYNC_MESSAGE_ROUTED2_1(ResourceHostMsg_SyncLoad,
-                           int /* request_id */,
-                           content::ResourceRequest,
-                           content::SyncLoadResult)
-
-// Sent when the renderer process is done processing a DataReceived
-// message.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_DataReceived_ACK,
-                     int /* request_id */)
-
-// Sent by the renderer process to acknowledge receipt of a
-// UploadProgress message.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_UploadProgress_ACK,
-                     int /* request_id */)
-
-// Sent when the renderer process deletes a resource loader.
-IPC_MESSAGE_CONTROL1(ResourceHostMsg_ReleaseDownloadedFile,
-                     int /* request_id */)
-
-// Sent by the renderer when a resource request changes priority.
-IPC_MESSAGE_CONTROL3(ResourceHostMsg_DidChangePriority,
-                     int /* request_id */,
-                     net::RequestPriority,
-                     int /* intra_priority_value */)
-
 #endif  // CONTENT_COMMON_RESOURCE_MESSAGES_H_
diff --git a/content/public/android/java/src/org/chromium/content/app/ChromiumLinkerParams.java b/content/public/android/java/src/org/chromium/content/app/ChromiumLinkerParams.java
index 304b383..2b2bf81 100644
--- a/content/public/android/java/src/org/chromium/content/app/ChromiumLinkerParams.java
+++ b/content/public/android/java/src/org/chromium/content/app/ChromiumLinkerParams.java
@@ -27,10 +27,6 @@
     // registered in the service process.
     public final String mTestRunnerClassNameForTesting;
 
-    // If mTestRunnerClassNameForTesting is not empty, the Linker implementation
-    // to force for testing.
-    public final int mLinkerImplementationForTesting;
-
     private static final String EXTRA_LINKER_PARAMS_BASE_LOAD_ADDRESS =
             "org.chromium.content.common.linker_params.base_load_address";
 
@@ -40,27 +36,20 @@
     private static final String EXTRA_LINKER_PARAMS_TEST_RUNNER_CLASS_NAME =
             "org.chromium.content.common.linker_params.test_runner_class_name";
 
-    private static final String EXTRA_LINKER_PARAMS_LINKER_IMPLEMENTATION =
-            "org.chromium.content.common.linker_params.linker_implementation";
-
     public ChromiumLinkerParams(long baseLoadAddress, boolean waitForSharedRelro) {
         mBaseLoadAddress = baseLoadAddress;
         mWaitForSharedRelro = waitForSharedRelro;
         mTestRunnerClassNameForTesting = null;
-        mLinkerImplementationForTesting = 0;
     }
 
     /**
      * Use this constructor to create a LinkerParams instance for testing.
      */
-    public ChromiumLinkerParams(long baseLoadAddress,
-                                boolean waitForSharedRelro,
-                                String testRunnerClassName,
-                                int linkerImplementation) {
+    public ChromiumLinkerParams(
+            long baseLoadAddress, boolean waitForSharedRelro, String testRunnerClassName) {
         mBaseLoadAddress = baseLoadAddress;
         mWaitForSharedRelro = waitForSharedRelro;
         mTestRunnerClassNameForTesting = testRunnerClassName;
-        mLinkerImplementationForTesting = linkerImplementation;
     }
 
     /**
@@ -73,8 +62,7 @@
     public static ChromiumLinkerParams create(Bundle bundle) {
         if (!bundle.containsKey(EXTRA_LINKER_PARAMS_BASE_LOAD_ADDRESS)
                 || !bundle.containsKey(EXTRA_LINKER_PARAMS_WAIT_FOR_SHARED_RELRO)
-                || !bundle.containsKey(EXTRA_LINKER_PARAMS_TEST_RUNNER_CLASS_NAME)
-                || !bundle.containsKey(EXTRA_LINKER_PARAMS_LINKER_IMPLEMENTATION)) {
+                || !bundle.containsKey(EXTRA_LINKER_PARAMS_TEST_RUNNER_CLASS_NAME)) {
             return null;
         }
         return new ChromiumLinkerParams(bundle);
@@ -85,8 +73,6 @@
         mWaitForSharedRelro = bundle.getBoolean(EXTRA_LINKER_PARAMS_WAIT_FOR_SHARED_RELRO, false);
         mTestRunnerClassNameForTesting =
                 bundle.getString(EXTRA_LINKER_PARAMS_TEST_RUNNER_CLASS_NAME);
-        mLinkerImplementationForTesting =
-                bundle.getInt(EXTRA_LINKER_PARAMS_LINKER_IMPLEMENTATION, 0);
     }
 
     /**
@@ -99,7 +85,6 @@
         bundle.putBoolean(EXTRA_LINKER_PARAMS_WAIT_FOR_SHARED_RELRO, mWaitForSharedRelro);
         bundle.putString(
                 EXTRA_LINKER_PARAMS_TEST_RUNNER_CLASS_NAME, mTestRunnerClassNameForTesting);
-        bundle.putInt(EXTRA_LINKER_PARAMS_LINKER_IMPLEMENTATION, mLinkerImplementationForTesting);
     }
 
     // For debugging traces only.
@@ -107,8 +92,8 @@
     public String toString() {
         return String.format(Locale.US,
                 "LinkerParams(baseLoadAddress:0x%x, waitForSharedRelro:%s, "
-                        + "testRunnerClassName:%s, linkerImplementation:%d",
+                        + "testRunnerClassName:%s",
                 mBaseLoadAddress, Boolean.toString(mWaitForSharedRelro),
-                mTestRunnerClassNameForTesting, mLinkerImplementationForTesting);
+                mTestRunnerClassNameForTesting);
     }
 }
diff --git a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java
index 47277ae1..f995e3e 100644
--- a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java
+++ b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java
@@ -196,8 +196,7 @@
             // For testing, set the Linker implementation and the test runner
             // class name to match those used by the parent.
             assert mLinkerParams != null;
-            Linker.setupForTesting(mLinkerParams.mLinkerImplementationForTesting,
-                    mLinkerParams.mTestRunnerClassNameForTesting);
+            Linker.setupForTesting(mLinkerParams.mTestRunnerClassNameForTesting);
         }
         return Linker.getInstance();
     }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java
index 24489ef..1ef5bfe0 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelper.java
@@ -111,8 +111,10 @@
                             ContentChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCount());
                     connectionBundle.putLong(
                             ContentChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.getMask());
-                    connectionBundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS,
-                            Linker.getInstance().getSharedRelros());
+                    if (Linker.isUsed()) {
+                        connectionBundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS,
+                                Linker.getInstance().getSharedRelros());
+                    }
                 }
 
                 @Override
@@ -583,8 +585,7 @@
         if (Linker.areTestsEnabled()) {
             Linker linker = Linker.getInstance();
             return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros,
-                    linker.getTestRunnerClassNameForTesting(),
-                    linker.getImplementationForTesting());
+                    linker.getTestRunnerClassNameForTesting());
         } else {
             return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros);
         }
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java
index 11e204db..9eea36a 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeUtils.java
@@ -80,33 +80,31 @@
             switch (inputMode) {
                 default:
                 case WebTextInputMode.DEFAULT:
-                case WebTextInputMode.VERBATIM:
-                case WebTextInputMode.LATIN:
-                case WebTextInputMode.LATIN_NAME:
-                case WebTextInputMode.LATIN_PROSE:
-                case WebTextInputMode.FULL_WIDTH_LATIN:
-                case WebTextInputMode.KANA:
-                case WebTextInputMode.KANA_NAME:
-                case WebTextInputMode.KATA_KANA:
+                case WebTextInputMode.TEXT:
+                case WebTextInputMode.SEARCH:
                     outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
                     if ((inputFlags & WebTextInputFlags.AUTOCORRECT_OFF) == 0) {
                         outAttrs.inputType |= EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;
                     }
                     break;
-                case WebTextInputMode.NUMERIC:
-                    outAttrs.inputType =
-                            InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL;
-                    break;
                 case WebTextInputMode.TEL:
                     outAttrs.inputType = InputType.TYPE_CLASS_PHONE;
                     break;
+                case WebTextInputMode.URL:
+                    outAttrs.inputType =
+                            InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI;
+                    break;
                 case WebTextInputMode.EMAIL:
                     outAttrs.inputType = InputType.TYPE_CLASS_TEXT
                             | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
                     break;
-                case WebTextInputMode.URL:
+                case WebTextInputMode.NUMERIC:
                     outAttrs.inputType =
-                            InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI;
+                            InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL;
+                    break;
+                case WebTextInputMode.DECIMAL:
+                    outAttrs.inputType =
+                            InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL;
                     break;
             }
         }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/VideoRotateToFullscreenTest.java b/content/public/android/javatests/src/org/chromium/content/browser/VideoRotateToFullscreenTest.java
index 16c2aea..470a42a 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/VideoRotateToFullscreenTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/VideoRotateToFullscreenTest.java
@@ -18,6 +18,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.content.browser.test.ContentJUnit4ClassRunner;
@@ -95,6 +96,7 @@
     @MediumTest
     @Feature({"VideoRotateToFullscreen"})
     @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
+    @DisabledTest(message = "crbug.com/726977")
     public void testPortraitToLandscapeAndBack() throws Exception {
         // Start off in portrait screen orientation.
         mRule.getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 8bbcd474..343fee5 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -9,8 +9,13 @@
           "discardable_memory::mojom::DiscardableSharedMemoryManager",
           "memory_instrumentation::mojom::Coordinator"
         ],
+        "field_trials": [
+          "content::mojom::FieldTrialRecorder"
+        ],
+        "font_cache": [
+          "content::mojom::FontCacheWin"
+        ],
         "gpu": [
-          "content::mojom::FieldTrialRecorder",
           "media::mojom::AndroidOverlayProvider"
         ],
         "plugin": [
@@ -29,6 +34,7 @@
           "blink::mojom::ReportingServiceProxy",
           "blink::mojom::WebDatabaseHost",
           "content::mojom::AppCacheBackend",
+          "content::mojom::ClipboardHost",
           "content::mojom::FieldTrialRecorder",
           "content::mojom::FileUtilitiesHost",
           "content::mojom::FrameSinkProvider",
@@ -124,6 +130,7 @@
           "autofill::mojom::AutofillDriver",
           "autofill::mojom::PasswordManagerDriver",
           "blink::mojom::BackgroundFetchService",
+          "blink::mojom::BudgetService",
           "blink::mojom::ColorChooserFactory",
           "blink::mojom::DedicatedWorkerFactory",
           "blink::mojom::LockManager",
@@ -155,8 +162,8 @@
           "device::mojom::VibrationManager",
           "device::mojom::VRService",
           "device::mojom::WakeLock",
+          "device::mojom::UsbDeviceManager",
           "device::mojom::VRService",
-          "device::usb::DeviceManager",
           "discardable_memory::mojom::DiscardableSharedMemoryManager",
           "media::mojom::ImageCapture",
           "media::mojom::InterfaceFactory",
@@ -164,8 +171,10 @@
           "media::mojom::RemoterFactory",
           "media::mojom::Renderer",
           "network::mojom::RestrictedCookieManager",
+          "password_manager::mojom::CredentialManager",
           "payments::mojom::PaymentManager",
           "payments::mojom::PaymentRequest",
+          "password_manager::mojom::CredentialManager",
           "resource_coordinator::mojom::FrameCoordinationUnit",
           "shape_detection::mojom::BarcodeDetection",
           "shape_detection::mojom::FaceDetectionProvider",
@@ -181,6 +190,7 @@
     "navigation:dedicated_worker": {
       "provides": {
         "renderer": [
+          "blink::mojom::BudgetService",
           "blink::mojom::LockManager",
           "blink::mojom::NotificationService",
           "blink::mojom::PermissionService",
@@ -195,6 +205,7 @@
       "provides": {
         "renderer": [
           "blink::mojom::BackgroundFetchService",
+          "blink::mojom::BudgetService",
           "blink::mojom::LockManager",
           "blink::mojom::NotificationService",
           "blink::mojom::PermissionService",
@@ -210,6 +221,7 @@
     "navigation:shared_worker": {
       "provides": {
         "renderer": [
+          "blink::mojom::BudgetService",
           "blink::mojom::LockManager",
           "blink::mojom::NotificationService",
           "blink::mojom::PermissionService",
diff --git a/content/public/app/mojo/content_gpu_manifest.json b/content/public/app/mojo/content_gpu_manifest.json
index 73477a0..77212945 100644
--- a/content/public/app/mojo/content_gpu_manifest.json
+++ b/content/public/app/mojo/content_gpu_manifest.json
@@ -20,7 +20,10 @@
       },
       "requires": {
         "*": [ "app" ],
-        "content_browser": [ "gpu" ],
+        "content_browser": [
+          "field_trials",
+          "gpu"
+        ],
         "device": [ "device:power_monitor" ],
         "metrics": [ "url_keyed_metrics" ]
       }
diff --git a/content/public/app/mojo/content_plugin_manifest.json b/content/public/app/mojo/content_plugin_manifest.json
index 58b9a977..b184bac 100644
--- a/content/public/app/mojo/content_plugin_manifest.json
+++ b/content/public/app/mojo/content_plugin_manifest.json
@@ -17,7 +17,11 @@
       },
       "requires": {
         "*": [ "app" ],
-        "content_browser": [ "plugin" ],
+        "content_browser": [
+          "field_trials",
+          "font_cache",
+          "plugin"
+        ],
         "device": [ "device:power_monitor" ],
         "ui": [ "discardable_memory" ]
       }
diff --git a/content/public/app/mojo/content_renderer_manifest.json b/content/public/app/mojo/content_renderer_manifest.json
index 27388c4..6cfc2ff 100644
--- a/content/public/app/mojo/content_renderer_manifest.json
+++ b/content/public/app/mojo/content_renderer_manifest.json
@@ -27,7 +27,10 @@
       },
       "requires": {
         "*": [ "app" ],
-        "content_browser": [ "renderer" ],
+        "content_browser": [
+          "field_trials",
+          "renderer"
+        ],
         "metrics": [ "url_keyed_metrics" ],
         "device": [
           "device:power_monitor",
diff --git a/content/public/app/mojo/content_utility_manifest.json b/content/public/app/mojo/content_utility_manifest.json
index 32ed07b..090b5632 100644
--- a/content/public/app/mojo/content_utility_manifest.json
+++ b/content/public/app/mojo/content_utility_manifest.json
@@ -20,6 +20,9 @@
       },
       "requires": {
         "*": [ "app" ],
+        "content_browser": [
+          "field_trials"
+        ],
         "device": [
           "device:power_monitor",
           "device:time_zone_monitor"
diff --git a/content/public/browser/android/compositor.h b/content/public/browser/android/compositor.h
index 9b8eb49..e454121 100644
--- a/content/public/browser/android/compositor.h
+++ b/content/public/browser/android/compositor.h
@@ -19,10 +19,7 @@
 }
 
 namespace gpu {
-namespace gles2 {
-struct ContextCreationAttribHelper;
-}  // namespace gles2
-
+struct ContextCreationAttribs;
 struct SharedMemoryLimits;
 }
 
@@ -53,7 +50,7 @@
       base::Callback<void(scoped_refptr<viz::ContextProvider>)>;
   static void CreateContextProvider(
       gpu::SurfaceHandle handle,
-      gpu::gles2::ContextCreationAttribHelper attributes,
+      gpu::ContextCreationAttribs attributes,
       gpu::SharedMemoryLimits shared_memory_limits,
       ContextProviderCallback callback);
 
diff --git a/content/public/browser/download_manager_delegate.cc b/content/public/browser/download_manager_delegate.cc
index d000feb4..c21286c5 100644
--- a/content/public/browser/download_manager_delegate.cc
+++ b/content/public/browser/download_manager_delegate.cc
@@ -35,6 +35,11 @@
   return true;
 }
 
+bool DownloadManagerDelegate::IsMostRecentDownloadItemAtFilePath(
+    DownloadItem* download) {
+  return true;
+}
+
 bool DownloadManagerDelegate::GenerateFileHash() {
   return false;
 }
diff --git a/content/public/browser/download_manager_delegate.h b/content/public/browser/download_manager_delegate.h
index 41ac4c3..7194560 100644
--- a/content/public/browser/download_manager_delegate.h
+++ b/content/public/browser/download_manager_delegate.h
@@ -159,6 +159,10 @@
   // Opens the file associated with this download.
   virtual void OpenDownload(DownloadItem* download) {}
 
+  // Returns whether this is the most recent download in the rare event where
+  // multiple downloads are associated with the same file path.
+  virtual bool IsMostRecentDownloadItemAtFilePath(DownloadItem* download);
+
   // Shows the download via the OS shell.
   virtual void ShowDownloadInShell(DownloadItem* download) {}
 
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h
index 05165995..61bea47 100644
--- a/content/public/browser/storage_partition.h
+++ b/content/public/browser/storage_partition.h
@@ -29,6 +29,12 @@
 class URLRequestContextGetter;
 }
 
+namespace network {
+namespace mojom {
+class CookieManager;
+}
+}  // namespace network
+
 namespace storage {
 class QuotaManager;
 class SpecialStoragePolicy;
@@ -71,12 +77,13 @@
   virtual net::URLRequestContextGetter* GetURLRequestContext() = 0;
   virtual net::URLRequestContextGetter* GetMediaURLRequestContext() = 0;
   virtual mojom::NetworkContext* GetNetworkContext() = 0;
-  // Returns a pointer to a URLLoaderFactory owned by the storage partition.
-  // Prefer to use this instead of creating a new URLLoaderFactory when issuing
-  // requests from the Browser process, to share resources. The returned
-  // URLLoaderFactory should not be sent to subprocesses, due to its
-  // permissions.
+  // Returns a pointer to a URLLoaderFactory/CookieManager owned by the
+  // storage partition.  Prefer to use this instead of creating a new
+  // URLLoaderFactory when issuing requests from the Browser process, to
+  // share resources and preserve ordering.
   virtual mojom::URLLoaderFactory* GetURLLoaderFactoryForBrowserProcess() = 0;
+  virtual network::mojom::CookieManager*
+  GetCookieManagerForBrowserProcess() = 0;
   virtual storage::QuotaManager* GetQuotaManager() = 0;
   virtual AppCacheService* GetAppCacheService() = 0;
   virtual storage::FileSystemContext* GetFileSystemContext() = 0;
diff --git a/content/public/common/cdm_info.h b/content/public/common/cdm_info.h
index 894f250..e6305bf 100644
--- a/content/public/common/cdm_info.h
+++ b/content/public/common/cdm_info.h
@@ -11,6 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/version.h"
 #include "content/common/content_export.h"
+#include "media/base/video_codecs.h"
 
 namespace content {
 
@@ -21,7 +22,7 @@
           const base::Version& version,
           const base::FilePath& path,
           const std::string& file_system_id,
-          const std::vector<std::string>& supported_codecs,
+          const std::vector<media::VideoCodec>& supported_video_codecs,
           bool supports_persistent_license,
           const std::string& supported_key_system,
           bool supports_sub_key_systems);
@@ -46,10 +47,12 @@
   // digits(0-9), or "._-".
   std::string file_system_id;
 
-  // List of codecs supported by the CDM (e.g. vp8).
-  // TODO(jrummell): use the enums from media::AudioCodec and media::VideoCodec
-  // instead of strings.
-  std::vector<std::string> supported_codecs;
+  // List of video codecs supported by the CDM (e.g. vp8). This is the set of
+  // codecs that can be decrypted and decoded by the CDM. As this is generic,
+  // not all profiles or levels of the specified codecs may actually be
+  // supported.
+  // TODO(crbug.com/796725) Find a way to include profiles and levels.
+  std::vector<media::VideoCodec> supported_video_codecs;
 
   // Whether this CDM supports persistent licenses.
   bool supports_persistent_license;
diff --git a/content/public/renderer/video_encode_accelerator.cc b/content/public/renderer/video_encode_accelerator.cc
index 9d75b2a..16247e9 100644
--- a/content/public/renderer/video_encode_accelerator.cc
+++ b/content/public/renderer/video_encode_accelerator.cc
@@ -6,7 +6,6 @@
 
 #include "base/task_runner_util.h"
 #include "content/renderer/render_thread_impl.h"
-#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 
 namespace content {
diff --git a/content/public/test/test_storage_partition.cc b/content/public/test/test_storage_partition.cc
index 49fb98b..9ec3908 100644
--- a/content/public/test/test_storage_partition.cc
+++ b/content/public/test/test_storage_partition.cc
@@ -31,6 +31,11 @@
   return url_loader_factory_for_browser_process_;
 }
 
+network::mojom::CookieManager*
+TestStoragePartition::GetCookieManagerForBrowserProcess() {
+  return cookie_manager_for_browser_process_;
+}
+
 storage::QuotaManager* TestStoragePartition::GetQuotaManager() {
   return quota_manager_;
 }
diff --git a/content/public/test/test_storage_partition.h b/content/public/test/test_storage_partition.h
index db264b36..32c66aaa 100644
--- a/content/public/test/test_storage_partition.h
+++ b/content/public/test/test_storage_partition.h
@@ -64,6 +64,12 @@
   }
   mojom::URLLoaderFactory* GetURLLoaderFactoryForBrowserProcess() override;
 
+  void set_cookie_manager_for_browser_process(
+      network::mojom::CookieManager* cookie_manager_for_browser_process) {
+    cookie_manager_for_browser_process_ = cookie_manager_for_browser_process;
+  }
+  network::mojom::CookieManager* GetCookieManagerForBrowserProcess() override;
+
   void set_quota_manager(storage::QuotaManager* manager) {
     quota_manager_ = manager;
   }
@@ -161,6 +167,7 @@
   net::URLRequestContextGetter* media_url_request_context_getter_ = nullptr;
   mojom::NetworkContext* network_context_ = nullptr;
   mojom::URLLoaderFactory* url_loader_factory_for_browser_process_ = nullptr;
+  network::mojom::CookieManager* cookie_manager_for_browser_process_ = nullptr;
   storage::QuotaManager* quota_manager_ = nullptr;
   AppCacheService* app_cache_service_ = nullptr;
   storage::FileSystemContext* file_system_context_ = nullptr;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 40741ec3..13b627c0 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -236,8 +236,6 @@
     "java/gin_java_function_invocation_helper.h",
     "layout_test_dependencies.cc",
     "layout_test_dependencies.h",
-    "loader/child_resource_message_filter.cc",
-    "loader/child_resource_message_filter.h",
     "loader/child_url_loader_factory_getter_impl.cc",
     "loader/child_url_loader_factory_getter_impl.h",
     "loader/cors_url_loader.cc",
@@ -250,12 +248,8 @@
     "loader/request_extra_data.h",
     "loader/resource_dispatcher.cc",
     "loader/resource_dispatcher.h",
-    "loader/resource_scheduling_filter.cc",
-    "loader/resource_scheduling_filter.h",
     "loader/shared_memory_data_consumer_handle.cc",
     "loader/shared_memory_data_consumer_handle.h",
-    "loader/shared_memory_received_data_factory.cc",
-    "loader/shared_memory_received_data_factory.h",
     "loader/site_isolation_stats_gatherer.cc",
     "loader/site_isolation_stats_gatherer.h",
     "loader/sync_load_context.cc",
@@ -419,8 +413,6 @@
     "sad_plugin.h",
     "savable_resources.cc",
     "savable_resources.h",
-    "scheduler/resource_dispatch_throttler.cc",
-    "scheduler/resource_dispatch_throttler.h",
     "screen_orientation/screen_orientation_dispatcher.cc",
     "screen_orientation/screen_orientation_dispatcher.h",
     "seccomp_sandbox_status_android.cc",
diff --git a/content/renderer/gpu/gpu_benchmarking_extension.cc b/content/renderer/gpu/gpu_benchmarking_extension.cc
index 9aab87d66..87c676f 100644
--- a/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -121,7 +121,7 @@
         }
         return data;
       };
-      auto data = picture->serialize(procs);
+      auto data = picture->serialize(&procs);
       file.write(data->data(), data->size());
       file.fsync();
     }
diff --git a/content/renderer/loader/child_resource_message_filter.cc b/content/renderer/loader/child_resource_message_filter.cc
deleted file mode 100644
index 542dc86f..0000000
--- a/content/renderer/loader/child_resource_message_filter.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 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/renderer/loader/child_resource_message_filter.h"
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/common/resource_messages.h"
-#include "content/renderer/loader/resource_dispatcher.h"
-
-namespace content {
-
-ChildResourceMessageFilter::ChildResourceMessageFilter(
-    ResourceDispatcher* resource_dispatcher)
-    : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      resource_dispatcher_(resource_dispatcher) {}
-
-ChildResourceMessageFilter::~ChildResourceMessageFilter() {}
-
-bool ChildResourceMessageFilter::OnMessageReceived(
-    const IPC::Message& message) {
-  if (message.type() == ResourceMsg_RequestComplete::ID ||
-      message.type() == ResourceMsg_ReceivedResponse::ID ||
-      message.type() == ResourceMsg_ReceivedRedirect::ID) {
-    main_thread_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&ResourceDispatcher::set_io_timestamp,
-                                  base::Unretained(resource_dispatcher_),
-                                  base::TimeTicks::Now()));
-  }
-  return false;
-}
-
-}  // namespace content
diff --git a/content/renderer/loader/child_resource_message_filter.h b/content/renderer/loader/child_resource_message_filter.h
deleted file mode 100644
index a8315fc..0000000
--- a/content/renderer/loader/child_resource_message_filter.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2013 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_RENDERER_LOADER_CHILD_RESOURCE_MESSAGE_FILTER_H_
-#define CONTENT_RENDERER_LOADER_CHILD_RESOURCE_MESSAGE_FILTER_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "ipc/message_filter.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace content {
-class ResourceDispatcher;
-
-// Supplies ResourceDispatcher with timestamps for some resource messages.
-//
-// Background: ResourceDispatcher converts browser process time to child
-// process time. This is done to achieve coherent timeline. Conversion is
-// a linear transformation such that given browser process time range is
-// mapped to corresponding child process time range. Timestamps for child
-// process time range should be taken by IO thread when resource messages
-// arrive. Otherwise, timestamps may be affected by long rendering / JS task.
-//
-// When specific message is processed by this filter, new task charged
-// with timestamp is posted to main thread. This task is processed just before
-// resource message and invokes ResourceDispatcher::set_io_timestamp.
-class ChildResourceMessageFilter : public IPC::MessageFilter {
- public:
-  explicit ChildResourceMessageFilter(ResourceDispatcher* resource_dispatcher);
-
-  // IPC::MessageFilter implementation.
-  bool OnMessageReceived(const IPC::Message& message) override;
-
-  void SetMainThreadTaskRunner(
-      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) {
-    main_thread_task_runner_ = main_thread_task_runner;
-  }
-
- private:
-  ~ChildResourceMessageFilter() override;
-
-  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-  ResourceDispatcher* resource_dispatcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(ChildResourceMessageFilter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_LOADER_CHILD_RESOURCE_MESSAGE_FILTER_H_
diff --git a/content/renderer/loader/request_extra_data.cc b/content/renderer/loader/request_extra_data.cc
index ea53c65..4202a41b 100644
--- a/content/renderer/loader/request_extra_data.cc
+++ b/content/renderer/loader/request_extra_data.cc
@@ -7,7 +7,6 @@
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/service_worker_modes.h"
-#include "ipc/ipc_message.h"
 #include "third_party/WebKit/common/page/page_visibility_state.mojom.h"
 
 using blink::WebString;
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc
index 1d6452d..0585c63 100644
--- a/content/renderer/loader/resource_dispatcher.cc
+++ b/content/renderer/loader/resource_dispatcher.cc
@@ -15,7 +15,6 @@
 #include "base/debug/stack_trace.h"
 #include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
@@ -24,7 +23,6 @@
 #include "build/build_config.h"
 #include "content/common/inter_process_time_ticks_converter.h"
 #include "content/common/navigation_params.h"
-#include "content/common/resource_messages.h"
 #include "content/common/throttling_url_loader.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/resource_request.h"
@@ -34,8 +32,6 @@
 #include "content/public/renderer/request_peer.h"
 #include "content/public/renderer/resource_dispatcher_delegate.h"
 #include "content/renderer/loader/request_extra_data.h"
-#include "content/renderer/loader/resource_scheduling_filter.h"
-#include "content/renderer/loader/shared_memory_received_data_factory.h"
 #include "content/renderer/loader/site_isolation_stats_gatherer.h"
 #include "content/renderer/loader/sync_load_context.h"
 #include "content/renderer/loader/sync_load_response.h"
@@ -59,14 +55,6 @@
   *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks();
 }
 
-void CrashOnMapFailure() {
-#if defined(OS_WIN)
-  DWORD last_err = GetLastError();
-  base::debug::Alias(&last_err);
-#endif
-  CHECK(false);
-}
-
 void CheckSchemeForReferrerPolicy(const ResourceRequest& request) {
   if ((request.referrer_policy == blink::kWebReferrerPolicyDefault ||
        request.referrer_policy ==
@@ -121,53 +109,14 @@
 }
 
 ResourceDispatcher::ResourceDispatcher(
-    IPC::Sender* sender,
     scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner)
-    : message_sender_(sender),
-      delegate_(nullptr),
-      io_timestamp_(base::TimeTicks()),
+    : delegate_(nullptr),
       thread_task_runner_(thread_task_runner),
       weak_factory_(this) {}
 
 ResourceDispatcher::~ResourceDispatcher() {
 }
 
-bool ResourceDispatcher::OnMessageReceived(const IPC::Message& message) {
-  if (!IsResourceDispatcherMessage(message)) {
-    return false;
-  }
-
-  int request_id;
-
-  base::PickleIterator iter(message);
-  if (!iter.ReadInt(&request_id)) {
-    NOTREACHED() << "malformed resource message";
-    return true;
-  }
-
-  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
-  if (!request_info) {
-    // Release resources in the message if it is a data message.
-    ReleaseResourcesInDataMessage(message);
-    return true;
-  }
-
-  if (request_info->is_deferred) {
-    request_info->deferred_message_queue.push_back(new IPC::Message(message));
-    return true;
-  }
-
-  // Make sure any deferred messages are dispatched before we dispatch more.
-  if (!request_info->deferred_message_queue.empty()) {
-    request_info->deferred_message_queue.push_back(new IPC::Message(message));
-    FlushDeferredMessages(request_id);
-    return true;
-  }
-
-  DispatchMessage(message);
-  return true;
-}
-
 ResourceDispatcher::PendingRequestInfo*
 ResourceDispatcher::GetPendingRequestInfo(int request_id) {
   PendingRequestMap::iterator it = pending_requests_.find(request_id);
@@ -186,13 +135,6 @@
     return;
 
   request_info->peer->OnUploadProgress(position, size);
-
-  // URLLoaderClientImpl has its own acknowledgement, and doesn't need the IPC
-  // message here.
-  if (!request_info->url_loader) {
-    // Acknowledge receipt
-    message_sender_->Send(new ResourceHostMsg_UploadProgress_ACK(request_id));
-  }
 }
 
 void ResourceDispatcher::OnReceivedResponse(
@@ -201,7 +143,7 @@
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   if (!request_info)
     return;
-  request_info->response_start = ConsumeIOTimestamp();
+  request_info->response_start = base::TimeTicks::Now();
 
   if (delegate_) {
     std::unique_ptr<RequestPeer> new_peer = delegate_->OnReceivedResponse(
@@ -241,80 +183,6 @@
   }
 }
 
-void ResourceDispatcher::OnSetDataBuffer(int request_id,
-                                         base::SharedMemoryHandle shm_handle,
-                                         int shm_size) {
-  TRACE_EVENT0("loader", "ResourceDispatcher::OnSetDataBuffer");
-  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
-  if (!request_info)
-    return;
-
-  bool shm_valid = base::SharedMemory::IsHandleValid(shm_handle);
-  CHECK((shm_valid && shm_size > 0) || (!shm_valid && !shm_size));
-
-  request_info->buffer.reset(
-      new base::SharedMemory(shm_handle, true));  // read only
-  request_info->received_data_factory =
-      base::MakeRefCounted<SharedMemoryReceivedDataFactory>(
-          message_sender_, request_id, request_info->buffer);
-
-  bool ok = request_info->buffer->Map(shm_size);
-  if (!ok) {
-    base::SharedMemoryHandle shm_handle_copy = shm_handle;
-    base::debug::Alias(&shm_handle_copy);
-
-    CrashOnMapFailure();
-    return;
-  }
-
-  // TODO(erikchen): Temporary debugging. http://crbug.com/527588.
-  CHECK_GE(shm_size, 0);
-  CHECK_LE(shm_size, 512 * 1024);
-  request_info->buffer_size = shm_size;
-}
-
-void ResourceDispatcher::OnReceivedData(int request_id,
-                                        int data_offset,
-                                        int data_length,
-                                        int encoded_data_length) {
-  TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData");
-  DCHECK_GT(data_length, 0);
-  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
-  bool send_ack = true;
-  if (request_info && data_length > 0) {
-    CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle()));
-    CHECK_GE(request_info->buffer_size, data_offset + data_length);
-
-    const char* data_start = static_cast<char*>(request_info->buffer->memory());
-    CHECK(data_start);
-    CHECK(data_start + data_offset);
-    const char* data_ptr = data_start + data_offset;
-
-    // Check whether this response data is compliant with our cross-site
-    // document blocking policy. We only do this for the first chunk of data.
-    if (request_info->site_isolation_metadata.get()) {
-      SiteIsolationStatsGatherer::OnReceivedFirstChunk(
-          request_info->site_isolation_metadata, data_ptr, data_length);
-      request_info->site_isolation_metadata.reset();
-    }
-
-    std::unique_ptr<RequestPeer::ReceivedData> data =
-        request_info->received_data_factory->Create(data_offset, data_length);
-    // |data| takes care of ACKing.
-    send_ack = false;
-    request_info->peer->OnReceivedData(std::move(data));
-  }
-
-  // Get the request info again as the client callback may modify the info.
-  request_info = GetPendingRequestInfo(request_id);
-  if (request_info && encoded_data_length > 0)
-    request_info->peer->OnTransferSizeUpdated(encoded_data_length);
-
-  // Acknowledge the reception of this data.
-  if (send_ack)
-    message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id));
-}
-
 void ResourceDispatcher::OnDownloadedData(int request_id,
                                           int data_len,
                                           int encoded_data_length) {
@@ -333,7 +201,7 @@
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   if (!request_info)
     return;
-  request_info->response_start = ConsumeIOTimestamp();
+  request_info->response_start = base::TimeTicks::Now();
 
   ResourceResponseInfo renderer_response_info;
   ToResourceResponseInfo(*request_info, response_head, &renderer_response_info);
@@ -349,8 +217,7 @@
     request_info->response_url = redirect_info.new_url;
     request_info->response_method = redirect_info.new_method;
     request_info->response_referrer = GURL(redirect_info.new_referrer);
-    request_info->pending_redirect_message.reset(
-        new ResourceHostMsg_FollowRedirect(request_id));
+    request_info->has_pending_redirect = true;
     if (!request_info->is_deferred) {
       FollowPendingRedirect(request_info);
     }
@@ -361,14 +228,9 @@
 
 void ResourceDispatcher::FollowPendingRedirect(
     PendingRequestInfo* request_info) {
-  IPC::Message* msg = request_info->pending_redirect_message.release();
-  if (msg) {
-    if (request_info->url_loader) {
-      request_info->url_loader->FollowRedirect();
-      delete msg;
-    } else {
-      message_sender_->Send(msg);
-    }
+  if (request_info->has_pending_redirect) {
+    request_info->has_pending_redirect = false;
+    request_info->url_loader->FollowRedirect();
   }
 }
 
@@ -380,11 +242,8 @@
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   if (!request_info)
     return;
-  request_info->completion_time = ConsumeIOTimestamp();
+  request_info->completion_time = base::TimeTicks::Now();
   request_info->buffer.reset();
-  if (request_info->received_data_factory)
-    request_info->received_data_factory->Stop();
-  request_info->received_data_factory = nullptr;
   request_info->buffer_size = 0;
 
   RequestPeer* peer = request_info->peer.get();
@@ -425,15 +284,6 @@
   if (it == pending_requests_.end())
     return false;
 
-  PendingRequestInfo* request_info = it->second.get();
-
-  // |url_loader_client| releases the downloaded file. Otherwise (i.e., we
-  // are using Chrome IPC), we should release it here.
-  bool release_downloaded_file =
-      request_info->download_to_file && !it->second->url_loader_client;
-
-  ReleaseResourcesInMessageQueue(&request_info->deferred_message_queue);
-
   // Cancel loading.
   it->second->url_loader = nullptr;
   // Clear URLLoaderClient to stop receiving further Mojo IPC from the browser
@@ -446,14 +296,6 @@
   thread_task_runner_->DeleteSoon(FROM_HERE, it->second.release());
   pending_requests_.erase(it);
 
-  if (release_downloaded_file) {
-    message_sender_->Send(
-        new ResourceHostMsg_ReleaseDownloadedFile(request_id));
-  }
-
-  if (resource_scheduling_filter_.get())
-    resource_scheduling_filter_->ClearRequestIdTaskRunner(request_id);
-
   return true;
 }
 
@@ -466,9 +308,6 @@
 
   // Cancel the request if it didn't complete, and clean it up so the bridge
   // will receive no more messages.
-  const PendingRequestInfo& info = *it->second;
-  if (info.completion_time.is_null() && !info.url_loader)
-    message_sender_->Send(new ResourceHostMsg_CancelRequest(request_id));
   RemovePendingRequest(request_id);
 }
 
@@ -480,19 +319,12 @@
   }
   if (value) {
     request_info->is_deferred = value;
-    if (request_info->url_loader_client)
-      request_info->url_loader_client->SetDefersLoading();
+    request_info->url_loader_client->SetDefersLoading();
   } else if (request_info->is_deferred) {
     request_info->is_deferred = false;
-
-    if (request_info->url_loader_client)
-      request_info->url_loader_client->UnsetDefersLoading();
+    request_info->url_loader_client->UnsetDefersLoading();
 
     FollowPendingRedirect(request_info);
-
-    thread_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&ResourceDispatcher::FlushDeferredMessages,
-                                  weak_factory_.GetWeakPtr(), request_id));
   }
 }
 
@@ -501,12 +333,7 @@
                                            int intra_priority_value) {
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   DCHECK(request_info);
-  if (request_info->url_loader) {
-    request_info->url_loader->SetPriority(new_priority, intra_priority_value);
-  } else {
-    message_sender_->Send(new ResourceHostMsg_DidChangePriority(
-        request_id, new_priority, intra_priority_value));
-  }
+  request_info->url_loader->SetPriority(new_priority, intra_priority_value);
 }
 
 void ResourceDispatcher::OnTransferSizeUpdated(int request_id,
@@ -544,72 +371,17 @@
 ResourceDispatcher::PendingRequestInfo::~PendingRequestInfo() {
 }
 
-void ResourceDispatcher::DispatchMessage(const IPC::Message& message) {
-  IPC_BEGIN_MESSAGE_MAP(ResourceDispatcher, message)
-    IPC_MESSAGE_HANDLER(ResourceMsg_UploadProgress, OnUploadProgress)
-    IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedResponse, OnReceivedResponse)
-    IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedCachedMetadata,
-                        OnReceivedCachedMetadata)
-    IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedRedirect, OnReceivedRedirect)
-    IPC_MESSAGE_HANDLER(ResourceMsg_SetDataBuffer, OnSetDataBuffer)
-    IPC_MESSAGE_HANDLER(ResourceMsg_DataReceived, OnReceivedData)
-    IPC_MESSAGE_HANDLER(ResourceMsg_DataDownloaded, OnDownloadedData)
-    IPC_MESSAGE_HANDLER(ResourceMsg_RequestComplete, OnRequestComplete)
-  IPC_END_MESSAGE_MAP()
-}
-
-void ResourceDispatcher::FlushDeferredMessages(int request_id) {
-  PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
-  if (!request_info || request_info->is_deferred)
-    return;
-
-  if (request_info->url_loader) {
-    DCHECK(request_info->deferred_message_queue.empty());
-    request_info->url_loader_client->FlushDeferredMessages();
-    return;
-  }
-
-  // Because message handlers could result in request_info being destroyed,
-  // we need to work with a stack reference to the deferred queue.
-  MessageQueue q;
-  q.swap(request_info->deferred_message_queue);
-  while (!q.empty()) {
-    IPC::Message* m = q.front();
-    q.pop_front();
-    DispatchMessage(*m);
-    delete m;
-    // We need to find the request again in the list as it may have completed
-    // by now and the request_info instance above may be invalid.
-    request_info = GetPendingRequestInfo(request_id);
-    if (!request_info) {
-      // The recipient is gone, the messages won't be handled and
-      // resources they might hold won't be released. Explicitly release
-      // them from here so that they won't leak.
-      ReleaseResourcesInMessageQueue(&q);
-      return;
-    }
-    // If this request is deferred in the context of the above message, then
-    // we should honor the same and stop dispatching further messages.
-    if (request_info->is_deferred) {
-      request_info->deferred_message_queue.swap(q);
-      return;
-    }
-  }
-}
-
 void ResourceDispatcher::StartSync(
     std::unique_ptr<ResourceRequest> request,
     int routing_id,
     const url::Origin& frame_origin,
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     SyncLoadResponse* response,
-    blink::WebURLRequest::LoadingIPCType ipc_type,
     mojom::URLLoaderFactory* url_loader_factory,
     std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
     double timeout) {
   CheckSchemeForReferrerPolicy(*request);
 
-  if (ipc_type == blink::WebURLRequest::LoadingIPCType::kMojo) {
     mojom::URLLoaderFactoryPtrInfo url_loader_factory_copy;
     url_loader_factory->Clone(mojo::MakeRequest(&url_loader_factory_copy));
     base::WaitableEvent completed_event(
@@ -634,32 +406,6 @@
                        base::Unretained(terminate_sync_load_event_), timeout));
 
     completed_event.Wait();
-  } else {
-    SyncLoadResult result;
-    IPC::SyncMessage* msg = new ResourceHostMsg_SyncLoad(
-        routing_id, MakeRequestID(), *request, &result);
-
-    // NOTE: This may pump events (see RenderThread::Send).
-    if (!message_sender_->Send(msg)) {
-      response->error_code = net::ERR_FAILED;
-      return;
-    }
-
-    response->error_code = result.error_code;
-    response->url = result.final_url;
-    response->info.headers = result.headers;
-    response->info.mime_type = result.mime_type;
-    response->info.charset = result.charset;
-    response->info.request_time = result.request_time;
-    response->info.response_time = result.response_time;
-    response->info.load_timing = result.load_timing;
-    response->info.devtools_info = result.devtools_info;
-    response->data.swap(result.data);
-    response->info.download_file_path = result.download_file_path;
-    response->info.socket_address = result.socket_address;
-    response->info.encoded_data_length = result.encoded_data_length;
-    response->info.encoded_body_length = result.encoded_body_length;
-  }
 }
 
 int ResourceDispatcher::StartAsync(
@@ -670,7 +416,6 @@
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     bool is_sync,
     std::unique_ptr<RequestPeer> peer,
-    blink::WebURLRequest::LoadingIPCType ipc_type,
     mojom::URLLoaderFactory* url_loader_factory,
     std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
     mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints) {
@@ -683,11 +428,6 @@
       frame_origin, request->url, request->method, request->referrer,
       request->download_to_file);
 
-  if (resource_scheduling_filter_.get() && loading_task_runner) {
-    resource_scheduling_filter_->SetRequestIdTaskRunner(request_id,
-                                                        loading_task_runner);
-  }
-
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       loading_task_runner ? loading_task_runner : thread_task_runner_;
 
@@ -703,35 +443,27 @@
     return request_id;
   }
 
-  if (ipc_type == blink::WebURLRequest::LoadingIPCType::kMojo) {
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner =
-        loading_task_runner ? loading_task_runner : thread_task_runner_;
-    std::unique_ptr<URLLoaderClientImpl> client(
-        new URLLoaderClientImpl(request_id, this, task_runner));
+  std::unique_ptr<URLLoaderClientImpl> client(
+      new URLLoaderClientImpl(request_id, this, task_runner));
 
-    uint32_t options = mojom::kURLLoadOptionNone;
-    // TODO(jam): use this flag for ResourceDispatcherHost code path once
-    // MojoLoading is the only IPC code path.
-    if (base::FeatureList::IsEnabled(features::kNetworkService) &&
-        request->fetch_request_context_type != REQUEST_CONTEXT_TYPE_FETCH) {
-      // MIME sniffing should be disabled for a request initiated by fetch().
-      options |= mojom::kURLLoadOptionSniffMimeType;
-    }
-    if (is_sync)
-      options |= mojom::kURLLoadOptionSynchronous;
-
-    std::unique_ptr<ThrottlingURLLoader> url_loader =
-        ThrottlingURLLoader::CreateLoaderAndStart(
-            url_loader_factory, std::move(throttles), routing_id, request_id,
-            options, *request, client.get(), traffic_annotation,
-            std::move(task_runner));
-    pending_requests_[request_id]->url_loader = std::move(url_loader);
-    pending_requests_[request_id]->url_loader_client = std::move(client);
-  } else {
-    message_sender_->Send(new ResourceHostMsg_RequestResource(
-        routing_id, request_id, *request,
-        net::MutableNetworkTrafficAnnotationTag(traffic_annotation)));
+  uint32_t options = mojom::kURLLoadOptionNone;
+  // TODO(jam): use this flag for ResourceDispatcherHost code path once
+  // MojoLoading is the only IPC code path.
+  if (base::FeatureList::IsEnabled(features::kNetworkService) &&
+      request->fetch_request_context_type != REQUEST_CONTEXT_TYPE_FETCH) {
+    // MIME sniffing should be disabled for a request initiated by fetch().
+    options |= mojom::kURLLoadOptionSniffMimeType;
   }
+  if (is_sync)
+    options |= mojom::kURLLoadOptionSynchronous;
+
+  std::unique_ptr<ThrottlingURLLoader> url_loader =
+      ThrottlingURLLoader::CreateLoaderAndStart(
+          url_loader_factory, std::move(throttles), routing_id, request_id,
+          options, *request, client.get(), traffic_annotation,
+          std::move(task_runner));
+  pending_requests_[request_id]->url_loader = std::move(url_loader);
+  pending_requests_[request_id]->url_loader_client = std::move(client);
 
   return request_id;
 }
@@ -791,14 +523,6 @@
   return base::TimeTicks::FromInternalValue(result);
 }
 
-base::TimeTicks ResourceDispatcher::ConsumeIOTimestamp() {
-  if (io_timestamp_ == base::TimeTicks())
-    return base::TimeTicks::Now();
-  base::TimeTicks result = io_timestamp_;
-  io_timestamp_ = base::TimeTicks();
-  return result;
-}
-
 void ResourceDispatcher::ContinueForNavigation(
     int request_id,
     mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints) {
@@ -824,63 +548,4 @@
   client_ptr->Bind(std::move(url_loader_client_endpoints));
 }
 
-// static
-bool ResourceDispatcher::IsResourceDispatcherMessage(
-    const IPC::Message& message) {
-  switch (message.type()) {
-    case ResourceMsg_UploadProgress::ID:
-    case ResourceMsg_ReceivedResponse::ID:
-    case ResourceMsg_ReceivedCachedMetadata::ID:
-    case ResourceMsg_ReceivedRedirect::ID:
-    case ResourceMsg_SetDataBuffer::ID:
-    case ResourceMsg_DataReceived::ID:
-    case ResourceMsg_DataDownloaded::ID:
-    case ResourceMsg_RequestComplete::ID:
-      return true;
-
-    default:
-      break;
-  }
-
-  return false;
-}
-
-// static
-void ResourceDispatcher::ReleaseResourcesInDataMessage(
-    const IPC::Message& message) {
-  base::PickleIterator iter(message);
-  int request_id;
-  if (!iter.ReadInt(&request_id)) {
-    NOTREACHED() << "malformed resource message";
-    return;
-  }
-
-  // If the message contains a shared memory handle, we should close the handle
-  // or there will be a memory leak.
-  if (message.type() == ResourceMsg_SetDataBuffer::ID) {
-    base::SharedMemoryHandle shm_handle;
-    if (IPC::ParamTraits<base::SharedMemoryHandle>::Read(&message,
-                                                         &iter,
-                                                         &shm_handle)) {
-      if (base::SharedMemory::IsHandleValid(shm_handle))
-        base::SharedMemory::CloseHandle(shm_handle);
-    }
-  }
-}
-
-// static
-void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) {
-  while (!queue->empty()) {
-    IPC::Message* message = queue->front();
-    ReleaseResourcesInDataMessage(*message);
-    queue->pop_front();
-    delete message;
-  }
-}
-
-void ResourceDispatcher::SetResourceSchedulingFilter(
-    scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter) {
-  resource_scheduling_filter_ = resource_scheduling_filter;
-}
-
 }  // namespace content
diff --git a/content/renderer/loader/resource_dispatcher.h b/content/renderer/loader/resource_dispatcher.h
index ce4a7ccb..d0f8329 100644
--- a/content/renderer/loader/resource_dispatcher.h
+++ b/content/renderer/loader/resource_dispatcher.h
@@ -25,8 +25,6 @@
 #include "content/public/common/resource_type.h"
 #include "content/public/common/url_loader.mojom.h"
 #include "content/public/common/url_loader_throttle.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "net/base/request_priority.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -49,11 +47,9 @@
 namespace content {
 class RequestPeer;
 class ResourceDispatcherDelegate;
-class ResourceSchedulingFilter;
 struct ResourceResponseInfo;
 struct ResourceRequest;
 struct ResourceResponseHead;
-class SharedMemoryReceivedDataFactory;
 struct SiteIsolationResponseMetaData;
 struct SyncLoadResponse;
 class ThrottlingURLLoader;
@@ -66,7 +62,7 @@
 // This class serves as a communication interface to the ResourceDispatcherHost
 // in the browser process. It can be used from any child process.
 // Virtual methods are for tests.
-class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
+class CONTENT_EXPORT ResourceDispatcher {
  public:
   // Generates ids for requests initiated by child processes unique to the
   // particular process, counted up from 0 (browser initiated requests count
@@ -77,13 +73,9 @@
   // CORS preflight requests.
   static int MakeRequestID();
 
-  ResourceDispatcher(
-      IPC::Sender* sender,
+  explicit ResourceDispatcher(
       scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner);
-  ~ResourceDispatcher() override;
-
-  // IPC::Listener implementation.
-  bool OnMessageReceived(const IPC::Message& message) override;
+  virtual ~ResourceDispatcher();
 
   // Call this method to load the resource synchronously (i.e., in one shot).
   // This is an alternative to the StartAsync method. Be warned that this method
@@ -102,15 +94,13 @@
       const url::Origin& frame_origin,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       SyncLoadResponse* response,
-      blink::WebURLRequest::LoadingIPCType ipc_type,
       mojom::URLLoaderFactory* url_loader_factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
       double timeout);
 
   // Call this method to initiate the request. If this method succeeds, then
   // the peer's methods will be called asynchronously to report various events.
-  // Returns the request id. |url_loader_factory| must be non-null if and only
-  // if |ipc_type| is LoadingIPCType::Mojo.
+  // Returns the request id. |url_loader_factory| must be non-null.
   //
   // |routing_id| is used to associated the bridge with a frame's network
   // context.
@@ -125,7 +115,6 @@
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       bool is_sync,
       std::unique_ptr<RequestPeer> peer,
-      blink::WebURLRequest::LoadingIPCType ipc_type,
       mojom::URLLoaderFactory* url_loader_factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
       mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints);
@@ -148,31 +137,17 @@
                          net::RequestPriority new_priority,
                          int intra_priority_value);
 
-  void set_message_sender(IPC::Sender* sender) {
-    DCHECK(sender);
-    DCHECK(pending_requests_.empty());
-    message_sender_ = sender;
-  }
-
   // This does not take ownership of the delegate. It is expected that the
   // delegate have a longer lifetime than the ResourceDispatcher.
   void set_delegate(ResourceDispatcherDelegate* delegate) {
     delegate_ = delegate;
   }
 
-  // Remembers IO thread timestamp for next resource message.
-  void set_io_timestamp(base::TimeTicks io_timestamp) {
-    io_timestamp_ = io_timestamp;
-  }
-
   void SetThreadTaskRunner(
       scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner) {
     thread_task_runner_ = thread_task_runner;
   }
 
-  void SetResourceSchedulingFilter(
-      scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter);
-
   base::WeakPtr<ResourceDispatcher> GetWeakPtr() {
     return weak_factory_.GetWeakPtr();
   }
@@ -193,7 +168,6 @@
   friend class URLResponseBodyConsumer;
   friend class ResourceDispatcherTest;
 
-  using MessageQueue = base::circular_deque<IPC::Message*>;
   struct PendingRequestInfo {
     PendingRequestInfo(std::unique_ptr<RequestPeer> peer,
                        ResourceType resource_type,
@@ -209,7 +183,6 @@
     std::unique_ptr<RequestPeer> peer;
     ResourceType resource_type;
     int render_frame_id;
-    MessageQueue deferred_message_queue;
     bool is_deferred = false;
     // Original requested url.
     GURL url;
@@ -221,12 +194,11 @@
     std::string response_method;
     GURL response_referrer;
     bool download_to_file;
-    std::unique_ptr<IPC::Message> pending_redirect_message;
+    bool has_pending_redirect = false;
     base::TimeTicks request_start;
     base::TimeTicks response_start;
     base::TimeTicks completion_time;
     linked_ptr<base::SharedMemory> buffer;
-    scoped_refptr<SharedMemoryReceivedDataFactory> received_data_factory;
     std::unique_ptr<SiteIsolationResponseMetaData> site_isolation_metadata;
     int buffer_size;
 
@@ -251,24 +223,10 @@
   void OnReceivedRedirect(int request_id,
                           const net::RedirectInfo& redirect_info,
                           const ResourceResponseHead& response_head);
-  void OnSetDataBuffer(int request_id,
-                       base::SharedMemoryHandle shm_handle,
-                       int shm_size);
-  void OnReceivedData(int request_id,
-                      int data_offset,
-                      int data_length,
-                      int encoded_data_length);
   void OnDownloadedData(int request_id, int data_len, int encoded_data_length);
   void OnRequestComplete(int request_id,
                          const network::URLLoaderCompletionStatus& status);
 
-  // Dispatch the message to one of the message response handlers.
-  void DispatchMessage(const IPC::Message& message);
-
-  // Dispatch any deferred messages for the given request, provided it is not
-  // again in the deferred state. This method may mutate |pending_requests_|.
-  void FlushDeferredMessages(int request_id);
-
   void ToResourceResponseInfo(const PendingRequestInfo& request_info,
                               const ResourceResponseHead& browser_info,
                               ResourceResponseInfo* renderer_info) const;
@@ -277,41 +235,16 @@
       const PendingRequestInfo& request_info,
       const base::TimeTicks& browser_completion_time) const;
 
-  // Returns timestamp provided by IO thread. If no timestamp is supplied,
-  // then current time is returned. Saved timestamp is reset, so following
-  // invocations will return current time until set_io_timestamp is called.
-  base::TimeTicks ConsumeIOTimestamp();
-
   void ContinueForNavigation(
       int request_id,
       mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints);
 
-  // Returns true if the message passed in is a resource related message.
-  static bool IsResourceDispatcherMessage(const IPC::Message& message);
-
-  // ViewHostMsg_Resource_DataReceived is not POD, it has a shared memory
-  // handle in it that we should cleanup it up nicely. This method accepts any
-  // message and determine whether the message is
-  // ViewHostMsg_Resource_DataReceived and clean up the shared memory handle.
-  static void ReleaseResourcesInDataMessage(const IPC::Message& message);
-
-  // Iterate through a message queue and clean up the messages by calling
-  // ReleaseResourcesInDataMessage and removing them from the queue. Intended
-  // for use on deferred message queues that are no longer needed.
-  static void ReleaseResourcesInMessageQueue(MessageQueue* queue);
-
-  IPC::Sender* message_sender_;
-
   // All pending requests issued to the host
   PendingRequestMap pending_requests_;
 
   ResourceDispatcherDelegate* delegate_;
 
-  // IO thread timestamp for ongoing IPC message.
-  base::TimeTicks io_timestamp_;
-
   scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
-  scoped_refptr<ResourceSchedulingFilter> resource_scheduling_filter_;
 
   base::WaitableEvent* terminate_sync_load_event_ = nullptr;
 
diff --git a/content/renderer/loader/resource_dispatcher_unittest.cc b/content/renderer/loader/resource_dispatcher_unittest.cc
index a32540d..7e428cb7 100644
--- a/content/renderer/loader/resource_dispatcher_unittest.cc
+++ b/content/renderer/loader/resource_dispatcher_unittest.cc
@@ -21,7 +21,6 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/common/appcache_interfaces.h"
-#include "content/common/resource_messages.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/resource_request_body.h"
@@ -44,169 +43,51 @@
 
 namespace content {
 
-static const char kTestPageUrl[] = "http://www.google.com/";
-static const char kTestPageHeaders[] =
-  "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
-static const char kTestPageMimeType[] = "text/html";
-static const char kTestPageCharset[] = "";
-static const char kTestPageContents[] =
-  "<html><head><title>Google</title></head><body><h1>Google</h1></body></html>";
-static const char kTestRedirectHeaders[] =
-  "HTTP/1.1 302 Found\nLocation:http://www.google.com/\n\n";
+static constexpr char kTestPageUrl[] = "http://www.google.com/";
+static constexpr char kTestPageHeaders[] =
+    "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
+static constexpr char kTestPageMimeType[] = "text/html";
+static constexpr char kTestPageCharset[] = "";
+static constexpr char kTestPageContents[] =
+    "<html><head><title>Google</title></head><body><h1>Google</h1></body></"
+    "html>";
 
 // Sets up the message sender override for the unit test.
-class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
+class ResourceDispatcherTest : public testing::Test,
+                               public mojom::URLLoaderFactory {
  public:
   ResourceDispatcherTest()
-      : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())) {
-  }
+      : dispatcher_(new ResourceDispatcher(message_loop_.task_runner())) {}
 
   ~ResourceDispatcherTest() override {
-    shared_memory_map_.clear();
     dispatcher_.reset();
     base::RunLoop().RunUntilIdle();
   }
 
-  // Emulates IPC send operations (IPC::Sender) by adding
-  // pending messages to the queue.
-  bool Send(IPC::Message* msg) override {
-    message_queue_.push_back(IPC::Message(*msg));
-    delete msg;
-    return true;
+  void CreateLoaderAndStart(
+      mojom::URLLoaderRequest request,
+      int32_t routing_id,
+      int32_t request_id,
+      uint32_t options,
+      const ResourceRequest& url_request,
+      mojom::URLLoaderClientPtr client,
+      const net::MutableNetworkTrafficAnnotationTag& annotation) override {
+    loader_and_clients_.emplace_back(std::move(request), std::move(client));
   }
 
-  size_t queued_messages() const { return message_queue_.size(); }
+  void Clone(mojom::URLLoaderFactoryRequest request) override { NOTREACHED(); }
 
-  // Returns the ID of the consumed request.  Can't make assumptions about the
-  // ID, because numbering is based on a global.
-  int ConsumeRequestResource() {
-    if (message_queue_.empty()) {
-      ADD_FAILURE() << "Missing resource request message";
-      return -1;
-    }
-
-    ResourceHostMsg_RequestResource::Param params;
-    if (static_cast<uint32_t>(ResourceHostMsg_RequestResource::ID) !=
-            message_queue_[0].type() ||
-        !ResourceHostMsg_RequestResource::Read(&message_queue_[0], &params)) {
-      ADD_FAILURE() << "Expected ResourceHostMsg_RequestResource message";
-      return -1;
-    }
-    ResourceRequest request = std::get<2>(params);
-    EXPECT_EQ(kTestPageUrl, request.url.spec());
-    message_queue_.erase(message_queue_.begin());
-    return std::get<1>(params);
-  }
-
-  void ConsumeFollowRedirect(int expected_request_id) {
-    ASSERT_FALSE(message_queue_.empty());
-    std::tuple<int> args;
-    ASSERT_EQ(static_cast<uint32_t>(ResourceHostMsg_FollowRedirect::ID),
-              message_queue_[0].type());
-    ASSERT_TRUE(ResourceHostMsg_FollowRedirect::Read(
-        &message_queue_[0], &args));
-    EXPECT_EQ(expected_request_id, std::get<0>(args));
-    message_queue_.erase(message_queue_.begin());
-  }
-
-  void ConsumeDataReceived_ACK(int expected_request_id) {
-    ASSERT_FALSE(message_queue_.empty());
-    std::tuple<int> args;
-    ASSERT_EQ(static_cast<uint32_t>(ResourceHostMsg_DataReceived_ACK::ID),
-              message_queue_[0].type());
-    ASSERT_TRUE(ResourceHostMsg_DataReceived_ACK::Read(
-        &message_queue_[0], &args));
-    EXPECT_EQ(expected_request_id, std::get<0>(args));
-    message_queue_.erase(message_queue_.begin());
-  }
-
-  void ConsumeReleaseDownloadedFile(int expected_request_id) {
-    ASSERT_FALSE(message_queue_.empty());
-    std::tuple<int> args;
-    ASSERT_EQ(static_cast<uint32_t>(ResourceHostMsg_ReleaseDownloadedFile::ID),
-              message_queue_[0].type());
-    ASSERT_TRUE(ResourceHostMsg_ReleaseDownloadedFile::Read(
-        &message_queue_[0], &args));
-    EXPECT_EQ(expected_request_id, std::get<0>(args));
-    message_queue_.erase(message_queue_.begin());
-  }
-
-  void ConsumeCancelRequest(int expected_request_id) {
-    ASSERT_FALSE(message_queue_.empty());
-    std::tuple<int> args;
-    ASSERT_EQ(static_cast<uint32_t>(ResourceHostMsg_CancelRequest::ID),
-              message_queue_[0].type());
-    ASSERT_TRUE(ResourceHostMsg_CancelRequest::Read(
-        &message_queue_[0], &args));
-    EXPECT_EQ(expected_request_id, std::get<0>(args));
-    message_queue_.erase(message_queue_.begin());
-  }
-
-  void NotifyReceivedRedirect(int request_id) {
-    ResourceResponseHead head;
-    std::string raw_headers(kTestRedirectHeaders);
-    std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0');
-    head.headers = new net::HttpResponseHeaders(raw_headers);
-    net::RedirectInfo redirect_info;
-    redirect_info.status_code = 302;
-    redirect_info.new_method = "GET";
-    redirect_info.new_url = GURL(kTestPageUrl);
-    redirect_info.new_site_for_cookies = GURL(kTestPageUrl);
-    EXPECT_EQ(true, dispatcher_->OnMessageReceived(ResourceMsg_ReceivedRedirect(
-                        request_id, redirect_info, head)));
-  }
-
-  void NotifyReceivedResponse(int request_id) {
+  void CallOnReceiveResponse(mojom::URLLoaderClient* client) {
     ResourceResponseHead head;
     std::string raw_headers(kTestPageHeaders);
     std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0');
     head.headers = new net::HttpResponseHeaders(raw_headers);
     head.mime_type = kTestPageMimeType;
     head.charset = kTestPageCharset;
-    EXPECT_EQ(true, dispatcher_->OnMessageReceived(
-                        ResourceMsg_ReceivedResponse(request_id, head)));
+    client->OnReceiveResponse(head, {}, {});
   }
 
-  void NotifySetDataBuffer(int request_id, size_t buffer_size) {
-    base::SharedMemory* shared_memory = new base::SharedMemory();
-    ASSERT_FALSE(shared_memory_map_[request_id]);
-    shared_memory_map_[request_id] = base::WrapUnique(shared_memory);
-    EXPECT_TRUE(shared_memory->CreateAndMapAnonymous(buffer_size));
-
-    base::SharedMemoryHandle duplicate_handle =
-        shared_memory->handle().Duplicate();
-    EXPECT_TRUE(duplicate_handle.IsValid());
-    EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_SetDataBuffer(
-        request_id, duplicate_handle, shared_memory->requested_size())));
-  }
-
-  void NotifyDataReceived(int request_id, const std::string& data) {
-    ASSERT_LE(data.length(), shared_memory_map_[request_id]->requested_size());
-    memcpy(shared_memory_map_[request_id]->memory(), data.c_str(),
-           data.length());
-
-    EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_DataReceived(
-        request_id, 0, data.length(), data.length())));
-  }
-
-  void NotifyDataDownloaded(int request_id,
-                            int decoded_length,
-                            int encoded_data_length) {
-    EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_DataDownloaded(
-        request_id, decoded_length, encoded_data_length)));
-  }
-
-  void NotifyRequestComplete(int request_id, size_t total_size) {
-    network::URLLoaderCompletionStatus status;
-    status.error_code = net::OK;
-    status.exists_in_cache = false;
-    status.encoded_data_length = total_size;
-    EXPECT_TRUE(dispatcher_->OnMessageReceived(
-        ResourceMsg_RequestComplete(request_id, status)));
-  }
-
-  std::unique_ptr<ResourceRequest> CreateResourceRequest(
-      bool download_to_file) {
+  std::unique_ptr<ResourceRequest> CreateResourceRequest() {
     std::unique_ptr<ResourceRequest> request(new ResourceRequest());
 
     request->method = "GET";
@@ -217,7 +98,6 @@
     request->priority = net::LOW;
     request->fetch_request_mode = network::mojom::FetchRequestMode::kNoCORS;
     request->fetch_frame_type = network::mojom::RequestContextFrameType::kNone;
-    request->download_to_file = download_to_file;
 
     const RequestExtraData extra_data;
     extra_data.CopyToResourceRequest(request.get());
@@ -234,19 +114,16 @@
         new TestRequestPeer(dispatcher(), peer_context));
     int request_id = dispatcher()->StartAsync(
         std::move(request), 0, nullptr, url::Origin(),
-        TRAFFIC_ANNOTATION_FOR_TESTS, false, std::move(peer),
-        blink::WebURLRequest::LoadingIPCType::kChromeIPC, nullptr,
+        TRAFFIC_ANNOTATION_FOR_TESTS, false, std::move(peer), this,
         std::vector<std::unique_ptr<URLLoaderThrottle>>(),
         mojom::URLLoaderClientEndpointsPtr());
     peer_context->request_id = request_id;
     return request_id;
   }
 
- private:
-  // Map of request IDs to shared memory.
-  std::map<int, std::unique_ptr<base::SharedMemory>> shared_memory_map_;
-
-  std::vector<IPC::Message> message_queue_;
+ protected:
+  std::vector<std::pair<mojom::URLLoaderRequest, mojom::URLLoaderClientPtr>>
+      loader_and_clients_;
   base::MessageLoop message_loop_;
   std::unique_ptr<ResourceDispatcher> dispatcher_;
 };
@@ -261,133 +138,6 @@
   EXPECT_GE(first_id, 0);
 }
 
-// Does a simple request and tests that the correct data is received.  Simulates
-// two reads.
-TEST_F(ResourceDispatcherTest, RoundTrip) {
-  // Number of bytes received in the first read.
-  const size_t kFirstReceiveSize = 2;
-  ASSERT_LT(kFirstReceiveSize, strlen(kTestPageContents));
-
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, std::string(kTestPageContents, kFirstReceiveSize));
-  ConsumeDataReceived_ACK(id);
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyDataReceived(id, kTestPageContents + kFirstReceiveSize);
-  ConsumeDataReceived_ACK(id);
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-}
-
-// Tests that the request IDs are straight when there are two interleaving
-// requests.
-TEST_F(ResourceDispatcherTest, MultipleRequests) {
-  const char kTestPageContents2[] = "Not kTestPageContents";
-
-  std::unique_ptr<ResourceRequest> request1(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context1;
-  StartAsync(std::move(request1), nullptr, &peer_context1);
-
-  std::unique_ptr<ResourceRequest> request2(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context2;
-  StartAsync(std::move(request2), nullptr, &peer_context2);
-
-  int id1 = ConsumeRequestResource();
-  int id2 = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id1);
-  EXPECT_TRUE(peer_context1.received_response);
-  EXPECT_FALSE(peer_context2.received_response);
-  NotifyReceivedResponse(id2);
-  EXPECT_TRUE(peer_context2.received_response);
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifySetDataBuffer(id2, strlen(kTestPageContents2));
-  NotifyDataReceived(id2, kTestPageContents2);
-  ConsumeDataReceived_ACK(id2);
-  NotifySetDataBuffer(id1, strlen(kTestPageContents));
-  NotifyDataReceived(id1, kTestPageContents);
-  ConsumeDataReceived_ACK(id1);
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyRequestComplete(id1, strlen(kTestPageContents));
-  EXPECT_EQ(kTestPageContents, peer_context1.data);
-  EXPECT_TRUE(peer_context1.complete);
-  EXPECT_FALSE(peer_context2.complete);
-
-  NotifyRequestComplete(id2, strlen(kTestPageContents2));
-  EXPECT_EQ(kTestPageContents2, peer_context2.data);
-  EXPECT_TRUE(peer_context2.complete);
-
-  EXPECT_EQ(0u, queued_messages());
-}
-
-// Tests that the cancel method prevents other messages from being received.
-TEST_F(ResourceDispatcherTest, Cancel) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  // Cancel the request.
-  dispatcher()->Cancel(request_id);
-  ConsumeCancelRequest(id);
-
-  // Any future messages related to the request should be ignored.
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.received_response);
-  EXPECT_FALSE(peer_context.complete);
-}
-
-// Tests that calling cancel during a callback works as expected.
-TEST_F(ResourceDispatcherTest, CancelDuringCallback) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  StartAsync(std::move(request), nullptr, &peer_context);
-  peer_context.cancel_on_receive_response = true;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id);
-  EXPECT_TRUE(peer_context.received_response);
-  // Request should have been cancelled.
-  ConsumeCancelRequest(id);
-
-  // Any future messages related to the request should be ignored.
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-}
-
 class TestResourceDispatcherDelegate : public ResourceDispatcherDelegate {
  public:
   TestResourceDispatcherDelegate() {}
@@ -453,409 +203,97 @@
 };
 
 TEST_F(ResourceDispatcherTest, DelegateTest) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
+  std::unique_ptr<ResourceRequest> request(CreateResourceRequest());
   TestRequestPeer::Context peer_context;
   StartAsync(std::move(request), nullptr, &peer_context);
 
+  ASSERT_EQ(1u, loader_and_clients_.size());
+  mojom::URLLoaderClientPtr client = std::move(loader_and_clients_[0].second);
+  loader_and_clients_.clear();
+
   // Set the delegate that inserts a new peer in OnReceivedResponse.
   TestResourceDispatcherDelegate delegate;
   dispatcher()->set_delegate(&delegate);
 
-  // Run a simple round-trip.
-  const size_t kFirstReceiveSize = 2;
-  ASSERT_LT(kFirstReceiveSize, strlen(kTestPageContents));
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
   // The wrapper eats all messages until RequestComplete message is sent.
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, std::string(kTestPageContents, kFirstReceiveSize));
-  ConsumeDataReceived_ACK(id);
-  NotifyDataReceived(id, kTestPageContents + kFirstReceiveSize);
-  ConsumeDataReceived_ACK(id);
+  CallOnReceiveResponse(client.get());
+
+  mojo::DataPipe data_pipe;
+  client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
+
+  uint32_t size = strlen(kTestPageContents);
+  auto result = data_pipe.producer_handle->WriteData(kTestPageContents, &size,
+                                                     MOJO_WRITE_DATA_FLAG_NONE);
+  ASSERT_EQ(result, MOJO_RESULT_OK);
+  ASSERT_EQ(size, strlen(kTestPageContents));
+
+  data_pipe.producer_handle.reset();
+
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(peer_context.received_response);
-  EXPECT_EQ(0u, queued_messages());
 
   // This lets the wrapper peer pass all the messages to the original
   // peer at once.
-  NotifyRequestComplete(id, strlen(kTestPageContents));
+  network::URLLoaderCompletionStatus status;
+  status.error_code = net::OK;
+  status.exists_in_cache = false;
+  status.encoded_data_length = strlen(kTestPageContents);
+  client->OnComplete(status);
+
+  base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(peer_context.received_response);
   EXPECT_EQ(kTestPageContents, peer_context.data);
   EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
 }
 
 TEST_F(ResourceDispatcherTest, CancelDuringCallbackWithWrapperPeer) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
+  std::unique_ptr<ResourceRequest> request(CreateResourceRequest());
   TestRequestPeer::Context peer_context;
   StartAsync(std::move(request), nullptr, &peer_context);
   peer_context.cancel_on_receive_response = true;
 
+  ASSERT_EQ(1u, loader_and_clients_.size());
+  mojom::URLLoaderClientPtr client = std::move(loader_and_clients_[0].second);
+  loader_and_clients_.clear();
+
   // Set the delegate that inserts a new peer in OnReceivedResponse.
   TestResourceDispatcherDelegate delegate;
   dispatcher()->set_delegate(&delegate);
 
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
+  CallOnReceiveResponse(client.get());
+  mojo::DataPipe data_pipe;
+  client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
+  uint32_t size = strlen(kTestPageContents);
+  auto result = data_pipe.producer_handle->WriteData(kTestPageContents, &size,
+                                                     MOJO_WRITE_DATA_FLAG_NONE);
+  ASSERT_EQ(result, MOJO_RESULT_OK);
+  ASSERT_EQ(size, strlen(kTestPageContents));
+  data_pipe.producer_handle.reset();
 
-  // The wrapper eats all messages until RequestComplete message is sent.
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  ConsumeDataReceived_ACK(id);
-
+  base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(peer_context.received_response);
-  EXPECT_EQ(0u, queued_messages());
 
   // This lets the wrapper peer pass all the messages to the original
   // peer at once, but the original peer cancels right after it receives
   // the response. (This will remove pending request info from
   // ResourceDispatcher while the wrapper peer is still running
   // OnCompletedRequest, but it should not lead to crashes.)
-  NotifyRequestComplete(id, strlen(kTestPageContents));
+  network::URLLoaderCompletionStatus status;
+  status.error_code = net::OK;
+  status.exists_in_cache = false;
+  status.encoded_data_length = strlen(kTestPageContents);
+  client->OnComplete(status);
 
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(peer_context.received_response);
   // Request should have been cancelled with no additional messages.
-  EXPECT_EQ(0u, queued_messages());
   EXPECT_TRUE(peer_context.cancelled);
-
-  // Any future messages related to the request should be ignored.
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  EXPECT_EQ(0u, queued_messages());
   EXPECT_EQ("", peer_context.data);
   EXPECT_FALSE(peer_context.complete);
 }
 
-// Checks that redirects work as expected.
-TEST_F(ResourceDispatcherTest, Redirect) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-
-  NotifyReceivedRedirect(id);
-  ConsumeFollowRedirect(id);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-
-  NotifyReceivedRedirect(id);
-  ConsumeFollowRedirect(id);
-  EXPECT_EQ(2, peer_context.seen_redirects);
-
-  NotifyReceivedResponse(id);
-  EXPECT_TRUE(peer_context.received_response);
-
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  ConsumeDataReceived_ACK(id);
-
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ(2, peer_context.seen_redirects);
-}
-
-// Tests that that cancelling during a redirect method prevents other messages
-// from being received.
-TEST_F(ResourceDispatcherTest, CancelDuringRedirect) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  StartAsync(std::move(request), nullptr, &peer_context);
-  peer_context.follow_redirects = false;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  // Redirect the request, which triggers a cancellation.
-  NotifyReceivedRedirect(id);
-  ConsumeCancelRequest(id);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-  EXPECT_EQ(0u, queued_messages());
-
-  // Any future messages related to the request should be ignored.  In practice,
-  // only the NotifyRequestComplete should be received after this point.
-  NotifyReceivedRedirect(id);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-}
-
-// Checks that deferring a request delays messages until it's resumed.
-TEST_F(ResourceDispatcherTest, Defer) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, true);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  // None of the messages should have been processed yet, so no queued messages
-  // to the browser process, and no data received by the peer.
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0, peer_context.seen_redirects);
-
-  // Resuming the request should asynchronously unleash the deferred messages.
-  dispatcher()->SetDefersLoading(request_id, false);
-  base::RunLoop().RunUntilIdle();
-
-  ConsumeDataReceived_ACK(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-}
-
-// Checks that deferring a request during a redirect delays messages until it's
-// resumed.
-TEST_F(ResourceDispatcherTest, DeferOnRedirect) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-  peer_context.defer_on_redirect = true;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  // The request should be deferred during the redirect, including the message
-  // to follow the redirect.
-  NotifyReceivedRedirect(id);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  // None of the messages should have been processed yet, so no queued messages
-  // to the browser process, and no data received by the peer.
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-
-  // Resuming the request should asynchronously unleash the deferred messages.
-  dispatcher()->SetDefersLoading(request_id, false);
-  base::RunLoop().RunUntilIdle();
-
-  ConsumeFollowRedirect(id);
-  ConsumeDataReceived_ACK(id);
-
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(1, peer_context.seen_redirects);
-}
-
-// Checks that a deferred request that's cancelled doesn't receive any messages.
-TEST_F(ResourceDispatcherTest, CancelDeferredRequest) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, true);
-  NotifyReceivedRedirect(id);
-  dispatcher()->Cancel(request_id);
-  ConsumeCancelRequest(id);
-
-  NotifyRequestComplete(id, 0);
-  base::RunLoop().RunUntilIdle();
-
-  // None of the messages should have been processed.
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0, peer_context.seen_redirects);
-}
-
-// Checks cancelling a request while flushing deferred requests from
-// the FlushDeferredMessages() task.
-TEST_F(ResourceDispatcherTest, CancelWhileFlushingDeferredRequests) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  // Cancel the request when the data message is handled.
-  peer_context.cancel_on_receive_data = true;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, true);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-
-  // None of the messages should have been processed yet.
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, false);
-
-  // Make sure that the FlushDeferredMessages() task posted from
-  // SetDefersLoading() is run. It should dispatch all the deferred
-  // messages.
-  base::RunLoop().RunUntilIdle();
-
-  // When the deferred DataReceived is dispatched, the handler will
-  // cancel the request, but the ACK is sent after the handler
-  // returns, so the cancel request ends up before the ACK in the
-  // message queue.
-  ConsumeCancelRequest(id);
-  ConsumeDataReceived_ACK(id);
-
-  // The data was consumed before the handler canceled
-  // the request, so the data should have been received.
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-}
-
-// Checks cancelling a request while flushing deferred requests from
-// OnMessageReceived().
-TEST_F(ResourceDispatcherTest,
-       CancelWhileFlushingDeferredRequestsFromOnMessageReceived) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  // Cancel the request when the data message is handled.
-  peer_context.cancel_on_receive_data = true;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, true);
-  NotifyReceivedResponse(id);
-  NotifySetDataBuffer(id, strlen(kTestPageContents));
-  NotifyDataReceived(id, kTestPageContents);
-
-  // None of the messages should have been processed yet.
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->SetDefersLoading(request_id, false);
-
-  // SetDefersLoading() posts a task to run FlushDeferredMessages() to dispatch
-  // the deferred messages. Since the message loop hasn't been run yet the
-  // task hasn't been run either and no IPC-messages should have been
-  // dispatched.
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  // Calling NotifyRequestComplete() here, before the task from
-  // SetDefersLoading() has been run, triggers the flush in
-  // OnMessageReceived().
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-
-  // When the deferred DataReceived is dispatched, the handler will
-  // cancel the request, but the ACK is sent after the handler
-  // returns, so the cancel request ends up before the ACK in the
-  // message queue.
-  ConsumeCancelRequest(id);
-  ConsumeDataReceived_ACK(id);
-
-  // The data was consumed before the handler canceled
-  // the request, so the data should have been received.
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  // Make sure that the FlushDeferredMessages() task posted from
-  // SetDefersLoading() is run. The messages should already have been
-  // flushed above, so it should be a NOOP.
-  base::RunLoop().RunUntilIdle();
-
-  // Check that the task didn't change anything.
-  EXPECT_EQ(kTestPageContents, peer_context.data);
-  EXPECT_FALSE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-}
-
-TEST_F(ResourceDispatcherTest, DownloadToFile) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(true));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-  const int kDownloadedIncrement = 100;
-  const int kEncodedIncrement = 50;
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-
-  int expected_total_downloaded_length = 0;
-  int expected_total_encoded_data_length = 0;
-  for (int i = 0; i < 10; ++i) {
-    NotifyDataDownloaded(id, kDownloadedIncrement, kEncodedIncrement);
-    expected_total_downloaded_length += kDownloadedIncrement;
-    expected_total_encoded_data_length += kEncodedIncrement;
-    EXPECT_EQ(expected_total_downloaded_length,
-              peer_context.total_downloaded_data_length);
-    EXPECT_EQ(expected_total_encoded_data_length,
-              peer_context.total_encoded_data_length);
-  }
-
-  NotifyRequestComplete(id, strlen(kTestPageContents));
-  EXPECT_EQ("", peer_context.data);
-  EXPECT_TRUE(peer_context.complete);
-  EXPECT_EQ(0u, queued_messages());
-
-  dispatcher()->RemovePendingRequest(request_id);
-  ConsumeReleaseDownloadedFile(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_EQ(expected_total_downloaded_length,
-            peer_context.total_downloaded_data_length);
-  EXPECT_EQ(expected_total_encoded_data_length,
-            peer_context.total_encoded_data_length);
-}
-
-// Make sure that when a download to file is cancelled, the file is destroyed.
-TEST_F(ResourceDispatcherTest, CancelDownloadToFile) {
-  std::unique_ptr<ResourceRequest> request(CreateResourceRequest(true));
-  TestRequestPeer::Context peer_context;
-  int request_id = StartAsync(std::move(request), nullptr, &peer_context);
-
-  int id = ConsumeRequestResource();
-  EXPECT_EQ(0u, queued_messages());
-
-  NotifyReceivedResponse(id);
-  EXPECT_EQ(0u, queued_messages());
-  EXPECT_TRUE(peer_context.received_response);
-
-  // Cancelling the request deletes the file.
-  dispatcher()->Cancel(request_id);
-  ConsumeCancelRequest(id);
-  ConsumeReleaseDownloadedFile(id);
-}
-
 TEST_F(ResourceDispatcherTest, Cookies) {
   // FIXME
 }
@@ -866,18 +304,15 @@
 
 class TimeConversionTest : public ResourceDispatcherTest {
  public:
-  bool Send(IPC::Message* msg) override {
-    delete msg;
-    return true;
-  }
-
   void PerformTest(const ResourceResponseHead& response_head) {
-    std::unique_ptr<ResourceRequest> request(CreateResourceRequest(false));
+    std::unique_ptr<ResourceRequest> request(CreateResourceRequest());
     TestRequestPeer::Context peer_context;
     StartAsync(std::move(request), nullptr, &peer_context);
 
-    dispatcher()->OnMessageReceived(
-        ResourceMsg_ReceivedResponse(0, response_head));
+    ASSERT_EQ(1u, loader_and_clients_.size());
+    auto client = std::move(loader_and_clients_[0].second);
+    loader_and_clients_.clear();
+    client->OnReceiveResponse(response_head, {}, {});
   }
 
   const ResourceResponseInfo& response_info() const { return response_info_; }
diff --git a/content/renderer/loader/resource_scheduling_filter.cc b/content/renderer/loader/resource_scheduling_filter.cc
deleted file mode 100644
index ca0cb037..0000000
--- a/content/renderer/loader/resource_scheduling_filter.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 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/renderer/loader/resource_scheduling_filter.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "content/renderer/loader/resource_dispatcher.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_message_start.h"
-
-namespace content {
-
-ResourceSchedulingFilter::ResourceSchedulingFilter(
-    const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
-    ResourceDispatcher* resource_dispatcher)
-    : main_thread_task_runner_(main_thread_task_runner),
-      resource_dispatcher_(resource_dispatcher->GetWeakPtr()),
-      weak_ptr_factory_(this) {
-  DCHECK(main_thread_task_runner_.get());
-}
-
-ResourceSchedulingFilter::~ResourceSchedulingFilter() {
-}
-
-bool ResourceSchedulingFilter::OnMessageReceived(const IPC::Message& message) {
-  base::AutoLock lock(request_id_to_task_runner_map_lock_);
-  int request_id;
-
-  base::PickleIterator pickle_iterator(message);
-  if (!pickle_iterator.ReadInt(&request_id)) {
-    NOTREACHED() << "malformed resource message";
-    return true;
-  }
-  // Dispatch the message on the request id specific task runner, if there is
-  // one, or on the general main_thread_task_runner if there isn't.
-  RequestIdToTaskRunnerMap::const_iterator iter =
-      request_id_to_task_runner_map_.find(request_id);
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner;
-  if (iter != request_id_to_task_runner_map_.end()) {
-    task_runner = iter->second;
-  } else {
-    task_runner = main_thread_task_runner_;
-  }
-  task_runner->PostTask(
-      FROM_HERE, base::BindOnce(&ResourceSchedulingFilter::DispatchMessage,
-                                weak_ptr_factory_.GetWeakPtr(), message));
-  return true;
-}
-
-void ResourceSchedulingFilter::SetRequestIdTaskRunner(
-    int id,
-    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
-  base::AutoLock lock(request_id_to_task_runner_map_lock_);
-  request_id_to_task_runner_map_.insert(std::make_pair(id, task_runner));
-}
-
-void ResourceSchedulingFilter::ClearRequestIdTaskRunner(int id) {
-  base::AutoLock lock(request_id_to_task_runner_map_lock_);
-  request_id_to_task_runner_map_.erase(id);
-}
-
-bool ResourceSchedulingFilter::GetSupportedMessageClasses(
-    std::vector<uint32_t>* supported_message_classes) const {
-  supported_message_classes->push_back(ResourceMsgStart);
-  return true;
-}
-
-void ResourceSchedulingFilter::DispatchMessage(const IPC::Message& message) {
-  if (resource_dispatcher_)
-    resource_dispatcher_->OnMessageReceived(message);
-}
-
-}  // namespace content
diff --git a/content/renderer/loader/resource_scheduling_filter.h b/content/renderer/loader/resource_scheduling_filter.h
deleted file mode 100644
index 63233b1..0000000
--- a/content/renderer/loader/resource_scheduling_filter.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 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_RENDERER_LOADER_RESOURCE_SCHEDULING_FILTER_H_
-#define CONTENT_RENDERER_LOADER_RESOURCE_SCHEDULING_FILTER_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "content/common/content_export.h"
-#include "ipc/message_filter.h"
-
-namespace content {
-class ResourceDispatcher;
-
-// This filter is used to dispatch resource messages on a specific
-// SingleThreadTaskRunner to facilitate task scheduling.
-class CONTENT_EXPORT ResourceSchedulingFilter : public IPC::MessageFilter {
- public:
-  ResourceSchedulingFilter(const scoped_refptr<base::SingleThreadTaskRunner>&
-                               main_thread_task_runner,
-                           ResourceDispatcher* resource_dispatcher);
-
-  // IPC::MessageFilter overrides:
-  bool OnMessageReceived(const IPC::Message& message) override;
-
-  bool GetSupportedMessageClasses(
-      std::vector<uint32_t>* supported_message_classes) const override;
-
-  // Sets the task runner associated with request messages with |id|.
-  void SetRequestIdTaskRunner(
-      int id,
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
-
-  // Removes the task runner associated with |id|.
-  void ClearRequestIdTaskRunner(int id);
-
-  void DispatchMessage(const IPC::Message& message);
-
- private:
-  ~ResourceSchedulingFilter() override;
-
-  using RequestIdToTaskRunnerMap =
-      std::map<int, scoped_refptr<base::SingleThreadTaskRunner>>;
-
-  // This lock guards |request_id_to_task_runner_map_|
-  base::Lock request_id_to_task_runner_map_lock_;
-  RequestIdToTaskRunnerMap request_id_to_task_runner_map_;
-
-  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-  base::WeakPtr<ResourceDispatcher> resource_dispatcher_;
-  base::WeakPtrFactory<ResourceSchedulingFilter> weak_ptr_factory_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ResourceSchedulingFilter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_LOADER_RESOURCE_SCHEDULING_FILTER_H_
diff --git a/content/renderer/loader/shared_memory_received_data_factory.cc b/content/renderer/loader/shared_memory_received_data_factory.cc
deleted file mode 100644
index b9530d50a..0000000
--- a/content/renderer/loader/shared_memory_received_data_factory.cc
+++ /dev/null
@@ -1,126 +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 "content/renderer/loader/shared_memory_received_data_factory.h"
-
-#include <algorithm>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "content/common/resource_messages.h"
-#include "ipc/ipc_sender.h"
-
-namespace content {
-
-class SharedMemoryReceivedDataFactory::SharedMemoryReceivedData final
-    : public RequestPeer::ReceivedData {
- public:
-  SharedMemoryReceivedData(
-      const char* payload,
-      int length,
-      scoped_refptr<SharedMemoryReceivedDataFactory> factory,
-      SharedMemoryReceivedDataFactory::TicketId id)
-      : payload_(payload),
-        length_(length),
-        factory_(factory),
-        id_(id) {}
-
-  ~SharedMemoryReceivedData() override { factory_->Reclaim(id_); }
-
-  const char* payload() const override { return payload_; }
-  int length() const override { return length_; }
-
- private:
-  const char* const payload_;
-  const int length_;
-
-  scoped_refptr<SharedMemoryReceivedDataFactory> factory_;
-  SharedMemoryReceivedDataFactory::TicketId id_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedMemoryReceivedData);
-};
-
-SharedMemoryReceivedDataFactory::SharedMemoryReceivedDataFactory(
-    IPC::Sender* message_sender,
-    int request_id,
-    linked_ptr<base::SharedMemory> memory)
-    : id_(0),
-      oldest_(0),
-      message_sender_(message_sender),
-      request_id_(request_id),
-      is_stopped_(false),
-      memory_(memory) {
-}
-
-SharedMemoryReceivedDataFactory::~SharedMemoryReceivedDataFactory() {
-  if (!is_stopped_)
-    SendAck(released_tickets_.size());
-}
-
-std::unique_ptr<RequestPeer::ReceivedData>
-SharedMemoryReceivedDataFactory::Create(int offset, int length) {
-  const char* start = static_cast<char*>(memory_->memory());
-  const char* payload = start + offset;
-  TicketId id = id_++;
-
-  return std::make_unique<SharedMemoryReceivedData>(payload, length, this, id);
-}
-
-void SharedMemoryReceivedDataFactory::Stop() {
-  is_stopped_ = true;
-  released_tickets_.clear();
-  message_sender_ = nullptr;
-}
-
-class SharedMemoryReceivedDataFactory::TicketComparator final {
- public:
-  explicit TicketComparator(TicketId oldest) : oldest_(oldest) {}
-  bool operator()(TicketId x, TicketId y) const {
-    if ((oldest_ <= x) == (oldest_ <= y))
-      return x <= y;
-
-    return (oldest_ <= x);
-  }
-
- private:
-  TicketId oldest_;
-};
-
-void SharedMemoryReceivedDataFactory::Reclaim(TicketId id) {
-  if (is_stopped_)
-    return;
-  if (oldest_ != id) {
-    released_tickets_.push_back(id);
-    return;
-  }
-
-  ++oldest_;
-  SendAck(1);
-  if (released_tickets_.empty()) {
-    // Fast path: (hopefully) the most typical case.
-    return;
-  }
-  std::sort(released_tickets_.begin(), released_tickets_.end(),
-            TicketComparator(oldest_));
-  size_t count = 0;
-  for (size_t i = 0;; ++i) {
-    if (i == released_tickets_.size() ||
-        released_tickets_[i] != static_cast<TicketId>(id + i + 1)) {
-      count = i;
-      break;
-    }
-  }
-  released_tickets_.erase(released_tickets_.begin(),
-                          released_tickets_.begin() + count);
-  oldest_ += count;
-  SendAck(count);
-}
-
-void SharedMemoryReceivedDataFactory::SendAck(size_t count) {
-  for (size_t i = 0; i < count; ++i) {
-    message_sender_->Send(new ResourceHostMsg_DataReceived_ACK(request_id_));
-  }
-}
-
-}  // namespace content
diff --git a/content/renderer/loader/shared_memory_received_data_factory.h b/content/renderer/loader/shared_memory_received_data_factory.h
deleted file mode 100644
index 72018cb7..0000000
--- a/content/renderer/loader/shared_memory_received_data_factory.h
+++ /dev/null
@@ -1,69 +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.
-
-#ifndef CONTENT_RENDERER_LOADER_SHARED_MEMORY_RECEIVED_DATA_FACTORY_H_
-#define CONTENT_RENDERER_LOADER_SHARED_MEMORY_RECEIVED_DATA_FACTORY_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/shared_memory.h"
-#include "content/common/content_export.h"
-#include "content/public/renderer/request_peer.h"
-
-namespace IPC {
-class Sender;
-}  // namespace IPC
-
-namespace content {
-
-class CONTENT_EXPORT SharedMemoryReceivedDataFactory final
-    : public base::RefCounted<SharedMemoryReceivedDataFactory> {
- public:
-  SharedMemoryReceivedDataFactory(IPC::Sender* message_sender,
-                                  int request_id,
-                                  linked_ptr<base::SharedMemory> memory);
-
-  std::unique_ptr<RequestPeer::ReceivedData> Create(int offset, int length);
-
-  // Stops this factory. After calling this function, releasing issued data
-  // won't send ack signal to the browser process.
-  void Stop();
-
- private:
-  // Here TicketId is uint32_t, but a factory may issue more data by reusing id.
-  using TicketId = uint32_t;
-
-  class SharedMemoryReceivedData;
-  // Called by SharedMemoryReceivedData.
-  void Reclaim(TicketId id);
-
-  class TicketComparator;
-  friend class base::RefCounted<SharedMemoryReceivedDataFactory>;
-  ~SharedMemoryReceivedDataFactory();
-
-  void SendAck(size_t count);
-
-  TicketId id_;
-  TicketId oldest_;
-  std::vector<TicketId> released_tickets_;
-  // We assume that |message_sender_| is valid until |Stop| is called.
-  IPC::Sender* message_sender_;
-  int request_id_;
-  bool is_stopped_;
-  // Just to keep the payload alive while issued data is alive.
-  linked_ptr<base::SharedMemory> memory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedMemoryReceivedDataFactory);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_LOADER_SHARED_MEMORY_RECEIVED_DATA_FACTORY_H_
diff --git a/content/renderer/loader/shared_memory_received_data_factory_unittest.cc b/content/renderer/loader/shared_memory_received_data_factory_unittest.cc
deleted file mode 100644
index 8957d3ff..0000000
--- a/content/renderer/loader/shared_memory_received_data_factory_unittest.cc
+++ /dev/null
@@ -1,225 +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 "content/renderer/loader/shared_memory_received_data_factory.h"
-
-#include <stddef.h>
-#include <tuple>
-
-#include "content/common/resource_messages.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_sender.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::MockFunction;
-using ::testing::Return;
-using ::testing::StrictMock;
-
-using Checkpoint = StrictMock<MockFunction<void(int)>>;
-using ReceivedData = RequestPeer::ReceivedData;
-
-class MockSender : public IPC::Sender {
- public:
-  bool Send(IPC::Message* message) override {
-    bool result = false;
-    if (message->type() == ResourceHostMsg_DataReceived_ACK::ID) {
-      std::tuple<int> args;
-      ResourceHostMsg_DataReceived_ACK::Read(message, &args);
-      result = SendAck(std::get<0>(args));
-    } else {
-      result = SendOtherwise(message);
-    }
-    delete message;
-    return result;
-  }
-  MOCK_METHOD1(SendAck, bool(int));
-  MOCK_METHOD1(SendOtherwise, bool(IPC::Message*));
-};
-
-class SharedMemoryReceivedDataFactoryTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    sender_.reset(new StrictMock<MockSender>);
-    request_id_ = 0xdeadbeaf;
-    memory_.reset(new base::SharedMemory);
-    factory_ = base::MakeRefCounted<SharedMemoryReceivedDataFactory>(
-        sender_.get(), request_id_, memory_);
-    ASSERT_TRUE(memory_->CreateAndMapAnonymous(memory_size));
-
-    ON_CALL(*sender_, SendAck(_)).WillByDefault(Return(true));
-    ON_CALL(*sender_, SendOtherwise(_)).WillByDefault(Return(true));
-  }
-
-  static const size_t memory_size = 4 * 1024;
-  std::unique_ptr<MockSender> sender_;
-  int request_id_;
-  linked_ptr<base::SharedMemory> memory_;
-  scoped_refptr<SharedMemoryReceivedDataFactory> factory_;
-};
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, Create) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(1));
-
-  std::unique_ptr<ReceivedData> data = factory_->Create(12, 34);
-  const char* memory_start = static_cast<const char*>(memory_->memory());
-
-  ASSERT_TRUE(data);
-  EXPECT_EQ(memory_start + 12, data->payload());
-  EXPECT_EQ(34, data->length());
-
-  checkpoint.Call(0);
-  data.reset();
-  checkpoint.Call(1);
-}
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, CreateMultiple) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(1));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(2));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(3));
-
-  std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1);
-  std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1);
-  std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1);
-
-  EXPECT_TRUE(data1);
-  EXPECT_TRUE(data2);
-  EXPECT_TRUE(data3);
-
-  checkpoint.Call(0);
-  data1.reset();
-  checkpoint.Call(1);
-  data2.reset();
-  checkpoint.Call(2);
-  data3.reset();
-  checkpoint.Call(3);
-}
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, ReclaimOutOfOrder) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(checkpoint, Call(1));
-  EXPECT_CALL(checkpoint, Call(2));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(3));
-
-  std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1);
-  std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1);
-  std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1);
-
-  EXPECT_TRUE(data1);
-  EXPECT_TRUE(data2);
-  EXPECT_TRUE(data3);
-
-  checkpoint.Call(0);
-  data3.reset();
-  checkpoint.Call(1);
-  data2.reset();
-  checkpoint.Call(2);
-  data1.reset();
-  checkpoint.Call(3);
-}
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, ReclaimOutOfOrderPartially) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(checkpoint, Call(1));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(2));
-  EXPECT_CALL(checkpoint, Call(3));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(4));
-
-  std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1);
-  std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1);
-  std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1);
-  std::unique_ptr<ReceivedData> data4 = factory_->Create(3, 1);
-  std::unique_ptr<ReceivedData> data5 = factory_->Create(4, 1);
-  std::unique_ptr<ReceivedData> data6 = factory_->Create(5, 1);
-
-  EXPECT_TRUE(data1);
-  EXPECT_TRUE(data2);
-  EXPECT_TRUE(data3);
-  EXPECT_TRUE(data4);
-  EXPECT_TRUE(data5);
-  EXPECT_TRUE(data6);
-
-  checkpoint.Call(0);
-  data3.reset();
-  data6.reset();
-  data2.reset();
-  checkpoint.Call(1);
-  data1.reset();
-  checkpoint.Call(2);
-  data5.reset();
-  checkpoint.Call(3);
-  data4.reset();
-  checkpoint.Call(4);
-}
-
-TEST_F(SharedMemoryReceivedDataFactoryTest, Stop) {
-  Checkpoint checkpoint;
-  InSequence s;
-  EXPECT_CALL(checkpoint, Call(0));
-  EXPECT_CALL(checkpoint, Call(1));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(*sender_, SendAck(request_id_));
-  EXPECT_CALL(checkpoint, Call(2));
-  EXPECT_CALL(checkpoint, Call(3));
-
-  std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1);
-  std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1);
-  std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1);
-  std::unique_ptr<ReceivedData> data4 = factory_->Create(3, 1);
-  std::unique_ptr<ReceivedData> data5 = factory_->Create(4, 1);
-  std::unique_ptr<ReceivedData> data6 = factory_->Create(5, 1);
-
-  EXPECT_TRUE(data1);
-  EXPECT_TRUE(data2);
-  EXPECT_TRUE(data3);
-  EXPECT_TRUE(data4);
-  EXPECT_TRUE(data5);
-  EXPECT_TRUE(data6);
-
-  checkpoint.Call(0);
-  data3.reset();
-  data6.reset();
-  data2.reset();
-  checkpoint.Call(1);
-  data1.reset();
-  checkpoint.Call(2);
-  factory_->Stop();
-  data5.reset();
-  data4.reset();
-  checkpoint.Call(3);
-}
-
-}  // namespace
-
-}  // namespace content
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc
index d3711f7e..2448196 100644
--- a/content/renderer/loader/sync_load_context.cc
+++ b/content/renderer/loader/sync_load_context.cc
@@ -35,7 +35,6 @@
   context->request_id_ = context->resource_dispatcher_->StartAsync(
       std::move(request), routing_id, nullptr, frame_origin, traffic_annotation,
       true /* is_sync */, base::WrapUnique(context),
-      blink::WebURLRequest::LoadingIPCType::kMojo,
       context->url_loader_factory_.get(), std::move(throttles),
       mojom::URLLoaderClientEndpointsPtr());
 }
@@ -60,8 +59,8 @@
   url_loader_factory_.Bind(std::move(url_loader_factory));
 
   // Constructs a new ResourceDispatcher specifically for this request.
-  resource_dispatcher_ = std::make_unique<ResourceDispatcher>(
-      nullptr, base::ThreadTaskRunnerHandle::Get());
+  resource_dispatcher_ =
+      std::make_unique<ResourceDispatcher>(base::ThreadTaskRunnerHandle::Get());
 
   // Initialize the final URL with the original request URL. It will be
   // overwritten on redirects.
diff --git a/content/renderer/loader/url_loader_client_impl.cc b/content/renderer/loader/url_loader_client_impl.cc
index 71f46ef..16b5d8a 100644
--- a/content/renderer/loader/url_loader_client_impl.cc
+++ b/content/renderer/loader/url_loader_client_impl.cc
@@ -8,7 +8,6 @@
 
 #include "base/callback.h"
 #include "base/single_thread_task_runner.h"
-#include "content/common/resource_messages.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/loader/url_response_body_consumer.h"
 #include "net/url_request/redirect_info.h"
@@ -144,10 +143,15 @@
 
 void URLLoaderClientImpl::UnsetDefersLoading() {
   is_deferred_ = false;
+
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&URLLoaderClientImpl::FlushDeferredMessages,
+                                weak_factory_.GetWeakPtr()));
 }
 
 void URLLoaderClientImpl::FlushDeferredMessages() {
-  DCHECK(!is_deferred_);
+  if (is_deferred_)
+    return;
   std::vector<std::unique_ptr<DeferredMessage>> messages;
   messages.swap(deferred_messages_);
   bool has_completion_message = false;
diff --git a/content/renderer/loader/url_loader_client_impl_unittest.cc b/content/renderer/loader/url_loader_client_impl_unittest.cc
index 9bb5741..4438d9c9 100644
--- a/content/renderer/loader/url_loader_client_impl_unittest.cc
+++ b/content/renderer/loader/url_loader_client_impl_unittest.cc
@@ -11,7 +11,6 @@
 #include "content/public/common/url_loader_factory.mojom.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/loader/test_request_peer.h"
-#include "ipc/ipc_sender.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -21,11 +20,10 @@
 namespace content {
 
 class URLLoaderClientImplTest : public ::testing::Test,
-                                IPC::Sender,
                                 mojom::URLLoaderFactory {
  protected:
   URLLoaderClientImplTest()
-      : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())),
+      : dispatcher_(new ResourceDispatcher(message_loop_.task_runner())),
         mojo_binding_(this) {
     mojo_binding_.Bind(mojo::MakeRequest(&url_loader_factory_proxy_));
 
@@ -34,7 +32,6 @@
         TRAFFIC_ANNOTATION_FOR_TESTS, false,
         std::make_unique<TestRequestPeer>(dispatcher_.get(),
                                           &request_peer_context_),
-        blink::WebURLRequest::LoadingIPCType::kMojo,
         url_loader_factory_proxy_.get(),
         std::vector<std::unique_ptr<URLLoaderThrottle>>(),
         mojom::URLLoaderClientEndpointsPtr());
@@ -49,11 +46,6 @@
     url_loader_factory_proxy_ = nullptr;
   }
 
-  bool Send(IPC::Message* message) override {
-    ADD_FAILURE() << "IPC::Sender::Send should not be called.";
-    return false;
-  }
-
   void CreateLoaderAndStart(mojom::URLLoaderRequest request,
                             int32_t routing_id,
                             int32_t request_id,
@@ -518,4 +510,42 @@
   EXPECT_FALSE(request_peer_context_.cancelled);
 }
 
+TEST_F(URLLoaderClientImplTest, CancelOnReceiveDataWhileFlushing) {
+  request_peer_context_.cancel_on_receive_data = true;
+  dispatcher_->SetDefersLoading(request_id_, true);
+
+  ResourceResponseHead response_head;
+  network::URLLoaderCompletionStatus status;
+
+  mojo::DataPipe data_pipe(DataPipeOptions());
+  uint32_t size = 5;
+  MojoResult result = data_pipe.producer_handle->WriteData(
+      "hello", &size, MOJO_WRITE_DATA_FLAG_NONE);
+  ASSERT_EQ(MOJO_RESULT_OK, result);
+  EXPECT_EQ(5u, size);
+
+  url_loader_client_->OnReceiveResponse(response_head, base::nullopt, nullptr);
+  url_loader_client_->OnStartLoadingResponseBody(
+      std::move(data_pipe.consumer_handle));
+  url_loader_client_->OnComplete(status);
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(request_peer_context_.received_response);
+  EXPECT_EQ("", request_peer_context_.data);
+  EXPECT_FALSE(request_peer_context_.complete);
+  EXPECT_FALSE(request_peer_context_.cancelled);
+
+  dispatcher_->SetDefersLoading(request_id_, false);
+  EXPECT_FALSE(request_peer_context_.received_response);
+  EXPECT_EQ("", request_peer_context_.data);
+  EXPECT_FALSE(request_peer_context_.complete);
+  EXPECT_FALSE(request_peer_context_.cancelled);
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(request_peer_context_.received_response);
+  EXPECT_EQ("hello", request_peer_context_.data);
+  EXPECT_FALSE(request_peer_context_.complete);
+  EXPECT_TRUE(request_peer_context_.cancelled);
+}
+
 }  // namespace content
diff --git a/content/renderer/loader/url_response_body_consumer.cc b/content/renderer/loader/url_response_body_consumer.cc
index 0ffa014..0379b99 100644
--- a/content/renderer/loader/url_response_body_consumer.cc
+++ b/content/renderer/loader/url_response_body_consumer.cc
@@ -8,7 +8,6 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "content/common/resource_messages.h"
 #include "content/public/renderer/request_peer.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/loader/site_isolation_stats_gatherer.h"
diff --git a/content/renderer/loader/url_response_body_consumer_unittest.cc b/content/renderer/loader/url_response_body_consumer_unittest.cc
index 6d699d5..6db7348 100644
--- a/content/renderer/loader/url_response_body_consumer_unittest.cc
+++ b/content/renderer/loader/url_response_body_consumer_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "content/common/resource_messages.h"
 #include "content/public/common/resource_request.h"
 #include "content/public/common/service_worker_modes.h"
 #include "content/public/renderer/request_peer.h"
@@ -88,23 +87,38 @@
   DISALLOW_COPY_AND_ASSIGN(TestRequestPeer);
 };
 
-class URLResponseBodyConsumerTest : public ::testing::Test,
-                                    public ::IPC::Sender {
+class URLResponseBodyConsumerTest : public ::testing::Test {
  protected:
+  // A URLResponseBodyConsumer needs an associated PendingRequestInfo, and
+  // we need a URLLoaderFactory to create a PendingRequestInfo. We don't need
+  // a true URLLoaderFactory, so here we define a no-op (other than keeping
+  // clients to avoid connection error notifications) factory.
+  class NoopURLLoaderFactory final : public mojom::URLLoaderFactory {
+   public:
+    void CreateLoaderAndStart(mojom::URLLoaderRequest request,
+                              int32_t routing_id,
+                              int32_t request_id,
+                              uint32_t options,
+                              const ResourceRequest& url_request,
+                              mojom::URLLoaderClientPtr client,
+                              const net::MutableNetworkTrafficAnnotationTag&
+                                  traffic_annotation) override {
+      clients_.push_back(std::move(client));
+    }
+
+    void Clone(mojom::URLLoaderFactoryRequest request) override {}
+
+    std::vector<mojom::URLLoaderClientPtr> clients_;
+  };
+
   URLResponseBodyConsumerTest()
-      : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())) {
-  }
+      : dispatcher_(new ResourceDispatcher(message_loop_.task_runner())) {}
 
   ~URLResponseBodyConsumerTest() override {
     dispatcher_.reset();
     base::RunLoop().RunUntilIdle();
   }
 
-  bool Send(IPC::Message* message) override {
-    delete message;
-    return true;
-  }
-
   std::unique_ptr<ResourceRequest> CreateResourceRequest() {
     std::unique_ptr<ResourceRequest> request(new ResourceRequest);
 
@@ -137,8 +151,7 @@
         std::move(request), 0, nullptr, url::Origin(),
         TRAFFIC_ANNOTATION_FOR_TESTS, false,
         std::make_unique<TestRequestPeer>(context, message_loop_.task_runner()),
-        blink::WebURLRequest::LoadingIPCType::kChromeIPC, nullptr,
-        std::vector<std::unique_ptr<URLLoaderThrottle>>(),
+        &factory_, std::vector<std::unique_ptr<URLLoaderThrottle>>(),
         mojom::URLLoaderClientEndpointsPtr());
   }
 
@@ -149,6 +162,7 @@
   }
 
   base::MessageLoop message_loop_;
+  NoopURLLoaderFactory factory_;
   std::unique_ptr<ResourceDispatcher> dispatcher_;
   static const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE;
 };
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index 538a8e06..cfa438bf 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -26,7 +26,6 @@
 #include "build/build_config.h"
 #include "content/child/child_thread_impl.h"
 #include "content/child/scoped_child_process_reference.h"
-#include "content/common/resource_messages.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/content_features.h"
@@ -692,7 +691,7 @@
     resource_dispatcher_->StartSync(
         std::move(resource_request), request.RequestorID(),
         extra_data->frame_origin(), GetTrafficAnnotationTag(request),
-        sync_load_response, request.GetLoadingIPCType(), url_loader_factory_,
+        sync_load_response, url_loader_factory_,
         extra_data->TakeURLLoaderThrottles(), request.TimeoutInterval());
     return;
   }
@@ -704,8 +703,7 @@
       extra_data->frame_origin(), GetTrafficAnnotationTag(request),
       false /* is_sync */,
       std::make_unique<WebURLLoaderImpl::RequestPeerImpl>(this),
-      request.GetLoadingIPCType(), url_loader_factory_,
-      extra_data->TakeURLLoaderThrottles(),
+      url_loader_factory_, extra_data->TakeURLLoaderThrottles(),
       std::move(url_loader_client_endpoints));
 
   if (defers_loading_ != NOT_DEFERRING)
diff --git a/content/renderer/loader/web_url_loader_impl_unittest.cc b/content/renderer/loader/web_url_loader_impl_unittest.cc
index 07c4c1e8..d58d48e 100644
--- a/content/renderer/loader/web_url_loader_impl_unittest.cc
+++ b/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -63,11 +63,8 @@
 
 class TestResourceDispatcher : public ResourceDispatcher {
  public:
-  TestResourceDispatcher() :
-      ResourceDispatcher(nullptr, nullptr),
-      canceled_(false),
-      defers_loading_(false) {
-  }
+  TestResourceDispatcher()
+      : ResourceDispatcher(nullptr), canceled_(false), defers_loading_(false) {}
 
   ~TestResourceDispatcher() override {}
 
@@ -78,7 +75,6 @@
                  const url::Origin& frame_origin,
                  const net::NetworkTrafficAnnotationTag& traffic_annotation,
                  SyncLoadResponse* response,
-                 blink::WebURLRequest::LoadingIPCType ipc_type,
                  mojom::URLLoaderFactory* url_loader_factory,
                  std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
                  double timeout) override {
@@ -93,7 +89,6 @@
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       bool is_sync,
       std::unique_ptr<RequestPeer> peer,
-      blink::WebURLRequest::LoadingIPCType ipc_type,
       mojom::URLLoaderFactory* url_loader_factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
       mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints) override {
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
index aa674e2..f0234c4 100644
--- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
+++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
@@ -24,7 +24,6 @@
 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
 #include "media/gpu/gpu_video_accelerator_util.h"
 #include "media/gpu/ipc/client/gpu_video_decode_accelerator_host.h"
-#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
 #include "media/gpu/ipc/common/media_messages.h"
 #include "media/mojo/clients/mojo_video_encode_accelerator.h"
 #include "media/video/video_decode_accelerator.h"
@@ -171,24 +170,20 @@
   if (CheckContextLost())
     return nullptr;
 
-  if (base::FeatureList::IsEnabled(features::kMojoVideoEncodeAccelerator)) {
-    media::mojom::VideoEncodeAcceleratorPtr vea;
-    vea_provider_->CreateVideoEncodeAccelerator(mojo::MakeRequest(&vea));
+  DCHECK(base::FeatureList::IsEnabled(features::kMojoVideoEncodeAccelerator));
 
-    if (vea) {
-      return std::unique_ptr<media::VideoEncodeAccelerator>(
-          new media::MojoVideoEncodeAccelerator(
-              std::move(vea),
-              context_provider_->GetCommandBufferProxy()
-                  ->channel()
-                  ->gpu_info()
-                  .video_encode_accelerator_supported_profiles));
-    }
-  }
+  media::mojom::VideoEncodeAcceleratorPtr vea;
+  vea_provider_->CreateVideoEncodeAccelerator(mojo::MakeRequest(&vea));
+
+  if (!vea)
+    return nullptr;
 
   return std::unique_ptr<media::VideoEncodeAccelerator>(
-      new media::GpuVideoEncodeAcceleratorHost(
-          context_provider_->GetCommandBufferProxy()));
+      new media::MojoVideoEncodeAccelerator(
+          std::move(vea), context_provider_->GetCommandBufferProxy()
+                              ->channel()
+                              ->gpu_info()
+                              .video_encode_accelerator_supported_profiles));
 }
 
 bool GpuVideoAcceleratorFactoriesImpl::CreateTextures(
@@ -310,8 +305,10 @@
     return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
   viz::ContextProvider::ScopedContextLock lock(context_provider_);
   auto capabilities = context_provider_->ContextCapabilities();
-  if (capabilities.image_ycbcr_420v)
+  if (capabilities.image_ycbcr_420v &&
+      !capabilities.image_ycbcr_420v_disabled_for_video_frames) {
     return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB;
+  }
   if (capabilities.image_ycbcr_422)
     return media::GpuVideoAcceleratorFactories::OutputFormat::UYVY;
   if (capabilities.texture_rg)
diff --git a/content/renderer/media/gpu/rtc_video_encoder_factory.cc b/content/renderer/media/gpu/rtc_video_encoder_factory.cc
index ff170a1f..14e12b1 100644
--- a/content/renderer/media/gpu/rtc_video_encoder_factory.cc
+++ b/content/renderer/media/gpu/rtc_video_encoder_factory.cc
@@ -12,7 +12,6 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
 #include "content/renderer/media/gpu/rtc_video_encoder.h"
-#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "third_party/webrtc/common_video/h264/profile_level_id.h"
 
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
index 3ee9442..0e0a6a5 100644
--- a/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
@@ -125,6 +125,8 @@
     return;
 
   const base::TimeTicks current_time = base::TimeTicks::Now();
+  if (start_capture_time_.is_null())
+    start_capture_time_ = current_time;
   const blink::WebSize resolution = web_media_player_->NaturalSize();
 
   cc::PaintFlags flags;
@@ -147,7 +149,7 @@
 
   scoped_refptr<media::VideoFrame> frame = frame_pool_.CreateFrame(
       media::PIXEL_FORMAT_I420, resolution, gfx::Rect(resolution), resolution,
-      base::TimeTicks::Now() - base::TimeTicks());
+      current_time - start_capture_time_);
 
   const uint32 source_pixel_format =
       (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source.h b/content/renderer/media_capture_from_element/html_video_element_capturer_source.h
index 888c6c8..ffa02a3 100644
--- a/content/renderer/media_capture_from_element/html_video_element_capturer_source.h
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source.h
@@ -74,6 +74,9 @@
   VideoCaptureDeliverFrameCB new_frame_callback_;
   double capture_frame_rate_;
 
+  // TimeTicks on which the first captured VideoFrame is produced.
+  base::TimeTicks start_capture_time_;
+
   // Target time for the next frame.
   base::TimeTicks next_capture_time_;
 
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
index 4e9e40e0..4e28d7c 100644
--- a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
@@ -139,10 +139,12 @@
 
   base::RunLoop run_loop;
   base::Closure quit_closure = run_loop.QuitClosure();
-  EXPECT_CALL(*this, DoOnDeliverFrame(_, _)).Times(1);
+  scoped_refptr<media::VideoFrame> first_frame;
+  scoped_refptr<media::VideoFrame> second_frame;
+  EXPECT_CALL(*this, DoOnDeliverFrame(_, _)).WillOnce(SaveArg<0>(&first_frame));
   EXPECT_CALL(*this, DoOnDeliverFrame(_, _))
       .Times(1)
-      .WillOnce(RunClosure(quit_closure));
+      .WillOnce(DoAll(SaveArg<0>(&second_frame), RunClosure(quit_closure)));
 
   html_video_capturer_->StartCapture(
       params, base::Bind(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
@@ -152,6 +154,8 @@
 
   run_loop.Run();
 
+  EXPECT_EQ(0u, first_frame->timestamp().InMilliseconds());
+  EXPECT_GT(second_frame->timestamp().InMilliseconds(), 30u);
   html_video_capturer_->StopCapture();
   Mock::VerifyAndClearExpectations(this);
 }
@@ -173,7 +177,7 @@
   media::VideoCaptureParams params;
   params.requested_format = formats[0];
 
-  EXPECT_CALL(*this, DoOnRunning(true)).Times(1);
+  EXPECT_CALL(*this, DoOnRunning(true));
   EXPECT_CALL(*this, DoOnDeliverFrame(_, _)).Times(0);
 
   html_video_capturer_->StartCapture(
diff --git a/content/renderer/pepper/pepper_video_encoder_host.cc b/content/renderer/pepper/pepper_video_encoder_host.cc
index 8212afd..e696e2fc 100644
--- a/content/renderer/pepper/pepper_video_encoder_host.cc
+++ b/content/renderer/pepper/pepper_video_encoder_host.cc
@@ -19,7 +19,7 @@
 #include "content/renderer/pepper/host_globals.h"
 #include "content/renderer/pepper/video_encoder_shim.h"
 #include "content/renderer/render_thread_impl.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/ipc/client/command_buffer_proxy_impl.h"
 #include "ppapi/c/pp_codecs.h"
 #include "ppapi/c/pp_errors.h"
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc
index 997d388..1b3c33f8 100644
--- a/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -23,7 +23,7 @@
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
 #include "gpu/GLES2/gl2extchromium.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/ipc/client/command_buffer_proxy_impl.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "ppapi/c/ppp_graphics_3d.h"
@@ -66,7 +66,7 @@
 PP_Resource PPB_Graphics3D_Impl::CreateRaw(
     PP_Instance instance,
     PP_Resource share_context,
-    const gpu::gles2::ContextCreationAttribHelper& attrib_helper,
+    const gpu::ContextCreationAttribs& attrib_helper,
     gpu::Capabilities* capabilities,
     base::SharedMemoryHandle* shared_state_handle,
     gpu::CommandBufferId* command_buffer_id) {
@@ -212,7 +212,7 @@
 
 bool PPB_Graphics3D_Impl::InitRaw(
     PPB_Graphics3D_API* share_context,
-    const gpu::gles2::ContextCreationAttribHelper& requested_attribs,
+    const gpu::ContextCreationAttribs& requested_attribs,
     gpu::Capabilities* capabilities,
     base::SharedMemoryHandle* shared_state_handle,
     gpu::CommandBufferId* command_buffer_id) {
@@ -255,9 +255,9 @@
 
   has_alpha_ = requested_attribs.alpha_size > 0;
 
-  gpu::gles2::ContextCreationAttribHelper attrib_helper = requested_attribs;
+  gpu::ContextCreationAttribs attrib_helper = requested_attribs;
   attrib_helper.should_use_native_gmb_for_backbuffer = use_image_chromium_;
-  attrib_helper.context_type = gpu::gles2::CONTEXT_TYPE_OPENGLES2;
+  attrib_helper.context_type = gpu::CONTEXT_TYPE_OPENGLES2;
 
   gpu::CommandBufferProxyImpl* share_buffer = nullptr;
   if (!plugin_instance->is_flash_plugin())
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.h b/content/renderer/pepper/ppb_graphics_3d_impl.h
index 8d6a17a..269fe93 100644
--- a/content/renderer/pepper/ppb_graphics_3d_impl.h
+++ b/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -20,11 +20,9 @@
 #include "ppapi/shared_impl/resource.h"
 
 namespace gpu {
-namespace gles2 {
-struct ContextCreationAttribHelper;
-}
 struct Capabilities;
 class CommandBufferProxyImpl;
+struct ContextCreationAttribs;
 }
 
 namespace content {
@@ -32,13 +30,12 @@
 class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared,
                             public gpu::GpuControlClient {
  public:
-  static PP_Resource CreateRaw(
-      PP_Instance instance,
-      PP_Resource share_context,
-      const gpu::gles2::ContextCreationAttribHelper& attrib_helper,
-      gpu::Capabilities* capabilities,
-      base::SharedMemoryHandle* shared_state_handle,
-      gpu::CommandBufferId* command_buffer_id);
+  static PP_Resource CreateRaw(PP_Instance instance,
+                               PP_Resource share_context,
+                               const gpu::ContextCreationAttribs& attrib_helper,
+                               gpu::Capabilities* capabilities,
+                               base::SharedMemoryHandle* shared_state_handle,
+                               gpu::CommandBufferId* command_buffer_id);
 
   // PPB_Graphics3D_API trusted implementation.
   PP_Bool SetGetBuffer(int32_t transfer_buffer_id) override;
@@ -83,7 +80,7 @@
   explicit PPB_Graphics3D_Impl(PP_Instance instance);
 
   bool InitRaw(PPB_Graphics3D_API* share_context,
-               const gpu::gles2::ContextCreationAttribHelper& requested_attribs,
+               const gpu::ContextCreationAttribs& requested_attribs,
                gpu::Capabilities* capabilities,
                base::SharedMemoryHandle* shared_state_handle,
                gpu::CommandBufferId* command_buffer_id);
diff --git a/content/renderer/pepper/resource_creation_impl.cc b/content/renderer/pepper/resource_creation_impl.cc
index f848425..6ace5f2 100644
--- a/content/renderer/pepper/resource_creation_impl.cc
+++ b/content/renderer/pepper/resource_creation_impl.cc
@@ -126,7 +126,7 @@
 PP_Resource ResourceCreationImpl::CreateGraphics3DRaw(
     PP_Instance instance,
     PP_Resource share_context,
-    const gpu::gles2::ContextCreationAttribHelper& attrib_helper,
+    const gpu::ContextCreationAttribs& attrib_helper,
     gpu::Capabilities* capabilities,
     base::SharedMemoryHandle* shared_state,
     gpu::CommandBufferId* command_buffer_id) {
diff --git a/content/renderer/pepper/resource_creation_impl.h b/content/renderer/pepper/resource_creation_impl.h
index 3e05ba3..f4d339c 100644
--- a/content/renderer/pepper/resource_creation_impl.h
+++ b/content/renderer/pepper/resource_creation_impl.h
@@ -58,7 +58,7 @@
   PP_Resource CreateGraphics3DRaw(
       PP_Instance instance,
       PP_Resource share_context,
-      const gpu::gles2::ContextCreationAttribHelper& attrib_helper,
+      const gpu::ContextCreationAttribs& attrib_helper,
       gpu::Capabilities* capabilities,
       base::SharedMemoryHandle* shared_state,
       gpu::CommandBufferId* command_buffer_id) override;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 014491be..186a82a0 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -68,7 +68,6 @@
 #include "content/common/frame_messages.h"
 #include "content/common/frame_owner_properties.h"
 #include "content/common/gpu_stream_constants.h"
-#include "content/common/resource_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/common/content_features.h"
@@ -102,9 +101,7 @@
 #include "content/renderer/input/input_event_filter.h"
 #include "content/renderer/input/input_handler_manager.h"
 #include "content/renderer/input/main_thread_input_event_filter.h"
-#include "content/renderer/loader/child_resource_message_filter.h"
 #include "content/renderer/loader/resource_dispatcher.h"
-#include "content/renderer/loader/resource_scheduling_filter.h"
 #include "content/renderer/mash_util.h"
 #include "content/renderer/media/audio_input_message_filter.h"
 #include "content/renderer/media/audio_message_filter.h"
@@ -124,7 +121,6 @@
 #include "content/renderer/render_process_impl.h"
 #include "content/renderer/render_view_impl.h"
 #include "content/renderer/renderer_blink_platform_impl.h"
-#include "content/renderer/scheduler/resource_dispatch_throttler.h"
 #include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
 #include "content/renderer/service_worker/service_worker_context_client.h"
 #include "content/renderer/service_worker/service_worker_context_message_filter.h"
@@ -244,16 +240,6 @@
 const int64_t kInitialIdleHandlerDelayMs = 1000;
 const int64_t kLongIdleHandlerDelayMs = 30 * 1000;
 
-#if defined(OS_ANDROID)
-// On Android, resource messages can each take ~1.5ms to dispatch on the browser
-// IO thread. Limiting the message rate to 3/frame at 60hz ensures that the
-// induced work takes but a fraction (~1/4) of the overall frame budget.
-const int kMaxResourceRequestsPerFlushWhenThrottled = 3;
-#else
-const int kMaxResourceRequestsPerFlushWhenThrottled = 8;
-#endif
-const double kThrottledResourceRequestFlushPeriodS = 1. / 60.;
-
 // Maximum allocation size allowed for image scaling filters that
 // require pre-scaling. Skia will fallback to a filter that doesn't
 // require pre-scaling if the default filter would require an
@@ -388,7 +374,7 @@
   // - The media context, used for accelerated video decoding.
   // This is for an offscreen context, so the default framebuffer doesn't need
   // alpha, depth, stencil, antialiasing.
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = -1;
   attributes.depth_size = 0;
   attributes.stencil_size = 0;
@@ -721,11 +707,8 @@
       new NotificationDispatcher(thread_safe_sender());
   AddFilter(notification_dispatcher_->GetFilter());
 
-  resource_dispatcher_.reset(new ResourceDispatcher(
-      this, message_loop()->task_runner()));
-  resource_message_filter_ =
-      new ChildResourceMessageFilter(resource_dispatcher_.get());
-  AddFilter(resource_message_filter_.get());
+  resource_dispatcher_.reset(
+      new ResourceDispatcher(message_loop()->task_runner()));
   quota_dispatcher_.reset(new QuotaDispatcher(message_loop()->task_runner()));
 
   auto registry = std::make_unique<service_manager::BinderRegistry>();
@@ -751,14 +734,6 @@
       new CacheStorageDispatcher(thread_safe_sender()));
   file_system_dispatcher_.reset(new FileSystemDispatcher());
 
-  // Note: This may reorder messages from the ResourceDispatcher with respect to
-  // other subsystems.
-  resource_dispatch_throttler_.reset(new ResourceDispatchThrottler(
-      static_cast<RenderThread*>(this), renderer_scheduler_.get(),
-      base::TimeDelta::FromSecondsD(kThrottledResourceRequestFlushPeriodS),
-      kMaxResourceRequestsPerFlushWhenThrottled));
-  resource_dispatcher_->set_message_sender(resource_dispatch_throttler_.get());
-
   blob_message_filter_ = new BlobMessageFilter(GetFileThreadTaskRunner());
   AddFilter(blob_message_filter_.get());
   vc_manager_.reset(new VideoCaptureImplManager());
@@ -1272,18 +1247,8 @@
   } else {
     resource_task_queue2 = renderer_scheduler_->LoadingTaskRunner();
   }
-  // Add a filter that forces resource messages to be dispatched via a
-  // particular task runner.
-  scoped_refptr<ResourceSchedulingFilter> filter(
-      new ResourceSchedulingFilter(
-          resource_task_queue2, resource_dispatcher_.get()));
-  channel()->AddFilter(filter.get());
-  resource_dispatcher_->SetResourceSchedulingFilter(filter);
-
-  // The ChildResourceMessageFilter and the ResourceDispatcher need to use the
-  // same queue to ensure tasks are executed in the expected order.
-  resource_message_filter_->SetMainThreadTaskRunner(
-      resource_task_queue2);
+  // The ResourceDispatcher needs to use the same queue to ensure tasks are
+  // executed in the expected order.
   resource_dispatcher_->SetThreadTaskRunner(resource_task_queue2);
 
   if (!command_line.HasSwitch(switches::kDisableThreadedCompositing))
@@ -1619,9 +1584,6 @@
 }
 
 bool RenderThreadImpl::OnMessageReceived(const IPC::Message& msg) {
-  // Resource responses are sent to the resource dispatcher.
-  if (resource_dispatcher_->OnMessageReceived(msg))
-    return true;
   if (file_system_dispatcher_->OnMessageReceived(msg))
     return true;
   return ChildThreadImpl::OnMessageReceived(msg);
@@ -2112,7 +2074,7 @@
 
   // This is for an offscreen context for the compositor. So the default
   // framebuffer doesn't need alpha, depth, stencil, antialiasing.
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = -1;
   attributes.depth_size = 0;
   attributes.stencil_size = 0;
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 7ede741b..fb53ccc 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -134,7 +134,6 @@
 class BrowserPluginManager;
 class CacheStorageDispatcher;
 class CategorizedWorkerPool;
-class ChildResourceMessageFilter;
 class CompositorForwardingMessageFilter;
 class DomStorageDispatcher;
 class FileSystemDispatcher;
@@ -151,7 +150,6 @@
 class RenderThreadObserver;
 class RendererBlinkPlatformImpl;
 class ResourceDispatcher;
-class ResourceDispatchThrottler;
 class ServiceWorkerMessageFilter;
 class VideoCaptureImplManager;
 
@@ -647,7 +645,6 @@
   std::unique_ptr<blink::scheduler::RendererScheduler> renderer_scheduler_;
   std::unique_ptr<RendererBlinkPlatformImpl> blink_platform_impl_;
   std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
-  std::unique_ptr<ResourceDispatchThrottler> resource_dispatch_throttler_;
   std::unique_ptr<CacheStorageDispatcher> main_thread_cache_storage_dispatcher_;
   std::unique_ptr<FileSystemDispatcher> file_system_dispatcher_;
   std::unique_ptr<QuotaDispatcher> quota_dispatcher_;
@@ -657,7 +654,6 @@
   scoped_refptr<AudioInputMessageFilter> audio_input_message_filter_;
   scoped_refptr<MidiMessageFilter> midi_message_filter_;
   scoped_refptr<ServiceWorkerMessageFilter> service_worker_message_filter_;
-  scoped_refptr<ChildResourceMessageFilter> resource_message_filter_;
 
   std::unique_ptr<BrowserPluginManager> browser_plugin_manager_;
 
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index 28957f2..1cb95d5 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -24,7 +24,6 @@
 #include "components/viz/common/resources/buffer_to_texture_target_map.h"
 #include "content/app/mojo/mojo_init.h"
 #include "content/common/in_process_child_thread_params.h"
-#include "content/common/resource_messages.h"
 #include "content/common/service_manager/child_connection.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
@@ -307,16 +306,6 @@
 
 // Disabled under LeakSanitizer due to memory leaks.
 TEST_F(RenderThreadImplBrowserTest,
-       WILL_LEAK(ResourceDispatchIPCTasksGoThroughScheduler)) {
-  sender()->Send(new ResourceHostMsg_FollowRedirect(0));
-  sender()->Send(new TestMsg_QuitRunLoop());
-
-  run_loop_->Run();
-  EXPECT_EQ(1, test_task_counter_->NumTasksPosted());
-}
-
-// Disabled under LeakSanitizer due to memory leaks.
-TEST_F(RenderThreadImplBrowserTest,
        WILL_LEAK(NonResourceDispatchIPCTasksDontGoThroughScheduler)) {
   // NOTE other than not being a resource message, the actual message is
   // unimportant.
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 25923f7..b1def01 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -1004,29 +1004,24 @@
 // changes.
 TEST_F(RenderViewImplTest, OnImeTypeChanged) {
   // Load an HTML page consisting of two input fields.
-  LoadHTML("<html>"
-           "<head>"
-           "</head>"
-           "<body>"
-           "<input id=\"test1\" type=\"text\" value=\"some text\"></input>"
-           "<input id=\"test2\" type=\"password\"></input>"
-           "<input id=\"test3\" type=\"text\" inputmode=\"verbatim\"></input>"
-           "<input id=\"test4\" type=\"text\" inputmode=\"latin\"></input>"
-           "<input id=\"test5\" type=\"text\" inputmode=\"latin-name\"></input>"
-           "<input id=\"test6\" type=\"text\" inputmode=\"latin-prose\">"
-               "</input>"
-           "<input id=\"test7\" type=\"text\" inputmode=\"full-width-latin\">"
-               "</input>"
-           "<input id=\"test8\" type=\"text\" inputmode=\"kana\"></input>"
-           "<input id=\"test9\" type=\"text\" inputmode=\"katakana\"></input>"
-           "<input id=\"test10\" type=\"text\" inputmode=\"numeric\"></input>"
-           "<input id=\"test11\" type=\"text\" inputmode=\"tel\"></input>"
-           "<input id=\"test12\" type=\"text\" inputmode=\"email\"></input>"
-           "<input id=\"test13\" type=\"text\" inputmode=\"url\"></input>"
-           "<input id=\"test14\" type=\"text\" inputmode=\"unknown\"></input>"
-           "<input id=\"test15\" type=\"text\" inputmode=\"verbatim\"></input>"
-           "</body>"
-           "</html>");
+  LoadHTML(
+      "<html>"
+      "<head>"
+      "</head>"
+      "<body>"
+      "<input id=\"test1\" type=\"text\" value=\"some text\"></input>"
+      "<input id=\"test2\" type=\"password\"></input>"
+      "<input id=\"test3\" type=\"text\" inputmode=\"none\"></input>"
+      "<input id=\"test4\" type=\"text\" inputmode=\"text\"></input>"
+      "<input id=\"test5\" type=\"text\" inputmode=\"tel\"></input>"
+      "<input id=\"test6\" type=\"text\" inputmode=\"url\"></input>"
+      "<input id=\"test7\" type=\"text\" inputmode=\"email\"></input>"
+      "<input id=\"test8\" type=\"text\" inputmode=\"numeric\"></input>"
+      "<input id=\"test9\" type=\"text\" inputmode=\"decimal\"></input>"
+      "<input id=\"test10\" type=\"text\" inputmode=\"search\"></input>"
+      "<input id=\"test11\" type=\"text\" inputmode=\"unknown\"></input>"
+      "</body>"
+      "</html>");
   render_thread_->sink().ClearMessages();
 
   struct InputModeTestCase {
@@ -1034,20 +1029,16 @@
     ui::TextInputMode expected_mode;
   };
   static const InputModeTestCase kInputModeTestCases[] = {
-     {"test1", ui::TEXT_INPUT_MODE_DEFAULT},
-     {"test3", ui::TEXT_INPUT_MODE_VERBATIM},
-     {"test4", ui::TEXT_INPUT_MODE_LATIN},
-     {"test5", ui::TEXT_INPUT_MODE_LATIN_NAME},
-     {"test6", ui::TEXT_INPUT_MODE_LATIN_PROSE},
-     {"test7", ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN},
-     {"test8", ui::TEXT_INPUT_MODE_KANA},
-     {"test9", ui::TEXT_INPUT_MODE_KATAKANA},
-     {"test10", ui::TEXT_INPUT_MODE_NUMERIC},
-     {"test11", ui::TEXT_INPUT_MODE_TEL},
-     {"test12", ui::TEXT_INPUT_MODE_EMAIL},
-     {"test13", ui::TEXT_INPUT_MODE_URL},
-     {"test14", ui::TEXT_INPUT_MODE_DEFAULT},
-     {"test15", ui::TEXT_INPUT_MODE_VERBATIM},
+      {"test1", ui::TEXT_INPUT_MODE_DEFAULT},
+      {"test3", ui::TEXT_INPUT_MODE_NONE},
+      {"test4", ui::TEXT_INPUT_MODE_TEXT},
+      {"test5", ui::TEXT_INPUT_MODE_TEL},
+      {"test6", ui::TEXT_INPUT_MODE_URL},
+      {"test7", ui::TEXT_INPUT_MODE_EMAIL},
+      {"test8", ui::TEXT_INPUT_MODE_NUMERIC},
+      {"test9", ui::TEXT_INPUT_MODE_DECIMAL},
+      {"test10", ui::TEXT_INPUT_MODE_SEARCH},
+      {"test11", ui::TEXT_INPUT_MODE_DEFAULT},
   };
 
   const int kRepeatCount = 10;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 0500572..d224eb8 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -1124,7 +1124,7 @@
   // antialiasing. But we do need those attributes for the "own
   // offscreen surface" optimization which supports directly drawing
   // to a custom surface backed frame buffer.
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = web_attributes.support_alpha ? 8 : -1;
   attributes.depth_size = web_attributes.support_depth ? 24 : 0;
   attributes.stencil_size = web_attributes.support_stencil ? 8 : 0;
@@ -1142,9 +1142,9 @@
   DCHECK_GT(web_attributes.web_gl_version, 0u);
   DCHECK_LE(web_attributes.web_gl_version, 2u);
   if (web_attributes.web_gl_version == 2)
-    attributes.context_type = gpu::gles2::CONTEXT_TYPE_WEBGL2;
+    attributes.context_type = gpu::CONTEXT_TYPE_WEBGL2;
   else
-    attributes.context_type = gpu::gles2::CONTEXT_TYPE_WEBGL1;
+    attributes.context_type = gpu::CONTEXT_TYPE_WEBGL1;
 
   constexpr bool automatic_flushes = true;
   constexpr bool support_locking = false;
diff --git a/content/renderer/scheduler/resource_dispatch_throttler.cc b/content/renderer/scheduler/resource_dispatch_throttler.cc
deleted file mode 100644
index 6eae599..0000000
--- a/content/renderer/scheduler/resource_dispatch_throttler.cc
+++ /dev/null
@@ -1,155 +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 "content/renderer/scheduler/resource_dispatch_throttler.h"
-
-#include "base/auto_reset.h"
-#include "base/containers/circular_deque.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/resource_messages.h"
-#include "ipc/ipc_message_macros.h"
-#include "third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h"
-
-namespace content {
-namespace {
-
-bool IsResourceRequest(const IPC::Message& msg) {
-  return msg.type() == ResourceHostMsg_RequestResource::ID;
-}
-
-}  // namespace
-
-ResourceDispatchThrottler::ResourceDispatchThrottler(
-    IPC::Sender* proxied_sender,
-    blink::scheduler::RendererScheduler* scheduler,
-    base::TimeDelta flush_period,
-    uint32_t max_requests_per_flush)
-    : proxied_sender_(proxied_sender),
-      scheduler_(scheduler),
-      flush_period_(flush_period),
-      max_requests_per_flush_(max_requests_per_flush),
-      flush_timer_(
-          FROM_HERE,
-          flush_period_,
-          base::Bind(&ResourceDispatchThrottler::Flush, base::Unretained(this)),
-          false /* is_repeating */),
-      sent_requests_since_last_flush_(0) {
-  DCHECK(proxied_sender);
-  DCHECK(scheduler);
-  DCHECK_NE(flush_period_, base::TimeDelta());
-  DCHECK(max_requests_per_flush_);
-  flush_timer_.SetTaskRunner(scheduler->LoadingTaskRunner());
-}
-
-ResourceDispatchThrottler::~ResourceDispatchThrottler() {
-  FlushAll();
-}
-
-bool ResourceDispatchThrottler::Send(IPC::Message* msg) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  if (msg->is_sync()) {
-    // Flush any pending requests, preserving dispatch order between async and
-    // sync requests.
-    FlushAll();
-    return ForwardMessage(msg);
-  }
-
-  // Always defer message forwarding if there are pending messages, ensuring
-  // message dispatch ordering consistency.
-  if (!throttled_messages_.empty()) {
-    TRACE_EVENT_INSTANT0("loader", "ResourceDispatchThrottler::ThrottleMessage",
-                         TRACE_EVENT_SCOPE_THREAD);
-    throttled_messages_.push_back(msg);
-    return true;
-  }
-
-  if (!IsResourceRequest(*msg))
-    return ForwardMessage(msg);
-
-  if (!scheduler_->IsHighPriorityWorkAnticipated()) {
-    // Treat an unthrottled request as a flush.
-    LogFlush();
-    return ForwardMessage(msg);
-  }
-
-  if (Now() > (last_flush_time_ + flush_period_)) {
-    // If sufficient time has passed since the previous flush, we can
-    // effectively mark the pipeline as flushed.
-    LogFlush();
-    return ForwardMessage(msg);
-  }
-
-  if (sent_requests_since_last_flush_ < max_requests_per_flush_)
-    return ForwardMessage(msg);
-
-  TRACE_EVENT_INSTANT0("loader", "ResourceDispatchThrottler::ThrottleRequest",
-                       TRACE_EVENT_SCOPE_THREAD);
-  throttled_messages_.push_back(msg);
-  ScheduleFlush();
-  return true;
-}
-
-base::TimeTicks ResourceDispatchThrottler::Now() const {
-  return base::TimeTicks::Now();
-}
-
-void ResourceDispatchThrottler::ScheduleFlush() {
-  DCHECK(!flush_timer_.IsRunning());
-  flush_timer_.Reset();
-}
-
-void ResourceDispatchThrottler::Flush() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  TRACE_EVENT1("loader", "ResourceDispatchThrottler::Flush",
-               "total_throttled_messages", throttled_messages_.size());
-  LogFlush();
-
-  // If high-priority work is no longer anticipated, dispatch can be safely
-  // accelerated. Avoid completely flushing in such case in the event that
-  // a large number of requests have been throttled.
-  uint32_t max_requests = scheduler_->IsHighPriorityWorkAnticipated()
-                              ? max_requests_per_flush_
-                              : max_requests_per_flush_ * 2;
-
-  while (!throttled_messages_.empty() &&
-         (sent_requests_since_last_flush_ < max_requests ||
-          !IsResourceRequest(*throttled_messages_.front()))) {
-    IPC::Message* msg = throttled_messages_.front();
-    throttled_messages_.pop_front();
-    ForwardMessage(msg);
-  }
-
-  if (!throttled_messages_.empty())
-    ScheduleFlush();
-}
-
-void ResourceDispatchThrottler::FlushAll() {
-  LogFlush();
-  if (throttled_messages_.empty())
-    return;
-
-  TRACE_EVENT1("loader", "ResourceDispatchThrottler::FlushAll",
-               "total_throttled_messages", throttled_messages_.size());
-  base::circular_deque<IPC::Message*> throttled_messages;
-  throttled_messages.swap(throttled_messages_);
-  for (auto* message : throttled_messages)
-    ForwardMessage(message);
-  // There shouldn't be re-entrancy issues when forwarding an IPC, but validate
-  // as a safeguard.
-  DCHECK(throttled_messages_.empty());
-}
-
-void ResourceDispatchThrottler::LogFlush() {
-  sent_requests_since_last_flush_ = 0;
-  last_flush_time_ = Now();
-}
-
-bool ResourceDispatchThrottler::ForwardMessage(IPC::Message* msg) {
-  if (IsResourceRequest(*msg))
-    ++sent_requests_since_last_flush_;
-
-  return proxied_sender_->Send(msg);
-}
-
-}  // namespace content
diff --git a/content/renderer/scheduler/resource_dispatch_throttler.h b/content/renderer/scheduler/resource_dispatch_throttler.h
deleted file mode 100644
index 6c4c933..0000000
--- a/content/renderer/scheduler/resource_dispatch_throttler.h
+++ /dev/null
@@ -1,77 +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.
-
-#ifndef CONTENT_RENDERER_SCHEDULER_RESOURCE_DISPATCH_THROTTLER_H_
-#define CONTENT_RENDERER_SCHEDULER_RESOURCE_DISPATCH_THROTTLER_H_
-
-#include <stdint.h>
-
-#include "base/containers/circular_deque.h"
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "content/common/content_export.h"
-#include "ipc/ipc_sender.h"
-
-namespace blink {
-namespace scheduler {
-class RendererScheduler;
-}
-}
-
-namespace content {
-
-// Utility class for throttling a stream of resource requests targetted to a
-// specific IPC sender. The throttling itself is very basic:
-//  * When there is no high-priority work imminent to the main thread, as
-//    indicated by the RendererScheduler, throttling is disabled.
-//  * When >= N requests have been sent in a given time window, requests are
-//    throttled. A timer periodically flushes a portion of the queued requests
-//    until all such requests have been flushed.
-// TODO(jdduke): Remove this class after resource requests become sufficiently
-// cheap on the IO thread, crbug.com/440037.
-class CONTENT_EXPORT ResourceDispatchThrottler : public IPC::Sender {
- public:
-  // |flush_period| and |max_requests_per_flush| must be strictly positive
-  // in duration/value.
-  ResourceDispatchThrottler(IPC::Sender* proxied_sender,
-                            blink::scheduler::RendererScheduler* scheduler,
-                            base::TimeDelta flush_period,
-                            uint32_t max_requests_per_flush);
-  ~ResourceDispatchThrottler() override;
-
-  // IPC::Sender implementation:
-  bool Send(IPC::Message* msg) override;
-
- private:
-  friend class ResourceDispatchThrottlerForTest;
-
-  // Virtual for testing.
-  virtual base::TimeTicks Now() const;
-  virtual void ScheduleFlush();
-
-  void Flush();
-  void FlushAll();
-  void LogFlush();
-  bool ForwardMessage(IPC::Message* msg);
-
-  base::ThreadChecker thread_checker_;
-
-  IPC::Sender* const proxied_sender_;
-  blink::scheduler::RendererScheduler* const scheduler_;
-  const base::TimeDelta flush_period_;
-  const uint32_t max_requests_per_flush_;
-
-  base::Timer flush_timer_;
-  base::TimeTicks last_flush_time_;
-  uint32_t sent_requests_since_last_flush_;
-  base::circular_deque<IPC::Message*> throttled_messages_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResourceDispatchThrottler);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_SCHEDULER_RESOURCE_DISPATCH_THROTTLER_H_
diff --git a/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc b/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc
deleted file mode 100644
index f18bfb1..0000000
--- a/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc
+++ /dev/null
@@ -1,424 +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/renderer/scheduler/resource_dispatch_throttler.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "content/common/resource_messages.h"
-#include "content/public/common/resource_request.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/scheduler/test/fake_renderer_scheduler.h"
-
-namespace content {
-namespace {
-
-const uint32_t kRequestsPerFlush = 4;
-const double kFlushPeriodSeconds = 1.f / 60;
-const int kRoutingId = 1;
-
-typedef std::vector<std::unique_ptr<IPC::Message>> ScopedMessages;
-
-int GetRequestId(const IPC::Message& msg) {
-  int request_id = -1;
-  switch (msg.type()) {
-    case ResourceHostMsg_RequestResource::ID: {
-      base::PickleIterator iter(msg);
-      int routing_id = -1;
-      if (!iter.ReadInt(&routing_id) || !iter.ReadInt(&request_id))
-        NOTREACHED() << "Invalid id for resource request message.";
-    } break;
-
-    case ResourceHostMsg_DidChangePriority::ID:
-    case ResourceHostMsg_ReleaseDownloadedFile::ID:
-    case ResourceHostMsg_CancelRequest::ID:
-      if (!base::PickleIterator(msg).ReadInt(&request_id))
-        NOTREACHED() << "Invalid id for resource message.";
-      break;
-
-    default:
-      NOTREACHED() << "Invalid message for resource throttling.";
-      break;
-  }
-  return request_id;
-}
-
-class RendererSchedulerForTest
-    : public blink::scheduler::FakeRendererScheduler {
- public:
-  RendererSchedulerForTest() : high_priority_work_anticipated_(false) {}
-  ~RendererSchedulerForTest() override {}
-
-  // RendererScheduler implementation:
-  bool IsHighPriorityWorkAnticipated() override {
-    return high_priority_work_anticipated_;
-  }
-
-  void set_high_priority_work_anticipated(bool anticipated) {
-    high_priority_work_anticipated_ = anticipated;
-  }
-
- private:
-  bool high_priority_work_anticipated_;
-};
-
-}  // namespace
-
-class ResourceDispatchThrottlerForTest : public ResourceDispatchThrottler {
- public:
-  ResourceDispatchThrottlerForTest(
-      IPC::Sender* sender,
-      blink::scheduler::RendererScheduler* scheduler)
-      : ResourceDispatchThrottler(
-            sender,
-            scheduler,
-            base::TimeDelta::FromSecondsD(kFlushPeriodSeconds),
-            kRequestsPerFlush),
-        now_(base::TimeTicks() + base::TimeDelta::FromDays(1)),
-        flush_scheduled_(false) {}
-  ~ResourceDispatchThrottlerForTest() override {}
-
-  void Advance(base::TimeDelta delta) { now_ += delta; }
-
-  bool RunScheduledFlush() {
-    if (!flush_scheduled_)
-      return false;
-
-    flush_scheduled_ = false;
-    Flush();
-    return true;
-  }
-
-  bool flush_scheduled() const { return flush_scheduled_; }
-
- private:
-  // ResourceDispatchThrottler overrides:
-  base::TimeTicks Now() const override { return now_; }
-  void ScheduleFlush() override { flush_scheduled_ = true; }
-
-  base::TimeTicks now_;
-  bool flush_scheduled_;
-};
-
-class ResourceDispatchThrottlerTest : public testing::Test, public IPC::Sender {
- public:
-  ResourceDispatchThrottlerTest() : last_request_id_(0) {
-    throttler_.reset(new ResourceDispatchThrottlerForTest(this, &scheduler_));
-  }
-  ~ResourceDispatchThrottlerTest() override {}
-
-  // IPC::Sender implementation:
-  bool Send(IPC::Message* msg) override {
-    sent_messages_.push_back(base::WrapUnique(msg));
-    return true;
-  }
-
- protected:
-  void SetHighPriorityWorkAnticipated(bool anticipated) {
-    scheduler_.set_high_priority_work_anticipated(anticipated);
-  }
-
-  void Advance(base::TimeDelta delta) { throttler_->Advance(delta); }
-
-  bool RunScheduledFlush() { return throttler_->RunScheduledFlush(); }
-
-  bool FlushScheduled() { return throttler_->flush_scheduled(); }
-
-  bool RequestResource() {
-    ResourceRequest request;
-    request.download_to_file = true;
-    return throttler_->Send(new ResourceHostMsg_RequestResource(
-        kRoutingId, ++last_request_id_, request,
-        net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)));
-  }
-
-  bool RequestResourceSync() {
-    SyncLoadResult result;
-    return throttler_->Send(new ResourceHostMsg_SyncLoad(
-        kRoutingId, ++last_request_id_, ResourceRequest(), &result));
-  }
-
-  void RequestResourcesUntilThrottled() {
-    SetHighPriorityWorkAnticipated(true);
-    GetAndResetSentMessageCount();
-    RequestResource();
-    while (GetAndResetSentMessageCount())
-      RequestResource();
-  }
-
-  bool UpdateRequestPriority(int request_id, net::RequestPriority priority) {
-    return throttler_->Send(
-        new ResourceHostMsg_DidChangePriority(request_id, priority, 0));
-  }
-
-  bool ReleaseDownloadedFile(int request_id) {
-    return throttler_->Send(
-        new ResourceHostMsg_ReleaseDownloadedFile(request_id));
-  }
-
-  bool CancelRequest(int request_id) {
-    return throttler_->Send(new ResourceHostMsg_CancelRequest(request_id));
-  }
-
-  size_t GetAndResetSentMessageCount() {
-    size_t sent_message_count = sent_messages_.size();
-    sent_messages_.clear();
-    return sent_message_count;
-  }
-
-  const IPC::Message* LastSentMessage() const {
-    return sent_messages_.empty() ? nullptr : sent_messages_.back().get();
-  }
-
-  int LastSentRequestId() const {
-    const IPC::Message* msg = LastSentMessage();
-    if (!msg)
-      return -1;
-
-    int routing_id = -1;
-    int request_id = -1;
-    base::PickleIterator iter(*msg);
-    CHECK(IPC::ReadParam(msg, &iter, &routing_id));
-    CHECK(IPC::ReadParam(msg, &iter, &request_id));
-    return request_id;
-  }
-
-  int last_request_id() const { return last_request_id_; }
-
-  ScopedMessages sent_messages_;
-
- private:
-  std::unique_ptr<ResourceDispatchThrottlerForTest> throttler_;
-  RendererSchedulerForTest scheduler_;
-  int last_request_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResourceDispatchThrottlerTest);
-};
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledByDefault) {
-  SetHighPriorityWorkAnticipated(false);
-  for (size_t i = 0; i < kRequestsPerFlush * 2; ++i) {
-    RequestResource();
-    EXPECT_EQ(i + 1, sent_messages_.size());
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSendLimitNotReached) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush; ++i) {
-    RequestResource();
-    EXPECT_EQ(i + 1, sent_messages_.size());
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, ThrottledWhenHighPriorityWork) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  RequestResource();
-  EXPECT_EQ(0U, sent_messages_.size());
-
-  EXPECT_TRUE(RunScheduledFlush());
-  EXPECT_EQ(1U, sent_messages_.size());
-}
-
-TEST_F(ResourceDispatchThrottlerTest,
-       ThrottledWhenDeferredMessageQueueNonEmpty) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  RequestResource();
-  EXPECT_EQ(0U, sent_messages_.size());
-  SetHighPriorityWorkAnticipated(false);
-  RequestResource();
-  EXPECT_EQ(0U, sent_messages_.size());
-
-  EXPECT_TRUE(RunScheduledFlush());
-  EXPECT_EQ(2U, sent_messages_.size());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSufficientTimePassed) {
-  SetHighPriorityWorkAnticipated(true);
-
-  for (size_t i = 0; i < kRequestsPerFlush * 2; ++i) {
-    Advance(base::TimeDelta::FromSecondsD(kFlushPeriodSeconds * 2));
-    RequestResource();
-    EXPECT_EQ(1U, GetAndResetSentMessageCount());
-    EXPECT_FALSE(FlushScheduled());
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSendRateSufficientlyLow) {
-  SetHighPriorityWorkAnticipated(true);
-
-  // Continuous dispatch of resource requests below the allowed send rate
-  // should never throttled.
-  const base::TimeDelta kAllowedContinuousSendInterval =
-      base::TimeDelta::FromSecondsD((kFlushPeriodSeconds / kRequestsPerFlush) +
-                                    .00001);
-  for (size_t i = 0; i < kRequestsPerFlush * 10; ++i) {
-    Advance(kAllowedContinuousSendInterval);
-    RequestResource();
-    EXPECT_EQ(1U, GetAndResetSentMessageCount());
-    EXPECT_FALSE(FlushScheduled());
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, ThrottledIfSendRateSufficientlyHigh) {
-  SetHighPriorityWorkAnticipated(true);
-
-  // Continuous dispatch of resource requests above the allowed send rate
-  // should be throttled.
-  const base::TimeDelta kThrottledContinuousSendInterval =
-      base::TimeDelta::FromSecondsD((kFlushPeriodSeconds / kRequestsPerFlush) -
-                                    .00001);
-
-  for (size_t i = 0; i < kRequestsPerFlush * 10; ++i) {
-    Advance(kThrottledContinuousSendInterval);
-    RequestResource();
-    // Only the first batch of requests under the limit should be unthrottled.
-    if (i < kRequestsPerFlush) {
-      EXPECT_EQ(1U, GetAndResetSentMessageCount());
-      EXPECT_FALSE(FlushScheduled());
-    } else {
-      EXPECT_EQ(0U, GetAndResetSentMessageCount());
-      EXPECT_TRUE(FlushScheduled());
-    }
-  }
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSyncMessage) {
-  SetHighPriorityWorkAnticipated(true);
-
-  RequestResourceSync();
-  EXPECT_EQ(1U, GetAndResetSentMessageCount());
-
-  // Saturate the queue.
-  for (size_t i = 0; i < kRequestsPerFlush * 2; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  // Synchronous messages should flush any previously throttled messages.
-  RequestResourceSync();
-  EXPECT_EQ(1U + kRequestsPerFlush, GetAndResetSentMessageCount());
-  RequestResourceSync();
-  EXPECT_EQ(1U, GetAndResetSentMessageCount());
-
-  // Previously throttled messages should already have been flushed.
-  RunScheduledFlush();
-  EXPECT_EQ(0U, GetAndResetSentMessageCount());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, MultipleFlushes) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush * 4; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  for (size_t i = 0; i < 3; ++i) {
-    SCOPED_TRACE(i);
-    EXPECT_TRUE(RunScheduledFlush());
-    EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-  }
-
-  EXPECT_FALSE(FlushScheduled());
-  EXPECT_EQ(0U, sent_messages_.size());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, MultipleFlushesWhileReceiving) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush * 4; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  for (size_t i = 0; i < 3; ++i) {
-    SCOPED_TRACE(i);
-    EXPECT_TRUE(RunScheduledFlush());
-    EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-    for (size_t j = 0; j < kRequestsPerFlush; ++j)
-      RequestResource();
-    EXPECT_EQ(0U, sent_messages_.size());
-  }
-
-  for (size_t i = 0; i < 3; ++i) {
-    EXPECT_TRUE(RunScheduledFlush());
-    EXPECT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-  }
-
-  EXPECT_FALSE(FlushScheduled());
-  EXPECT_EQ(0U, sent_messages_.size());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NonRequestsNeverTriggerThrottling) {
-  RequestResource();
-  ASSERT_EQ(1U, GetAndResetSentMessageCount());
-
-  for (size_t i = 0; i < kRequestsPerFlush * 3; ++i)
-    UpdateRequestPriority(last_request_id(), net::HIGHEST);
-  EXPECT_EQ(kRequestsPerFlush * 3, sent_messages_.size());
-
-  RequestResource();
-  EXPECT_EQ(1U + kRequestsPerFlush * 3, GetAndResetSentMessageCount());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, NonRequestsDeferredWhenThrottling) {
-  RequestResource();
-  ASSERT_EQ(1U, GetAndResetSentMessageCount());
-
-  RequestResourcesUntilThrottled();
-  UpdateRequestPriority(last_request_id(), net::HIGHEST);
-  ReleaseDownloadedFile(last_request_id());
-  CancelRequest(last_request_id());
-
-  EXPECT_TRUE(RunScheduledFlush());
-  EXPECT_EQ(4U, GetAndResetSentMessageCount());
-  EXPECT_FALSE(FlushScheduled());
-}
-
-TEST_F(ResourceDispatchThrottlerTest, MessageOrderingPreservedWhenThrottling) {
-  SetHighPriorityWorkAnticipated(true);
-  for (size_t i = 0; i < kRequestsPerFlush; ++i)
-    RequestResource();
-  ASSERT_EQ(kRequestsPerFlush, GetAndResetSentMessageCount());
-
-  for (size_t i = 0; i < kRequestsPerFlush; ++i) {
-    RequestResource();
-    UpdateRequestPriority(last_request_id(), net::HIGHEST);
-    CancelRequest(last_request_id() - 1);
-  }
-  ASSERT_EQ(0U, sent_messages_.size());
-
-  EXPECT_TRUE(RunScheduledFlush());
-  ASSERT_EQ(kRequestsPerFlush * 3, sent_messages_.size());
-  for (size_t i = 0; i < sent_messages_.size(); i += 3) {
-    SCOPED_TRACE(i);
-    const auto& request_msg = *sent_messages_[i];
-    const auto& priority_msg = *sent_messages_[i + 1];
-    const auto& cancel_msg = *sent_messages_[i + 2];
-
-    EXPECT_EQ(request_msg.type(),
-              static_cast<uint32_t>(ResourceHostMsg_RequestResource::ID));
-    EXPECT_EQ(priority_msg.type(),
-              static_cast<uint32_t>(ResourceHostMsg_DidChangePriority::ID));
-    EXPECT_EQ(cancel_msg.type(),
-              static_cast<uint32_t>(ResourceHostMsg_CancelRequest::ID));
-
-    EXPECT_EQ(GetRequestId(request_msg), GetRequestId(priority_msg));
-    EXPECT_EQ(GetRequestId(request_msg) - 1, GetRequestId(cancel_msg));
-  }
-  EXPECT_FALSE(FlushScheduled());
-}
-
-}  // namespace content
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index f22b82e..f0fd7a02 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -33,8 +33,8 @@
 
 void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread(
     scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner) {
-  resource_dispatcher_ = std::make_unique<ResourceDispatcher>(
-      nullptr, std::move(loading_task_runner));
+  resource_dispatcher_ =
+      std::make_unique<ResourceDispatcher>(std::move(loading_task_runner));
   resource_dispatcher_->set_terminate_sync_load_event(
       &terminate_sync_load_event_);
 
diff --git a/content/renderer/service_worker/web_service_worker_impl.cc b/content/renderer/service_worker/web_service_worker_impl.cc
index 4b6b93f3..c078c10b 100644
--- a/content/renderer/service_worker/web_service_worker_impl.cc
+++ b/content/renderer/service_worker/web_service_worker_impl.cc
@@ -84,7 +84,7 @@
   return state_;
 }
 
-void WebServiceWorkerImpl::PostMessage(
+void WebServiceWorkerImpl::PostMessageToWorker(
     blink::WebServiceWorkerProvider* provider,
     const WebString& message,
     const WebSecurityOrigin& source_origin,
diff --git a/content/renderer/service_worker/web_service_worker_impl.h b/content/renderer/service_worker/web_service_worker_impl.h
index 56affc3..0bba378 100644
--- a/content/renderer/service_worker/web_service_worker_impl.h
+++ b/content/renderer/service_worker/web_service_worker_impl.h
@@ -46,7 +46,7 @@
   blink::WebServiceWorkerProxy* Proxy() override;
   blink::WebURL Url() const override;
   blink::mojom::ServiceWorkerState GetState() const override;
-  void PostMessage(
+  void PostMessageToWorker(
       blink::WebServiceWorkerProvider* provider,
       const blink::WebString& message,
       const blink::WebSecurityOrigin& source_origin,
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.cc b/content/renderer/service_worker/worker_fetch_context_impl.cc
index c42e3d1..8132b9c 100644
--- a/content/renderer/service_worker/worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/worker_fetch_context_impl.cc
@@ -125,8 +125,8 @@
   DCHECK(loading_task_runner->RunsTasksInCurrentSequence());
   DCHECK(!resource_dispatcher_);
   DCHECK(!binding_.is_bound());
-  resource_dispatcher_ = std::make_unique<ResourceDispatcher>(
-      nullptr, std::move(loading_task_runner));
+  resource_dispatcher_ =
+      std::make_unique<ResourceDispatcher>(std::move(loading_task_runner));
   resource_dispatcher_->set_terminate_sync_load_event(
       &terminate_sync_load_event_);
 
diff --git a/content/shell/android/java/src/org/chromium/content_shell/Shell.java b/content/shell/android/java/src/org/chromium/content_shell/Shell.java
index 3693814..e8153f3 100644
--- a/content/shell/android/java/src/org/chromium/content_shell/Shell.java
+++ b/content/shell/android/java/src/org/chromium/content_shell/Shell.java
@@ -377,6 +377,11 @@
         }
     }
 
+    @CalledByNative
+    public void sizeTo(int width, int height) {
+        mWebContents.setSize(width, height);
+    }
+
     public void setOverayModeChangedCallbackForTesting(Callback<Boolean> callback) {
         mOverlayModeChangedCallbackForTesting = callback;
     }
diff --git a/content/shell/android/linker_test_apk/chromium_linker_test_linker_tests.cc b/content/shell/android/linker_test_apk/chromium_linker_test_linker_tests.cc
index 3dbdadc..b86538cb 100644
--- a/content/shell/android/linker_test_apk/chromium_linker_test_linker_tests.cc
+++ b/content/shell/android/linker_test_apk/chromium_linker_test_linker_tests.cc
@@ -46,11 +46,6 @@
   //
   //   "/dev/ashmem/RELRO:<libname> (deleted)"
   //
-  // and for the ModernLinker, something like:
-  //
-  //   "/data/data/org.chromium.chromium_linker_test_apk/
-  //       app_chromium_linker_test/RELRO:<libname> (deleted)"
-  //
   // Where <libname> is the library name and '(deleted)' is actually
   // added by the kernel to indicate there is no corresponding file
   // on the filesystem.
@@ -59,7 +54,6 @@
   // section, but for the component build, there are several libraries,
   // each one with its own RELRO.
   static const char kLegacyRelroSectionPattern[] = "/dev/ashmem/RELRO:.*";
-  static const char kModernRelroSectionPattern[] = "/data/.*/RELRO:.*";
 
   // Parse /proc/self/maps and builds a list of region mappings in this
   // process.
@@ -78,7 +72,6 @@
   }
 
   const RE2 legacy_linker_re(kLegacyRelroSectionPattern);
-  const RE2 modern_linker_re(kModernRelroSectionPattern);
 
   int num_shared_relros = 0;
   int num_bad_shared_relros = 0;
@@ -88,15 +81,8 @@
 
     const std::string path = region.path;
     const bool is_legacy_relro = re2::RE2::FullMatch(path, legacy_linker_re);
-    const bool is_modern_relro = re2::RE2::FullMatch(path, modern_linker_re);
 
-    if (is_legacy_relro && is_modern_relro) {
-      LOG(ERROR) << prefix
-                 << "FAIL RELRO cannot be both Legacy and Modern (test error)";
-      return false;
-    }
-
-    if (!is_legacy_relro && !is_modern_relro) {
+    if (!is_legacy_relro) {
       // Ignore any mapping that isn't a shared RELRO.
       continue;
     }
@@ -127,16 +113,6 @@
       continue;
     }
 
-    // Shared RELROs implemented by the Android M+ system linker are not in
-    // ashmem. The Android M+ system linker maps everything with MAP_PRIVATE
-    // rather than MAP_SHARED. Remapping such a RELRO section read-write will
-    // therefore succeed, but it is not a problem. The memory copy-on-writes,
-    // and updates are not visible to either the mapped file or other processes
-    // mapping the same file. So... we skip the remap test for ModernLinker.
-    if (is_modern_relro) {
-      continue;
-    }
-
     // Check that trying to remap it read-write fails with EACCES
     size_t region_size = region.end - region.start;
     int ret = ::mprotect(region_start, region_size, PROT_READ | PROT_WRITE);
diff --git a/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java b/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java
index 0385a5d..a283ed5 100644
--- a/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java
+++ b/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java
@@ -39,12 +39,6 @@
     // target device running the test really is.
     private static final String LOW_MEMORY_DEVICE = "--low-memory-device";
 
-    // Use one of these on the command-line to force a specific Linker
-    // implementation. Passed from the main process to sub-processes so that
-    // everything that participates in a test uses a consistent implementation.
-    private static final String USE_MODERN_LINKER = "--use-linker=modern";
-    private static final String USE_LEGACY_LINKER = "--use-linker=legacy";
-
     private ShellManager mShellManager;
     private ActivityWindowAndroid mWindowAndroid;
 
@@ -64,8 +58,6 @@
         // CommandLine.getInstance().hasSwitch() doesn't work here for some funky
         // reason, so parse the command-line differently here:
         boolean hasLowMemoryDeviceSwitch = false;
-        boolean hasModernLinkerSwitch = false;
-        boolean hasLegacyLinkerSwitch = false;
         String[] commandLine = CommandLine.getJavaSwitchesOrNull();
         if (commandLine == null) {
             Log.i(TAG, "Command line is null");
@@ -76,32 +68,10 @@
                 Log.i(TAG, "  '" + option + "'");
                 if (option.equals(LOW_MEMORY_DEVICE)) {
                     hasLowMemoryDeviceSwitch = true;
-                } else if (option.equals(USE_MODERN_LINKER)) {
-                    hasModernLinkerSwitch = true;
-                } else if (option.equals(USE_LEGACY_LINKER)) {
-                    hasLegacyLinkerSwitch = true;
                 }
             }
         }
 
-        if (!(hasModernLinkerSwitch || hasLegacyLinkerSwitch)) {
-            Log.e(TAG, "Missing --use-linker command line argument.");
-            finish();
-        } else if (hasModernLinkerSwitch && hasLegacyLinkerSwitch) {
-            Log.e(TAG, "Conflicting --use-linker command line arguments.");
-            finish();
-        }
-
-        // Set the requested Linker implementation from the command-line, and
-        // register the test runner class by name.
-        if (hasModernLinkerSwitch) {
-            Linker.setupForTesting(Linker.LINKER_IMPLEMENTATION_MODERN,
-                                   LinkerTests.class.getName());
-        } else {
-            Linker.setupForTesting(Linker.LINKER_IMPLEMENTATION_LEGACY,
-                                   LinkerTests.class.getName());
-        }
-
         // Determine which kind of device to simulate from the command-line.
         int memoryDeviceConfig = Linker.MEMORY_DEVICE_CONFIG_NORMAL;
         if (hasLowMemoryDeviceSwitch) {
diff --git a/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/LinkerTests.java b/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/LinkerTests.java
index 337a2c8..f41e44dab 100644
--- a/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/LinkerTests.java
+++ b/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/LinkerTests.java
@@ -23,37 +23,24 @@
                              boolean isBrowserProcess) {
         boolean checkSharedRelro;
         if (isBrowserProcess) {
-            Linker linker = Linker.getInstance();
-            int linkerImplementation = linker.getImplementationForTesting();
-
-            if (linkerImplementation == Linker.LINKER_IMPLEMENTATION_LEGACY) {
-                // LegacyLinker may share RELROs in the browser.
-                switch (Linker.BROWSER_SHARED_RELRO_CONFIG) {
-                    case Linker.BROWSER_SHARED_RELRO_CONFIG_NEVER:
-                        checkSharedRelro = false;
-                        break;
-                    case Linker.BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY:
-                        // A shared RELRO should only be used on low-end devices.
-                        checkSharedRelro =
-                                (memoryDeviceConfig == Linker.MEMORY_DEVICE_CONFIG_LOW);
-                        break;
-                    case Linker.BROWSER_SHARED_RELRO_CONFIG_ALWAYS:
-                        // Always check for a shared RELRO.
-                        checkSharedRelro = true;
-                        break;
-                    default:
-                        Log.e(TAG, "Invalid shared RELRO linker configuration: "
-                                + Linker.BROWSER_SHARED_RELRO_CONFIG);
-                        return false;
-                }
-
-            } else if (linkerImplementation == Linker.LINKER_IMPLEMENTATION_MODERN) {
-                // ModernLinker never shares RELROs in the browser.
-                checkSharedRelro = false;
-
-            } else {
-                Log.e(TAG, "Unknown linker: " + linker.getClass().getName());
-                return false;
+            // LegacyLinker may share RELROs in the browser.
+            switch (Linker.BROWSER_SHARED_RELRO_CONFIG) {
+                case Linker.BROWSER_SHARED_RELRO_CONFIG_NEVER:
+                    checkSharedRelro = false;
+                    break;
+                case Linker.BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY:
+                    // A shared RELRO should only be used on low-end devices.
+                    checkSharedRelro = (memoryDeviceConfig == Linker.MEMORY_DEVICE_CONFIG_LOW);
+                    break;
+                case Linker.BROWSER_SHARED_RELRO_CONFIG_ALWAYS:
+                    // Always check for a shared RELRO.
+                    checkSharedRelro = true;
+                    break;
+                default:
+                    Log.e(TAG,
+                            "Invalid shared RELRO linker configuration: "
+                                    + Linker.BROWSER_SHARED_RELRO_CONFIG);
+                    return false;
             }
         } else {
             // Service processes should always use a shared RELRO section.
diff --git a/content/shell/browser/layout_test/blink_test_controller.cc b/content/shell/browser/layout_test/blink_test_controller.cc
index 81bdb4e..4819c4d2 100644
--- a/content/shell/browser/layout_test/blink_test_controller.cc
+++ b/content/shell/browser/layout_test/blink_test_controller.cc
@@ -408,6 +408,14 @@
       LoadDevToolsJSTest();
     else
       main_window_->LoadURL(test_url_);
+
+#if defined(OS_ANDROID)
+    // On Android, the browser main loop runs on the UI thread so the view
+    // hierarchy never gets to layout since the UI thread is blocked. This call
+    // simulates a layout and ensures our RenderWidget hierarchy gets correctly
+    // sized.
+    main_window_->SizeTo(initial_size_);
+#endif
   } else {
 #if defined(OS_MACOSX)
     // Shell::SizeTo is not implemented on all platforms.
diff --git a/content/shell/browser/shell.h b/content/shell/browser/shell.h
index 92d30bb11..317cdcb 100644
--- a/content/shell/browser/shell.h
+++ b/content/shell/browser/shell.h
@@ -82,7 +82,7 @@
   void ShowDevTools();
   void CloseDevTools();
   bool hide_toolbar() { return hide_toolbar_; }
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
   // Resizes the web content view to the given dimensions.
   void SizeTo(const gfx::Size& content_size);
 #endif
diff --git a/content/shell/browser/shell_android.cc b/content/shell/browser/shell_android.cc
index 9ca2b93aa..c61a333 100644
--- a/content/shell/browser/shell_android.cc
+++ b/content/shell/browser/shell_android.cc
@@ -68,6 +68,12 @@
   // Not needed; subviews are bound.
 }
 
+void Shell::SizeTo(const gfx::Size& content_size) {
+  JNIEnv* env = AttachCurrentThread();
+  Java_Shell_sizeTo(env, java_object_, content_size.width(),
+                    content_size.height());
+}
+
 void Shell::PlatformSetTitle(const base::string16& title) {
   NOTIMPLEMENTED() << ": " << title;
 }
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc
index d49cf323..2f471903 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.cc
+++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -430,17 +430,6 @@
       routing_id(), call_id, script));
 }
 
-std::string BlinkTestRunner::EvaluateInWebInspectorOverlay(
-    const std::string& script) {
-  WebDevToolsAgent* agent =
-      render_view()->GetMainRenderFrame()->GetWebFrame()->DevToolsAgent();
-  if (!agent)
-    return std::string();
-
-  return agent->EvaluateInWebInspectorOverlay(WebString::FromUTF8(script))
-      .Utf8();
-}
-
 void BlinkTestRunner::ClearAllDatabases() {
   Send(new LayoutTestHostMsg_ClearAllDatabases(routing_id()));
 }
diff --git a/content/shell/renderer/layout_test/blink_test_runner.h b/content/shell/renderer/layout_test/blink_test_runner.h
index 977167b1..66b8d1cc 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.h
+++ b/content/shell/renderer/layout_test/blink_test_runner.h
@@ -96,7 +96,6 @@
                     const std::string& frontend_url) override;
   void CloseDevTools() override;
   void EvaluateInWebInspector(int call_id, const std::string& script) override;
-  std::string EvaluateInWebInspectorOverlay(const std::string& script) override;
   void ClearAllDatabases() override;
   void SetDatabaseQuota(int quota) override;
   void SimulateWebNotificationClick(
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc
index b1dcb52..3f0bc1f 100644
--- a/content/shell/test_runner/test_runner.cc
+++ b/content/shell/test_runner/test_runner.cc
@@ -264,7 +264,6 @@
                             int min_height,
                             int max_width,
                             int max_height);
-  std::string EvaluateInWebInspectorOverlay(const std::string& script);
   v8::Local<v8::Value> EvaluateScriptInIsolatedWorldAndReturnValue(
       int world_id,
       const std::string& script);
@@ -427,8 +426,6 @@
                  &TestRunnerBindings::EnableUseZoomForDSF)
       .SetMethod("evaluateInWebInspector",
                  &TestRunnerBindings::EvaluateInWebInspector)
-      .SetMethod("evaluateInWebInspectorOverlay",
-                 &TestRunnerBindings::EvaluateInWebInspectorOverlay)
       .SetMethod("evaluateScriptInIsolatedWorld",
                  &TestRunnerBindings::EvaluateScriptInIsolatedWorld)
       .SetMethod(
@@ -1279,14 +1276,6 @@
     runner_->EvaluateInWebInspector(call_id, script);
 }
 
-std::string TestRunnerBindings::EvaluateInWebInspectorOverlay(
-    const std::string& script) {
-  if (runner_)
-    return runner_->EvaluateInWebInspectorOverlay(script);
-
-  return std::string();
-}
-
 void TestRunnerBindings::ClearAllDatabases() {
   if (runner_)
     runner_->ClearAllDatabases();
@@ -2659,11 +2648,6 @@
   delegate_->EvaluateInWebInspector(call_id, script);
 }
 
-std::string TestRunner::EvaluateInWebInspectorOverlay(
-    const std::string& script) {
-  return delegate_->EvaluateInWebInspectorOverlay(script);
-}
-
 void TestRunner::ClearAllDatabases() {
   delegate_->ClearAllDatabases();
 }
diff --git a/content/shell/test_runner/test_runner.h b/content/shell/test_runner/test_runner.h
index 2a24b3d..4329d61 100644
--- a/content/shell/test_runner/test_runner.h
+++ b/content/shell/test_runner/test_runner.h
@@ -486,10 +486,6 @@
 
   // Allows layout tests to exec scripts at WebInspector side.
   void EvaluateInWebInspector(int call_id, const std::string& script);
-  // Allows layout tests to evaluate scripts in InspectorOverlay page.
-  // Script may have an output represented as a string, return values of other
-  // types would be ignored.
-  std::string EvaluateInWebInspectorOverlay(const std::string& script);
 
   // Clears all databases.
   void ClearAllDatabases();
diff --git a/content/shell/test_runner/web_test_delegate.h b/content/shell/test_runner/web_test_delegate.h
index b28c3026..01be2c0 100644
--- a/content/shell/test_runner/web_test_delegate.h
+++ b/content/shell/test_runner/web_test_delegate.h
@@ -143,10 +143,6 @@
   virtual void EvaluateInWebInspector(int call_id,
                                       const std::string& script) = 0;
 
-  // Evaluate the given script in the inspector overlay page.
-  virtual std::string EvaluateInWebInspectorOverlay(
-      const std::string& script) = 0;
-
   // Controls WebSQL databases.
   virtual void ClearAllDatabases() = 0;
   // Setting quota to kDefaultDatabaseQuota will reset it to the default value.
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 6eef3245..60fc209e 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -247,6 +247,8 @@
     "test_navigation_url_loader_delegate.h",
     "test_navigation_url_loader_factory.cc",
     "test_navigation_url_loader_factory.h",
+    "test_overscroll_delegate.cc",
+    "test_overscroll_delegate.h",
     "test_render_frame.cc",
     "test_render_frame.h",
     "test_render_frame_host.cc",
@@ -731,7 +733,6 @@
     "../browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc",
     "../browser/indexed_db/mock_browsertest_indexed_db_class_factory.h",
     "../browser/isolated_origin_browsertest.cc",
-    "../browser/loader/async_resource_handler_browsertest.cc",
     "../browser/loader/cross_site_document_blocking_browsertest.cc",
     "../browser/loader/cross_site_resource_handler_browsertest.cc",
     "../browser/loader/reload_cache_control_browsertest.cc",
@@ -1293,7 +1294,6 @@
     "../browser/indexed_db/mock_mojo_indexed_db_database_callbacks.cc",
     "../browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h",
     "../browser/leveldb_wrapper_impl_unittest.cc",
-    "../browser/loader/async_resource_handler_unittest.cc",
     "../browser/loader/cross_site_document_resource_handler_unittest.cc",
     "../browser/loader/detachable_resource_handler_unittest.cc",
     "../browser/loader/intercepting_resource_handler_unittest.cc",
@@ -1405,6 +1405,7 @@
     "../browser/renderer_host/media/video_capture_manager_unittest.cc",
     "../browser/renderer_host/media/video_capture_unittest.cc",
     "../browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc",
+    "../browser/renderer_host/overscroll_controller_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",
@@ -1466,9 +1467,6 @@
     "../browser/web_contents/web_contents_view_mac_unittest.mm",
     "../browser/web_contents/web_drag_dest_mac_unittest.mm",
     "../browser/web_contents/web_drag_source_mac_unittest.mm",
-    "../browser/webauth/cbor/cbor_reader_unittest.cc",
-    "../browser/webauth/cbor/cbor_values_unittest.cc",
-    "../browser/webauth/cbor/cbor_writer_unittest.cc",
     "../browser/websockets/websocket_manager_unittest.cc",
     "../browser/webui/url_data_manager_backend_unittest.cc",
     "../browser/webui/web_ui_data_source_unittest.cc",
@@ -1563,7 +1561,6 @@
     "../renderer/loader/cors_url_loader_unittest.cc",
     "../renderer/loader/resource_dispatcher_unittest.cc",
     "../renderer/loader/shared_memory_data_consumer_handle_unittest.cc",
-    "../renderer/loader/shared_memory_received_data_factory_unittest.cc",
     "../renderer/loader/site_isolation_stats_gatherer_unittest.cc",
     "../renderer/loader/test_request_peer.cc",
     "../renderer/loader/test_request_peer.h",
@@ -1590,7 +1587,6 @@
     "../renderer/presentation/test_presentation_connection.h",
     "../renderer/render_thread_impl_unittest.cc",
     "../renderer/render_widget_unittest.cc",
-    "../renderer/scheduler/resource_dispatch_throttler_unittest.cc",
     "../renderer/service_worker/service_worker_context_client_unittest.cc",
     "../renderer/service_worker/service_worker_dispatcher_unittest.cc",
     "../renderer/service_worker/service_worker_provider_context_unittest.cc",
@@ -1985,7 +1981,10 @@
   is_linux_without_udev = is_linux && !use_udev
   if (!is_linux_without_udev && !is_android) {
     sources += [ "../browser/webauth/authenticator_impl_unittest.cc" ]
-    deps += [ "//device/u2f:test_support" ]
+    deps += [
+      "//components/cbor",
+      "//device/u2f:test_support",
+    ]
   }
 
   if (use_aura) {
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn
index 3df1822..3907fe2 100644
--- a/content/test/fuzzer/BUILD.gn
+++ b/content/test/fuzzer/BUILD.gn
@@ -99,15 +99,3 @@
   ]
   testonly = true
 }
-
-fuzzer_test("cbor_reader_fuzzer") {
-  sources = [
-    "cbor_reader_fuzzer.cc",
-  ]
-  deps = [
-    ":fuzzer_support",
-    "//content/browser:for_content_tests",
-  ]
-  seed_corpus = "../data/fuzzer_corpus/cbor_data/"
-  libfuzzer_options = [ "max_len=65535" ]
-}
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py
index db0f9cb..2d11531 100755
--- a/content/test/gpu/generate_buildbot_json.py
+++ b/content/test/gpu/generate_buildbot_json.py
@@ -1366,6 +1366,8 @@
           'Android Release (Nexus 5)',
           'Android Release (Nexus 6)',
           'Android Release (Nexus 9)',
+          # Temporarily disabled due to AMDGPU-PRO issues crbug.com/786219
+          'Linux Release (AMD R7 240)',
         ],
       },
     ],
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index c557096..2269d75 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -366,7 +366,7 @@
       override {
     // This is for an offscreen context for the compositor. So the default
     // framebuffer doesn't need alpha, depth, stencil, antialiasing.
-    gpu::gles2::ContextCreationAttribHelper attributes;
+    gpu::ContextCreationAttribs attributes;
     attributes.alpha_size = -1;
     attributes.depth_size = 0;
     attributes.stencil_size = 0;
diff --git a/content/test/test_overscroll_delegate.cc b/content/test/test_overscroll_delegate.cc
new file mode 100644
index 0000000..83733490
--- /dev/null
+++ b/content/test/test_overscroll_delegate.cc
@@ -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.
+
+#include "content/test/test_overscroll_delegate.h"
+
+namespace content {
+
+TestOverscrollDelegate::TestOverscrollDelegate(const gfx::Size& display_size)
+    : display_size_(display_size),
+      current_mode_(OVERSCROLL_NONE),
+      completed_mode_(OVERSCROLL_NONE),
+      delta_x_(0.f),
+      delta_y_(0.f) {}
+
+TestOverscrollDelegate::~TestOverscrollDelegate() {}
+
+void TestOverscrollDelegate::Reset() {
+  current_mode_ = OVERSCROLL_NONE;
+  completed_mode_ = OVERSCROLL_NONE;
+  historical_modes_.clear();
+  delta_x_ = delta_y_ = 0.f;
+}
+
+gfx::Size TestOverscrollDelegate::GetDisplaySize() const {
+  return display_size_;
+}
+
+bool TestOverscrollDelegate::OnOverscrollUpdate(float delta_x, float delta_y) {
+  delta_x_ = delta_x;
+  delta_y_ = delta_y;
+  return true;
+}
+
+void TestOverscrollDelegate::OnOverscrollComplete(
+    OverscrollMode overscroll_mode) {
+  DCHECK_EQ(current_mode_, overscroll_mode);
+  completed_mode_ = overscroll_mode;
+  current_mode_ = OVERSCROLL_NONE;
+}
+
+void TestOverscrollDelegate::OnOverscrollModeChange(OverscrollMode old_mode,
+                                                    OverscrollMode new_mode,
+                                                    OverscrollSource source) {
+  DCHECK_EQ(current_mode_, old_mode);
+  current_mode_ = new_mode;
+  historical_modes_.push_back(new_mode);
+  delta_x_ = delta_y_ = 0.f;
+}
+
+base::Optional<float> TestOverscrollDelegate::GetMaxOverscrollDelta() const {
+  return delta_cap_;
+}
+
+}  // namespace content
diff --git a/content/test/test_overscroll_delegate.h b/content/test/test_overscroll_delegate.h
new file mode 100644
index 0000000..54b580f
--- /dev/null
+++ b/content/test/test_overscroll_delegate.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.
+
+#include <vector>
+
+#include "base/optional.h"
+#include "content/browser/renderer_host/overscroll_controller.h"
+#include "content/browser/renderer_host/overscroll_controller_delegate.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+
+class TestOverscrollDelegate : public OverscrollControllerDelegate {
+ public:
+  explicit TestOverscrollDelegate(const gfx::Size& display_size);
+  ~TestOverscrollDelegate() override;
+
+  void set_delta_cap(float delta_cap) { delta_cap_ = delta_cap; }
+
+  OverscrollMode current_mode() const { return current_mode_; }
+  OverscrollMode completed_mode() const { return completed_mode_; }
+  const std::vector<OverscrollMode>& historical_modes() const {
+    return historical_modes_;
+  }
+  float delta_x() const { return delta_x_; }
+  float delta_y() const { return delta_y_; }
+
+  void Reset();
+
+ private:
+  // Overridden from OverscrollControllerDelegate:
+  gfx::Size GetDisplaySize() const override;
+  bool OnOverscrollUpdate(float delta_x, float delta_y) override;
+  void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
+  void OnOverscrollModeChange(OverscrollMode old_mode,
+                              OverscrollMode new_mode,
+                              OverscrollSource source) override;
+  base::Optional<float> GetMaxOverscrollDelta() const override;
+
+  gfx::Size display_size_;
+
+  base::Optional<float> delta_cap_;
+  OverscrollMode current_mode_;
+  OverscrollMode completed_mode_;
+  std::vector<OverscrollMode> historical_modes_;
+
+  float delta_x_;
+  float delta_y_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestOverscrollDelegate);
+};
+
+}  // namespace content
diff --git a/content/utility/utility_service_factory.cc b/content/utility/utility_service_factory.cc
index 499ec6bb..028e6a2 100644
--- a/content/utility/utility_service_factory.cc
+++ b/content/utility/utility_service_factory.cc
@@ -34,7 +34,7 @@
 #include "media/cdm/cdm_adapter_factory.h"           // nogncheck
 #include "media/mojo/features.h"                     // nogncheck
 #include "media/mojo/interfaces/constants.mojom.h"   // nogncheck
-#include "media/mojo/services/media_service.h"       // nogncheck
+#include "media/mojo/services/cdm_service.h"         // nogncheck
 #include "media/mojo/services/mojo_cdm_helper.h"     // nogncheck
 #include "media/mojo/services/mojo_media_client.h"   // nogncheck
 #if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
@@ -100,7 +100,7 @@
 
 std::unique_ptr<service_manager::Service> CreateCdmService() {
   return std::unique_ptr<service_manager::Service>(
-      new ::media::MediaService(std::make_unique<CdmMojoMediaClient>()));
+      new ::media::CdmService(std::make_unique<CdmMojoMediaClient>()));
 }
 #endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
diff --git a/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc b/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc
index 831d417..097fa5e 100644
--- a/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc
+++ b/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc
@@ -35,6 +35,25 @@
       static_cast<mojom::MtpFileEntry::FileType>(entry.file_type()));
 }
 
+mojom::MtpStorageInfo GetMojoMtpStorageInfoFromProtobuf(
+    const MtpStorageInfo& protobuf) {
+  return mojom::MtpStorageInfo(
+        protobuf.storage_name(),
+        protobuf.vendor(),
+        protobuf.vendor_id(),
+        protobuf.product(),
+        protobuf.product_id(),
+        protobuf.device_flags(),
+        protobuf.storage_type(),
+        protobuf.filesystem_type(),
+        protobuf.access_capability(),
+        protobuf.max_capacity(),
+        protobuf.free_space_in_bytes(),
+        protobuf.free_space_in_objects(),
+        protobuf.storage_description(),
+        protobuf.volume_identifier());
+}
+
 // The MediaTransferProtocolDaemonClient implementation.
 class MediaTransferProtocolDaemonClientImpl
     : public MediaTransferProtocolDaemonClient {
@@ -326,7 +345,7 @@
       error_callback.Run();
       return;
     }
-    callback.Run(protobuf);
+    callback.Run(GetMojoMtpStorageInfoFromProtobuf(protobuf));
   }
 
   // Handles the result of OpenStorage and calls |callback| or |error_callback|.
diff --git a/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h b/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h
index 8a6b7717..0ecf235 100644
--- a/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h
+++ b/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h
@@ -20,13 +20,12 @@
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "device/media_transfer_protocol/public/interfaces/mtp_file_entry.mojom.h"
+#include "device/media_transfer_protocol/public/interfaces/mtp_storage_info.mojom.h"
 
 #if !defined(OS_CHROMEOS)
 #error "Only used on ChromeOS"
 #endif
 
-class MtpStorageInfo;
-
 namespace dbus {
 class Bus;
 }
@@ -49,7 +48,7 @@
   // A callback to handle the result of GetStorageInfo.
   // The argument is the information about the specified storage.
   using GetStorageInfoCallback =
-      base::Callback<void(const MtpStorageInfo& storage_info)>;
+      base::Callback<void(const mojom::MtpStorageInfo& storage_info)>;
 
   // A callback to handle the result of OpenStorage.
   // The argument is the returned handle.
diff --git a/device/media_transfer_protocol/media_transfer_protocol_manager.cc b/device/media_transfer_protocol/media_transfer_protocol_manager.cc
index 148f188..e235333e 100644
--- a/device/media_transfer_protocol/media_transfer_protocol_manager.cc
+++ b/device/media_transfer_protocol/media_transfer_protocol_manager.cc
@@ -100,7 +100,7 @@
   }
 
   // MediaTransferProtocolManager override.
-  const MtpStorageInfo* GetStorageInfo(
+  const mojom::MtpStorageInfo* GetStorageInfo(
       const std::string& storage_name) const override {
     DCHECK(thread_checker_.CalledOnValidThread());
     const auto it = storage_info_map_.find(storage_name);
@@ -113,7 +113,7 @@
       const GetStorageInfoFromDeviceCallback& callback) override {
     DCHECK(thread_checker_.CalledOnValidThread());
     if (!base::ContainsKey(storage_info_map_, storage_name) || !mtp_client_) {
-      MtpStorageInfo info;
+      mojom::MtpStorageInfo info;
       callback.Run(info, true /* error */);
       return;
     }
@@ -360,9 +360,9 @@
     }
   }
 
-  void OnGetStorageInfo(const MtpStorageInfo& storage_info) {
+  void OnGetStorageInfo(const mojom::MtpStorageInfo& storage_info) {
     DCHECK(thread_checker_.CalledOnValidThread());
-    const std::string& storage_name = storage_info.storage_name();
+    const std::string& storage_name = storage_info.storage_name;
     if (base::ContainsKey(storage_info_map_, storage_name)) {
       // This should not happen, since MediaTransferProtocolManagerImpl should
       // only call EnumerateStorages() once, which populates |storage_info_map_|
@@ -381,14 +381,14 @@
       observer.StorageChanged(true /* is attach */, storage_name);
   }
 
-  void OnGetStorageInfoFromDevice(const MtpStorageInfo& storage_info) {
+  void OnGetStorageInfoFromDevice(const mojom::MtpStorageInfo& storage_info) {
     get_storage_info_from_device_callbacks_.front().Run(storage_info,
                                                         false /* no error */);
     get_storage_info_from_device_callbacks_.pop();
   }
 
   void OnGetStorageInfoFromDeviceError() {
-    MtpStorageInfo info;
+    mojom::MtpStorageInfo info;
     get_storage_info_from_device_callbacks_.front().Run(info, true /* error */);
     get_storage_info_from_device_callbacks_.pop();
   }
@@ -646,7 +646,7 @@
   base::ObserverList<Observer> observers_;
 
   // Map to keep track of attached storages by name.
-  base::flat_map<std::string, MtpStorageInfo> storage_info_map_;
+  base::flat_map<std::string, mojom::MtpStorageInfo> storage_info_map_;
 
   // Set of open storage handles.
   base::flat_set<std::string> handles_;
diff --git a/device/media_transfer_protocol/media_transfer_protocol_manager.h b/device/media_transfer_protocol/media_transfer_protocol_manager.h
index aae23da..9d1b39e 100644
--- a/device/media_transfer_protocol/media_transfer_protocol_manager.h
+++ b/device/media_transfer_protocol/media_transfer_protocol_manager.h
@@ -16,13 +16,12 @@
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
 #include "device/media_transfer_protocol/public/interfaces/mtp_file_entry.mojom.h"
+#include "device/media_transfer_protocol/public/interfaces/mtp_storage_info.mojom.h"
 
 #if !defined(OS_CHROMEOS)
 #error "Only used on ChromeOS"
 #endif
 
-class MtpStorageInfo;
-
 namespace device {
 
 // This class handles the interaction with mtpd.
@@ -33,7 +32,7 @@
   // The first argument is the returned storage info.
   // The second argument is true if there was an error.
   using GetStorageInfoFromDeviceCallback =
-      base::Callback<void(const MtpStorageInfo& storage_info,
+      base::Callback<void(const mojom::MtpStorageInfo& storage_info,
                           const bool error)>;
 
   // A callback to handle the result of OpenStorage.
@@ -107,7 +106,7 @@
 
   // On success, returns the metadata for |storage_name|.
   // Otherwise returns NULL.
-  virtual const MtpStorageInfo* GetStorageInfo(
+  virtual const mojom::MtpStorageInfo* GetStorageInfo(
       const std::string& storage_name) const = 0;
 
   // Read the metadata of |storage_name| from device and runs |callback|.
diff --git a/device/media_transfer_protocol/public/interfaces/BUILD.gn b/device/media_transfer_protocol/public/interfaces/BUILD.gn
index 736660f..146d7de 100644
--- a/device/media_transfer_protocol/public/interfaces/BUILD.gn
+++ b/device/media_transfer_protocol/public/interfaces/BUILD.gn
@@ -7,5 +7,6 @@
 mojom("interfaces") {
   sources = [
     "mtp_file_entry.mojom",
+    "mtp_storage_info.mojom",
   ]
 }
diff --git a/device/media_transfer_protocol/public/interfaces/mtp_storage_info.mojom b/device/media_transfer_protocol/public/interfaces/mtp_storage_info.mojom
new file mode 100644
index 0000000..dcdb917
--- /dev/null
+++ b/device/media_transfer_protocol/public/interfaces/mtp_storage_info.mojom
@@ -0,0 +1,25 @@
+// 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 device.mojom;
+
+// This is a mojo counterpart of the MtpStorageInfo protobuf message from
+// //src/third_party/cros_system_api/dbus/mtp_storage_info.proto
+// See discussion on https://crbug.com/769630.
+struct MtpStorageInfo {
+  string storage_name;
+  string vendor;
+  uint32 vendor_id = 0;
+  string product;
+  uint32 product_id = 0;
+  uint32 device_flags = 0;
+  uint32 storage_type = 0;
+  uint32 filesystem_type = 0;
+  uint32 access_capability = 0;
+  uint64 max_capacity = 0;
+  uint64 free_space_in_bytes = 0;
+  uint64 free_space_in_objects = 0;
+  string storage_description;
+  string volume_identifier;
+};
diff --git a/extensions/browser/api/cast_channel/cast_channel_api.cc b/extensions/browser/api/cast_channel/cast_channel_api.cc
index 27b16efe..c5d40367 100644
--- a/extensions/browser/api/cast_channel/cast_channel_api.cc
+++ b/extensions/browser/api/cast_channel/cast_channel_api.cc
@@ -400,8 +400,10 @@
     AsyncWorkCompleted();
     return;
   }
+  // TODO(https://crbug.com/656607): Add proper annotation.
   socket->transport()->SendMessage(
-      message_to_send, base::Bind(&CastChannelSendFunction::OnSend, this));
+      message_to_send, base::Bind(&CastChannelSendFunction::OnSend, this),
+      NO_TRAFFIC_ANNOTATION_BUG_656607);
 }
 
 void CastChannelSendFunction::OnSend(int result) {
diff --git a/extensions/browser/api/cast_channel/cast_channel_apitest.cc b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
index a3aecd39..f984eb2 100644
--- a/extensions/browser/api/cast_channel/cast_channel_apitest.cc
+++ b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
@@ -28,6 +28,7 @@
 #include "net/base/ip_address.h"
 #include "net/base/net_errors.h"
 #include "net/log/test_net_log.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gmock_mutant.h"
 
@@ -115,7 +116,7 @@
       EXPECT_CALL(*mock_cast_socket_, ready_state())
           .WillOnce(Return(ReadyState::OPEN));
       EXPECT_CALL(*mock_cast_socket_->mock_transport(),
-                  SendMessage(A<const CastMessage&>(), _))
+                  SendMessage(A<const CastMessage&>(), _, _))
           .WillOnce(InvokeCompletionCallback<1>(net::OK));
       EXPECT_CALL(*mock_cast_socket_, ready_state())
           .WillOnce(Return(ReadyState::OPEN));
diff --git a/extensions/common/api/networking_private.idl b/extensions/common/api/networking_private.idl
index 0d707c2d..cb25d0cd 100644
--- a/extensions/common/api/networking_private.idl
+++ b/extensions/common/api/networking_private.idl
@@ -439,6 +439,7 @@
     DOMString? StaticChallenge;
     DOMString? TLSAuthContents;
     DOMString? TLSRemote;
+    DOMString? TLSVersionMin;
     DOMString? UserAuthenticationType;
     DOMString? Username;
     DOMString? Verb;
@@ -479,6 +480,7 @@
     ManagedDOMString? StaticChallenge;
     ManagedDOMString? TLSAuthContents;
     ManagedDOMString? TLSRemote;
+    ManagedDOMString? TLSVersionMin;
     ManagedDOMString? UserAuthenticationType;
     ManagedDOMString? Username;
     ManagedDOMString? Verb;
diff --git a/extensions/renderer/bindings/api_event_handler.cc b/extensions/renderer/bindings/api_event_handler.cc
index 314062e..a3098e4 100644
--- a/extensions/renderer/bindings/api_event_handler.cc
+++ b/extensions/renderer/bindings/api_event_handler.cc
@@ -102,7 +102,7 @@
   gin::Converter<EventEmitter*>::FromV8(isolate, v8_emitter.Get(isolate),
                                         &emitter);
   CHECK(emitter);
-  emitter->Fire(context, &args, nullptr);
+  emitter->Fire(context, &args, nullptr, JSRunner::ResultCallback());
 }
 
 }  // namespace
@@ -221,14 +221,16 @@
   for (const auto& arg : args)
     v8_args.push_back(converter->ToV8Value(&arg, context));
 
-  FireEventInContext(event_name, context, &v8_args, filter);
+  FireEventInContext(event_name, context, &v8_args, filter,
+                     JSRunner::ResultCallback());
 }
 
 void APIEventHandler::FireEventInContext(
     const std::string& event_name,
     v8::Local<v8::Context> context,
     std::vector<v8::Local<v8::Value>>* arguments,
-    const EventFilteringInfo* filter) {
+    const EventFilteringInfo* filter,
+    JSRunner::ResultCallback callback) {
   APIEventPerContextData* data = GetContextData(context, false);
   if (!data)
     return;
@@ -243,8 +245,10 @@
 
   auto massager_iter = data->massagers.find(event_name);
   if (massager_iter == data->massagers.end()) {
-    emitter->Fire(context, arguments, filter);
+    emitter->Fire(context, arguments, filter, std::move(callback));
   } else {
+    DCHECK(!callback) << "Can't use an event callback with argument massagers.";
+
     v8::Isolate* isolate = context->GetIsolate();
     v8::HandleScope handle_scope(isolate);
     v8::Local<v8::Function> massager = massager_iter->second.Get(isolate);
diff --git a/extensions/renderer/bindings/api_event_handler.h b/extensions/renderer/bindings/api_event_handler.h
index 56c857bc..15abe8c 100644
--- a/extensions/renderer/bindings/api_event_handler.h
+++ b/extensions/renderer/bindings/api_event_handler.h
@@ -78,7 +78,8 @@
   void FireEventInContext(const std::string& event_name,
                           v8::Local<v8::Context> context,
                           std::vector<v8::Local<v8::Value>>* arguments,
-                          const EventFilteringInfo* filter);
+                          const EventFilteringInfo* filter,
+                          JSRunner::ResultCallback callback);
 
   // Registers a |function| to serve as an "argument massager" for the given
   // |event_name|, mutating the original arguments.
diff --git a/extensions/renderer/bindings/event_emitter.cc b/extensions/renderer/bindings/event_emitter.cc
index 5c8919a..b0caf87 100644
--- a/extensions/renderer/bindings/event_emitter.cc
+++ b/extensions/renderer/bindings/event_emitter.cc
@@ -50,8 +50,9 @@
 
 void EventEmitter::Fire(v8::Local<v8::Context> context,
                         std::vector<v8::Local<v8::Value>>* args,
-                        const EventFilteringInfo* filter) {
-  DispatchAsync(context, args, filter);
+                        const EventFilteringInfo* filter,
+                        JSRunner::ResultCallback callback) {
+  DispatchAsync(context, args, filter, std::move(callback));
 }
 
 void EventEmitter::Invalidate(v8::Local<v8::Context> context) {
@@ -206,7 +207,8 @@
 
 void EventEmitter::DispatchAsync(v8::Local<v8::Context> context,
                                  std::vector<v8::Local<v8::Value>>* args,
-                                 const EventFilteringInfo* filter) {
+                                 const EventFilteringInfo* filter,
+                                 JSRunner::ResultCallback callback) {
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope handle_scope(isolate);
 
@@ -248,7 +250,8 @@
   CHECK(v8::Function::New(context, &DispatchAsyncHelper, data)
             .ToLocal(&function));
 
-  JSRunner::Get(context)->RunJSFunction(function, context, 0, nullptr);
+  JSRunner::Get(context)->RunJSFunction(function, context, 0, nullptr,
+                                        std::move(callback));
 }
 
 // static
@@ -293,8 +296,8 @@
 
   // We know that dispatching synchronously should be safe because this function
   // was triggered by JS execution.
-  emitter->DispatchSync(context, &arguments,
-                        filter ? &filter.value() : nullptr);
+  info.GetReturnValue().Set(emitter->DispatchSync(
+      context, &arguments, filter ? &filter.value() : nullptr));
 }
 
 }  // namespace extensions
diff --git a/extensions/renderer/bindings/event_emitter.h b/extensions/renderer/bindings/event_emitter.h
index 29d4655..d7554580 100644
--- a/extensions/renderer/bindings/event_emitter.h
+++ b/extensions/renderer/bindings/event_emitter.h
@@ -42,7 +42,8 @@
   // invalidated after this!
   void Fire(v8::Local<v8::Context> context,
             std::vector<v8::Local<v8::Value>>* args,
-            const EventFilteringInfo* filter);
+            const EventFilteringInfo* filter,
+            JSRunner::ResultCallback callback);
 
   // Removes all listeners and marks this object as invalid so that no more
   // are added.
@@ -68,7 +69,8 @@
   // Dispatches an event asynchronously to listeners.
   void DispatchAsync(v8::Local<v8::Context> context,
                      std::vector<v8::Local<v8::Value>>* args,
-                     const EventFilteringInfo* filter);
+                     const EventFilteringInfo* filter,
+                     JSRunner::ResultCallback callback);
   static void DispatchAsyncHelper(
       const v8::FunctionCallbackInfo<v8::Value>& info);
 
diff --git a/extensions/renderer/bindings/event_emitter_unittest.cc b/extensions/renderer/bindings/event_emitter_unittest.cc
index 47e6c1a8..9a1023e 100644
--- a/extensions/renderer/bindings/event_emitter_unittest.cc
+++ b/extensions/renderer/bindings/event_emitter_unittest.cc
@@ -178,7 +178,7 @@
   EXPECT_EQ(kNumListeners, event->GetNumListeners());
 
   std::vector<v8::Local<v8::Value>> args;
-  event->Fire(context, &args, nullptr);
+  event->Fire(context, &args, nullptr, JSRunner::ResultCallback());
 
   EXPECT_TRUE(closure_data.did_invalidate_context);
 }
diff --git a/extensions/renderer/bindings/js_runner.cc b/extensions/renderer/bindings/js_runner.cc
index 2e02cf1..e1e690f 100644
--- a/extensions/renderer/bindings/js_runner.cc
+++ b/extensions/renderer/bindings/js_runner.cc
@@ -73,4 +73,11 @@
   return g_instance_for_testing;
 }
 
+void JSRunner::RunJSFunction(v8::Local<v8::Function> function,
+                             v8::Local<v8::Context> context,
+                             int argc,
+                             v8::Local<v8::Value> argv[]) {
+  RunJSFunction(function, context, argc, argv, ResultCallback());
+}
+
 }  // namespace extensions
diff --git a/extensions/renderer/bindings/js_runner.h b/extensions/renderer/bindings/js_runner.h
index 099081b..73e9d11 100644
--- a/extensions/renderer/bindings/js_runner.h
+++ b/extensions/renderer/bindings/js_runner.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/callback.h"
 #include "v8/include/v8.h"
 
 namespace extensions {
@@ -25,13 +26,28 @@
 
   virtual ~JSRunner() {}
 
+  // Called with the result of executing the function, as well as the context
+  // it was executed in. Note: This callback is *not* guaranteed to be invoked
+  // (and won't be if, for instance, the context is destroyed before this is
+  // ran).
+  // NOTE(devlin): We could easily change that if desired.
+  using ResultCallback = base::OnceCallback<void(v8::Local<v8::Context>,
+                                                 v8::MaybeLocal<v8::Value>)>;
+
   // Calls the given |function| in the specified |context| and with the provided
   // arguments. JS may be executed asynchronously if it has been suspended in
   // the context.
+  void RunJSFunction(v8::Local<v8::Function> function,
+                     v8::Local<v8::Context> context,
+                     int argc,
+                     v8::Local<v8::Value> argv[]);
+  // Same as above, but if a |callback| is provided, it will be called with the
+  // results of the function running.
   virtual void RunJSFunction(v8::Local<v8::Function> function,
                              v8::Local<v8::Context> context,
                              int argc,
-                             v8::Local<v8::Value> argv[]) = 0;
+                             v8::Local<v8::Value> argv[],
+                             ResultCallback callback) = 0;
 
   // Executes the given |function| synchronously and returns the result. This
   // should *only* be called in direct response to script running, since it
diff --git a/extensions/renderer/bindings/test_js_runner.cc b/extensions/renderer/bindings/test_js_runner.cc
index d8b8e6ab1..697e680f 100644
--- a/extensions/renderer/bindings/test_js_runner.cc
+++ b/extensions/renderer/bindings/test_js_runner.cc
@@ -67,7 +67,8 @@
 void TestJSRunner::RunJSFunction(v8::Local<v8::Function> function,
                                  v8::Local<v8::Context> context,
                                  int argc,
-                                 v8::Local<v8::Value> argv[]) {
+                                 v8::Local<v8::Value> argv[],
+                                 ResultCallback callback) {
   if (g_suspended) {
     // Script is suspended. Queue up the call and return.
     v8::Isolate* isolate = context->GetIsolate();
@@ -76,6 +77,7 @@
     call.function.Reset(isolate, function);
     call.context.Reset(isolate, context);
     call.arguments.reserve(argc);
+    call.callback = std::move(callback);
     for (int i = 0; i < argc; ++i)
       call.arguments.push_back(v8::Global<v8::Value>(isolate, argv[i]));
     pending_calls_.push_back(std::move(call));
@@ -85,10 +87,15 @@
   if (will_call_js_)
     will_call_js_.Run();
 
-  if (g_allow_errors)
-    ignore_result(function->Call(context, context->Global(), argc, argv));
-  else
-    RunFunctionOnGlobal(function, context, argc, argv);
+  v8::MaybeLocal<v8::Value> result;
+  if (g_allow_errors) {
+    result = function->Call(context, context->Global(), argc, argv);
+  } else {
+    result = RunFunctionOnGlobal(function, context, argc, argv);
+  }
+
+  if (callback)
+    std::move(callback).Run(context, result);
 }
 
 v8::MaybeLocal<v8::Value> TestJSRunner::RunJSFunctionSync(
@@ -121,8 +128,11 @@
     local_arguments.reserve(call.arguments.size());
     for (auto& arg : call.arguments)
       local_arguments.push_back(arg.Get(isolate));
-    RunJSFunctionSync(call.function.Get(isolate), context,
-                      local_arguments.size(), local_arguments.data());
+    v8::MaybeLocal<v8::Value> result =
+        RunJSFunctionSync(call.function.Get(isolate), context,
+                          local_arguments.size(), local_arguments.data());
+    if (call.callback)
+      std::move(call.callback).Run(context, result);
   }
 }
 
diff --git a/extensions/renderer/bindings/test_js_runner.h b/extensions/renderer/bindings/test_js_runner.h
index d2731fa..0e3c6b2 100644
--- a/extensions/renderer/bindings/test_js_runner.h
+++ b/extensions/renderer/bindings/test_js_runner.h
@@ -78,7 +78,8 @@
   void RunJSFunction(v8::Local<v8::Function> function,
                      v8::Local<v8::Context> context,
                      int argc,
-                     v8::Local<v8::Value> argv[]) override;
+                     v8::Local<v8::Value> argv[],
+                     ResultCallback callback) override;
   v8::MaybeLocal<v8::Value> RunJSFunctionSync(
       v8::Local<v8::Function> function,
       v8::Local<v8::Context> context,
@@ -97,6 +98,7 @@
     v8::Global<v8::Function> function;
     v8::Global<v8::Context> context;
     std::vector<v8::Global<v8::Value>> arguments;
+    ResultCallback callback;
   };
 
   // Runs all pending calls.
diff --git a/extensions/renderer/extension_js_runner.cc b/extensions/renderer/extension_js_runner.cc
index 032f2ed..0066880 100644
--- a/extensions/renderer/extension_js_runner.cc
+++ b/extensions/renderer/extension_js_runner.cc
@@ -6,22 +6,30 @@
 
 #include "content/public/renderer/worker_thread.h"
 #include "extensions/renderer/script_context.h"
+#include "extensions/renderer/script_injection_callback.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 
 namespace extensions {
 
 ExtensionJSRunner::ExtensionJSRunner(ScriptContext* script_context)
-    : script_context_(script_context) {}
+    : script_context_(script_context), weak_factory_(this) {}
 ExtensionJSRunner::~ExtensionJSRunner() {}
 
 void ExtensionJSRunner::RunJSFunction(v8::Local<v8::Function> function,
                                       v8::Local<v8::Context> context,
                                       int argc,
-                                      v8::Local<v8::Value> argv[]) {
-  DCHECK(script_context_->v8_context() == context);
+                                      v8::Local<v8::Value> argv[],
+                                      ResultCallback callback) {
+  ScriptInjectionCallback::CompleteCallback wrapper_callback;
+  if (callback) {
+    // TODO(devlin): Update ScriptContext to take a OnceCallback.
+    wrapper_callback = base::BindRepeating(
+        &ExtensionJSRunner::OnFunctionComplete, weak_factory_.GetWeakPtr(),
+        base::Passed(std::move(callback)));
+  }
 
   // TODO(devlin): Move ScriptContext::SafeCallFunction() into here?
-  script_context_->SafeCallFunction(function, argc, argv);
+  script_context_->SafeCallFunction(function, argc, argv, wrapper_callback);
 }
 
 v8::MaybeLocal<v8::Value> ExtensionJSRunner::RunJSFunctionSync(
@@ -61,4 +69,15 @@
   return result;
 }
 
+void ExtensionJSRunner::OnFunctionComplete(
+    ResultCallback callback,
+    const std::vector<v8::Local<v8::Value>>& results) {
+  DCHECK(script_context_->is_valid());
+
+  v8::MaybeLocal<v8::Value> result;
+  if (!results.empty() && !results[0].IsEmpty())
+    result = results[0];
+  std::move(callback).Run(script_context_->v8_context(), result);
+}
+
 }  // namespace extensions
diff --git a/extensions/renderer/extension_js_runner.h b/extensions/renderer/extension_js_runner.h
index 1b48063..5cd49adf 100644
--- a/extensions/renderer/extension_js_runner.h
+++ b/extensions/renderer/extension_js_runner.h
@@ -6,6 +6,7 @@
 #define EXTENSIONS_RENDERER_EXTENSION_JS_RUNNER_H_
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "extensions/renderer/bindings/js_runner.h"
 
 namespace extensions {
@@ -21,7 +22,8 @@
   void RunJSFunction(v8::Local<v8::Function> function,
                      v8::Local<v8::Context> context,
                      int argc,
-                     v8::Local<v8::Value> argv[]) override;
+                     v8::Local<v8::Value> argv[],
+                     ResultCallback callback) override;
   v8::MaybeLocal<v8::Value> RunJSFunctionSync(
       v8::Local<v8::Function> function,
       v8::Local<v8::Context> context,
@@ -29,9 +31,15 @@
       v8::Local<v8::Value> argv[]) override;
 
  private:
+  // Called with the result of executing the JS function.
+  void OnFunctionComplete(ResultCallback callback,
+                          const std::vector<v8::Local<v8::Value>>& results);
+
   // The associated ScriptContext. Guaranteed to outlive this object.
   ScriptContext* const script_context_;
 
+  base::WeakPtrFactory<ExtensionJSRunner> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(ExtensionJSRunner);
 };
 
diff --git a/extensions/renderer/gin_port.cc b/extensions/renderer/gin_port.cc
index 3dee4ac..046b85c 100644
--- a/extensions/renderer/gin_port.cc
+++ b/extensions/renderer/gin_port.cc
@@ -191,7 +191,7 @@
   gin::Converter<EventEmitter*>::FromV8(isolate, on_message, &emitter);
   CHECK(emitter);
 
-  emitter->Fire(context, args, nullptr);
+  emitter->Fire(context, args, nullptr, JSRunner::ResultCallback());
 }
 
 void GinPort::Invalidate(v8::Local<v8::Context> context) {
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc
index e29a790..50d73ed 100644
--- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc
+++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc
@@ -62,8 +62,9 @@
         post_message_function_template_.Reset(
             isolate,
             gin::CreateFunctionTemplate(
-                isolate, base::Bind(&MimeHandlerViewContainer::PostMessage,
-                                    container_, isolate)));
+                isolate,
+                base::Bind(&MimeHandlerViewContainer::PostJavaScriptMessage,
+                           container_, isolate)));
       }
       v8::Local<v8::FunctionTemplate> function_template =
           v8::Local<v8::FunctionTemplate>::New(isolate,
@@ -226,8 +227,9 @@
   CreateMimeHandlerViewGuestIfNecessary();
 }
 
-void MimeHandlerViewContainer::PostMessage(v8::Isolate* isolate,
-                                           v8::Local<v8::Value> message) {
+void MimeHandlerViewContainer::PostJavaScriptMessage(
+    v8::Isolate* isolate,
+    v8::Local<v8::Value> message) {
   if (!guest_loaded_) {
     pending_messages_.push_back(v8::Global<v8::Value>(isolate, message));
     return;
@@ -270,8 +272,9 @@
   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   v8::HandleScope handle_scope(isolate);
   v8::Context::Scope context_scope(frame->MainWorldScriptContext());
-  PostMessage(isolate, content::V8ValueConverter::Create()->ToV8Value(
-                           &message, frame->MainWorldScriptContext()));
+  PostJavaScriptMessage(isolate,
+                        content::V8ValueConverter::Create()->ToV8Value(
+                            &message, frame->MainWorldScriptContext()));
 }
 
 void MimeHandlerViewContainer::OnCreateMimeHandlerViewGuestACK(
@@ -310,7 +313,8 @@
   v8::HandleScope handle_scope(isolate);
   v8::Context::Scope context_scope(frame->MainWorldScriptContext());
   for (const auto& pending_message : pending_messages_)
-    PostMessage(isolate, v8::Local<v8::Value>::New(isolate, pending_message));
+    PostJavaScriptMessage(isolate,
+                          v8::Local<v8::Value>::New(isolate, pending_message));
 
   pending_messages_.clear();
 }
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h
index deaa4d72..a11ce1b 100644
--- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h
+++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h
@@ -69,7 +69,8 @@
   void OnRenderFrameDestroyed() override;
 
   // Post a JavaScript message to the guest.
-  void PostMessage(v8::Isolate* isolate, v8::Local<v8::Value> message);
+  void PostJavaScriptMessage(v8::Isolate* isolate,
+                             v8::Local<v8::Value> message);
 
   // Post |message| to the guest.
   void PostMessageFromValue(const base::Value& message);
diff --git a/extensions/renderer/native_renderer_messaging_service.cc b/extensions/renderer/native_renderer_messaging_service.cc
index 4e20228..78548fdc 100644
--- a/extensions/renderer/native_renderer_messaging_service.cc
+++ b/extensions/renderer/native_renderer_messaging_service.cc
@@ -245,7 +245,7 @@
   port->SetSender(v8_context, sender);
   std::vector<v8::Local<v8::Value>> args = {port.ToV8()};
   bindings_system_->api_system()->event_handler()->FireEventInContext(
-      event_name, v8_context, &args, nullptr);
+      event_name, v8_context, &args, nullptr, JSRunner::ResultCallback());
 }
 
 void NativeRendererMessagingService::DispatchOnMessageToListeners(
diff --git a/extensions/renderer/native_renderer_messaging_service_unittest.cc b/extensions/renderer/native_renderer_messaging_service_unittest.cc
index dd6e492..7c572817 100644
--- a/extensions/renderer/native_renderer_messaging_service_unittest.cc
+++ b/extensions/renderer/native_renderer_messaging_service_unittest.cc
@@ -447,9 +447,11 @@
       R"((function() {
            chrome.runtime.onMessage.addListener((message) => {
              this.onMessageReceived = message;
+             return true;  // Keep the channel open.
            });
            chrome.runtime.onMessageExternal.addListener((message) => {
              this.onMessageExternalReceived = message;
+             return true;  // Keep the channel open.
            });
          }))";
 
diff --git a/extensions/renderer/one_time_message_handler.cc b/extensions/renderer/one_time_message_handler.cc
index 9025e3d..054663e 100644
--- a/extensions/renderer/one_time_message_handler.cc
+++ b/extensions/renderer/one_time_message_handler.cc
@@ -22,6 +22,7 @@
 #include "extensions/renderer/native_extension_bindings_system.h"
 #include "extensions/renderer/script_context.h"
 #include "gin/arguments.h"
+#include "gin/dictionary.h"
 #include "gin/handle.h"
 #include "gin/per_context_data.h"
 #include "ipc/ipc_message.h"
@@ -105,6 +106,43 @@
   std::move(*callback).Run(&arguments);
 }
 
+// Called with the results of dispatching an onMessage event to listeners.
+// Returns true if any of the listeners responded with `true`, indicating they
+// will respond to the call asynchronously.
+bool WillListenerReplyAsync(v8::Local<v8::Context> context,
+                            v8::Local<v8::Value> results) {
+  if (!results->IsObject())
+    return false;
+
+  // Suppress any script errors, but bail out if they happen (in theory, we
+  // shouldn't have any).
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::TryCatch try_catch(isolate);
+  // We expect results in the form of an object with an array of results as
+  // a `results` property.
+  v8::Local<v8::Value> results_property;
+  if (!results.As<v8::Object>()
+           ->Get(context, gin::StringToSymbol(isolate, "results"))
+           .ToLocal(&results_property) ||
+      !results_property->IsArray()) {
+    return false;
+  }
+
+  // Check if any of the results is `true`.
+  v8::Local<v8::Array> array = results_property.As<v8::Array>();
+  uint32_t length = array->Length();
+  for (uint32_t i = 0; i < length; ++i) {
+    v8::Local<v8::Value> val;
+    if (!array->Get(context, i).ToLocal(&val))
+      return false;
+
+    if (val->IsTrue())
+      return true;
+  }
+
+  return false;
+}
+
 }  // namespace
 
 OneTimeMessageHandler::OneTimeMessageHandler(
@@ -267,9 +305,18 @@
   std::vector<v8::Local<v8::Value>> args = {v8_message, v8_sender,
                                             response_function};
 
+  JSRunner::ResultCallback dispatch_callback;
+  // For runtime.onMessage, we require that the listener return `true` if they
+  // intend to respond asynchronously. Check the results of the listeners.
+  if (port.event_name == messaging_util::kOnMessageEvent) {
+    dispatch_callback =
+        base::BindOnce(&OneTimeMessageHandler::OnEventFired,
+                       weak_factory_.GetWeakPtr(), target_port_id);
+  }
+
   data->pending_callbacks.push_back(std::move(callback));
   bindings_system_->api_system()->event_handler()->FireEventInContext(
-      port.event_name, context, &args, nullptr);
+      port.event_name, context, &args, nullptr, std::move(dispatch_callback));
 
   return handled;
 }
@@ -359,10 +406,20 @@
     gin::Arguments* arguments) {
   v8::Isolate* isolate = arguments->isolate();
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
+
+  // The listener may try replying after the context or the channel has been
+  // closed. Fail gracefully.
+  // TODO(devlin): At least in the case of the channel being closed (e.g.
+  // because the listener did not return `true`), it might be good to surface an
+  // error.
   OneTimeMessageContextData* data = GetPerContextData(context, false);
-  DCHECK(data);
+  if (!data)
+    return;
+
   auto iter = data->receivers.find(port_id);
-  DCHECK(iter != data->receivers.end());
+  if (iter == data->receivers.end())
+    return;
+
   int routing_id = iter->second.routing_id;
   data->receivers.erase(iter);
 
@@ -416,4 +473,35 @@
   ipc_sender->SendCloseMessagePort(routing_id, port_id, close_channel);
 }
 
+void OneTimeMessageHandler::OnEventFired(const PortId& port_id,
+                                         v8::Local<v8::Context> context,
+                                         v8::MaybeLocal<v8::Value> result) {
+  // The context could be tearing down by the time the event is fully
+  // dispatched.
+  OneTimeMessageContextData* data = GetPerContextData(context, false);
+  if (!data)
+    return;
+
+  // The result should never be empty since it's from executing an internal
+  // function in the EventEmitter.
+  DCHECK(!result.IsEmpty());
+  if (WillListenerReplyAsync(context, result.ToLocalChecked()))
+    return;  // The listener will reply later; leave the channel open.
+
+  auto iter = data->receivers.find(port_id);
+  // The channel may already be closed (if the listener replied).
+  if (iter == data->receivers.end())
+    return;
+
+  int routing_id = iter->second.routing_id;
+  data->receivers.erase(iter);
+
+  // The listener did not reply and did not return `true` from any of its
+  // listeners. Close the message port. Don't close the channel because another
+  // listener (in a separate context) may reply.
+  IPCMessageSender* ipc_sender = bindings_system_->GetIPCMessageSender();
+  bool close_channel = false;
+  ipc_sender->SendCloseMessagePort(routing_id, port_id, close_channel);
+}
+
 }  // namespace extensions
diff --git a/extensions/renderer/one_time_message_handler.h b/extensions/renderer/one_time_message_handler.h
index cbd46d1..39c96de 100644
--- a/extensions/renderer/one_time_message_handler.h
+++ b/extensions/renderer/one_time_message_handler.h
@@ -116,6 +116,12 @@
   void OnResponseCallbackCollected(ScriptContext* script_context,
                                    const PortId& port_id);
 
+  // Called when the messaging event has been dispatched with the result of the
+  // listeners.
+  void OnEventFired(const PortId& port_id,
+                    v8::Local<v8::Context> context,
+                    v8::MaybeLocal<v8::Value> result);
+
   // The associated bindings system. Outlives this object.
   NativeExtensionBindingsSystem* const bindings_system_;
 
diff --git a/extensions/renderer/one_time_message_handler_unittest.cc b/extensions/renderer/one_time_message_handler_unittest.cc
index c9f78bb4..9d14142 100644
--- a/extensions/renderer/one_time_message_handler_unittest.cc
+++ b/extensions/renderer/one_time_message_handler_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
 #include "extensions/common/api/messaging/message.h"
 #include "extensions/common/api/messaging/port_id.h"
 #include "extensions/common/extension.h"
@@ -215,6 +216,7 @@
       "      function(message, sender, reply) {\n"
       "    this.eventMessage = message;\n"
       "    this.eventSender = sender;\n"
+      "    return true;  // Reply later\n"
       "  });\n"
       "})";
   v8::Local<v8::Function> add_listener =
@@ -304,6 +306,7 @@
       "  chrome.runtime.onMessage.addListener(\n"
       "      function(message, sender, reply) {\n"
       "    this.sendReply = reply;\n"
+      "    return true;  // Reply later\n"
       "  });\n"
       "})";
   v8::Local<v8::Function> add_listener =
@@ -350,7 +353,9 @@
   constexpr char kRegisterListener[] =
       "(function() {\n"
       "  chrome.runtime.onMessage.addListener(\n"
-      "      function(message, sender, reply) {});\n"
+      "      function(message, sender, reply) {\n"
+      "        return true;  // Reply later\n"
+      "      });\n"
       "})";
   v8::Local<v8::Function> add_listener =
       FunctionFromString(context, kRegisterListener);
@@ -378,4 +383,55 @@
   EXPECT_FALSE(message_handler()->HasPort(script_context(), port_id));
 }
 
+// runtime.onMessage requires that a listener return `true` if they intend to
+// respond to the message asynchronously. Verify that we close the port if no
+// listener does so.
+TEST_F(OneTimeMessageHandlerTest, ChannelClosedIfTrueNotReturned) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  auto register_listener = [context](const char* listener) {
+    constexpr char kRegisterListenerTemplate[] =
+        "(function() { chrome.runtime.onMessage.addListener(%s); })";
+    v8::Local<v8::Function> add_listener = FunctionFromString(
+        context, base::StringPrintf(kRegisterListenerTemplate, listener));
+    RunFunctionOnGlobal(add_listener, context, 0, nullptr);
+  };
+
+  register_listener("function(message, reply, sender) { }");
+  // Add a listener that returns a truthy value, but not `true`.
+  register_listener("function(message, reply, sender) { return {}; }");
+  // Add a listener that throws an error.
+  register_listener(
+      "function(message, reply, sender) { throw new Error('hi!'); }");
+
+  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
+  const PortId port_id(other_context_id, 0, false);
+
+  v8::Local<v8::Object> sender = v8::Object::New(isolate());
+  message_handler()->AddReceiver(script_context(), port_id, sender,
+                                 messaging_util::kOnMessageEvent);
+  EXPECT_TRUE(message_handler()->HasPort(script_context(), port_id));
+
+  TestJSRunner::AllowErrors allow_errors;
+
+  // Dispatch the message. Since none of these listeners return `true`, the port
+  // should close.
+  const Message message("\"Hi\"", false);
+  EXPECT_CALL(*ipc_message_sender(),
+              SendCloseMessagePort(MSG_ROUTING_NONE, port_id, false));
+  message_handler()->DeliverMessage(script_context(), message, port_id);
+  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
+  EXPECT_FALSE(message_handler()->HasPort(script_context(), port_id));
+
+  // If any of the listeners return `true`, the channel should be left open.
+  register_listener("function(message, reply, sender) { return true; }");
+  message_handler()->AddReceiver(script_context(), port_id, sender,
+                                 messaging_util::kOnMessageEvent);
+  EXPECT_TRUE(message_handler()->HasPort(script_context(), port_id));
+
+  message_handler()->DeliverMessage(script_context(), message, port_id);
+  EXPECT_TRUE(message_handler()->HasPort(script_context(), port_id));
+}
+
 }  // namespace extensions
diff --git a/gin/array_buffer.cc b/gin/array_buffer.cc
index 10ee5ea..34e83db 100644
--- a/gin/array_buffer.cc
+++ b/gin/array_buffer.cc
@@ -85,29 +85,27 @@
 void ArrayBufferAllocator::SetProtection(void* data,
                                          size_t length,
                                          Protection protection) {
-  CHECK(SetProtection(protection, data, length));
-}
-
-bool ArrayBufferAllocator::SetProtection(Protection protection,
-                                         void* data,
-                                         size_t length) {
   switch (protection) {
-    case Protection::kNoAccess:
+    case Protection::kNoAccess: {
 #if defined(OS_POSIX)
-      return mprotect(data, length, PROT_NONE) == 0;
+      int ret = mprotect(data, length, PROT_NONE);
+      CHECK(!ret);
 #else
-      return VirtualFree(data, length, MEM_DECOMMIT);
+      BOOL ret = VirtualFree(data, length, MEM_DECOMMIT);
+      CHECK(ret);
 #endif
+      break;
+    }
     case Protection::kReadWrite:
 #if defined(OS_POSIX)
-      return mprotect(data, length, PROT_READ | PROT_WRITE) == 0;
+      mprotect(data, length, PROT_READ | PROT_WRITE);
 #else
-      return VirtualAlloc(data, length, MEM_COMMIT, PAGE_READWRITE);
+      VirtualAlloc(data, length, MEM_COMMIT, PAGE_READWRITE);
 #endif
+      break;
     default:
       NOTREACHED();
   }
-  return false;
 }
 
 ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() {
diff --git a/gin/array_buffer.h b/gin/array_buffer.h
index 0c665b6..0b2b1ecf 100644
--- a/gin/array_buffer.h
+++ b/gin/array_buffer.h
@@ -25,12 +25,7 @@
   void Free(void* data, size_t length) override;
   void Free(void* data, size_t length, AllocationMode mode) override;
 
-  // SetProtection should return result of mprotect calls - duplication of
-  // methods here as this change needs coordination between V8/Chromium.
-  // Subsequent changes will implement 'bool SetProtection(...)' to be the
-  // default method.
-  void SetProtection(void* data, size_t length, Protection protection) final;
-  bool SetProtection(Protection protection, void* data, size_t length);
+  void SetProtection(void* data, size_t length, Protection protection) override;
 
   GIN_EXPORT static ArrayBufferAllocator* SharedInstance();
 };
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index bacacf935..4757a7a 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -62,7 +62,6 @@
       "//build/config:exe_and_shlib_deps",
       "//gpu/command_buffer/client:gles2_c_lib",
       "//gpu/command_buffer/client:gles2_implementation",
-      "//gpu/command_buffer/common:gles2_utils",
       "//ui/gl:gl",
     ]
 
@@ -135,7 +134,7 @@
     "//gpu/command_buffer/client:gles2_interface",
   ]
   deps = [
-    "//gpu/command_buffer/common:gles2_utils",
+    "//gpu/command_buffer/common",
     "//testing/gmock",
     "//testing/gtest",
     "//ui/gl:gl_unittest_utils",
@@ -469,7 +468,6 @@
     "//base",
     "//base/test:test_support",
     "//gpu/command_buffer/client:gles2_implementation",
-    "//gpu/command_buffer/common:gles2_utils",
     "//testing/gtest",
     "//testing/perf",
     "//ui/gfx/geometry",
@@ -498,7 +496,6 @@
     ":gpu",
     "//base",
     "//base/third_party/dynamic_annotations",
-    "//gpu/command_buffer/common:gles2_utils",
     "//ui/gfx/geometry",
     "//ui/gl",
     "//ui/gl:test_support",
@@ -519,7 +516,6 @@
       ":gpu",
       "//base",
       "//base/third_party/dynamic_annotations",
-      "//gpu/command_buffer/common:gles2_utils",
       "//ui/gfx/geometry",
       "//ui/gl",
       "//ui/gl:test_support",
@@ -542,7 +538,6 @@
       ":gpu",
       "//base",
       "//base/third_party/dynamic_annotations",
-      "//gpu/command_buffer/common:gles2_utils",
       "//ui/gfx/geometry",
       "//ui/gl",
       "//ui/gl:test_support",
@@ -562,7 +557,6 @@
       ":gpu",
       "//base",
       "//base/third_party/dynamic_annotations",
-      "//gpu/command_buffer/common:gles2_utils",
       "//ui/gfx/geometry",
       "//ui/gl",
       "//ui/gl:test_support",
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 4124ef5..8c57bb0e 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -39,7 +39,7 @@
 #include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/common/id_allocator.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 7f8d26abc..a067418 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -31,9 +31,9 @@
 #include "gpu/command_buffer/client/ref_counted.h"
 #include "gpu/command_buffer/client/share_group.h"
 #include "gpu/command_buffer/common/capabilities.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/common/context_result.h"
 #include "gpu/command_buffer/common/debug_marker_manager.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
 
 #if DCHECK_IS_ON() && !defined(__native_client__) && \
     !defined(GLES2_CONFORMANCE_TESTS)
diff --git a/gpu/command_buffer/common/BUILD.gn b/gpu/command_buffer/common/BUILD.gn
index 9c6ce10..2262fda 100644
--- a/gpu/command_buffer/common/BUILD.gn
+++ b/gpu/command_buffer/common/BUILD.gn
@@ -47,6 +47,8 @@
     "command_buffer.h",
     "command_buffer_id.h",
     "constants.h",
+    "context_creation_attribs.cc",
+    "context_creation_attribs.h",
     "context_result.h",
     "discardable_handle.cc",
     "discardable_handle.h",
@@ -123,7 +125,6 @@
 
   deps = [
     "//base",
-    "//ui/gfx/geometry",
   ]
 
   all_dependent_configs = [ "//third_party/khronos:khronos_headers" ]
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h
index 1fc272e..9247748e 100644
--- a/gpu/command_buffer/common/capabilities.h
+++ b/gpu/command_buffer/common/capabilities.h
@@ -143,6 +143,7 @@
   bool color_buffer_half_float_rgba = false;
   bool image_ycbcr_422 = false;
   bool image_ycbcr_420v = false;
+  bool image_ycbcr_420v_disabled_for_video_frames = false;
   bool render_buffer_format_bgra8888 = false;
   bool occlusion_query = false;
   bool occlusion_query_boolean = false;
diff --git a/gpu/command_buffer/common/context_creation_attribs.cc b/gpu/command_buffer/common/context_creation_attribs.cc
new file mode 100644
index 0000000..fae1da2
--- /dev/null
+++ b/gpu/command_buffer/common/context_creation_attribs.cc
@@ -0,0 +1,64 @@
+// 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 "gpu/command_buffer/common/context_creation_attribs.h"
+
+#include "base/logging.h"
+
+namespace gpu {
+
+bool IsWebGLContextType(ContextType context_type) {
+  // Switch statement to cause a compile-time error if we miss a case.
+  switch (context_type) {
+    case CONTEXT_TYPE_WEBGL1:
+    case CONTEXT_TYPE_WEBGL2:
+      return true;
+    case CONTEXT_TYPE_OPENGLES2:
+    case CONTEXT_TYPE_OPENGLES3:
+      return false;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+bool IsWebGL1OrES2ContextType(ContextType context_type) {
+  // Switch statement to cause a compile-time error if we miss a case.
+  switch (context_type) {
+    case CONTEXT_TYPE_WEBGL1:
+    case CONTEXT_TYPE_OPENGLES2:
+      return true;
+    case CONTEXT_TYPE_WEBGL2:
+    case CONTEXT_TYPE_OPENGLES3:
+      return false;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+bool IsWebGL2OrES3ContextType(ContextType context_type) {
+  // Switch statement to cause a compile-time error if we miss a case.
+  switch (context_type) {
+    case CONTEXT_TYPE_OPENGLES3:
+    case CONTEXT_TYPE_WEBGL2:
+      return true;
+    case CONTEXT_TYPE_WEBGL1:
+    case CONTEXT_TYPE_OPENGLES2:
+      return false;
+  }
+
+  NOTREACHED();
+  return false;
+}
+
+ContextCreationAttribs::ContextCreationAttribs() = default;
+
+ContextCreationAttribs::ContextCreationAttribs(
+    const ContextCreationAttribs& other) = default;
+
+ContextCreationAttribs& ContextCreationAttribs::operator=(
+    const ContextCreationAttribs& other) = default;
+
+}  // namespace gpu
diff --git a/gpu/command_buffer/common/context_creation_attribs.h b/gpu/command_buffer/common/context_creation_attribs.h
new file mode 100644
index 0000000..dcc680be
--- /dev/null
+++ b/gpu/command_buffer/common/context_creation_attribs.h
@@ -0,0 +1,69 @@
+// 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 GPU_COMMAND_BUFFER_COMMON_CONTEXT_CREATION_ATTRIBS_H_
+#define GPU_COMMAND_BUFFER_COMMON_CONTEXT_CREATION_ATTRIBS_H_
+
+#include <stdint.h>
+
+#include "gpu/gpu_export.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gl/gpu_preference.h"
+
+namespace gpu {
+
+enum ContextType {
+  CONTEXT_TYPE_WEBGL1,
+  CONTEXT_TYPE_WEBGL2,
+  CONTEXT_TYPE_OPENGLES2,
+  CONTEXT_TYPE_OPENGLES3,
+  CONTEXT_TYPE_LAST = CONTEXT_TYPE_OPENGLES3
+};
+
+GPU_EXPORT bool IsWebGLContextType(ContextType context_type);
+GPU_EXPORT bool IsWebGL1OrES2ContextType(ContextType context_type);
+GPU_EXPORT bool IsWebGL2OrES3ContextType(ContextType context_type);
+
+enum ColorSpace {
+  COLOR_SPACE_UNSPECIFIED,
+  COLOR_SPACE_SRGB,
+  COLOR_SPACE_DISPLAY_P3,
+  COLOR_SPACE_LAST = COLOR_SPACE_DISPLAY_P3
+};
+
+struct GPU_EXPORT ContextCreationAttribs {
+  ContextCreationAttribs();
+  ContextCreationAttribs(const ContextCreationAttribs& other);
+  ContextCreationAttribs& operator=(const ContextCreationAttribs& other);
+
+  gfx::Size offscreen_framebuffer_size;
+  gl::GpuPreference gpu_preference = gl::PreferIntegratedGpu;
+  // -1 if invalid or unspecified.
+  int32_t alpha_size = -1;
+  int32_t blue_size = -1;
+  int32_t green_size = -1;
+  int32_t red_size = -1;
+  int32_t depth_size = -1;
+  int32_t stencil_size = -1;
+  int32_t samples = -1;
+  int32_t sample_buffers = -1;
+  bool buffer_preserved = true;
+  bool bind_generates_resource = true;
+  bool fail_if_major_perf_caveat = false;
+  bool lose_context_when_out_of_memory = false;
+  bool should_use_native_gmb_for_backbuffer = false;
+  bool own_offscreen_surface = false;
+  bool single_buffer = false;
+  bool enable_gles2_interface = true;
+  bool enable_raster_interface = false;
+  bool enable_oop_rasterization = false;
+  bool enable_swap_timestamps_if_supported = false;
+
+  ContextType context_type = CONTEXT_TYPE_OPENGLES2;
+  ColorSpace color_space = COLOR_SPACE_UNSPECIFIED;
+};
+
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_COMMON_CONTEXT_CREATION_ATTRIBS_H_
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 8901681..6c807a7 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -1829,56 +1829,6 @@
   return format;
 }
 
-bool IsWebGLContextType(ContextType context_type) {
-  // Switch statement to cause a compile-time error if we miss a case.
-  switch (context_type) {
-    case CONTEXT_TYPE_WEBGL1:
-    case CONTEXT_TYPE_WEBGL2:
-      return true;
-    case CONTEXT_TYPE_OPENGLES2:
-    case CONTEXT_TYPE_OPENGLES3:
-      return false;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
-bool IsWebGL1OrES2ContextType(ContextType context_type) {
-  // Switch statement to cause a compile-time error if we miss a case.
-  switch (context_type) {
-    case CONTEXT_TYPE_WEBGL1:
-    case CONTEXT_TYPE_OPENGLES2:
-      return true;
-    case CONTEXT_TYPE_WEBGL2:
-    case CONTEXT_TYPE_OPENGLES3:
-      return false;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
-bool IsWebGL2OrES3ContextType(ContextType context_type) {
-  // Switch statement to cause a compile-time error if we miss a case.
-  switch (context_type) {
-    case CONTEXT_TYPE_OPENGLES3:
-    case CONTEXT_TYPE_WEBGL2:
-      return true;
-    case CONTEXT_TYPE_WEBGL1:
-    case CONTEXT_TYPE_OPENGLES2:
-      return false;
-  }
-
-  NOTREACHED();
-  return false;
-}
-
-ContextCreationAttribHelper::ContextCreationAttribHelper() = default;
-
-ContextCreationAttribHelper::ContextCreationAttribHelper(
-    const ContextCreationAttribHelper& other) = default;
-
 #include "gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h"
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index 66c2991..8ee82ba 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -13,14 +13,11 @@
 
 #include <limits>
 #include <string>
-#include <vector>
 
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/numerics/safe_math.h"
 #include "gpu/command_buffer/common/gles2_utils_export.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gl/gpu_preference.h"
 
 namespace gpu {
 namespace gles2 {
@@ -301,55 +298,6 @@
   DISALLOW_COPY_AND_ASSIGN(GLSLArrayName);
 };
 
-enum ContextType {
-  CONTEXT_TYPE_WEBGL1,
-  CONTEXT_TYPE_WEBGL2,
-  CONTEXT_TYPE_OPENGLES2,
-  CONTEXT_TYPE_OPENGLES3,
-  CONTEXT_TYPE_LAST = CONTEXT_TYPE_OPENGLES3
-};
-GLES2_UTILS_EXPORT bool IsWebGLContextType(ContextType context_type);
-GLES2_UTILS_EXPORT bool IsWebGL1OrES2ContextType(ContextType context_type);
-GLES2_UTILS_EXPORT bool IsWebGL2OrES3ContextType(ContextType context_type);
-
-enum ColorSpace {
-  COLOR_SPACE_UNSPECIFIED,
-  COLOR_SPACE_SRGB,
-  COLOR_SPACE_DISPLAY_P3,
-  COLOR_SPACE_LAST = COLOR_SPACE_DISPLAY_P3
-};
-
-struct GLES2_UTILS_EXPORT ContextCreationAttribHelper {
-  ContextCreationAttribHelper();
-  ContextCreationAttribHelper(const ContextCreationAttribHelper& other);
-
-  gfx::Size offscreen_framebuffer_size;
-  gl::GpuPreference gpu_preference = gl::PreferIntegratedGpu;
-  // -1 if invalid or unspecified.
-  int32_t alpha_size = -1;
-  int32_t blue_size = -1;
-  int32_t green_size = -1;
-  int32_t red_size = -1;
-  int32_t depth_size = -1;
-  int32_t stencil_size = -1;
-  int32_t samples = -1;
-  int32_t sample_buffers = -1;
-  bool buffer_preserved = true;
-  bool bind_generates_resource = true;
-  bool fail_if_major_perf_caveat = false;
-  bool lose_context_when_out_of_memory = false;
-  bool should_use_native_gmb_for_backbuffer = false;
-  bool own_offscreen_surface = false;
-  bool single_buffer = false;
-  bool enable_gles2_interface = true;
-  bool enable_raster_interface = false;
-  bool enable_oop_rasterization = false;
-  bool enable_swap_timestamps_if_supported = false;
-
-  ContextType context_type = CONTEXT_TYPE_OPENGLES2;
-  ColorSpace color_space = COLOR_SPACE_UNSPECIFIED;
-};
-
 }  // namespace gles2
 }  // namespace gpu
 
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index 33e2ce4..5842f39 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -1050,9 +1050,9 @@
     validators_.g_l_state.AddValue(GL_TEXTURE_BINDING_RECTANGLE_ARB);
   }
 
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
   // TODO(dcastagna): Determine ycbcr_420v_image on CrOS at runtime
-  // querying minigbm. crbug.com/646148
+  // querying minigbm. https://crbug.com/646148
   if (gl::GetGLImplementation() != gl::kGLImplementationOSMesaGL) {
     AddExtensionString("GL_CHROMIUM_ycbcr_420v_image");
     feature_flags_.chromium_image_ycbcr_420v = true;
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index cc9d17c..24e2c75b 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/gles2_cmd_validation.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index cb6a1147..15b81b0 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -565,7 +565,7 @@
       const scoped_refptr<gl::GLContext>& context,
       bool offscreen,
       const DisallowedFeatures& disallowed_features,
-      const ContextCreationAttribHelper& attrib_helper) override;
+      const ContextCreationAttribs& attrib_helper) override;
   void Destroy(bool have_context) override;
   void SetSurface(const scoped_refptr<gl::GLSurface>& surface) override;
   void ReleaseSurface() override;
@@ -3241,7 +3241,7 @@
     const scoped_refptr<gl::GLContext>& context,
     bool offscreen,
     const DisallowedFeatures& disallowed_features,
-    const ContextCreationAttribHelper& attrib_helper) {
+    const ContextCreationAttribs& attrib_helper) {
   TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize");
   DCHECK(context->IsCurrent(surface.get()));
   DCHECK(!context_.get());
@@ -4008,6 +4008,9 @@
       feature_info_->feature_flags().chromium_image_ycbcr_422;
   caps.image_ycbcr_420v =
       feature_info_->feature_flags().chromium_image_ycbcr_420v;
+  caps.image_ycbcr_420v_disabled_for_video_frames =
+      group_->gpu_preferences()
+          .disable_biplanar_gpu_memory_buffers_for_video_frames;
   caps.max_copy_texture_chromium_size =
       workarounds().max_copy_texture_chromium_size;
   caps.render_buffer_format_bgra8888 =
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index e24b60a..1138bc9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -37,6 +37,7 @@
 
 namespace gpu {
 
+struct ContextCreationAttribs;
 struct Mailbox;
 struct SyncToken;
 
@@ -57,7 +58,6 @@
 class TextureBase;
 class TransformFeedbackManager;
 class VertexArrayManager;
-struct ContextCreationAttribHelper;
 struct ContextState;
 
 struct DisallowedFeatures {
@@ -182,7 +182,7 @@
       const scoped_refptr<gl::GLContext>& context,
       bool offscreen,
       const DisallowedFeatures& disallowed_features,
-      const ContextCreationAttribHelper& attrib_helper) = 0;
+      const ContextCreationAttribs& attrib_helper) = 0;
 
   // Destroys the graphics context.
   virtual void Destroy(bool have_context) = 0;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc b/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc
index 05b0163..3b110a0 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.cc
@@ -4,7 +4,7 @@
 
 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
 
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 
 namespace gpu {
 namespace gles2 {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 389b1c1..ca122ca2 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -13,7 +13,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
 #include "gpu/command_buffer/service/shader_translator.h"
@@ -43,13 +43,12 @@
 
   base::WeakPtr<GLES2Decoder> AsWeakPtr() override;
 
-  MOCK_METHOD5(
-      Initialize,
-      gpu::ContextResult(const scoped_refptr<gl::GLSurface>& surface,
-                         const scoped_refptr<gl::GLContext>& context,
-                         bool offscreen,
-                         const DisallowedFeatures& disallowed_features,
-                         const ContextCreationAttribHelper& attrib_helper));
+  MOCK_METHOD5(Initialize,
+               gpu::ContextResult(const scoped_refptr<gl::GLSurface>& surface,
+                                  const scoped_refptr<gl::GLContext>& context,
+                                  bool offscreen,
+                                  const DisallowedFeatures& disallowed_features,
+                                  const ContextCreationAttribs& attrib_helper));
   MOCK_METHOD1(Destroy, void(bool have_context));
   MOCK_METHOD1(SetSurface, void(const scoped_refptr<gl::GLSurface>& surface));
   MOCK_METHOD0(ReleaseSurface, void());
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
index 83517aa..da59dd0 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -567,7 +567,7 @@
     const scoped_refptr<gl::GLContext>& context,
     bool offscreen,
     const DisallowedFeatures& disallowed_features,
-    const ContextCreationAttribHelper& attrib_helper) {
+    const ContextCreationAttribs& attrib_helper) {
   TRACE_EVENT0("gpu", "GLES2DecoderPassthroughImpl::Initialize");
   DCHECK(context->IsCurrent(surface.get()));
   api_ = gl::g_current_gl_context;
@@ -1167,6 +1167,9 @@
       feature_info_->feature_flags().chromium_image_ycbcr_422;
   caps.image_ycbcr_420v =
       feature_info_->feature_flags().chromium_image_ycbcr_420v;
+  caps.image_ycbcr_420v_disabled_for_video_frames =
+      group_->gpu_preferences()
+          .disable_biplanar_gpu_memory_buffers_for_video_frames;
   caps.max_copy_texture_chromium_size =
       feature_info_->workarounds().max_copy_texture_chromium_size;
   caps.render_buffer_format_bgra8888 =
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
index a9da26b6..cdce850a0 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -133,7 +133,7 @@
       const scoped_refptr<gl::GLContext>& context,
       bool offscreen,
       const DisallowedFeatures& disallowed_features,
-      const ContextCreationAttribHelper& attrib_helper) override;
+      const ContextCreationAttribs& attrib_helper) override;
 
   // Destroys the graphics context.
   void Destroy(bool have_context) override;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index df1033d2..09ef3e7 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -486,7 +486,7 @@
   shared_memory_base_ = buffer->memory();
   ClearSharedMemory();
 
-  gles2::ContextCreationAttribHelper attribs;
+  ContextCreationAttribs attribs;
   attribs.alpha_size = normalized_init.request_alpha ? 8 : 0;
   attribs.depth_size = normalized_init.request_depth ? 24 : 0;
   attribs.stencil_size = normalized_init.request_stencil ? 8 : 0;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index af472e5..a299404 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -982,7 +982,7 @@
   uint32_t immediate_buffer_[64];
 
  private:
-  ContextCreationAttribHelper context_creation_attribs_;
+  ContextCreationAttribs context_creation_attribs_;
   GpuPreferences gpu_preferences_;
   MailboxManagerImpl mailbox_manager_;
   ShaderTranslatorCache shader_translator_cache_;
diff --git a/gpu/command_buffer/service/gpu_preferences.h b/gpu/command_buffer/service/gpu_preferences.h
index ab20cb9..cbfe520 100644
--- a/gpu/command_buffer/service/gpu_preferences.h
+++ b/gpu/command_buffer/service/gpu_preferences.h
@@ -150,6 +150,10 @@
   // Use the Pass-through command decoder, skipping all validation and state
   // tracking.
   bool use_passthrough_cmd_decoder = false;
+
+  // Disable using a single multiplanar GpuMemoryBuffer to store biplanar
+  // VideoFrames (e.g. NV12), see https://crbug.com/791676.
+  bool disable_biplanar_gpu_memory_buffers_for_video_frames = false;
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 204aeb04..34d599d 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -75,7 +75,7 @@
     const scoped_refptr<gl::GLContext>& context,
     bool offscreen,
     const DisallowedFeatures& disallowed_features,
-    const ContextCreationAttribHelper& attrib_helper) {
+    const ContextCreationAttribs& attrib_helper) {
   TRACE_EVENT0("gpu", "RasterDecoder::Initialize");
   DCHECK(context->IsCurrent(surface.get()));
   DCHECK(!context_.get());
diff --git a/gpu/command_buffer/service/raster_decoder.h b/gpu/command_buffer/service/raster_decoder.h
index 9b81cfd..4cdf58f7 100644
--- a/gpu/command_buffer/service/raster_decoder.h
+++ b/gpu/command_buffer/service/raster_decoder.h
@@ -52,7 +52,7 @@
       const scoped_refptr<gl::GLContext>& context,
       bool offscreen,
       const gles2::DisallowedFeatures& disallowed_features,
-      const gles2::ContextCreationAttribHelper& attrib_helper) override;
+      const ContextCreationAttribs& attrib_helper) override;
   void Destroy(bool have_context) override;
   void SetSurface(const scoped_refptr<gl::GLSurface>& surface) override;
   void ReleaseSurface() override;
diff --git a/gpu/command_buffer/service/service_utils.cc b/gpu/command_buffer/service/service_utils.cc
index 0204e02..7b9363a 100644
--- a/gpu/command_buffer/service/service_utils.cc
+++ b/gpu/command_buffer/service/service_utils.cc
@@ -19,7 +19,7 @@
 namespace gles2 {
 
 gl::GLContextAttribs GenerateGLContextAttribs(
-    const ContextCreationAttribHelper& attribs_helper,
+    const ContextCreationAttribs& attribs_helper,
     const ContextGroup* context_group) {
   DCHECK(context_group != nullptr);
   gl::GLContextAttribs attribs;
diff --git a/gpu/command_buffer/service/service_utils.h b/gpu/command_buffer/service/service_utils.h
index 5817aced..8514ed0f 100644
--- a/gpu/command_buffer/service/service_utils.h
+++ b/gpu/command_buffer/service/service_utils.h
@@ -10,13 +10,13 @@
 #include "ui/gl/gl_context.h"
 
 namespace gpu {
+struct ContextCreationAttribs;
 
 namespace gles2 {
-struct ContextCreationAttribHelper;
 class ContextGroup;
 
 GPU_EXPORT gl::GLContextAttribs GenerateGLContextAttribs(
-    const ContextCreationAttribHelper& attribs_helper,
+    const ContextCreationAttribs& attribs_helper,
     const ContextGroup* context_group);
 
 // Returns true if the passthrough command decoder has been requested
diff --git a/gpu/command_buffer/service/test_helper.h b/gpu/command_buffer/service/test_helper.h
index e096a7a..bd4f50d 100644
--- a/gpu/command_buffer/service/test_helper.h
+++ b/gpu/command_buffer/service/test_helper.h
@@ -10,7 +10,7 @@
 #include <string>
 #include <vector>
 
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/service/shader_translator.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_mock.h"
diff --git a/gpu/command_buffer/tests/decoder_perftest.cc b/gpu/command_buffer/tests/decoder_perftest.cc
index a5ceab86..a46dd18 100644
--- a/gpu/command_buffer/tests/decoder_perftest.cc
+++ b/gpu/command_buffer/tests/decoder_perftest.cc
@@ -11,7 +11,7 @@
 #include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/constants.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/service/command_buffer_direct.h"
 #include "gpu/command_buffer/service/context_group.h"
@@ -190,7 +190,7 @@
 
     decoder_->GetLogger()->set_log_synthesized_gl_errors(false);
 
-    gles2::ContextCreationAttribHelper attrib_helper;
+    ContextCreationAttribs attrib_helper;
     attrib_helper.offscreen_framebuffer_size = gfx::Size(16, 16);
     attrib_helper.red_size = 8;
     attrib_helper.green_size = 8;
@@ -198,7 +198,7 @@
     attrib_helper.alpha_size = 8;
     attrib_helper.depth_size = 0;
     attrib_helper.stencil_size = 0;
-    attrib_helper.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    attrib_helper.context_type = CONTEXT_TYPE_OPENGLES3;
 
     ContextResult result =
         decoder_->Initialize(surface_.get(), context_.get(), true,
diff --git a/gpu/command_buffer/tests/es3_misc_functions_unittest.cc b/gpu/command_buffer/tests/es3_misc_functions_unittest.cc
index 65d8e94..f718ba6 100644
--- a/gpu/command_buffer/tests/es3_misc_functions_unittest.cc
+++ b/gpu/command_buffer/tests/es3_misc_functions_unittest.cc
@@ -23,7 +23,7 @@
  protected:
   void SetUp() override {
     GLManager::Options options;
-    options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    options.context_type = CONTEXT_TYPE_OPENGLES3;
     gl_.Initialize(options);
   }
   void TearDown() override { gl_.Destroy(); }
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index 6e71fd9..ec3a4e7c 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -17,7 +17,7 @@
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
 #include "gpu/command_buffer/common/constants.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/service/buffer_manager.h"
 #include "gpu/command_buffer/service/command_buffer_direct.h"
@@ -227,7 +227,7 @@
     attrib_helper.single_buffer = it.GetBit();
     bool es3 = it.GetBit();
     attrib_helper.context_type =
-        es3 ? gles2::CONTEXT_TYPE_OPENGLES3 : gles2::CONTEXT_TYPE_OPENGLES2;
+        es3 ? CONTEXT_TYPE_OPENGLES3 : CONTEXT_TYPE_OPENGLES2;
 
 #if defined(GPU_FUZZER_USE_STUB)
     std::vector<base::StringPiece> enabled_extensions;
@@ -255,7 +255,7 @@
   };
 
   GpuDriverBugWorkarounds workarounds;
-  gles2::ContextCreationAttribHelper attrib_helper;
+  ContextCreationAttribs attrib_helper;
 #if defined(GPU_FUZZER_USE_STUB)
   const char* version;
   std::string extensions;
diff --git a/gpu/command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc
index 1a12f565..9ffb790e 100644
--- a/gpu/command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc
+++ b/gpu/command_buffer/tests/gl_apply_screen_space_antialiasing_CHROMIUM_unittest.cc
@@ -100,7 +100,7 @@
  protected:
   void SetUp() override {
     GLManager::Options options;
-    options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    options.context_type = CONTEXT_TYPE_OPENGLES3;
     gl_.Initialize(options);
     CheckStatus();
   }
diff --git a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
index b84382eb..7a46a4c 100644
--- a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
+++ b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
@@ -520,7 +520,7 @@
  protected:
   void SetUp() override {
     GLManager::Options options;
-    options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    options.context_type = CONTEXT_TYPE_OPENGLES3;
     options.size = gfx::Size(64, 64);
     GpuDriverBugWorkarounds workarounds;
 #if defined(OS_MACOSX)
diff --git a/gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc b/gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc
index 4332b9f..18be863 100644
--- a/gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc
+++ b/gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc
@@ -248,7 +248,7 @@
   void SetUp() override {
     GLManager::Options options;
     options.size = gfx::Size(kWidth, kHeight);
-    options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    options.context_type = CONTEXT_TYPE_OPENGLES3;
     options.force_shader_name_hashing = GetParam();
     gl_.Initialize(options);
   }
diff --git a/gpu/command_buffer/tests/gl_ext_window_rectangles_unittest.cc b/gpu/command_buffer/tests/gl_ext_window_rectangles_unittest.cc
index 7ef2cea..ea69662 100644
--- a/gpu/command_buffer/tests/gl_ext_window_rectangles_unittest.cc
+++ b/gpu/command_buffer/tests/gl_ext_window_rectangles_unittest.cc
@@ -18,7 +18,7 @@
  protected:
   void SetUp() override {
     GLManager::Options options;
-    options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    options.context_type = CONTEXT_TYPE_OPENGLES3;
     gl_.Initialize(options);
   }
 
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index 94498fb..9752df9e 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -24,7 +24,7 @@
 #include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/common/constants.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/common/sync_token.h"
 #include "gpu/command_buffer/service/command_buffer_direct.h"
 #include "gpu/command_buffer/service/context_group.h"
@@ -299,7 +299,7 @@
 
   share_group_ = share_group ? share_group : new gl::GLShareGroup;
 
-  gles2::ContextCreationAttribHelper attribs;
+  ContextCreationAttribs attribs;
   attribs.red_size = 8;
   attribs.green_size = 8;
   attribs.blue_size = 8;
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h
index 44ef18b..d699ae0 100644
--- a/gpu/command_buffer/tests/gl_manager.h
+++ b/gpu/command_buffer/tests/gl_manager.h
@@ -12,7 +12,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "gpu/command_buffer/client/gpu_control.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/service/feature_info.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/command_buffer/service/gpu_tracer.h"
@@ -66,7 +66,7 @@
     bool lose_context_when_out_of_memory = false;
     // Whether or not it's ok to lose the context.
     bool context_lost_allowed = false;
-    gles2::ContextType context_type = gles2::CONTEXT_TYPE_OPENGLES2;
+    ContextType context_type = CONTEXT_TYPE_OPENGLES2;
     // Force shader name hashing for all context types.
     bool force_shader_name_hashing = false;
     // Whether the buffer is multisampled.
diff --git a/gpu/command_buffer/tests/gl_map_buffer_range_unittest.cc b/gpu/command_buffer/tests/gl_map_buffer_range_unittest.cc
index e5298b8..9b74792 100644
--- a/gpu/command_buffer/tests/gl_map_buffer_range_unittest.cc
+++ b/gpu/command_buffer/tests/gl_map_buffer_range_unittest.cc
@@ -25,7 +25,7 @@
   void SetUp() override {
     GLManager::Options options;
     options.size = gfx::Size(kCanvasSize, kCanvasSize);
-    options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    options.context_type = CONTEXT_TYPE_OPENGLES3;
 
     gl_.Initialize(options);
   }
diff --git a/gpu/command_buffer/tests/gl_object_bindings_unittest.cc b/gpu/command_buffer/tests/gl_object_bindings_unittest.cc
index 8440c94..2bc3db14 100644
--- a/gpu/command_buffer/tests/gl_object_bindings_unittest.cc
+++ b/gpu/command_buffer/tests/gl_object_bindings_unittest.cc
@@ -19,7 +19,7 @@
  protected:
   void SetUp() override {
     GLManager::Options options;
-    options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    options.context_type = CONTEXT_TYPE_OPENGLES3;
     gl_.Initialize(options);
   }
 
diff --git a/gpu/command_buffer/tests/gl_program_unittest.cc b/gpu/command_buffer/tests/gl_program_unittest.cc
index 82f9cd9e..284f5edc 100644
--- a/gpu/command_buffer/tests/gl_program_unittest.cc
+++ b/gpu/command_buffer/tests/gl_program_unittest.cc
@@ -30,7 +30,7 @@
  protected:
   void SetUp() override {
     GLManager::Options options;
-    options.context_type = gles2::CONTEXT_TYPE_WEBGL1;
+    options.context_type = CONTEXT_TYPE_WEBGL1;
     gl_.Initialize(options);
   }
 };
diff --git a/gpu/command_buffer/tests/gl_request_extension_unittest.cc b/gpu/command_buffer/tests/gl_request_extension_unittest.cc
index c924c6b..ddf8f39 100644
--- a/gpu/command_buffer/tests/gl_request_extension_unittest.cc
+++ b/gpu/command_buffer/tests/gl_request_extension_unittest.cc
@@ -17,7 +17,7 @@
 namespace gpu {
 
 class RequestExtensionCHROMIUMTest
-    : public testing::TestWithParam<gles2::ContextType> {
+    : public testing::TestWithParam<ContextType> {
  protected:
   void SetUp() override {
     GLManager::Options options;
@@ -67,8 +67,8 @@
     std::set<std::string> extensions_from_string(extensions.begin(),
                                                  extensions.end());
 
-    if (GetParam() == gles2::CONTEXT_TYPE_WEBGL2 ||
-        GetParam() == gles2::CONTEXT_TYPE_OPENGLES3) {
+    if (GetParam() == CONTEXT_TYPE_WEBGL2 ||
+        GetParam() == CONTEXT_TYPE_OPENGLES3) {
       // Test that GetString(GL_EXTENSIONS) is consistent with
       // GetStringi(GL_EXTENSIONS, index)
       GLint num_extensions = 0;
@@ -94,8 +94,8 @@
 }
 INSTANTIATE_TEST_CASE_P(WithContextTypes,
                         RequestExtensionCHROMIUMTest,
-                        ::testing::Values(gles2::CONTEXT_TYPE_WEBGL1,
-                                          gles2::CONTEXT_TYPE_WEBGL2,
-                                          gles2::CONTEXT_TYPE_OPENGLES2,
-                                          gles2::CONTEXT_TYPE_OPENGLES3));
+                        ::testing::Values(CONTEXT_TYPE_WEBGL1,
+                                          CONTEXT_TYPE_WEBGL2,
+                                          CONTEXT_TYPE_OPENGLES2,
+                                          CONTEXT_TYPE_OPENGLES3));
 }
diff --git a/gpu/command_buffer/tests/gl_set_aggressively_free_resources_unittest.cc b/gpu/command_buffer/tests/gl_set_aggressively_free_resources_unittest.cc
index 1d7fc08..f80fe6d 100644
--- a/gpu/command_buffer/tests/gl_set_aggressively_free_resources_unittest.cc
+++ b/gpu/command_buffer/tests/gl_set_aggressively_free_resources_unittest.cc
@@ -18,10 +18,10 @@
  protected:
   void SetUp() override {
     GLManager::Options options;
-    options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    options.context_type = CONTEXT_TYPE_OPENGLES3;
     gl_.Initialize(options);
     if (!gl_.IsInitialized()) {
-      options.context_type = gles2::CONTEXT_TYPE_OPENGLES2;
+      options.context_type = CONTEXT_TYPE_OPENGLES2;
       gl_.Initialize(options);
     }
     context_type_ = options.context_type;
@@ -34,7 +34,7 @@
   void TearDown() override { gl_.Destroy(); }
 
   GLManager gl_;
-  gles2::ContextType context_type_ = gles2::CONTEXT_TYPE_OPENGLES3;
+  ContextType context_type_ = CONTEXT_TYPE_OPENGLES3;
 };
 
 // Tests that SetAggressivelyFreeResources releases command buffer memory.
@@ -133,7 +133,7 @@
   memcpy(data, kData, sizeof(kData));
   glUnmapBufferSubDataCHROMIUM(data);
 
-  if (context_type_ == gles2::CONTEXT_TYPE_OPENGLES3) {
+  if (context_type_ == CONTEXT_TYPE_OPENGLES3) {
     data = gl_.gles2_implementation()->GetBufferSubDataAsyncCHROMIUM(
         GL_ARRAY_BUFFER, 0, sizeof(kData));
     gl_.gles2_implementation()->FreeSharedMemory(data);
diff --git a/gpu/command_buffer/tests/gl_virtual_contexts_ext_window_rectangles_unittest.cc b/gpu/command_buffer/tests/gl_virtual_contexts_ext_window_rectangles_unittest.cc
index 2083cbf3..9e412b8 100644
--- a/gpu/command_buffer/tests/gl_virtual_contexts_ext_window_rectangles_unittest.cc
+++ b/gpu/command_buffer/tests/gl_virtual_contexts_ext_window_rectangles_unittest.cc
@@ -18,7 +18,7 @@
  protected:
   void SetUp() override {
     GLManager::Options options;
-    options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+    options.context_type = CONTEXT_TYPE_OPENGLES3;
     gl_real_shared_.Initialize(options);
     options.virtual_manager = &gl_real_shared_;
     gl1_.Initialize(options);
diff --git a/gpu/gles2_conform_support/egl/BUILD.gn b/gpu/gles2_conform_support/egl/BUILD.gn
index a40d25be..edc1ed7b 100644
--- a/gpu/gles2_conform_support/egl/BUILD.gn
+++ b/gpu/gles2_conform_support/egl/BUILD.gn
@@ -32,7 +32,6 @@
     "//gpu",
     "//gpu/command_buffer/client:gles2_c_lib_nocheck",
     "//gpu/command_buffer/client:gles2_implementation_no_check",
-    "//gpu/command_buffer/common:gles2_utils",
     "//gpu/command_buffer/service",
     "//ui/base",
     "//ui/gfx",
diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc
index 329934c2..fae825b 100644
--- a/gpu/gles2_conform_support/egl/context.cc
+++ b/gpu/gles2_conform_support/egl/context.cc
@@ -288,7 +288,7 @@
 
   gl_context->MakeCurrent(gl_surface);
 
-  gpu::gles2::ContextCreationAttribHelper helper;
+  gpu::ContextCreationAttribs helper;
   config_->GetAttrib(EGL_ALPHA_SIZE, &helper.alpha_size);
   config_->GetAttrib(EGL_DEPTH_SIZE, &helper.depth_size);
   config_->GetAttrib(EGL_STENCIL_SIZE, &helper.stencil_size);
@@ -297,7 +297,7 @@
   helper.bind_generates_resource = kBindGeneratesResources;
   helper.fail_if_major_perf_caveat = false;
   helper.lose_context_when_out_of_memory = kLoseContextWhenOutOfMemory;
-  helper.context_type = gpu::gles2::CONTEXT_TYPE_OPENGLES2;
+  helper.context_type = gpu::CONTEXT_TYPE_OPENGLES2;
   helper.offscreen_framebuffer_size = gl_surface->GetSize();
 
   auto result = decoder->Initialize(gl_surface, gl_context.get(),
diff --git a/gpu/ipc/BUILD.gn b/gpu/ipc/BUILD.gn
index 6c99b960..c4a579a 100644
--- a/gpu/ipc/BUILD.gn
+++ b/gpu/ipc/BUILD.gn
@@ -64,7 +64,6 @@
     "//base/third_party/dynamic_annotations",
     "//gpu",
     "//gpu/command_buffer/client:gles2_implementation",
-    "//gpu/command_buffer/common:gles2_utils",
     "//gpu/ipc:command_buffer",
     "//ui/gfx/geometry",
     "//ui/gl",
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.cc b/gpu/ipc/client/command_buffer_proxy_impl.cc
index 04d5687..5d509cc 100644
--- a/gpu/ipc/client/command_buffer_proxy_impl.cc
+++ b/gpu/ipc/client/command_buffer_proxy_impl.cc
@@ -76,7 +76,7 @@
     gpu::SurfaceHandle surface_handle,
     CommandBufferProxyImpl* share_group,
     gpu::SchedulingPriority stream_priority,
-    const gpu::gles2::ContextCreationAttribHelper& attribs,
+    const gpu::ContextCreationAttribs& attribs,
     const GURL& active_url) {
   DCHECK(!share_group || (stream_id_ == share_group->stream_id_));
   TRACE_EVENT1("gpu", "GpuChannelHost::CreateViewCommandBuffer",
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.h b/gpu/ipc/client/command_buffer_proxy_impl.h
index bd7b870..afa5eb7 100644
--- a/gpu/ipc/client/command_buffer_proxy_impl.h
+++ b/gpu/ipc/client/command_buffer_proxy_impl.h
@@ -49,13 +49,10 @@
 }
 
 namespace gpu {
+struct ContextCreationAttribs;
 struct Mailbox;
 struct SwapBuffersCompleteParams;
 struct SyncToken;
-
-namespace gles2 {
-struct ContextCreationAttribHelper;
-}
 }
 
 namespace gpu {
@@ -88,12 +85,11 @@
   ~CommandBufferProxyImpl() override;
 
   // Connect to a command buffer in the GPU process.
-  ContextResult Initialize(
-      gpu::SurfaceHandle surface_handle,
-      CommandBufferProxyImpl* share_group,
-      gpu::SchedulingPriority stream_priority,
-      const gpu::gles2::ContextCreationAttribHelper& attribs,
-      const GURL& active_url);
+  ContextResult Initialize(gpu::SurfaceHandle surface_handle,
+                           CommandBufferProxyImpl* share_group,
+                           gpu::SchedulingPriority stream_priority,
+                           const gpu::ContextCreationAttribs& attribs,
+                           const GURL& active_url);
 
   // IPC::Listener implementation:
   bool OnMessageReceived(const IPC::Message& message) override;
diff --git a/gpu/ipc/client/gpu_in_process_context_tests.cc b/gpu/ipc/client/gpu_in_process_context_tests.cc
index e0c7349..da057f6 100644
--- a/gpu/ipc/client/gpu_in_process_context_tests.cc
+++ b/gpu/ipc/client/gpu_in_process_context_tests.cc
@@ -24,7 +24,7 @@
 class ContextTestBase : public testing::Test {
  public:
   std::unique_ptr<gpu::GLInProcessContext> CreateGLInProcessContext() {
-    gpu::gles2::ContextCreationAttribHelper attributes;
+    gpu::ContextCreationAttribs attributes;
     attributes.alpha_size = 8;
     attributes.depth_size = 24;
     attributes.red_size = 8;
diff --git a/gpu/ipc/common/BUILD.gn b/gpu/ipc/common/BUILD.gn
index 901586d..746024e 100644
--- a/gpu/ipc/common/BUILD.gn
+++ b/gpu/ipc/common/BUILD.gn
@@ -65,7 +65,6 @@
 
   deps = [
     "//base",
-    "//gpu/command_buffer/common:gles2_utils",
     "//ui/gfx/ipc",
     "//ui/gfx/ipc/geometry",
   ]
diff --git a/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
index c6e49c8..52f7d580 100644
--- a/gpu/ipc/common/gpu_command_buffer_traits_multi.h
+++ b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
@@ -7,7 +7,7 @@
 #include "gpu/command_buffer/common/capabilities.h"
 #include "gpu/command_buffer/common/command_buffer.h"
 #include "gpu/command_buffer/common/constants.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/gpu_export.h"
 #include "ipc/ipc_message_utils.h"
 #include "ipc/param_traits_macros.h"
@@ -25,9 +25,8 @@
     gpu::CommandBufferNamespace::INVALID,
     gpu::CommandBufferNamespace::NUM_COMMAND_BUFFER_NAMESPACES - 1)
 IPC_ENUM_TRAITS_MAX_VALUE(gl::GpuPreference, gl::GpuPreferenceLast)
-IPC_ENUM_TRAITS_MAX_VALUE(gpu::gles2::ContextType,
-                          gpu::gles2::CONTEXT_TYPE_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(gpu::gles2::ColorSpace, gpu::gles2::COLOR_SPACE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(gpu::ContextType, gpu::CONTEXT_TYPE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(gpu::ColorSpace, gpu::COLOR_SPACE_LAST)
 
 IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities::ShaderPrecision)
   IPC_STRUCT_TRAITS_MEMBER(min_range)
@@ -152,7 +151,7 @@
   IPC_STRUCT_TRAITS_MEMBER(set_get_buffer_count)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(gpu::gles2::ContextCreationAttribHelper)
+IPC_STRUCT_TRAITS_BEGIN(gpu::ContextCreationAttribs)
   IPC_STRUCT_TRAITS_MEMBER(offscreen_framebuffer_size)
   IPC_STRUCT_TRAITS_MEMBER(gpu_preference)
   IPC_STRUCT_TRAITS_MEMBER(alpha_size)
diff --git a/gpu/ipc/common/gpu_messages.h b/gpu/ipc/common/gpu_messages.h
index 60d1d537..77eeab1f 100644
--- a/gpu/ipc/common/gpu_messages.h
+++ b/gpu/ipc/common/gpu_messages.h
@@ -59,7 +59,7 @@
   IPC_STRUCT_MEMBER(int32_t, share_group_id)
   IPC_STRUCT_MEMBER(int32_t, stream_id)
   IPC_STRUCT_MEMBER(gpu::SchedulingPriority, stream_priority)
-  IPC_STRUCT_MEMBER(gpu::gles2::ContextCreationAttribHelper, attribs)
+  IPC_STRUCT_MEMBER(gpu::ContextCreationAttribs, attribs)
   IPC_STRUCT_MEMBER(GURL, active_url)
 IPC_STRUCT_END()
 
diff --git a/gpu/ipc/common/gpu_preferences.mojom b/gpu/ipc/common/gpu_preferences.mojom
index 09c7eb3..ce7b269b 100644
--- a/gpu/ipc/common/gpu_preferences.mojom
+++ b/gpu/ipc/common/gpu_preferences.mojom
@@ -55,4 +55,5 @@
   bool enable_gpu_service_logging;
   bool enable_gpu_service_tracing;
   bool use_passthrough_cmd_decoder;
+  bool disable_biplanar_gpu_memory_buffers_for_video_frames;
 };
diff --git a/gpu/ipc/common/gpu_preferences_struct_traits.h b/gpu/ipc/common/gpu_preferences_struct_traits.h
index 1c95637..fed6d70 100644
--- a/gpu/ipc/common/gpu_preferences_struct_traits.h
+++ b/gpu/ipc/common/gpu_preferences_struct_traits.h
@@ -96,6 +96,8 @@
     out->enable_gpu_service_logging = prefs.enable_gpu_service_logging();
     out->enable_gpu_service_tracing = prefs.enable_gpu_service_tracing();
     out->use_passthrough_cmd_decoder = prefs.use_passthrough_cmd_decoder();
+    out->disable_biplanar_gpu_memory_buffers_for_video_frames =
+        prefs.disable_biplanar_gpu_memory_buffers_for_video_frames();
     return true;
   }
 
@@ -211,6 +213,10 @@
   static bool use_passthrough_cmd_decoder(const gpu::GpuPreferences& prefs) {
     return prefs.use_passthrough_cmd_decoder;
   }
+  static bool disable_biplanar_gpu_memory_buffers_for_video_frames(
+      const gpu::GpuPreferences& prefs) {
+    return prefs.disable_biplanar_gpu_memory_buffers_for_video_frames;
+  }
 };
 
 }  // namespace mojo
diff --git a/gpu/ipc/gl_in_process_context.cc b/gpu/ipc/gl_in_process_context.cc
index a983202..4358143 100644
--- a/gpu/ipc/gl_in_process_context.cc
+++ b/gpu/ipc/gl_in_process_context.cc
@@ -59,7 +59,7 @@
       bool is_offscreen,
       SurfaceHandle window,
       GLInProcessContext* share_context,
-      const gpu::gles2::ContextCreationAttribHelper& attribs,
+      const gpu::ContextCreationAttribs& attribs,
       const SharedMemoryLimits& mem_limits,
       GpuMemoryBufferManager* gpu_memory_buffer_manager,
       ImageFactory* image_factory,
@@ -154,7 +154,7 @@
     bool is_offscreen,
     SurfaceHandle window,
     GLInProcessContext* share_context,
-    const gles2::ContextCreationAttribHelper& attribs,
+    const ContextCreationAttribs& attribs,
     const SharedMemoryLimits& mem_limits,
     GpuMemoryBufferManager* gpu_memory_buffer_manager,
     ImageFactory* image_factory,
diff --git a/gpu/ipc/gl_in_process_context.h b/gpu/ipc/gl_in_process_context.h
index d160b8da..551282e 100644
--- a/gpu/ipc/gl_in_process_context.h
+++ b/gpu/ipc/gl_in_process_context.h
@@ -11,7 +11,7 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/single_thread_task_runner.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/ipc/gl_in_process_context_export.h"
 #include "gpu/ipc/in_process_command_buffer.h"
 #include "ui/gfx/native_widget_types.h"
@@ -50,7 +50,7 @@
       bool is_offscreen,
       SurfaceHandle window,
       GLInProcessContext* share_context,
-      const gpu::gles2::ContextCreationAttribHelper& attribs,
+      const gpu::ContextCreationAttribs& attribs,
       const SharedMemoryLimits& memory_limits,
       GpuMemoryBufferManager* gpu_memory_buffer_manager,
       ImageFactory* image_factory,
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc
index 9ec3e8a..3cc7d15 100644
--- a/gpu/ipc/in_process_command_buffer.cc
+++ b/gpu/ipc/in_process_command_buffer.cc
@@ -240,7 +240,7 @@
     scoped_refptr<gl::GLSurface> surface,
     bool is_offscreen,
     SurfaceHandle window,
-    const gles2::ContextCreationAttribHelper& attribs,
+    const ContextCreationAttribs& attribs,
     InProcessCommandBuffer* share_group,
     GpuMemoryBufferManager* gpu_memory_buffer_manager,
     ImageFactory* image_factory,
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h
index 62eb96b9f..6294d9a 100644
--- a/gpu/ipc/in_process_command_buffer.h
+++ b/gpu/ipc/in_process_command_buffer.h
@@ -58,6 +58,7 @@
 
 namespace gpu {
 
+struct ContextCreationAttribs;
 class ServiceDiscardableManager;
 class SyncPointClientState;
 class SyncPointOrderData;
@@ -65,7 +66,6 @@
 struct SwapBuffersCompleteParams;
 
 namespace gles2 {
-struct ContextCreationAttribHelper;
 class FramebufferCompletenessCache;
 class MailboxManager;
 class Outputter;
@@ -102,7 +102,7 @@
       scoped_refptr<gl::GLSurface> surface,
       bool is_offscreen,
       SurfaceHandle window,
-      const gles2::ContextCreationAttribHelper& attribs,
+      const ContextCreationAttribs& attribs,
       InProcessCommandBuffer* share_group,
       GpuMemoryBufferManager* gpu_memory_buffer_manager,
       ImageFactory* image_factory,
@@ -277,18 +277,17 @@
   struct InitializeOnGpuThreadParams {
     bool is_offscreen;
     SurfaceHandle window;
-    const gles2::ContextCreationAttribHelper& attribs;
+    const ContextCreationAttribs& attribs;
     Capabilities* capabilities;  // Ouptut.
     InProcessCommandBuffer* context_group;
     ImageFactory* image_factory;
 
-    InitializeOnGpuThreadParams(
-        bool is_offscreen,
-        SurfaceHandle window,
-        const gles2::ContextCreationAttribHelper& attribs,
-        Capabilities* capabilities,
-        InProcessCommandBuffer* share_group,
-        ImageFactory* image_factory)
+    InitializeOnGpuThreadParams(bool is_offscreen,
+                                SurfaceHandle window,
+                                const ContextCreationAttribs& attribs,
+                                Capabilities* capabilities,
+                                InProcessCommandBuffer* share_group,
+                                ImageFactory* image_factory)
         : is_offscreen(is_offscreen),
           window(window),
           attribs(attribs),
diff --git a/gpu/ipc/service/BUILD.gn b/gpu/ipc/service/BUILD.gn
index 6f2b3d5..2946c237 100644
--- a/gpu/ipc/service/BUILD.gn
+++ b/gpu/ipc/service/BUILD.gn
@@ -173,7 +173,6 @@
     "//base",
     "//base/test:test_support",
     "//gpu/command_buffer/common",
-    "//gpu/command_buffer/common:gles2_utils",
     "//gpu/command_buffer/service",
     "//gpu/config",
     "//gpu/ipc/common",
diff --git a/gpu/ipc/service/command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc
index 27187c2..b61c968b 100644
--- a/gpu/ipc/service/command_buffer_stub.cc
+++ b/gpu/ipc/service/command_buffer_stub.cc
@@ -71,13 +71,13 @@
   do {                                                                     \
     uint64_t mb_used = tracking_group_->GetSize() / (1024 * 1024);         \
     switch (context_type_) {                                               \
-      case gles2::CONTEXT_TYPE_WEBGL1:                                     \
-      case gles2::CONTEXT_TYPE_WEBGL2:                                     \
+      case CONTEXT_TYPE_WEBGL1:                                            \
+      case CONTEXT_TYPE_WEBGL2:                                            \
         UMA_HISTOGRAM_MEMORY_LARGE_MB("GPU.ContextMemory.WebGL." category, \
                                       mb_used);                            \
         break;                                                             \
-      case gles2::CONTEXT_TYPE_OPENGLES2:                                  \
-      case gles2::CONTEXT_TYPE_OPENGLES3:                                  \
+      case CONTEXT_TYPE_OPENGLES2:                                         \
+      case CONTEXT_TYPE_OPENGLES3:                                         \
         UMA_HISTOGRAM_MEMORY_LARGE_MB("GPU.ContextMemory.GLES." category,  \
                                       mb_used);                            \
         break;                                                             \
@@ -103,7 +103,7 @@
   explicit GpuCommandBufferMemoryTracker(
       GpuChannel* channel,
       uint64_t share_group_tracing_guid,
-      gles2::ContextType context_type,
+      ContextType context_type,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner)
       : tracking_group_(
             channel->gpu_channel_manager()
@@ -158,7 +158,7 @@
   const uint64_t share_group_tracing_guid_;
 
   // Variables used in memory stat histogram logging.
-  const gles2::ContextType context_type_;
+  const ContextType context_type_;
   base::RepeatingTimer memory_stats_timer_;
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
diff --git a/gpu/ipc/service/gles2_command_buffer_stub.cc b/gpu/ipc/service/gles2_command_buffer_stub.cc
index fb94388..63a5022 100644
--- a/gpu/ipc/service/gles2_command_buffer_stub.cc
+++ b/gpu/ipc/service/gles2_command_buffer_stub.cc
@@ -211,14 +211,14 @@
     }
   } else {
     switch (init_params.attribs.color_space) {
-      case gles2::COLOR_SPACE_UNSPECIFIED:
+      case COLOR_SPACE_UNSPECIFIED:
         surface_format.SetColorSpace(
             gl::GLSurfaceFormat::COLOR_SPACE_UNSPECIFIED);
         break;
-      case gles2::COLOR_SPACE_SRGB:
+      case COLOR_SPACE_SRGB:
         surface_format.SetColorSpace(gl::GLSurfaceFormat::COLOR_SPACE_SRGB);
         break;
-      case gles2::COLOR_SPACE_DISPLAY_P3:
+      case COLOR_SPACE_DISPLAY_P3:
         surface_format.SetColorSpace(
             gl::GLSurfaceFormat::COLOR_SPACE_DISPLAY_P3);
         break;
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc
index 6745702..48b97f93 100644
--- a/gpu/ipc/service/gpu_channel.cc
+++ b/gpu/ipc/service/gpu_channel.cc
@@ -441,10 +441,10 @@
 
 bool GpuChannel::HasActiveWebGLContext() const {
   for (auto& kv : stubs_) {
-    gles2::ContextType context_type =
+    ContextType context_type =
         kv.second->context_group()->feature_info()->context_type();
-    if (context_type == gles2::CONTEXT_TYPE_WEBGL1 ||
-        context_type == gles2::CONTEXT_TYPE_WEBGL2) {
+    if (context_type == CONTEXT_TYPE_WEBGL1 ||
+        context_type == CONTEXT_TYPE_WEBGL2) {
       return true;
     }
   }
diff --git a/gpu/ipc/service/gpu_channel_manager_unittest.cc b/gpu/ipc/service/gpu_channel_manager_unittest.cc
index 821529c..8cd9b32 100644
--- a/gpu/ipc/service/gpu_channel_manager_unittest.cc
+++ b/gpu/ipc/service/gpu_channel_manager_unittest.cc
@@ -18,7 +18,7 @@
   ~GpuChannelManagerTest() override = default;
 
 #if defined(OS_ANDROID)
-  void TestOnApplicationStateChange(gles2::ContextType type,
+  void TestOnApplicationStateChange(ContextType type,
                                     bool should_destroy_channel) {
     ASSERT_TRUE(channel_manager());
 
@@ -34,7 +34,7 @@
     init_params.share_group_id = MSG_ROUTING_NONE;
     init_params.stream_id = 0;
     init_params.stream_priority = SchedulingPriority::kNormal;
-    init_params.attribs = gles2::ContextCreationAttribHelper();
+    init_params.attribs = ContextCreationAttribs();
     init_params.attribs.context_type = type;
     init_params.active_url = GURL();
     gpu::ContextResult result = gpu::ContextResult::kFatalFailure;
@@ -73,17 +73,17 @@
 #if defined(OS_ANDROID)
 TEST_F(GpuChannelManagerTest, OnLowEndBackgroundedWithoutWebGL) {
   channel_manager()->set_low_end_mode_for_testing(true);
-  TestOnApplicationStateChange(gles2::CONTEXT_TYPE_OPENGLES2, true);
+  TestOnApplicationStateChange(CONTEXT_TYPE_OPENGLES2, true);
 }
 
 TEST_F(GpuChannelManagerTest, OnLowEndBackgroundedWithWebGL) {
   channel_manager()->set_low_end_mode_for_testing(true);
-  TestOnApplicationStateChange(gles2::CONTEXT_TYPE_WEBGL2, false);
+  TestOnApplicationStateChange(CONTEXT_TYPE_WEBGL2, false);
 }
 
 TEST_F(GpuChannelManagerTest, OnHighEndBackgrounded) {
   channel_manager()->set_low_end_mode_for_testing(false);
-  TestOnApplicationStateChange(gles2::CONTEXT_TYPE_OPENGLES2, false);
+  TestOnApplicationStateChange(CONTEXT_TYPE_OPENGLES2, false);
 }
 #endif
 
diff --git a/gpu/ipc/service/gpu_channel_unittest.cc b/gpu/ipc/service/gpu_channel_unittest.cc
index 36d4325..570a682 100644
--- a/gpu/ipc/service/gpu_channel_unittest.cc
+++ b/gpu/ipc/service/gpu_channel_unittest.cc
@@ -33,7 +33,7 @@
   init_params.share_group_id = MSG_ROUTING_NONE;
   init_params.stream_id = 0;
   init_params.stream_priority = SchedulingPriority::kNormal;
-  init_params.attribs = gles2::ContextCreationAttribHelper();
+  init_params.attribs = ContextCreationAttribs();
   init_params.active_url = GURL();
   gpu::ContextResult result = gpu::ContextResult::kSuccess;
   gpu::Capabilities capabilities;
@@ -61,7 +61,7 @@
   init_params.share_group_id = MSG_ROUTING_NONE;
   init_params.stream_id = 0;
   init_params.stream_priority = SchedulingPriority::kNormal;
-  init_params.attribs = gles2::ContextCreationAttribHelper();
+  init_params.attribs = ContextCreationAttribs();
   init_params.active_url = GURL();
   gpu::ContextResult result = gpu::ContextResult::kSuccess;
   gpu::Capabilities capabilities;
@@ -85,7 +85,7 @@
   init_params.share_group_id = MSG_ROUTING_NONE;
   init_params.stream_id = 0;
   init_params.stream_priority = SchedulingPriority::kNormal;
-  init_params.attribs = gles2::ContextCreationAttribHelper();
+  init_params.attribs = ContextCreationAttribs();
   init_params.active_url = GURL();
   gpu::ContextResult result = gpu::ContextResult::kSuccess;
   gpu::Capabilities capabilities;
@@ -111,7 +111,7 @@
   init_params.share_group_id = MSG_ROUTING_NONE;
   init_params.stream_id = kStreamId1;
   init_params.stream_priority = SchedulingPriority::kNormal;
-  init_params.attribs = gles2::ContextCreationAttribHelper();
+  init_params.attribs = ContextCreationAttribs();
   init_params.active_url = GURL();
   gpu::ContextResult result = gpu::ContextResult::kSuccess;
   gpu::Capabilities capabilities;
@@ -130,7 +130,7 @@
   init_params.share_group_id = kRouteId1;
   init_params.stream_id = kStreamId2;
   init_params.stream_priority = SchedulingPriority::kNormal;
-  init_params.attribs = gles2::ContextCreationAttribHelper();
+  init_params.attribs = ContextCreationAttribs();
   init_params.active_url = GURL();
   HandleMessage(channel, new GpuChannelMsg_CreateCommandBuffer(
                              init_params, kRouteId2, GetSharedHandle(), &result,
@@ -155,7 +155,7 @@
   init_params.share_group_id = MSG_ROUTING_NONE;
   init_params.stream_id = kStreamId;
   init_params.stream_priority = SchedulingPriority::kHigh;
-  init_params.attribs = gles2::ContextCreationAttribHelper();
+  init_params.attribs = ContextCreationAttribs();
   init_params.active_url = GURL();
   gpu::ContextResult result = gpu::ContextResult::kSuccess;
   gpu::Capabilities capabilities;
@@ -187,7 +187,7 @@
   init_params.share_group_id = MSG_ROUTING_NONE;
   init_params.stream_id = 1;
   init_params.stream_priority = SchedulingPriority::kHigh;
-  init_params.attribs = gles2::ContextCreationAttribHelper();
+  init_params.attribs = ContextCreationAttribs();
   init_params.active_url = GURL();
   gpu::ContextResult result = gpu::ContextResult::kSuccess;
   gpu::Capabilities capabilities;
@@ -223,7 +223,7 @@
     init_params.share_group_id = MSG_ROUTING_NONE;
     init_params.stream_id = 0;
     init_params.stream_priority = SchedulingPriority::kNormal;
-    init_params.attribs = gles2::ContextCreationAttribHelper();
+    init_params.attribs = ContextCreationAttribs();
     init_params.active_url = GURL();
     gpu::ContextResult result = gpu::ContextResult::kSuccess;
     gpu::Capabilities capabilities;
@@ -243,7 +243,7 @@
     init_params.share_group_id = kSharedRouteId;
     init_params.stream_id = 0;
     init_params.stream_priority = SchedulingPriority::kNormal;
-    init_params.attribs = gles2::ContextCreationAttribHelper();
+    init_params.attribs = ContextCreationAttribs();
     init_params.active_url = GURL();
     gpu::ContextResult result = gpu::ContextResult::kSuccess;
     gpu::Capabilities capabilities;
@@ -267,7 +267,7 @@
     init_params.share_group_id = kSharedRouteId;
     init_params.stream_id = 0;
     init_params.stream_priority = SchedulingPriority::kNormal;
-    init_params.attribs = gles2::ContextCreationAttribHelper();
+    init_params.attribs = ContextCreationAttribs();
     init_params.active_url = GURL();
     gpu::ContextResult result = gpu::ContextResult::kSuccess;
     gpu::Capabilities capabilities;
diff --git a/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm b/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm
index 2cb7c9b..4a7bf97 100644
--- a/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_util_unittest.mm
@@ -14,7 +14,7 @@
 #endif
 
 namespace {
-const CGFloat kTestBubbleAlignmentOffset = 25.0f;
+const CGFloat kTestBubbleAlignmentOffset = 26.0f;
 }  // namespace
 
 namespace bubble_util {
diff --git a/ios/chrome/browser/ui/bubble/bubble_view.mm b/ios/chrome/browser/ui/bubble/bubble_view.mm
index 2a78d49..b83b2c0 100644
--- a/ios/chrome/browser/ui/bubble/bubble_view.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_view.mm
@@ -12,7 +12,7 @@
 #error "This file requires ARC support."
 #endif
 
-const CGFloat kBubbleAlignmentOffset = 25.0f;
+const CGFloat kBubbleAlignmentOffset = 26.0f;
 
 namespace {
 // The color of the bubble (both circular background and arrow).
@@ -21,7 +21,7 @@
 }
 // The corner radius of the bubble's background, which causes the ends of the
 // badge to be circular.
-const CGFloat kBubbleCornerRadius = 18.0f;
+const CGFloat kBubbleCornerRadius = 17.0f;
 // The minimum bubble width is two times the bubble alignment offset, which
 // causes the bubble to appear center-aligned for short display text.
 const CGFloat kMinBubbleWidth = kBubbleAlignmentOffset * 2;
@@ -44,9 +44,6 @@
 
 // The size that the arrow will appear to have.
 const CGSize kArrowSize = {14.0f, 10.0f};
-// The factor by which the arrow's size is scaled. Drawing the arrow larger than
-// its desired size prevents gaps between the arrow and the background view.
-const CGFloat kArrowScaleFactor = 1.5f;
 
 // The offset of the bubble's drop shadow, which will be slightly below the
 // bubble.
@@ -112,10 +109,8 @@
   // If the instance variable for the arrow has not been set up, load the arrow
   // and set the instance variable equal to the arrow.
   if (!_arrow) {
-    // Draw the arrow slightly larger than the desired size in order to prevent
-    // gaps between the background view and the arrow.
-    CGFloat width = kArrowSize.width * kArrowScaleFactor;
-    CGFloat height = kArrowSize.height * kArrowScaleFactor;
+    CGFloat width = kArrowSize.width;
+    CGFloat height = kArrowSize.height;
     UIView* arrow =
         [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, width, height)];
     UIBezierPath* path = UIBezierPath.bezierPath;
@@ -211,10 +206,8 @@
         constraintEqualToAnchor:self.background.centerYAnchor],
     // Enforce the arrow's size, scaling by |kArrowScaleFactor| to prevent gaps
     // between the arrow and the background view.
-    [self.arrow.widthAnchor
-        constraintEqualToConstant:kArrowSize.width * kArrowScaleFactor],
-    [self.arrow.heightAnchor
-        constraintEqualToConstant:kArrowSize.height * kArrowScaleFactor]
+    [self.arrow.widthAnchor constraintEqualToConstant:kArrowSize.width],
+    [self.arrow.heightAnchor constraintEqualToConstant:kArrowSize.height]
 
   ];
   return constraints;
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm
index 9f9d756..11ed70fe 100644
--- a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm
@@ -6,6 +6,7 @@
 
 #import "base/ios/block_types.h"
 #include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
 #include "ios/chrome/browser/ui/bubble/bubble_util.h"
 #import "ios/chrome/browser/ui/bubble/bubble_view_controller.h"
 
@@ -21,6 +22,29 @@
 // after the bubble first becomes visible.
 const NSTimeInterval kBubbleEngagementDuration = 30.0;
 
+// The name for the histogram that tracks why a bubble was dismissed.
+const char kBubbleDismissalHistogramName[] = "IOS.IPHBubbleDismissalReason";
+
+// Reasosn for why a bubble is dismissed. This enum backs a histogram, and
+// therefore entries should not be renumbered and numeric values should never
+// be reused.
+enum class BubbleDismissalReason {
+  // The dismissal timer dismissed the bubble.
+  kTimerDismissal = 0,
+  // A tap inside the bubble dismissed the bubble.
+  kTapInsideBubble = 1,
+  // A tap outside the bubble dismissed the bubble.
+  kTapOutsideBubble = 2,
+  // The count of entries in the enum.
+  kCount
+};
+
+// Log the reason for why the bubble was dismissed.
+void LogBubbleDismissalReason(BubbleDismissalReason reason) {
+  UMA_HISTOGRAM_ENUMERATION(kBubbleDismissalHistogramName, reason,
+                            BubbleDismissalReason::kCount);
+}
+
 }  // namespace
 
 @interface BubbleViewControllerPresenter ()<UIGestureRecognizerDelegate>
@@ -193,16 +217,19 @@
 
 // Invoked by tapping inside the bubble. Dismisses the bubble.
 - (void)tapInsideBubbleRecognized:(id)sender {
+  LogBubbleDismissalReason(BubbleDismissalReason::kTapInsideBubble);
   [self dismissAnimated:YES];
 }
 
 // Invoked by tapping outside the bubble. Dismisses the bubble.
 - (void)tapOutsideBubbleRecognized:(id)sender {
+  LogBubbleDismissalReason(BubbleDismissalReason::kTapOutsideBubble);
   [self dismissAnimated:YES];
 }
 
 // Automatically dismisses the bubble view when |bubbleDismissalTimer| fires.
 - (void)bubbleDismissalTimerFired:(id)sender {
+  LogBubbleDismissalReason(BubbleDismissalReason::kTimerDismissal);
   [self dismissAnimated:YES];
 }
 
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm b/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm
index ae88d60..2532b6f 100644
--- a/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm
@@ -46,7 +46,7 @@
   CGSize bubbleSize = [bubble sizeThatFits:maxSize_];
   // Since the label is shorter than the minimum line width, expect the bubble
   // to be the minimum width and accommodate one line of text.
-  EXPECT_NEAR(50.0f, bubbleSize.width, 1.0f);
+  EXPECT_NEAR(52.0f, bubbleSize.width, 1.0f);
   EXPECT_NEAR(53.5f, bubbleSize.height, 1.0f);
 }
 
@@ -57,7 +57,7 @@
                                               alignment:alignment_];
   CGSize bubbleSize = [bubble sizeThatFits:maxSize_];
   // The bubble should fit the label, which contains two lines of text.
-  EXPECT_NEAR(341.0f, bubbleSize.width, 1.0f);
+  EXPECT_NEAR(339.0f, bubbleSize.width, 1.0f);
   EXPECT_NEAR(72.5f, bubbleSize.height, 1.0f);
 }
 
diff --git a/ios/chrome/browser/ui/fullscreen/BUILD.gn b/ios/chrome/browser/ui/fullscreen/BUILD.gn
index c9bb9fc..8186228 100644
--- a/ios/chrome/browser/ui/fullscreen/BUILD.gn
+++ b/ios/chrome/browser/ui/fullscreen/BUILD.gn
@@ -39,6 +39,21 @@
   ]
 }
 
+source_set("new_fullscreen_coordinators") {
+  sources = [
+    "chrome_coordinator+fullscreen_disabling.h",
+    "chrome_coordinator+fullscreen_disabling.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  deps = [
+    ":new_fullscreen",
+    "//base",
+    "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
+  ]
+}
+
 source_set("new_fullscreen_internal") {
   sources = [
     "fullscreen_controller_factory.mm",
diff --git a/ios/chrome/browser/ui/fullscreen/chrome_coordinator+fullscreen_disabling.h b/ios/chrome/browser/ui/fullscreen/chrome_coordinator+fullscreen_disabling.h
new file mode 100644
index 0000000..688df7a
--- /dev/null
+++ b/ios/chrome/browser/ui/fullscreen/chrome_coordinator+fullscreen_disabling.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 IOS_CHROME_BROWSER_UI_FULLSCREEN_CHROME_COORDINATOR_FULLSCREEN_DISABLING_H_
+#define IOS_CHROME_BROWSER_UI_FULLSCREEN_CHROME_COORDINATOR_FULLSCREEN_DISABLING_H_
+
+#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
+
+// A ChromeCoordinator category that handles disabling fullscreen calculations
+// while a coordinator has been started.
+@interface ChromeCoordinator (FullscreenDisabling)
+
+// Increments and decrements the fullscreen disable counter for the
+// FullscreenController associated with this coordinator's ChromeBrowserState.
+- (void)didStartFullscreenDisablingUI;
+- (void)didStopFullscreenDisablingUI;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_FULLSCREEN_CHROME_COORDINATOR_FULLSCREEN_DISABLING_H_
diff --git a/ios/chrome/browser/ui/fullscreen/chrome_coordinator+fullscreen_disabling.mm b/ios/chrome/browser/ui/fullscreen/chrome_coordinator+fullscreen_disabling.mm
new file mode 100644
index 0000000..66cb81a
--- /dev/null
+++ b/ios/chrome/browser/ui/fullscreen/chrome_coordinator+fullscreen_disabling.mm
@@ -0,0 +1,106 @@
+// 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 "ios/chrome/browser/ui/fullscreen/chrome_coordinator+fullscreen_disabling.h"
+
+#import <objc/runtime.h>
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h"
+#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.h"
+#import "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// The key under which ScopedFullscreenDisablerWrapper are associated with their
+// ChromeCoordinators.
+const void* const kFullscreenDisablerKey = &kFullscreenDisablerKey;
+}
+
+#pragma mark - ScopedFullscreenDisablerWrapper
+
+// A wrapper object for ScopedFullscreenDisablers.
+@interface ScopedFullscreenDisablerWrapper : NSObject {
+  // The disabler that prevents the toolbar from being hidden while the
+  // coordinator's UI is started.
+  std::unique_ptr<ScopedFullscreenDisabler> _disabler;
+}
+
+// The FullscreenController being disabled.
+@property(nonatomic, readonly) FullscreenController* controller;
+
+// Factory method that returns the disabler wrapper associated with
+// |coordinator|, lazily instantiating it if necessary.
++ (instancetype)wrapperForCoordinator:(ChromeCoordinator*)coordinator;
+
+// Initializer for a wrapper that disables |controller|.
+- (instancetype)initWithFullscreenController:(FullscreenController*)controller
+    NS_DESIGNATED_INITIALIZER;
+- (instancetype)init NS_UNAVAILABLE;
+
+// Creates and resets the diabler.
+- (void)createDisabler;
+- (void)resetDisabler;
+
+@end
+
+@implementation ScopedFullscreenDisablerWrapper
+@synthesize controller = _controller;
+
++ (instancetype)wrapperForCoordinator:(ChromeCoordinator*)coordinator {
+  // ChromeCoordinators that need to disable fullscreen must be initialized with
+  // a ChromeBrowserState.
+  ios::ChromeBrowserState* browserState = coordinator.browserState;
+  DCHECK(browserState);
+  // Fetch the associated wrapper.
+  ScopedFullscreenDisablerWrapper* wrapper =
+      objc_getAssociatedObject(coordinator, kFullscreenDisablerKey);
+  if (!wrapper) {
+    FullscreenController* controller =
+        FullscreenControllerFactory::GetInstance()->GetForBrowserState(
+            browserState);
+    wrapper = [[ScopedFullscreenDisablerWrapper alloc]
+        initWithFullscreenController:controller];
+    objc_setAssociatedObject(coordinator, kFullscreenDisablerKey, wrapper,
+                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+  }
+  DCHECK(wrapper);
+  return wrapper;
+}
+
+- (instancetype)initWithFullscreenController:(FullscreenController*)controller {
+  if (self = [super init]) {
+    _controller = controller;
+    DCHECK(_controller);
+  }
+  return self;
+}
+
+- (void)createDisabler {
+  _disabler = base::MakeUnique<ScopedFullscreenDisabler>(self.controller);
+}
+
+- (void)resetDisabler {
+  _disabler = nullptr;
+}
+
+@end
+
+#pragma mark - ChromeCoordinator
+
+@implementation ChromeCoordinator (FullscreenDisabling)
+
+- (void)didStartFullscreenDisablingUI {
+  [[ScopedFullscreenDisablerWrapper wrapperForCoordinator:self] createDisabler];
+}
+
+- (void)didStopFullscreenDisablingUI {
+  [[ScopedFullscreenDisablerWrapper wrapperForCoordinator:self] resetDisabler];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/payments/payment_request_manager.mm b/ios/chrome/browser/ui/payments/payment_request_manager.mm
index fa45823..0afe825 100644
--- a/ios/chrome/browser/ui/payments/payment_request_manager.mm
+++ b/ios/chrome/browser/ui/payments/payment_request_manager.mm
@@ -387,6 +387,10 @@
   DCHECK(_pendingPaymentRequest->state() ==
          payments::PaymentRequest::State::INTERACTIVE);
 
+  [_unblockEventQueueTimer invalidate];
+  [_paymentResponseTimeoutTimer invalidate];
+  [_updateEventTimeoutTimer invalidate];
+
   [self resetIOSPaymentInstrumentLauncherDelegate];
 
   __weak PaymentRequestManager* weakSelf = self;
@@ -661,10 +665,6 @@
     return YES;
   }
 
-  [_unblockEventQueueTimer invalidate];
-  [_paymentResponseTimeoutTimer invalidate];
-  [_updateEventTimeoutTimer invalidate];
-
   __weak PaymentRequestManager* weakSelf = self;
   ProceduralBlockWithBool cancellationCallback = ^(BOOL) {
     [[weakSelf paymentRequestJsManager]
@@ -755,10 +755,6 @@
     return YES;
   }
 
-  [_unblockEventQueueTimer invalidate];
-  [_paymentResponseTimeoutTimer invalidate];
-  [_updateEventTimeoutTimer invalidate];
-
   __weak PaymentRequestManager* weakSelf = self;
   ProceduralBlock callback = ^{
     [weakSelf abortPendingRequestWithReason:payments::JourneyLogger::
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 2ca8b1b..ce4853b6d 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
@@ -24,6 +24,7 @@
 #include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
+#import "ios/chrome/browser/ui/authentication/signin_promo_view_configurator.h"
 #import "ios/chrome/browser/ui/authentication/signin_promo_view_consumer.h"
 #import "ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h"
 #include "ios/chrome/browser/ui/commands/application_commands.h"
@@ -103,7 +104,8 @@
                                     TabSwitcherViewDelegate,
                                     TabSwitcherHeaderViewDelegate,
                                     TabSwitcherHeaderViewDataSource,
-                                    TabSwitcherPanelControllerDelegate> {
+                                    TabSwitcherPanelControllerDelegate,
+                                    TabSwitcherPanelOverlayViewDelegate> {
   // weak.
   ios::ChromeBrowserState* _browserState;
   // weak.
@@ -1048,24 +1050,29 @@
   _signInPanelType = panelType;
   DCHECK_EQ(nil, _signInPanelOverlayView);
   if (panelType != TabSwitcherSignInPanelsType::NO_PANEL) {
-    TabSwitcherPanelOverlayView* panelView =
-        [[TabSwitcherPanelOverlayView alloc]
-            initWithFrame:CGRectZero
-             browserState:_browserState
-                presenter:self /* id<SigninPresenter, SyncPresenter> */
-               dispatcher:self.dispatcher];
-    _signInPanelOverlayView = panelView;
+    _signInPanelOverlayView = [[TabSwitcherPanelOverlayView alloc]
+        initWithFrame:CGRectZero
+         browserState:_browserState
+            presenter:self /* id<SigninPresenter, SyncPresenter> */
+           dispatcher:self.dispatcher];
+    [_signInPanelOverlayView
+        setOverlayType:PanelOverlayTypeFromSignInPanelsType(panelType)];
+    _signInPanelOverlayView.delegate = self;
     if (panelType == TabSwitcherSignInPanelsType::PANEL_USER_SIGNED_OUT) {
+      DCHECK_NE(nil, _signInPanelOverlayView.signinPromoView);
       _signinPromoViewMediator = [[SigninPromoViewMediator alloc]
           initWithBrowserState:_browserState
                    accessPoint:signin_metrics::AccessPoint::
                                    ACCESS_POINT_TAB_SWITCHER
                      presenter:self];
       _signinPromoViewMediator.consumer = self;
-      panelView.signinPromoViewMediator = _signinPromoViewMediator;
+      _signInPanelOverlayView.signinPromoView.delegate =
+          _signinPromoViewMediator;
+      [[_signinPromoViewMediator createConfigurator]
+          configureSigninPromoView:_signInPanelOverlayView.signinPromoView];
     }
-    [panelView setOverlayType:PanelOverlayTypeFromSignInPanelsType(panelType)];
-    [_tabSwitcherView addPanelView:panelView atIndex:kSignInPromoPanelIndex];
+    [_tabSwitcherView addPanelView:_signInPanelOverlayView
+                           atIndex:kSignInPromoPanelIndex];
   }
 }
 
@@ -1307,14 +1314,26 @@
 - (void)configureSigninPromoWithConfigurator:
             (SigninPromoViewConfigurator*)configurator
                              identityChanged:(BOOL)identityChanged {
-  DCHECK(nil != _signInPanelOverlayView);
-  [_signInPanelOverlayView
-      configureSigninPromoWithConfigurator:configurator
-                           identityChanged:identityChanged];
+  DCHECK_NE(nil, _signInPanelOverlayView);
+  DCHECK_NE(nil, _signInPanelOverlayView.signinPromoView);
+  [configurator
+      configureSigninPromoView:_signInPanelOverlayView.signinPromoView];
 }
 
 - (void)signinDidFinish {
   [_tabSwitcherModel syncedSessionsChanged];
 }
 
+#pragma mark - TabSwitcherPanelOverlayViewDelegate
+
+- (void)tabSwitcherPanelOverlViewWasShown:
+    (TabSwitcherPanelOverlayView*)tabSwitcherPanelOverlayView {
+  [_signinPromoViewMediator signinPromoViewVisible];
+}
+
+- (void)tabSwitcherPanelOverlViewWasHidden:
+    (TabSwitcherPanelOverlayView*)tabSwitcherPanelOverlayView {
+  [_signinPromoViewMediator signinPromoViewHidden];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.h b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.h
index 257b3737..e224978 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.h
@@ -10,9 +10,9 @@
 @protocol ApplicationCommands;
 @protocol BrowserCommands;
 @protocol SigninPresenter;
-@class SigninPromoViewConfigurator;
-@class SigninPromoViewMediator;
+@class SigninPromoView;
 @protocol SyncPresenter;
+@class TabSwitcherPanelOverlayView;
 
 namespace ios {
 class ChromeBrowserState;
@@ -33,6 +33,18 @@
 TabSwitcherPanelOverlayType PanelOverlayTypeFromSignInPanelsType(
     TabSwitcherSignInPanelsType signInPanelType);
 
+// Delegate protocol for TabSwitcherPanelOverlayView.
+@protocol TabSwitcherPanelOverlayViewDelegate<NSObject>
+
+// Called when TabSwitcherPanelOverlayView is shown.
+- (void)tabSwitcherPanelOverlViewWasShown:
+    (TabSwitcherPanelOverlayView*)tabSwitcherPanelOverlayView;
+// Called when TabSwitcherPanelOverlayView is hidden.
+- (void)tabSwitcherPanelOverlViewWasHidden:
+    (TabSwitcherPanelOverlayView*)tabSwitcherPanelOverlayView;
+
+@end
+
 @interface TabSwitcherPanelOverlayView : UIView
 
 @property(nonatomic, assign) TabSwitcherPanelOverlayType overlayType;
@@ -40,7 +52,11 @@
     presenter;
 @property(nonatomic, readonly, weak) id<ApplicationCommands, BrowserCommands>
     dispatcher;
-@property(nonatomic) SigninPromoViewMediator* signinPromoViewMediator;
+// Sign-in promo view. Nil if the |overlayType| is not
+// |OVERLAY_PANEL_USER_SIGNED_OUT|.
+@property(nonatomic, readonly) SigninPromoView* signinPromoView;
+// Delegate, can be nil.
+@property(nonatomic, weak) id<TabSwitcherPanelOverlayViewDelegate> delegate;
 
 - (instancetype)initWithFrame:(CGRect)frame
                  browserState:(ios::ChromeBrowserState*)browserState
@@ -48,16 +64,6 @@
                    dispatcher:
                        (id<ApplicationCommands, BrowserCommands>)dispatcher;
 
-// Should be called when the tab switcher was shown.
-- (void)wasShown;
-// Should be called when the tab switcher was hidden.
-- (void)wasHidden;
-
-// Called when the sign-in promo view should be reloaded.
-- (void)configureSigninPromoWithConfigurator:
-            (SigninPromoViewConfigurator*)configurator
-                             identityChanged:(BOOL)identityChanged;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_SWITCHER_PANEL_OVERLAY_VIEW_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.mm
index f63608e..682230b 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.mm
@@ -10,8 +10,6 @@
 #include "components/signin/core/browser/signin_metrics.h"
 #include "ios/chrome/browser/experimental_flags.h"
 #import "ios/chrome/browser/ui/authentication/signin_promo_view.h"
-#import "ios/chrome/browser/ui/authentication/signin_promo_view_configurator.h"
-#import "ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h"
 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
@@ -88,7 +86,8 @@
 @synthesize overlayType = _overlayType;
 @synthesize presenter = _presenter;
 @synthesize dispatcher = _dispatcher;
-@synthesize signinPromoViewMediator = _signinPromoViewMediator;
+@synthesize signinPromoView = _signinPromoView;
+@synthesize delegate = _delegate;
 
 - (instancetype)initWithFrame:(CGRect)frame
                  browserState:(ios::ChromeBrowserState*)browserState
@@ -218,26 +217,17 @@
 }
 
 - (void)wasShown {
-  [_signinPromoViewMediator signinPromoViewVisible];
+  [self.delegate tabSwitcherPanelOverlViewWasShown:self];
 }
 
 - (void)wasHidden {
-  [_signinPromoViewMediator signinPromoViewHidden];
-}
-
-- (void)configureSigninPromoWithConfigurator:
-            (SigninPromoViewConfigurator*)configurator
-                             identityChanged:(BOOL)identityChanged {
-  DCHECK(_signinPromoView);
-  DCHECK(_signinPromoViewMediator);
-  [configurator configureSigninPromoView:_signinPromoView];
+  [self.delegate tabSwitcherPanelOverlViewWasHidden:self];
 }
 
 #pragma mark - Private
 
 // Creates the sign-in view and its mediator if it doesn't exist.
 - (void)createSigninPromoViewIfNeeded {
-  DCHECK(_signinPromoViewMediator);
   if (_signinPromoView)
     return;
   _signinPromoView = [[SigninPromoView alloc] initWithFrame:CGRectZero];
@@ -258,13 +248,10 @@
       constraintEqualToAnchor:self.centerYAnchor
                      constant:kContainerOriginYOffset]
       .active = YES;
-  _signinPromoView.delegate = _signinPromoViewMediator;
-  [[_signinPromoViewMediator createConfigurator]
-      configureSigninPromoView:_signinPromoView];
 }
 
 - (void)updateText {
-  DCHECK(_signinPromoView == nil && _signinPromoViewMediator == nil);
+  DCHECK(_signinPromoView == nil);
   NSMutableAttributedString* titleString = nil;
   NSMutableAttributedString* subtitleString = nil;
 
@@ -393,7 +380,7 @@
 }
 
 - (void)updateButtonTarget {
-  DCHECK(_signinPromoView == nil && _signinPromoViewMediator == nil);
+  DCHECK(_signinPromoView == nil);
   NSInteger tag = 0;
   SEL selector = nil;
   _recordedMetricString = "";
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_mediator.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_mediator.mm
index 913c950d..cf49258 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_mediator.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_mediator.mm
@@ -92,6 +92,12 @@
 }
 
 - (void)webState:(web::WebState*)webState
+    didFinishNavigation:(web::NavigationContext*)navigation {
+  DCHECK_EQ(_webState, webState);
+  [self updateConsumer];
+}
+
+- (void)webState:(web::WebState*)webState
     didPruneNavigationItemsWithCount:(size_t)pruned_item_count {
   DCHECK_EQ(_webState, webState);
   [self updateConsumer];
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_mediator_unittest.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_mediator_unittest.mm
index e75f4fc..358f2ecb 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_mediator_unittest.mm
@@ -19,6 +19,7 @@
 #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
 #import "ios/chrome/browser/web_state_list/web_state_opener.h"
 #import "ios/public/provider/chrome/browser/voice/voice_search_provider.h"
+#import "ios/web/public/test/fakes/fake_navigation_context.h"
 #import "ios/web/public/test/fakes/test_navigation_manager.h"
 #import "ios/web/public/test/fakes/test_web_state.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
@@ -358,6 +359,28 @@
 }
 
 // Test the Toolbar is updated when the Webstate observer method
+// didFinishNavigation is called.
+TEST_F(ToolbarMediatorTest, TestDidFinishNavigation) {
+  SetUpBookmarks();
+  mediator_.webStateList = web_state_list_.get();
+  SetUpActiveWebState();
+  mediator_.consumer = consumer_;
+  mediator_.bookmarkModel = bookmark_model_;
+
+  navigation_manager_->set_can_go_forward(true);
+  navigation_manager_->set_can_go_back(true);
+
+  web_state_->SetCurrentURL(GURL(kTestUrl));
+  web::FakeNavigationContext context;
+  web_state_->OnNavigationFinished(&context);
+
+  [[consumer_ verify] setCanGoForward:YES];
+  [[consumer_ verify] setCanGoBack:YES];
+  [[consumer_ verify] setPageBookmarked:YES];
+  [[consumer_ verify] setShareMenuEnabled:YES];
+}
+
+// Test the Toolbar is updated when the Webstate observer method
 // didChangeLoadingProgress is called.
 TEST_F(ToolbarMediatorTest, TestLoadingProgress) {
   mediator_.webStateList = web_state_list_.get();
diff --git a/ios/chrome/content_widget_extension/content_widget_view_controller.mm b/ios/chrome/content_widget_extension/content_widget_view_controller.mm
index cfa82e7..3d55176 100644
--- a/ios/chrome/content_widget_extension/content_widget_view_controller.mm
+++ b/ios/chrome/content_widget_extension/content_widget_view_controller.mm
@@ -24,7 +24,6 @@
 // cannot be used. This class makes a very basic use of x-callback-url, so no
 // full implementation is required.
 NSString* const kXCallbackURLHost = @"x-callback-url";
-const CGFloat widgetCompactHeightIOS9 = 110;
 }  // namespace
 
 @interface ContentWidgetViewController ()<ContentWidgetViewDelegate>
@@ -51,10 +50,9 @@
 #pragma mark - properties
 
 - (BOOL)isCompact {
-  if (@available(iOS 10, *)) {
-    return [self.extensionContext widgetActiveDisplayMode] ==
-           NCWidgetDisplayModeCompact;
-  }
+  DCHECK(self.extensionContext);
+  return [self.extensionContext widgetActiveDisplayMode] ==
+         NCWidgetDisplayModeCompact;
   return NO;
 }
 
@@ -62,25 +60,16 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
+  DCHECK(self.extensionContext);
+  CGFloat height =
+      [self.extensionContext
+          widgetMaximumSizeForDisplayMode:NCWidgetDisplayModeCompact]
+          .height;
 
-  CGFloat height = widgetCompactHeightIOS9;
-  if (@available(iOS 10, *)) {
-    if (self.extensionContext) {
-      height = [self.extensionContext
-                   widgetMaximumSizeForDisplayMode:NCWidgetDisplayModeCompact]
-                   .height;
-    }
-  }
-
-  // On the today view <iOS10, the full screen size is useable.
-  CGFloat width = [UIScreen mainScreen].bounds.size.width;
-  if (@available(iOS 10, *)) {
-    if (self.extensionContext) {
-      width = [self.extensionContext
-                  widgetMaximumSizeForDisplayMode:NCWidgetDisplayModeCompact]
-                  .width;
-    }
-  }
+  CGFloat width =
+      [self.extensionContext
+          widgetMaximumSizeForDisplayMode:NCWidgetDisplayModeCompact]
+          .width;
 
   // A local variable is necessary here as the property is declared weak and the
   // object would be deallocated before being retained by the addSubview call.
@@ -91,12 +80,8 @@
   self.widgetView = widgetView;
   [self.view addSubview:self.widgetView];
 
-  if (@available(iOS 10, *)) {
-    self.extensionContext.widgetLargestAvailableDisplayMode =
-        NCWidgetDisplayModeExpanded;
-  } else {
-    [self setExpanded:[[UIScreen mainScreen] bounds].size];
-  }
+  self.extensionContext.widgetLargestAvailableDisplayMode =
+      NCWidgetDisplayModeExpanded;
 
   self.widgetView.translatesAutoresizingMaskIntoConstraints = NO;
   AddSameConstraints(self.widgetView, self.view);
@@ -146,15 +131,6 @@
   }
 }
 
-// Implementing this method removes the leading edge inset for iOS version < 10.
-// TODO(crbug.com/720490): Remove implementation when dropping ios9 support.
-#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
-- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:
-    (UIEdgeInsets)defaultMa‌​rginInsets {
-  return UIEdgeInsetsZero;
-}
-#endif
-
 #pragma mark - internal
 
 - (void)setExpanded:(CGSize)maxSize {
diff --git a/ios/chrome/content_widget_extension/most_visited_tile_view.mm b/ios/chrome/content_widget_extension/most_visited_tile_view.mm
index 658d2f4..f5d38fab 100644
--- a/ios/chrome/content_widget_extension/most_visited_tile_view.mm
+++ b/ios/chrome/content_widget_extension/most_visited_tile_view.mm
@@ -39,15 +39,8 @@
 - (instancetype)init {
   self = [super initWithFrame:CGRectZero];
   if (self) {
-    UIVibrancyEffect* labelEffect;
-    if (@available(iOS 10, *)) {
-      labelEffect = [UIVibrancyEffect widgetSecondaryVibrancyEffect];
-    }
-#if !defined(__IPHONE_10_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
-    else {
-      labelEffect = [UIVibrancyEffect notificationCenterVibrancyEffect];
-    }
-#endif
+    UIVibrancyEffect* labelEffect =
+        [UIVibrancyEffect widgetSecondaryVibrancyEffect];
 
     UIVisualEffectView* titleLabelEffectView =
         [[UIVisualEffectView alloc] initWithEffect:labelEffect];
diff --git a/ios/chrome/search_widget_extension/copied_url_view.mm b/ios/chrome/search_widget_extension/copied_url_view.mm
index 2330062..a231e1b9 100644
--- a/ios/chrome/search_widget_extension/copied_url_view.mm
+++ b/ios/chrome/search_widget_extension/copied_url_view.mm
@@ -67,18 +67,10 @@
                   action:actionSelector
         forControlEvents:UIControlEventTouchUpInside];
 
-    UIVibrancyEffect* primaryEffect;
-    UIVibrancyEffect* secondaryEffect;
-    if (@available(iOS 10, *)) {
-      primaryEffect = [UIVibrancyEffect widgetPrimaryVibrancyEffect];
-      secondaryEffect = [UIVibrancyEffect widgetSecondaryVibrancyEffect];
-    }
-#if !defined(__IPHONE_10_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
-    else {
-      primaryEffect = [UIVibrancyEffect notificationCenterVibrancyEffect];
-      secondaryEffect = [UIVibrancyEffect notificationCenterVibrancyEffect];
-    }
-#endif
+    UIVibrancyEffect* primaryEffect =
+        [UIVibrancyEffect widgetPrimaryVibrancyEffect];
+    UIVibrancyEffect* secondaryEffect =
+        [UIVibrancyEffect widgetSecondaryVibrancyEffect];
 
     UIVisualEffectView* primaryEffectView =
         [[UIVisualEffectView alloc] initWithEffect:primaryEffect];
@@ -94,9 +86,7 @@
     }
 
     _hairlineView = [[UIView alloc] initWithFrame:CGRectZero];
-    _hairlineView.backgroundColor = base::ios::IsRunningOnIOS10OrLater()
-                                        ? [UIColor colorWithWhite:0 alpha:0.05]
-                                        : [UIColor whiteColor];
+    _hairlineView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.05];
     _hairlineView.translatesAutoresizingMaskIntoConstraints = NO;
     [secondaryEffectView.contentView addSubview:_hairlineView];
 
@@ -193,10 +183,8 @@
   self.accessibilityLabel =
       NSLocalizedString(@"IDS_IOS_NO_COPIED_LINK_TITLE", nil);
   self.accessibilityTraits = UIAccessibilityTraitNone;
-  if (base::ios::IsRunningOnIOS10OrLater()) {
-    self.copiedURLLabel.alpha = 0.5;
-    self.openCopiedURLTitleLabel.alpha = 0.5;
-  }
+  self.copiedURLLabel.alpha = 0.5;
+  self.openCopiedURLTitleLabel.alpha = 0.5;
 }
 
 @end
diff --git a/ios/chrome/search_widget_extension/search_action_view.mm b/ios/chrome/search_widget_extension/search_action_view.mm
index 8c0d031..f0bbc95 100644
--- a/ios/chrome/search_widget_extension/search_action_view.mm
+++ b/ios/chrome/search_widget_extension/search_action_view.mm
@@ -31,19 +31,10 @@
   if (self) {
     self.translatesAutoresizingMaskIntoConstraints = NO;
 
-    UIVibrancyEffect* primaryEffect;
-    UIVibrancyEffect* secondaryEffect;
-    if (@available(iOS 10, *)) {
-      primaryEffect = [UIVibrancyEffect widgetPrimaryVibrancyEffect];
-      secondaryEffect = [UIVibrancyEffect widgetSecondaryVibrancyEffect];
-    }
-#if !defined(__IPHONE_10_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
-    else {
-      primaryEffect = [UIVibrancyEffect notificationCenterVibrancyEffect];
-      secondaryEffect = [UIVibrancyEffect notificationCenterVibrancyEffect];
-    }
-#endif  // !defined(__IPHONE_10_0) || __IPHONE_OS_VERSION_MIN_REQUIRED <
-        // __IPHONE_10_0
+    UIVibrancyEffect* primaryEffect =
+        [UIVibrancyEffect widgetPrimaryVibrancyEffect];
+    UIVibrancyEffect* secondaryEffect =
+        [UIVibrancyEffect widgetSecondaryVibrancyEffect];
 
     UIVisualEffectView* primaryEffectView =
         [[UIVisualEffectView alloc] initWithEffect:primaryEffect];
@@ -59,11 +50,7 @@
     }
 
     UIView* circleView = [[UIView alloc] initWithFrame:CGRectZero];
-    if (@available(iOS 10, *)) {
-      circleView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.05];
-    } else {
-      circleView.backgroundColor = [UIColor whiteColor];
-    }
+    circleView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.05];
     circleView.layer.cornerRadius = kActionButtonSize / 2;
 
     UILabel* labelView = [[UILabel alloc] initWithFrame:CGRectZero];
@@ -86,18 +73,12 @@
     [NSLayoutConstraint activateConstraints:ui_util::CreateSameConstraints(
                                                 secondaryEffectView, stack)];
     UIImage* iconImage = [UIImage imageNamed:imageName];
-    if (@available(iOS 10, *)) {
-      iconImage =
-          [iconImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
-    }
+    iconImage =
+        [iconImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
 
     UIImageView* icon = [[UIImageView alloc] initWithImage:iconImage];
     icon.translatesAutoresizingMaskIntoConstraints = NO;
-    if (@available(iOS 10, *)) {
-      [primaryEffectView.contentView addSubview:icon];
-    } else {
-      [self addSubview:icon];
-    }
+    [primaryEffectView.contentView addSubview:icon];
 
     [NSLayoutConstraint activateConstraints:@[
       [circleView.widthAnchor constraintEqualToConstant:kActionButtonSize],
diff --git a/ios/chrome/search_widget_extension/search_widget_view_controller.mm b/ios/chrome/search_widget_extension/search_widget_view_controller.mm
index 4142616..4fe56774 100644
--- a/ios/chrome/search_widget_extension/search_widget_view_controller.mm
+++ b/ios/chrome/search_widget_extension/search_widget_view_controller.mm
@@ -71,15 +71,12 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
+  DCHECK(self.extensionContext);
 
-  CGFloat height = 110;
-  if (@available(iOS 10, *)) {
-    if (self.extensionContext) {
-      height = [self.extensionContext
-                   widgetMaximumSizeForDisplayMode:NCWidgetDisplayModeCompact]
-                   .height;
-    }
-  }
+  CGFloat height =
+      [self.extensionContext
+          widgetMaximumSizeForDisplayMode:NCWidgetDisplayModeCompact]
+          .height;
 
   // A local variable is necessary here as the property is declared weak and the
   // object would be deallocated before being retained by the addSubview call.
@@ -89,14 +86,8 @@
   [self.view addSubview:self.widgetView];
   [self updateWidget];
 
-  if (@available(iOS 10, *)) {
-    self.extensionContext.widgetLargestAvailableDisplayMode =
-        NCWidgetDisplayModeExpanded;
-  } else {
-    self.preferredContentSize =
-        CGSizeMake([[UIScreen mainScreen] bounds].size.width,
-                   [self.widgetView widgetHeight]);
-  }
+  self.extensionContext.widgetLargestAvailableDisplayMode =
+      NCWidgetDisplayModeExpanded;
 
   self.widgetView.translatesAutoresizingMaskIntoConstraints = NO;
 
@@ -110,11 +101,8 @@
 
   // |widgetActiveDisplayMode| does not contain a valid value in viewDidLoad. By
   // the time viewWillAppear is called, it is correct, so set the mode here.
-  BOOL initiallyCompact = NO;
-  if (@available(iOS 10, *)) {
-    initiallyCompact = [self.extensionContext widgetActiveDisplayMode] ==
-                       NCWidgetDisplayModeCompact;
-  }
+  BOOL initiallyCompact = [self.extensionContext widgetActiveDisplayMode] ==
+                          NCWidgetDisplayModeCompact;
   [self.widgetView showMode:initiallyCompact];
 }
 
@@ -171,15 +159,6 @@
   }
 }
 
-// Implementing this method removes the leading edge inset for iOS version < 10.
-// TODO(crbug.com/720490): Remove implementation when dropping ios9 support.
-#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0
-- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:
-    (UIEdgeInsets)defaultMa‌​rginInsets {
-  return UIEdgeInsetsZero;
-}
-#endif
-
 #pragma mark - SearchWidgetViewActionTarget
 
 - (void)openSearch:(id)sender {
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium
index 7c4548d5..33efd4d2 100644
--- a/ios/third_party/material_components_ios/README.chromium
+++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@
 Name: Material Components for iOS
 URL: https://github.com/material-components/material-components-ios
 Version: 0
-Revision: e4ef28e6796430e550023be60ff58d6418b40a49
+Revision: 7e090434dde5009a693101a63864ab47b895e87f
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/ios/third_party/motion_animator_objc/README.chromium b/ios/third_party/motion_animator_objc/README.chromium
index 20d2547..cd967df 100644
--- a/ios/third_party/motion_animator_objc/README.chromium
+++ b/ios/third_party/motion_animator_objc/README.chromium
@@ -1,7 +1,7 @@
 Name: Motion Animator for Objective-C
 URL: https://github.com/material-motion/motion-animator-objc
 Version: 0
-Revision: 213bfb3a75018c49a223bf1269f6a48fbbfc3a12
+Revision: ff39ecc69fdee46d388cc9f882201d54c3d5039c
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
@@ -11,4 +11,4 @@
 into animations.
 
 Local Modifications:
-None
+None
\ No newline at end of file
diff --git a/ios/web/web_state/js/context_menu_js_unittest.mm b/ios/web/web_state/js/context_menu_js_unittest.mm
index 2039507..2ca3ca2c 100644
--- a/ios/web/web_state/js/context_menu_js_unittest.mm
+++ b/ios/web/web_state/js/context_menu_js_unittest.mm
@@ -248,7 +248,13 @@
 
 // Tests that getElementFromPoint finds an element at the bottom of a very long
 // page.
-TEST_F(ContextMenuJsTest, FLAKY_LinkOfTextFromTallPage) {
+// TODO(crbug.com/796418): This test is flaky on devices.
+#if TARGET_IPHONE_SIMULATOR
+#define MAYBE_LinkOfTextFromTallPage LinkOfTextFromTallPage
+#else
+#define MAYBE_LinkOfTextFromTallPage FLAKY_LinkOfTextFromTallPage
+#endif
+TEST_F(ContextMenuJsTest, MAYBE_LinkOfTextFromTallPage) {
   const char kHtml[] =
       "<html><body>"
       " <div style='height:4000px'></div>"
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index ebfbcf9..6316835 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -146,6 +146,10 @@
 // Key of UMA IOSFix.ViewportZoomBugCount histogram.
 const char kUMAViewportZoomBugCount[] = "Renderer.ViewportZoomBugCount";
 
+// Key of UMA Renderer.WKWebViewCallbackAfterDestroy histogram.
+const char kUMAWKWebViewCallbackAfterDestroy[] =
+    "Renderer.WKWebViewCallbackAfterDestroy";
+
 // Key of the UMA Navigation.IOSWKWebViewSlowFastBackForward histogram.
 const char kUMAWKWebViewSlowFastBackForwardNavigationKey[] =
     "Navigation.IOSWKWebViewSlowFastBackForward";
@@ -873,6 +877,11 @@
 // NSURLErrorCancelled code should be cancelled.
 - (BOOL)shouldCancelLoadForCancelledError:(NSError*)error;
 
+// This method should be called on receiving WKNavigationDelegate callbacks. It
+// will log a metric if the callback occurs after the reciever has already been
+// closed.
+- (void)didReceiveWebViewNavigationDelegateCallback;
+
 // Sets up WebUI for URL.
 - (void)createWebUIForURL:(const GURL&)URL;
 // Clears WebUI, if one exists.
@@ -3037,6 +3046,12 @@
   return source != NAVIGATION;
 }
 
+- (void)didReceiveWebViewNavigationDelegateCallback {
+  if (_isBeingDestroyed) {
+    UMA_HISTOGRAM_BOOLEAN(kUMAWKWebViewCallbackAfterDestroy, true);
+  }
+}
+
 #pragma mark -
 #pragma mark WebUI
 
@@ -4203,6 +4218,8 @@
     decidePolicyForNavigationAction:(WKNavigationAction*)action
                     decisionHandler:
                         (void (^)(WKNavigationActionPolicy))decisionHandler {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   _webProcessCrashed = NO;
   if (_isBeingDestroyed) {
     decisionHandler(WKNavigationActionPolicyCancel);
@@ -4260,6 +4277,8 @@
     decidePolicyForNavigationResponse:(WKNavigationResponse*)navigationResponse
                       decisionHandler:
                           (void (^)(WKNavigationResponsePolicy))handler {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   GURL responseURL = net::GURLWithNSURL(navigationResponse.response.URL);
 
   // If this is a placeholder navigation, pass through.
@@ -4341,6 +4360,8 @@
 
 - (void)webView:(WKWebView*)webView
     didStartProvisionalNavigation:(WKNavigation*)navigation {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   GURL webViewURL = net::GURLWithNSURL(webView.URL);
 
   // If this is a placeholder URL, there are only two possibilities:
@@ -4443,6 +4464,8 @@
 
 - (void)webView:(WKWebView*)webView
     didReceiveServerRedirectForProvisionalNavigation:(WKNavigation*)navigation {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   GURL webViewURL = net::GURLWithNSURL(webView.URL);
 
   // This callback should never be triggered for placeholder navigations.
@@ -4464,6 +4487,8 @@
 - (void)webView:(WKWebView*)webView
     didFailProvisionalNavigation:(WKNavigation*)navigation
                        withError:(NSError*)error {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   [_navigationStates setState:web::WKNavigationState::PROVISIONALY_FAILED
                 forNavigation:navigation];
 
@@ -4513,6 +4538,8 @@
 
 - (void)webView:(WKWebView*)webView
     didCommitNavigation:(WKNavigation*)navigation {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   // TODO(crbug.com/787497): Always use webView.backForwardList.currentItem.URL
   // to obtain lastCommittedURL once loadHTML: is no longer user for WebUI.
   GURL webViewURL = net::GURLWithNSURL(webView.URL);
@@ -4640,6 +4667,8 @@
 
 - (void)webView:(WKWebView*)webView
     didFinishNavigation:(WKNavigation*)navigation {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   GURL webViewURL = net::GURLWithNSURL(webView.URL);
 
   // If this is a placeholder navigation for an app-specific URL, finish
@@ -4690,6 +4719,8 @@
 - (void)webView:(WKWebView*)webView
     didFailNavigation:(WKNavigation*)navigation
             withError:(NSError*)error {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   // This callback should never be triggered for placeholder navigations.
   if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) {
     DCHECK(!IsPlaceholderUrl(net::GURLWithNSURL(webView.URL)));
@@ -4715,6 +4746,8 @@
                     completionHandler:
                         (void (^)(NSURLSessionAuthChallengeDisposition,
                                   NSURLCredential*))completionHandler {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   // This callback should never be triggered for placeholder navigations.
   DCHECK(!(web::GetWebClient()->IsSlimNavigationManagerEnabled() &&
            IsPlaceholderUrl(net::GURLWithNSURL(webView.URL))));
@@ -4756,6 +4789,8 @@
 }
 
 - (void)webViewWebContentProcessDidTerminate:(WKWebView*)webView {
+  [self didReceiveWebViewNavigationDelegateCallback];
+
   _certVerificationErrors->Clear();
   [self webViewWebProcessDidCrash];
 }
diff --git a/ipc/ipc_channel_mojo.cc b/ipc/ipc_channel_mojo.cc
index 2dafc7b..d7ce34a 100644
--- a/ipc/ipc_channel_mojo.cc
+++ b/ipc/ipc_channel_mojo.cc
@@ -259,6 +259,10 @@
     listener_->OnBadMessageReceived(message);
 }
 
+void ChannelMojo::OnBrokenDataReceived() {
+  listener_->OnBadMessageReceived(Message());
+}
+
 // static
 MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
     Message* message,
diff --git a/ipc/ipc_channel_mojo.h b/ipc/ipc_channel_mojo.h
index 340d80c..aa6ba435 100644
--- a/ipc/ipc_channel_mojo.h
+++ b/ipc/ipc_channel_mojo.h
@@ -89,6 +89,7 @@
   // MessagePipeReader::Delegate
   void OnPeerPidReceived(int32_t peer_pid) override;
   void OnMessageReceived(const Message& message) override;
+  void OnBrokenDataReceived() override;
   void OnPipeError() override;
   void OnAssociatedInterfaceRequest(
       const std::string& name,
diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h
index 8a924e21..d1ea54e 100644
--- a/ipc/ipc_message.h
+++ b/ipc/ipc_message.h
@@ -72,6 +72,8 @@
   Message(const Message& other);
   Message& operator=(const Message& other);
 
+  bool IsValid() const { return header_size() == sizeof(Header) && header(); }
+
   PriorityValue priority() const {
     return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK);
   }
diff --git a/ipc/ipc_message_pipe_reader.cc b/ipc/ipc_message_pipe_reader.cc
index ebc18a3..4a8ca8f 100644
--- a/ipc/ipc_message_pipe_reader.cc
+++ b/ipc/ipc_message_pipe_reader.cc
@@ -50,9 +50,9 @@
 }
 
 bool MessagePipeReader::Send(std::unique_ptr<Message> message) {
+  CHECK(message->IsValid());
   TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
-                         "MessagePipeReader::Send",
-                         message->flags(),
+                         "MessagePipeReader::Send", message->flags(),
                          TRACE_EVENT_FLAG_FLOW_OUT);
   base::Optional<std::vector<mojo::native::SerializedHandlePtr>> handles;
   MojoResult result = MOJO_RESULT_OK;
@@ -87,9 +87,16 @@
 void MessagePipeReader::Receive(
     base::span<const uint8_t> data,
     base::Optional<std::vector<mojo::native::SerializedHandlePtr>> handles) {
-  Message message(
-      data.empty() ? "" : reinterpret_cast<const char*>(data.data()),
-      static_cast<uint32_t>(data.size()));
+  if (data.empty()) {
+    delegate_->OnBrokenDataReceived();
+    return;
+  }
+  Message message(reinterpret_cast<const char*>(data.data()),
+                  static_cast<uint32_t>(data.size()));
+  if (!message.IsValid()) {
+    delegate_->OnBrokenDataReceived();
+    return;
+  }
 
   DVLOG(4) << "Receive " << message.type() << ": " << message.size();
   MojoResult write_result =
diff --git a/ipc/ipc_message_pipe_reader.h b/ipc/ipc_message_pipe_reader.h
index a155dcf..a609f6c 100644
--- a/ipc/ipc_message_pipe_reader.h
+++ b/ipc/ipc_message_pipe_reader.h
@@ -49,6 +49,7 @@
    public:
     virtual void OnPeerPidReceived(int32_t peer_pid) = 0;
     virtual void OnMessageReceived(const Message& message) = 0;
+    virtual void OnBrokenDataReceived() = 0;
     virtual void OnPipeError() = 0;
     virtual void OnAssociatedInterfaceRequest(
         const std::string& name,
diff --git a/ipc/ipc_mojo_bootstrap_unittest.cc b/ipc/ipc_mojo_bootstrap_unittest.cc
index 7bfd77c3..46dca0e 100644
--- a/ipc/ipc_mojo_bootstrap_unittest.cc
+++ b/ipc/ipc_mojo_bootstrap_unittest.cc
@@ -29,12 +29,43 @@
 constexpr int32_t kTestServerPid = 42;
 constexpr int32_t kTestClientPid = 4242;
 
+class Connection {
+ public:
+  explicit Connection(std::unique_ptr<IPC::MojoBootstrap> bootstrap,
+                      int32_t sender_id)
+      : bootstrap_(std::move(bootstrap)) {
+    bootstrap_->Connect(&sender_, &receiver_);
+    sender_->SetPeerPid(sender_id);
+  }
+
+  void TakeReceiver(IPC::mojom::ChannelAssociatedRequest* receiver) {
+    *receiver = std::move(receiver_);
+  }
+
+  IPC::mojom::ChannelAssociatedPtr& GetSender() { return sender_; }
+
+ private:
+  IPC::mojom::ChannelAssociatedPtr sender_;
+  IPC::mojom::ChannelAssociatedRequest receiver_;
+  std::unique_ptr<IPC::MojoBootstrap> bootstrap_;
+};
+
 class PeerPidReceiver : public IPC::mojom::Channel {
  public:
-  PeerPidReceiver(IPC::mojom::ChannelAssociatedRequest request,
-                  const base::Closure& on_peer_pid_set)
-      : binding_(this, std::move(request)), on_peer_pid_set_(on_peer_pid_set) {}
-  ~PeerPidReceiver() override = default;
+  enum class MessageExpectation {
+    kNotExpected,
+    kExpectedValid,
+    kExptectedInvalid
+  };
+
+  PeerPidReceiver(
+      IPC::mojom::ChannelAssociatedRequest request,
+      const base::Closure& on_peer_pid_set,
+      MessageExpectation message_expectation = MessageExpectation::kNotExpected)
+      : binding_(this, std::move(request)),
+        on_peer_pid_set_(on_peer_pid_set),
+        message_expectation_(message_expectation) {}
+  ~PeerPidReceiver() override {}
 
   // mojom::Channel:
   void SetPeerPid(int32_t pid) override {
@@ -44,7 +75,15 @@
 
   void Receive(base::span<const uint8_t> data,
                base::Optional<std::vector<mojo::native::SerializedHandlePtr>>
-                   handles) override {}
+                   handles) override {
+    ASSERT_NE(MessageExpectation::kNotExpected, message_expectation_);
+
+    IPC::Message message(reinterpret_cast<const char*>(data.data()),
+                         static_cast<uint32_t>(data.size()));
+    bool expected_valid =
+        message_expectation_ == MessageExpectation::kExpectedValid;
+    EXPECT_EQ(expected_valid, message.IsValid());
+  }
 
   void GetAssociatedInterface(
       const std::string& name,
@@ -55,6 +94,7 @@
  private:
   mojo::AssociatedBinding<IPC::mojom::Channel> binding_;
   const base::Closure on_peer_pid_set_;
+  MessageExpectation message_expectation_;
   int32_t peer_pid_ = -1;
 
   DISALLOW_COPY_AND_ASSIGN(PeerPidReceiver);
@@ -67,15 +107,15 @@
 
 TEST_F(IPCMojoBootstrapTest, Connect) {
   base::MessageLoop message_loop;
-  std::unique_ptr<IPC::MojoBootstrap> bootstrap = IPC::MojoBootstrap::Create(
-      helper_.StartChild("IPCMojoBootstrapTestClient"),
-      IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
-      base::ThreadTaskRunnerHandle::Get());
+  Connection connection(
+      IPC::MojoBootstrap::Create(
+          helper_.StartChild("IPCMojoBootstrapTestClient"),
+          IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
+          base::ThreadTaskRunnerHandle::Get()),
+      kTestServerPid);
 
-  IPC::mojom::ChannelAssociatedPtr sender;
   IPC::mojom::ChannelAssociatedRequest receiver;
-  bootstrap->Connect(&sender, &receiver);
-  sender->SetPeerPid(kTestServerPid);
+  connection.TakeReceiver(&receiver);
 
   base::RunLoop run_loop;
   PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
@@ -86,20 +126,40 @@
   EXPECT_TRUE(helper_.WaitForChildTestShutdown());
 }
 
+TEST_F(IPCMojoBootstrapTest, ReceiveEmptyMessage) {
+  base::MessageLoop message_loop;
+  Connection connection(
+      IPC::MojoBootstrap::Create(
+          helper_.StartChild("IPCMojoBootstrapTestEmptyMessage"),
+          IPC::Channel::MODE_SERVER, base::ThreadTaskRunnerHandle::Get(),
+          base::ThreadTaskRunnerHandle::Get()),
+      kTestServerPid);
+
+  IPC::mojom::ChannelAssociatedRequest receiver;
+  connection.TakeReceiver(&receiver);
+
+  base::RunLoop run_loop;
+  PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure(),
+                       PeerPidReceiver::MessageExpectation::kExptectedInvalid);
+  run_loop.Run();
+
+  EXPECT_TRUE(helper_.WaitForChildTestShutdown());
+}
+
 // A long running process that connects to us.
 MULTIPROCESS_TEST_MAIN_WITH_SETUP(
     IPCMojoBootstrapTestClientTestChildMain,
     ::mojo::edk::test::MultiprocessTestHelper::ChildSetup) {
   base::MessageLoop message_loop;
-  std::unique_ptr<IPC::MojoBootstrap> bootstrap = IPC::MojoBootstrap::Create(
-      std::move(mojo::edk::test::MultiprocessTestHelper::primordial_pipe),
-      IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
-      base::ThreadTaskRunnerHandle::Get());
+  Connection connection(
+      IPC::MojoBootstrap::Create(
+          std::move(mojo::edk::test::MultiprocessTestHelper::primordial_pipe),
+          IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
+          base::ThreadTaskRunnerHandle::Get()),
+      kTestClientPid);
 
-  IPC::mojom::ChannelAssociatedPtr sender;
   IPC::mojom::ChannelAssociatedRequest receiver;
-  bootstrap->Connect(&sender, &receiver);
-  sender->SetPeerPid(kTestClientPid);
+  connection.TakeReceiver(&receiver);
 
   base::RunLoop run_loop;
   PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
@@ -110,4 +170,30 @@
   return 0;
 }
 
+// A long running process that connects to us.
+MULTIPROCESS_TEST_MAIN_WITH_SETUP(
+    IPCMojoBootstrapTestEmptyMessageTestChildMain,
+    ::mojo::edk::test::MultiprocessTestHelper::ChildSetup) {
+  base::MessageLoop message_loop;
+  Connection connection(
+      IPC::MojoBootstrap::Create(
+          std::move(mojo::edk::test::MultiprocessTestHelper::primordial_pipe),
+          IPC::Channel::MODE_CLIENT, base::ThreadTaskRunnerHandle::Get(),
+          base::ThreadTaskRunnerHandle::Get()),
+      kTestClientPid);
+
+  IPC::mojom::ChannelAssociatedRequest receiver;
+  connection.TakeReceiver(&receiver);
+  auto& sender = connection.GetSender();
+
+  uint8_t data = 0;
+  sender->Receive(base::make_span(&data, 0), {});
+
+  base::RunLoop run_loop;
+  PeerPidReceiver impl(std::move(receiver), run_loop.QuitClosure());
+  run_loop.Run();
+
+  return 0;
+}
+
 }  // namespace
diff --git a/media/cast/net/udp_transport.cc b/media/cast/net/udp_transport.cc
index 8ed8517..db98cbd 100644
--- a/media/cast/net/udp_transport.cc
+++ b/media/cast/net/udp_transport.cc
@@ -17,6 +17,7 @@
 #include "net/base/net_errors.h"
 #include "net/base/rand_callback.h"
 #include "net/log/net_log_source.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 
 namespace media {
 namespace cast {
@@ -258,15 +259,41 @@
     // If we called Connect() before we must call Write() instead of
     // SendTo(). Otherwise on some platforms we might get
     // ERR_SOCKET_IS_CONNECTED.
-    // TODO(crbug.com/656607): Add proper annotation.
+    net::NetworkTrafficAnnotationTag traffic_annotation =
+        net::DefineNetworkTrafficAnnotation("cast_udp_transport", R"(
+        semantics {
+          sender: "Cast Streaming"
+          description:
+            "Media streaming protocol for LAN transport of screen mirroring "
+            "audio/video. This is also used by browser features that wish to "
+            "send browser content for remote display, and such features are "
+            "generally started/stopped from the Media Router dialog."
+          trigger:
+            "User invokes feature from the Media Router dialog (right click on "
+            "page, 'Cast...')."
+          data:
+            "Media and related protocol-level control and performance messages."
+          destination: OTHER
+          destination_other:
+            "A playback receiver, such as a Chromecast device."
+        }
+        policy {
+          cookies_allowed: NO
+          setting: "This feature cannot be disabled in settings."
+          chrome_policy {
+            EnableMediaRouter {
+              EnableMediaRouter: false
+            }
+          }
+        })");
+
     result =
         udp_socket_->Write(buf.get(), static_cast<int>(packet->data.size()),
-                           callback, NO_TRAFFIC_ANNOTATION_BUG_656607);
+                           callback, traffic_annotation);
   } else if (!IsEmpty(remote_addr_)) {
-    result = udp_socket_->SendTo(buf.get(),
-                                 static_cast<int>(packet->data.size()),
-                                 remote_addr_,
-                                 callback);
+    result =
+        udp_socket_->SendTo(buf.get(), static_cast<int>(packet->data.size()),
+                            remote_addr_, callback);
   } else {
     VLOG(1) << "Failed to send packet; socket is neither bound nor "
             << "connected.";
diff --git a/media/cdm/BUILD.gn b/media/cdm/BUILD.gn
index f35272f..a3287d1 100644
--- a/media/cdm/BUILD.gn
+++ b/media/cdm/BUILD.gn
@@ -171,7 +171,7 @@
       "simple_cdm_buffer.cc",
       "simple_cdm_buffer.h",
     ]
-    data_deps += [ "//media/cdm/ppapi:clearkeycdm" ]
+    data_deps += [ "//media/cdm/ppapi/clear_key_cdm" ]
 
     deps += [
       ":cdm_api",
diff --git a/media/cdm/ppapi/BUILD.gn b/media/cdm/ppapi/BUILD.gn
index 0000751..2d0945fc 100644
--- a/media/cdm/ppapi/BUILD.gn
+++ b/media/cdm/ppapi/BUILD.gn
@@ -2,58 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/features.gni")
 import("//chrome/process_version_rc_template.gni")
 import("//media/cdm/ppapi/cdm_paths.gni")
 import("//media/cdm/ppapi/ppapi_cdm_adapter.gni")
-import("//media/media_options.gni")
-
-shared_library("clearkeycdm") {
-  output_dir = "$root_out_dir/$clearkey_cdm_path"
-  sources = [
-    "cdm_file_io_test.cc",
-    "cdm_file_io_test.h",
-    "clear_key_cdm/cdm_file_adapter.cc",
-    "clear_key_cdm/cdm_file_adapter.h",
-    "clear_key_cdm/cdm_host_proxy.h",
-    "clear_key_cdm/cdm_host_proxy_impl.h",
-    "clear_key_cdm/cdm_video_decoder.cc",
-    "clear_key_cdm/cdm_video_decoder.h",
-    "clear_key_cdm/clear_key_cdm.cc",
-    "clear_key_cdm/clear_key_cdm.h",
-    "clear_key_cdm/clear_key_persistent_session_cdm.cc",
-    "clear_key_cdm/clear_key_persistent_session_cdm.h",
-  ]
-
-  # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
-
-  defines = [ "CDM_IMPLEMENTATION" ]
-
-  deps = [
-    "//base",
-    "//build/config:exe_and_shlib_deps",
-    "//media",  # For media::AudioTimestampHelper
-    "//media:shared_memory_support",  # For media::AudioBus.
-    "//media/cdm:cdm_api",  # For content_decryption_module.h
-    "//url",
-  ]
-
-  if (media_use_ffmpeg) {
-    sources += [
-      "clear_key_cdm/ffmpeg_cdm_audio_decoder.cc",
-      "clear_key_cdm/ffmpeg_cdm_audio_decoder.h",
-      "clear_key_cdm/ffmpeg_cdm_video_decoder.cc",
-      "clear_key_cdm/ffmpeg_cdm_video_decoder.h",
-    ]
-    defines += [ "CLEAR_KEY_CDM_USE_FFMPEG_DECODER" ]
-    deps += [ "//third_party/ffmpeg" ]
-  }
-
-  if (is_mac) {
-    ldflags = [ "-Wl,-install_name,@loader_path/libclearkeycdm.dylib" ]
-  }
-}
 
 process_version_rc_template("clearkeycdmadapter_resources") {
   visibility = [ ":*" ]
@@ -70,10 +21,10 @@
   # Check whether the plugin's origin URL is valid.
   defines = [ "CHECK_DOCUMENT_URL" ]
   deps = [
-    ":clearkeycdm",
     ":clearkeycdmadapter_resources",
     "//base",  # Required for the allocator implementation.
     "//media:shared_memory_support",
+    "//media/cdm/ppapi/clear_key_cdm",
     "//ui/gfx/geometry",
   ]
 }
diff --git a/media/cdm/ppapi/clear_key_cdm/BUILD.gn b/media/cdm/ppapi/clear_key_cdm/BUILD.gn
new file mode 100644
index 0000000..f9f9396
--- /dev/null
+++ b/media/cdm/ppapi/clear_key_cdm/BUILD.gn
@@ -0,0 +1,57 @@
+# 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.
+
+import("//build/config/features.gni")
+import("//media/cdm/ppapi/cdm_paths.gni")
+import("//media/media_options.gni")
+
+shared_library("clear_key_cdm") {
+  output_dir = "$root_out_dir/$clearkey_cdm_path"
+  output_name = "clearkeycdm"
+  sources = [
+    "cdm_file_adapter.cc",
+    "cdm_file_adapter.h",
+    "cdm_file_io_test.cc",
+    "cdm_file_io_test.h",
+    "cdm_host_proxy.h",
+    "cdm_host_proxy_impl.h",
+    "cdm_proxy_test.cc",
+    "cdm_proxy_test.h",
+    "cdm_video_decoder.cc",
+    "cdm_video_decoder.h",
+    "clear_key_cdm.cc",
+    "clear_key_cdm.h",
+    "clear_key_persistent_session_cdm.cc",
+    "clear_key_persistent_session_cdm.h",
+  ]
+
+  # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+  configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+
+  defines = [ "CDM_IMPLEMENTATION" ]
+
+  deps = [
+    "//base",
+    "//build/config:exe_and_shlib_deps",
+    "//media",  # For media::AudioTimestampHelper
+    "//media:shared_memory_support",  # For media::AudioBus.
+    "//media/cdm:cdm_api",  # For content_decryption_module.h
+    "//url",
+  ]
+
+  if (media_use_ffmpeg) {
+    sources += [
+      "ffmpeg_cdm_audio_decoder.cc",
+      "ffmpeg_cdm_audio_decoder.h",
+      "ffmpeg_cdm_video_decoder.cc",
+      "ffmpeg_cdm_video_decoder.h",
+    ]
+    defines += [ "CLEAR_KEY_CDM_USE_FFMPEG_DECODER" ]
+    deps += [ "//third_party/ffmpeg" ]
+  }
+
+  if (is_mac) {
+    ldflags = [ "-Wl,-install_name,@loader_path/libclearkeycdm.dylib" ]
+  }
+}
diff --git a/media/cdm/ppapi/clear_key_cdm/cdm_file_adapter.h b/media/cdm/ppapi/clear_key_cdm/cdm_file_adapter.h
index c09cd5a..7465faa 100644
--- a/media/cdm/ppapi/clear_key_cdm/cdm_file_adapter.h
+++ b/media/cdm/ppapi/clear_key_cdm/cdm_file_adapter.h
@@ -58,7 +58,7 @@
   FileOpenedCB open_cb_;
   ReadCB read_cb_;
   WriteCB write_cb_;
-  cdm::FileIO* file_io_;
+  cdm::FileIO* file_io_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(CdmFileAdapter);
 };
diff --git a/media/cdm/ppapi/cdm_file_io_test.cc b/media/cdm/ppapi/clear_key_cdm/cdm_file_io_test.cc
similarity index 98%
rename from media/cdm/ppapi/cdm_file_io_test.cc
rename to media/cdm/ppapi/clear_key_cdm/cdm_file_io_test.cc
index 05540c1e..4bf027d 100644
--- a/media/cdm/ppapi/cdm_file_io_test.cc
+++ b/media/cdm/ppapi/clear_key_cdm/cdm_file_io_test.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 "media/cdm/ppapi/cdm_file_io_test.h"
+#include "media/cdm/ppapi/clear_key_cdm/cdm_file_io_test.h"
 
 #include <limits>
 
@@ -72,9 +72,7 @@
 // FileIOTestRunner implementation.
 
 FileIOTestRunner::FileIOTestRunner(const CreateFileIOCB& create_file_io_cb)
-    : create_file_io_cb_(create_file_io_cb),
-      total_num_tests_(0),
-      num_passed_tests_(0) {
+    : create_file_io_cb_(create_file_io_cb) {
   // Generate |large_data_|.
   large_data_.resize(kLargeDataSize);
   for (size_t i = 0; i < kLargeDataSize; ++i)
diff --git a/media/cdm/ppapi/cdm_file_io_test.h b/media/cdm/ppapi/clear_key_cdm/cdm_file_io_test.h
similarity index 94%
rename from media/cdm/ppapi/cdm_file_io_test.h
rename to media/cdm/ppapi/clear_key_cdm/cdm_file_io_test.h
index 37d8fc7..5fcdd0ac 100644
--- a/media/cdm/ppapi/cdm_file_io_test.h
+++ b/media/cdm/ppapi/clear_key_cdm/cdm_file_io_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 MEDIA_CDM_PPAPI_CDM_FILE_IO_TEST_H_
-#define MEDIA_CDM_PPAPI_CDM_FILE_IO_TEST_H_
+#ifndef MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_CDM_FILE_IO_TEST_H_
+#define MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_CDM_FILE_IO_TEST_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -155,12 +155,12 @@
   CompletionCB completion_cb_;
   std::list<FileIOTest> remaining_tests_;
   std::vector<uint8_t> large_data_;
-  size_t total_num_tests_;  // Total number of tests.
-  size_t num_passed_tests_;  // Number of passed tests.
+  size_t total_num_tests_ = 0;  // Total number of tests.
+  size_t num_passed_tests_ = 0;  // Number of passed tests.
 
   DISALLOW_COPY_AND_ASSIGN (FileIOTestRunner);
 };
 
 }  // namespace media
 
-#endif  // MEDIA_CDM_PPAPI_CDM_FILE_IO_TEST_H_
+#endif  // MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_CDM_FILE_IO_TEST_H_
diff --git a/media/cdm/ppapi/clear_key_cdm/cdm_proxy_test.cc b/media/cdm/ppapi/clear_key_cdm/cdm_proxy_test.cc
new file mode 100644
index 0000000..9823126
--- /dev/null
+++ b/media/cdm/ppapi/clear_key_cdm/cdm_proxy_test.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 "media/cdm/ppapi/clear_key_cdm/cdm_proxy_test.h"
+
+#include "base/logging.h"
+#include "media/cdm/ppapi/clear_key_cdm/cdm_host_proxy.h"
+
+namespace media {
+
+CdmProxyTest::CdmProxyTest(CdmHostProxy* cdm_host_proxy)
+    : cdm_host_proxy_(cdm_host_proxy) {}
+
+CdmProxyTest::~CdmProxyTest() {}
+
+void CdmProxyTest::Run(CompletionCB completion_cb) {
+  DVLOG(1) << __func__;
+  completion_cb_ = std::move(completion_cb);
+
+  cdm_proxy_ = cdm_host_proxy_->CreateCdmProxy();
+  if (!cdm_proxy_)
+    OnTestComplete(false);
+
+  cdm_proxy_->Initialize(this);
+}
+
+void CdmProxyTest::OnTestComplete(bool success) {
+  DVLOG(1) << __func__ << ": success = " << success;
+  std::move(completion_cb_).Run(success);
+}
+
+void CdmProxyTest::OnInitialized(Status status,
+                                 Protocol protocol,
+                                 uint32_t crypto_session_id) {
+  DVLOG(1) << __func__ << ": status = " << status;
+  // Ignore the |status| for now.
+  // TODO(xhwang): Add a test CdmProxy and test all APIs.
+  OnTestComplete(true);
+}
+void CdmProxyTest::OnProcessed(Status status,
+                               const uint8_t* output_data,
+                               uint32_t output_data_size) {
+  DVLOG(1) << __func__ << ": status = " << status;
+  NOTREACHED();
+}
+
+void CdmProxyTest::OnMediaCryptoSessionCreated(Status status,
+                                               uint32_t crypto_session_id,
+                                               uint64_t output_data) {
+  DVLOG(1) << __func__ << ": status = " << status;
+  NOTREACHED();
+}
+
+void CdmProxyTest::NotifyHardwareReset() {
+  DVLOG(1) << __func__;
+  NOTREACHED();
+}
+
+}  // namespace media
diff --git a/media/cdm/ppapi/clear_key_cdm/cdm_proxy_test.h b/media/cdm/ppapi/clear_key_cdm/cdm_proxy_test.h
new file mode 100644
index 0000000..b090d68
--- /dev/null
+++ b/media/cdm/ppapi/clear_key_cdm/cdm_proxy_test.h
@@ -0,0 +1,50 @@
+// 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 MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_CDM_PROXY_TEST_H_
+#define MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_CDM_PROXY_TEST_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "media/cdm/api/content_decryption_module.h"
+
+namespace media {
+
+class CdmHostProxy;
+
+class CdmProxyTest : public cdm::CdmProxyClient {
+ public:
+  using CompletionCB = base::OnceCallback<void(bool success)>;
+
+  explicit CdmProxyTest(CdmHostProxy* cdm_host_proxy);
+  ~CdmProxyTest() override;
+
+  // Runs the test and returns the test result through |completion_cb|.
+  void Run(CompletionCB completion_cb);
+
+ private:
+  void OnTestComplete(bool success);
+
+  // cdm::CdmProxyClient implementation.
+  void OnInitialized(Status status,
+                     Protocol protocol,
+                     uint32_t crypto_session_id) final;
+  void OnProcessed(Status status,
+                   const uint8_t* output_data,
+                   uint32_t output_data_size) final;
+  void OnMediaCryptoSessionCreated(Status status,
+                                   uint32_t crypto_session_id,
+                                   uint64_t output_data) final;
+  void NotifyHardwareReset() final;
+
+  CdmHostProxy* const cdm_host_proxy_ = nullptr;
+  CompletionCB completion_cb_;
+  cdm::CdmProxy* cdm_proxy_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(CdmProxyTest);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_CDM_PROXY_TEST_H_
diff --git a/media/cdm/ppapi/clear_key_cdm/clear_key_cdm.cc b/media/cdm/ppapi/clear_key_cdm/clear_key_cdm.cc
index 5ff7e7c..0551840 100644
--- a/media/cdm/ppapi/clear_key_cdm/clear_key_cdm.cc
+++ b/media/cdm/ppapi/clear_key_cdm/clear_key_cdm.cc
@@ -23,9 +23,10 @@
 #include "media/base/decrypt_config.h"
 #include "media/cdm/api/content_decryption_module_ext.h"
 #include "media/cdm/json_web_key.h"
-#include "media/cdm/ppapi/cdm_file_io_test.h"
+#include "media/cdm/ppapi/clear_key_cdm/cdm_file_io_test.h"
 #include "media/cdm/ppapi/clear_key_cdm/cdm_host_proxy.h"
 #include "media/cdm/ppapi/clear_key_cdm/cdm_host_proxy_impl.h"
+#include "media/cdm/ppapi/clear_key_cdm/cdm_proxy_test.h"
 #include "media/cdm/ppapi/clear_key_cdm/cdm_video_decoder.h"
 #include "media/media_features.h"
 
@@ -72,10 +73,11 @@
     "org.chromium.externalclearkey.storageidtest";
 const char kExternalClearKeyDifferentGuidTestKeySystem[] =
     "org.chromium.externalclearkey.differentguid";
+const char kExternalClearKeyCdmProxyTestKeySystem[] =
+    "org.chromium.externalclearkey.cdmproxytest";
 
 const int64_t kSecondsPerMinute = 60;
 const int64_t kMsPerSecond = 1000;
-const int64_t kInitialTimerDelayMs = 200;
 const int64_t kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond;
 
 // CDM unit test result header. Must be in sync with UNIT_TEST_RESULT_HEADER in
@@ -261,7 +263,8 @@
       key_system_string != kExternalClearKeyCrashKeySystem &&
       key_system_string != kExternalClearKeyVerifyCdmHostTestKeySystem &&
       key_system_string != kExternalClearKeyStorageIdTestKeySystem &&
-      key_system_string != kExternalClearKeyDifferentGuidTestKeySystem) {
+      key_system_string != kExternalClearKeyDifferentGuidTestKeySystem &&
+      key_system_string != kExternalClearKeyCdmProxyTestKeySystem) {
     DVLOG(1) << "Unsupported key system:" << key_system_string;
     return nullptr;
   }
@@ -363,13 +366,7 @@
           base::Bind(&ClearKeyCdm::OnSessionKeysChange, base::Unretained(this)),
           base::Bind(&ClearKeyCdm::OnSessionExpirationUpdate,
                      base::Unretained(this)))),
-      key_system_(key_system),
-      allow_persistent_state_(false),
-      timer_delay_ms_(kInitialTimerDelayMs),
-      renewal_timer_set_(false),
-      is_running_output_protection_test_(false),
-      is_running_platform_verification_test_(false),
-      is_running_storage_id_test_(false) {
+      key_system_(key_system) {
   DCHECK(g_is_cdm_module_initialized);
 }
 
@@ -432,6 +429,8 @@
     VerifyCdmHostTest();
   } else if (key_system_ == kExternalClearKeyStorageIdTestKeySystem) {
     StartStorageIdTest();
+  } else if (key_system_ == kExternalClearKeyCdmProxyTestKeySystem) {
+    StartCdmProxyTest();
   }
 }
 
@@ -959,4 +958,21 @@
   cdm_host_proxy_->RequestStorageId(0);
 }
 
+void ClearKeyCdm::StartCdmProxyTest() {
+  DVLOG(1) << __func__;
+  DCHECK(!cdm_proxy_test_);
+
+  cdm_proxy_test_.reset(new CdmProxyTest(cdm_host_proxy_.get()));
+  cdm_proxy_test_->Run(base::BindOnce(&ClearKeyCdm::OnCdmProxyTestComplete,
+                                      base::Unretained(this)));
+}
+
+void ClearKeyCdm::OnCdmProxyTestComplete(bool success) {
+  DVLOG(1) << __func__;
+  DCHECK(cdm_proxy_test_);
+
+  cdm_proxy_test_.reset();
+  OnUnitTestComplete(success);
+}
+
 }  // namespace media
diff --git a/media/cdm/ppapi/clear_key_cdm/clear_key_cdm.h b/media/cdm/ppapi/clear_key_cdm/clear_key_cdm.h
index 4d00f8b..417bc06 100644
--- a/media/cdm/ppapi/clear_key_cdm/clear_key_cdm.h
+++ b/media/cdm/ppapi/clear_key_cdm/clear_key_cdm.h
@@ -22,11 +22,14 @@
 namespace media {
 
 class CdmHostProxy;
+class CdmProxyTest;
 class CdmVideoDecoder;
 class DecoderBuffer;
 class FFmpegCdmAudioDecoder;
 class FileIOTestRunner;
 
+const int64_t kInitialTimerDelayMs = 200;
+
 // Clear key implementation of the cdm::ContentDecryptionModule interfaces.
 class ClearKeyCdm : public cdm::ContentDecryptionModule_9,
                     public cdm::ContentDecryptionModule_10 {
@@ -128,8 +131,6 @@
   void OnUnitTestComplete(bool success);
 
   void StartFileIOTest();
-
-  // Callback for CDM File IO test.
   void OnFileIOTestComplete(bool success);
 
   void StartOutputProtectionTest();
@@ -137,21 +138,24 @@
   void VerifyCdmHostTest();
   void StartStorageIdTest();
 
+  void StartCdmProxyTest();
+  void OnCdmProxyTestComplete(bool success);
+
   std::unique_ptr<CdmHostProxy> cdm_host_proxy_;
   scoped_refptr<ContentDecryptionModule> cdm_;
 
   const std::string key_system_;
-  bool allow_persistent_state_;
+  bool allow_persistent_state_ = false;
 
   std::string last_session_id_;
   std::string next_renewal_message_;
 
   // Timer delay in milliseconds for the next cdm_host_proxy_->SetTimer() call.
-  int64_t timer_delay_ms_;
+  int64_t timer_delay_ms_ = kInitialTimerDelayMs;
 
   // Indicates whether a renewal timer has been set to prevent multiple timers
   // from running.
-  bool renewal_timer_set_;
+  bool renewal_timer_set_ = false;
 
 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
   std::unique_ptr<FFmpegCdmAudioDecoder> audio_decoder_;
@@ -160,10 +164,11 @@
   std::unique_ptr<CdmVideoDecoder> video_decoder_;
 
   std::unique_ptr<FileIOTestRunner> file_io_test_runner_;
+  std::unique_ptr<CdmProxyTest> cdm_proxy_test_;
 
-  bool is_running_output_protection_test_;
-  bool is_running_platform_verification_test_;
-  bool is_running_storage_id_test_;
+  bool is_running_output_protection_test_ = false;
+  bool is_running_platform_verification_test_ = false;
+  bool is_running_storage_id_test_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(ClearKeyCdm);
 };
diff --git a/media/cdm/ppapi/clear_key_cdm/clear_key_persistent_session_cdm.h b/media/cdm/ppapi/clear_key_cdm/clear_key_persistent_session_cdm.h
index 1e1d194..ce6907b 100644
--- a/media/cdm/ppapi/clear_key_cdm/clear_key_persistent_session_cdm.h
+++ b/media/cdm/ppapi/clear_key_cdm/clear_key_persistent_session_cdm.h
@@ -100,7 +100,7 @@
   void OnSessionClosed(const std::string& session_id);
 
   scoped_refptr<AesDecryptor> cdm_;
-  CdmHostProxy* const cdm_host_proxy_;
+  CdmHostProxy* const cdm_host_proxy_ = nullptr;
 
   // Callbacks for firing session events. Other events aren't intercepted.
   SessionClosedCB session_closed_cb_;
diff --git a/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_audio_decoder.cc b/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_audio_decoder.cc
index 59037bf..68558a5 100644
--- a/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_audio_decoder.cc
+++ b/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_audio_decoder.cc
@@ -16,7 +16,6 @@
 #include "media/base/audio_timestamp_helper.h"
 #include "media/base/data_buffer.h"
 #include "media/base/limits.h"
-#include "media/base/timestamp_constants.h"
 #include "media/cdm/ppapi/clear_key_cdm/cdm_host_proxy.h"
 #include "media/ffmpeg/ffmpeg_common.h"
 #include "media/ffmpeg/ffmpeg_decoding_loop.h"
@@ -130,13 +129,7 @@
 }
 
 FFmpegCdmAudioDecoder::FFmpegCdmAudioDecoder(CdmHostProxy* cdm_host_proxy)
-    : is_initialized_(false),
-      cdm_host_proxy_(cdm_host_proxy),
-      samples_per_second_(0),
-      channels_(0),
-      av_sample_format_(0),
-      bytes_per_frame_(0),
-      last_input_timestamp_(kNoTimestamp) {}
+    : cdm_host_proxy_(cdm_host_proxy) {}
 
 FFmpegCdmAudioDecoder::~FFmpegCdmAudioDecoder() {
   ReleaseFFmpegResources();
diff --git a/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_audio_decoder.h b/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_audio_decoder.h
index da28819..5856fe2f 100644
--- a/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_audio_decoder.h
+++ b/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_audio_decoder.h
@@ -13,6 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/time/time.h"
+#include "media/base/timestamp_constants.h"
 #include "media/cdm/api/content_decryption_module.h"
 #include "media/ffmpeg/ffmpeg_deleters.h"
 
@@ -61,25 +62,25 @@
   void ReleaseFFmpegResources();
   void SerializeInt64(int64_t value, uint8_t* dest);
 
-  bool is_initialized_;
+  bool is_initialized_ = false;
 
-  CdmHostProxy* const cdm_host_proxy_;
+  CdmHostProxy* const cdm_host_proxy_ = nullptr;
 
   // FFmpeg structures owned by this object.
   std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context_;
   std::unique_ptr<FFmpegDecodingLoop> decoding_loop_;
 
   // Audio format.
-  int samples_per_second_;
-  int channels_;
+  int samples_per_second_ = 0;
+  int channels_ = 0;
 
   // AVSampleFormat initially requested; not Chrome's SampleFormat.
-  int av_sample_format_;
+  int av_sample_format_ = 0;
 
   // Used for computing output timestamps.
   std::unique_ptr<AudioTimestampHelper> output_timestamp_helper_;
-  int bytes_per_frame_;
-  base::TimeDelta last_input_timestamp_;
+  int bytes_per_frame_ = 0;
+  base::TimeDelta last_input_timestamp_ = kNoTimestamp;
 
   DISALLOW_COPY_AND_ASSIGN(FFmpegCdmAudioDecoder);
 };
diff --git a/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_video_decoder.cc b/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_video_decoder.cc
index 4e6cdf7..8514853 100644
--- a/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_video_decoder.cc
+++ b/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_video_decoder.cc
@@ -130,7 +130,7 @@
 }
 
 FFmpegCdmVideoDecoder::FFmpegCdmVideoDecoder(CdmHostProxy* cdm_host_proxy)
-    : is_initialized_(false), cdm_host_proxy_(cdm_host_proxy) {}
+    : cdm_host_proxy_(cdm_host_proxy) {}
 
 FFmpegCdmVideoDecoder::~FFmpegCdmVideoDecoder() {
   ReleaseFFmpegResources();
diff --git a/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_video_decoder.h b/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_video_decoder.h
index 9b70ee4..b57c235 100644
--- a/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_video_decoder.h
+++ b/media/cdm/ppapi/clear_key_cdm/ffmpeg_cdm_video_decoder.h
@@ -56,9 +56,9 @@
   std::unique_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context_;
   std::unique_ptr<FFmpegDecodingLoop> decoding_loop_;
 
-  bool is_initialized_;
+  bool is_initialized_ = false;
 
-  CdmHostProxy* const cdm_host_proxy_;
+  CdmHostProxy* const cdm_host_proxy_ = nullptr;
 
   base::circular_deque<std::unique_ptr<AVFrame, ScopedPtrAVFreeFrame>>
       pending_frames_;
diff --git a/media/cdm/ppapi/clear_key_cdm/libvpx_cdm_video_decoder.cc b/media/cdm/ppapi/clear_key_cdm/libvpx_cdm_video_decoder.cc
index d816dfe..1c7331d 100644
--- a/media/cdm/ppapi/clear_key_cdm/libvpx_cdm_video_decoder.cc
+++ b/media/cdm/ppapi/clear_key_cdm/libvpx_cdm_video_decoder.cc
@@ -27,10 +27,7 @@
 static const int kDecodeThreads = 2;
 
 LibvpxCdmVideoDecoder::LibvpxCdmVideoDecoder(CdmHostProxy* cdm_host_proxy)
-    : is_initialized_(false),
-      cdm_host_proxy_(cdm_host_proxy),
-      vpx_codec_(NULL),
-      vpx_image_(NULL) {}
+    : cdm_host_proxy_(cdm_host_proxy) {}
 
 LibvpxCdmVideoDecoder::~LibvpxCdmVideoDecoder() {
   Deinitialize();
diff --git a/media/cdm/ppapi/clear_key_cdm/libvpx_cdm_video_decoder.h b/media/cdm/ppapi/clear_key_cdm/libvpx_cdm_video_decoder.h
index e680e20..7c0f2d5 100644
--- a/media/cdm/ppapi/clear_key_cdm/libvpx_cdm_video_decoder.h
+++ b/media/cdm/ppapi/clear_key_cdm/libvpx_cdm_video_decoder.h
@@ -44,12 +44,12 @@
   // |cdm_video_frame|. Returns true when allocation and copy succeed.
   bool CopyVpxImageTo(cdm::VideoFrame* cdm_video_frame);
 
-  bool is_initialized_;
+  bool is_initialized_ = false;
 
-  CdmHostProxy* const cdm_host_proxy_;
+  CdmHostProxy* const cdm_host_proxy_ = nullptr;
 
-  vpx_codec_ctx* vpx_codec_;
-  vpx_image* vpx_image_;
+  vpx_codec_ctx* vpx_codec_ = nullptr;
+  vpx_image* vpx_image_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(LibvpxCdmVideoDecoder);
 };
diff --git a/media/gpu/ipc/client/BUILD.gn b/media/gpu/ipc/client/BUILD.gn
index 45f8d62..427c8d3 100644
--- a/media/gpu/ipc/client/BUILD.gn
+++ b/media/gpu/ipc/client/BUILD.gn
@@ -6,8 +6,6 @@
   sources = [
     "gpu_video_decode_accelerator_host.cc",
     "gpu_video_decode_accelerator_host.h",
-    "gpu_video_encode_accelerator_host.cc",
-    "gpu_video_encode_accelerator_host.h",
   ]
 
   configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
diff --git a/media/gpu/ipc/client/gpu_video_encode_accelerator_host.cc b/media/gpu/ipc/client/gpu_video_encode_accelerator_host.cc
deleted file mode 100644
index 350a16f..0000000
--- a/media/gpu/ipc/client/gpu_video_encode_accelerator_host.cc
+++ /dev/null
@@ -1,305 +0,0 @@
-// Copyright 2013 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 "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
-
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "gpu/ipc/client/gpu_channel_host.h"
-#include "media/base/video_frame.h"
-#include "media/gpu/gpu_video_accelerator_util.h"
-#include "media/gpu/ipc/common/media_messages.h"
-#include "media/video/video_encode_accelerator.h"
-
-namespace media {
-
-GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost(
-    gpu::CommandBufferProxyImpl* impl)
-    : channel_(impl->channel()),
-      encoder_route_id_(MSG_ROUTING_NONE),
-      client_(nullptr),
-      impl_(impl),
-      next_frame_id_(0),
-      media_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      weak_this_factory_(this) {
-  DCHECK(channel_);
-  DCHECK(impl_);
-  impl_->AddDeletionObserver(this);
-}
-
-GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (channel_ && encoder_route_id_ != MSG_ROUTING_NONE)
-    channel_->RemoveRoute(encoder_route_id_);
-
-  base::AutoLock lock(impl_lock_);
-  if (impl_)
-    impl_->RemoveDeletionObserver(this);
-}
-
-bool GpuVideoEncodeAcceleratorHost::OnMessageReceived(
-    const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAcceleratorHost, message)
-    IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers,
-                        OnRequireBitstreamBuffers)
-    IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInputDone,
-                        OnNotifyInputDone)
-    IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady,
-                        OnBitstreamBufferReady)
-    IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyError,
-                        OnNotifyError)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  DCHECK(handled);
-  // See OnNotifyError for why |this| mustn't be used after OnNotifyError might
-  // have been called above.
-  return handled;
-}
-
-void GpuVideoEncodeAcceleratorHost::OnChannelError() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (channel_) {
-    if (encoder_route_id_ != MSG_ROUTING_NONE)
-      channel_->RemoveRoute(encoder_route_id_);
-    channel_ = nullptr;
-  }
-  PostNotifyError(FROM_HERE, kPlatformFailureError, "OnChannelError()");
-}
-
-VideoEncodeAccelerator::SupportedProfiles
-GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!channel_)
-    return VideoEncodeAccelerator::SupportedProfiles();
-  return GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
-      channel_->gpu_info().video_encode_accelerator_supported_profiles);
-}
-
-bool GpuVideoEncodeAcceleratorHost::Initialize(
-    VideoPixelFormat input_format,
-    const gfx::Size& input_visible_size,
-    VideoCodecProfile output_profile,
-    uint32_t initial_bitrate,
-    Client* client) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  client_ = client;
-
-  base::AutoLock lock(impl_lock_);
-  if (!impl_) {
-    DLOG(ERROR) << "impl_ destroyed";
-    return false;
-  }
-
-  int32_t route_id = channel_->GenerateRouteID();
-  channel_->AddRoute(route_id, weak_this_factory_.GetWeakPtr());
-
-  CreateVideoEncoderParams params;
-  params.input_format = input_format;
-  params.input_visible_size = input_visible_size;
-  params.output_profile = output_profile;
-  params.initial_bitrate = initial_bitrate;
-  params.encoder_route_id = route_id;
-  bool succeeded = false;
-  Send(new GpuCommandBufferMsg_CreateVideoEncoder(impl_->route_id(), params,
-                                                  &succeeded));
-  if (!succeeded) {
-    DLOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoEncoder()) failed";
-    channel_->RemoveRoute(route_id);
-    return false;
-  }
-  encoder_route_id_ = route_id;
-  return true;
-}
-
-void GpuVideoEncodeAcceleratorHost::Encode(
-    const scoped_refptr<VideoFrame>& frame,
-    bool force_keyframe) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_EQ(PIXEL_FORMAT_I420, frame->format());
-  DCHECK_EQ(VideoFrame::STORAGE_SHMEM, frame->storage_type());
-  if (!channel_)
-    return;
-
-  switch (frame->storage_type()) {
-    case VideoFrame::STORAGE_SHMEM:
-      EncodeSharedMemoryFrame(frame, force_keyframe);
-      break;
-    default:
-      PostNotifyError(FROM_HERE, kPlatformFailureError,
-                      "Encode(): cannot encode frame with invalid handles");
-      return;
-  }
-
-  frame_map_[next_frame_id_] = frame;
-
-  // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
-  next_frame_id_ = (next_frame_id_ + 1) & 0x3FFFFFFF;
-}
-
-void GpuVideoEncodeAcceleratorHost::UseOutputBitstreamBuffer(
-    const BitstreamBuffer& buffer) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!channel_)
-    return;
-
-  base::SharedMemoryHandle handle =
-      channel_->ShareToGpuProcess(buffer.handle());
-  if (!base::SharedMemory::IsHandleValid(handle)) {
-    PostNotifyError(
-        FROM_HERE, kPlatformFailureError,
-        base::StringPrintf("UseOutputBitstreamBuffer(): failed to duplicate "
-                           "buffer handle for GPU process: buffer.id()=%d",
-                           buffer.id()));
-    return;
-  }
-  Send(new AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer(
-      encoder_route_id_, buffer.id(), handle, buffer.size()));
-}
-
-void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange(
-    uint32_t bitrate,
-    uint32_t framerate) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!channel_)
-    return;
-
-  Send(new AcceleratedVideoEncoderMsg_RequestEncodingParametersChange(
-      encoder_route_id_, bitrate, framerate));
-}
-
-void GpuVideoEncodeAcceleratorHost::Destroy() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (channel_)
-    Send(new AcceleratedVideoEncoderMsg_Destroy(encoder_route_id_));
-  client_ = nullptr;
-  delete this;
-}
-
-void GpuVideoEncodeAcceleratorHost::OnWillDeleteImpl() {
-  base::AutoLock lock(impl_lock_);
-  impl_ = nullptr;
-
-  // The gpu::CommandBufferProxyImpl is going away; error out this VEA.
-  media_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&GpuVideoEncodeAcceleratorHost::OnChannelError,
-                            weak_this_factory_.GetWeakPtr()));
-}
-
-void GpuVideoEncodeAcceleratorHost::EncodeSharedMemoryFrame(
-    const scoped_refptr<VideoFrame>& frame,
-    bool force_keyframe) {
-  if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) {
-    PostNotifyError(FROM_HERE, kPlatformFailureError,
-                    "EncodeSharedMemory(): cannot encode frame with invalid "
-                    "shared memory handle");
-    return;
-  }
-
-  AcceleratedVideoEncoderMsg_Encode_Params params;
-  params.frame_id = next_frame_id_;
-  params.timestamp = frame->timestamp();
-  params.buffer_handle =
-      channel_->ShareToGpuProcess(frame->shared_memory_handle());
-  if (!base::SharedMemory::IsHandleValid(params.buffer_handle)) {
-    PostNotifyError(FROM_HERE, kPlatformFailureError,
-                    "Encode(): failed to duplicate shared memory buffer handle "
-                    "for GPU process");
-    return;
-  }
-  params.buffer_offset =
-      base::checked_cast<uint32_t>(frame->shared_memory_offset());
-  params.buffer_size =
-      VideoFrame::AllocationSize(frame->format(), frame->coded_size());
-  params.force_keyframe = force_keyframe;
-
-  Send(new AcceleratedVideoEncoderMsg_Encode(encoder_route_id_, params));
-}
-
-void GpuVideoEncodeAcceleratorHost::PostNotifyError(
-    const base::Location& location,
-    Error error,
-    const std::string& message) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DLOG(ERROR) << "Error from " << location.ToString() << ", " << message
-              << " (error = " << error << ")";
-  // Post the error notification back to this thread, to avoid re-entrancy.
-  media_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&GpuVideoEncodeAcceleratorHost::OnNotifyError,
-                            weak_this_factory_.GetWeakPtr(), error));
-}
-
-void GpuVideoEncodeAcceleratorHost::Send(IPC::Message* message) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  uint32_t message_type = message->type();
-  if (!channel_->Send(message)) {
-    PostNotifyError(FROM_HERE, kPlatformFailureError,
-                    base::StringPrintf("Send(%d) failed", message_type));
-  }
-}
-
-void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers(
-    uint32_t input_count,
-    const gfx::Size& input_coded_size,
-    uint32_t output_buffer_size) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DVLOG(2) << __func__ << " input_count=" << input_count
-           << ", input_coded_size=" << input_coded_size.ToString()
-           << ", output_buffer_size=" << output_buffer_size;
-  if (!client_)
-    return;
-  client_->RequireBitstreamBuffers(input_count, input_coded_size,
-                                   output_buffer_size);
-}
-
-void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32_t frame_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DVLOG(3) << __func__ << " frame_id=" << frame_id;
-  // Fun-fact: std::hash_map is not spec'd to be re-entrant; since freeing a
-  // frame can trigger a further encode to be kicked off and thus an .insert()
-  // back into the map, we separate the frame's dtor running from the .erase()
-  // running by holding on to the frame temporarily.  This isn't "just
-  // theoretical" - Android's std::hash_map crashes if we don't do this.
-  scoped_refptr<VideoFrame> frame = frame_map_[frame_id];
-  if (!frame_map_.erase(frame_id)) {
-    DLOG(ERROR) << __func__ << " invalid frame_id=" << frame_id;
-    // See OnNotifyError for why this needs to be the last thing in this
-    // function.
-    OnNotifyError(kPlatformFailureError);
-    return;
-  }
-  frame =
-      nullptr;  // Not necessary but nice to be explicit; see fun-fact above.
-}
-
-void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady(
-    int32_t bitstream_buffer_id,
-    uint32_t payload_size,
-    bool key_frame,
-    base::TimeDelta timestamp) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DVLOG(3) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id
-           << ", payload_size=" << payload_size << ", key_frame=" << key_frame;
-  if (!client_)
-    return;
-  client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame,
-                                timestamp);
-}
-
-void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DLOG(ERROR) << __func__ << " error=" << error;
-  if (!client_)
-    return;
-  weak_this_factory_.InvalidateWeakPtrs();
-
-  // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
-  // last thing done on this stack!
-  VideoEncodeAccelerator::Client* client = nullptr;
-  std::swap(client_, client);
-  client->NotifyError(error);
-}
-
-}  // namespace media
diff --git a/media/gpu/ipc/client/gpu_video_encode_accelerator_host.h b/media/gpu/ipc/client/gpu_video_encode_accelerator_host.h
deleted file mode 100644
index 3ac0b9a..0000000
--- a/media/gpu/ipc/client/gpu_video_encode_accelerator_host.h
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2013 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 MEDIA_GPU_IPC_CLIENT_GPU_VIDEO_ENCODE_ACCELERATOR_HOST_H_
-#define MEDIA_GPU_IPC_CLIENT_GPU_VIDEO_ENCODE_ACCELERATOR_HOST_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequence_checker.h"
-#include "base/single_thread_task_runner.h"
-#include "gpu/config/gpu_info.h"
-#include "gpu/ipc/client/command_buffer_proxy_impl.h"
-#include "ipc/ipc_listener.h"
-#include "media/video/video_encode_accelerator.h"
-
-namespace gfx {
-class Size;
-}  // namespace gfx
-
-namespace gpu {
-class GpuChannelHost;
-}  // namespace gpu
-
-namespace media {
-class VideoFrame;
-}  // namespace media
-
-namespace base {
-class Location;
-}  // namespace base
-
-namespace media {
-
-// This class is the renderer-side host for the VideoEncodeAccelerator in the
-// GPU process, coordinated over IPC.
-class GpuVideoEncodeAcceleratorHost
-    : public IPC::Listener,
-      public VideoEncodeAccelerator,
-      public gpu::CommandBufferProxyImpl::DeletionObserver {
- public:
-  // |this| is guaranteed not to outlive |impl|.  (See comments for |impl_|.)
-  explicit GpuVideoEncodeAcceleratorHost(gpu::CommandBufferProxyImpl* impl);
-
-  // IPC::Listener implementation.
-  bool OnMessageReceived(const IPC::Message& message) override;
-  void OnChannelError() override;
-
-  // VideoEncodeAccelerator implementation.
-  SupportedProfiles GetSupportedProfiles() override;
-  bool Initialize(VideoPixelFormat input_format,
-                  const gfx::Size& input_visible_size,
-                  VideoCodecProfile output_profile,
-                  uint32_t initial_bitrate,
-                  Client* client) override;
-  void Encode(const scoped_refptr<VideoFrame>& frame,
-              bool force_keyframe) override;
-  void UseOutputBitstreamBuffer(const BitstreamBuffer& buffer) override;
-  void RequestEncodingParametersChange(uint32_t bitrate,
-                                       uint32_t framerate_num) override;
-  void Destroy() override;
-
-  // gpu::CommandBufferProxyImpl::DeletionObserver implementation.
-  void OnWillDeleteImpl() override;
-
- private:
-  // Only Destroy() should be deleting |this|.
-  ~GpuVideoEncodeAcceleratorHost() override;
-
-  // Encode specific video frame types.
-  void EncodeSharedMemoryFrame(const scoped_refptr<VideoFrame>& frame,
-                               bool force_keyframe);
-
-  // Notify |client_| of an error.  Posts a task to avoid re-entrancy.
-  void PostNotifyError(const base::Location& location,
-                       Error error,
-                       const std::string& message);
-
-  void Send(IPC::Message* message);
-
-  // IPC handlers, proxying VideoEncodeAccelerator::Client for the GPU
-  // process.  Should not be called directly.
-  void OnRequireBitstreamBuffers(uint32_t input_count,
-                                 const gfx::Size& input_coded_size,
-                                 uint32_t output_buffer_size);
-  void OnNotifyInputDone(int32_t frame_id);
-  void OnBitstreamBufferReady(int32_t bitstream_buffer_id,
-                              uint32_t payload_size,
-                              bool key_frame,
-                              base::TimeDelta timestamp);
-  void OnNotifyError(Error error);
-
-  scoped_refptr<gpu::GpuChannelHost> channel_;
-
-  // Route ID for the associated encoder in the GPU process.
-  int32_t encoder_route_id_;
-
-  // The client that will receive callbacks from the encoder.
-  Client* client_;
-
-  // Protect |impl_|. |impl_| is used on media thread, but it can be invalidated
-  // on main thread.
-  base::Lock impl_lock_;
-
-  // Unowned reference to the gpu::CommandBufferProxyImpl that created us.
-  // |this| registers as a DeletionObserver of |impl_|, so the reference is
-  // always valid as long as it is not NULL.
-  gpu::CommandBufferProxyImpl* impl_;
-
-  // VideoFrames sent to the encoder.
-  // base::IDMap not used here, since that takes pointers, not scoped_refptr.
-  typedef base::hash_map<int32_t, scoped_refptr<VideoFrame>> FrameMap;
-  FrameMap frame_map_;
-
-  // ID serial number for the next frame to send to the GPU process.
-  int32_t next_frame_id_;
-
-  // Task runner for tasks that should run on the thread this class is
-  // constructed.
-  scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
-
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  // WeakPtr factory for posting tasks back to itself.
-  base::WeakPtrFactory<GpuVideoEncodeAcceleratorHost> weak_this_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuVideoEncodeAcceleratorHost);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_GPU_IPC_CLIENT_GPU_VIDEO_ENCODE_ACCELERATOR_HOST_H_
diff --git a/media/gpu/ipc/common/media_messages.h b/media/gpu/ipc/common/media_messages.h
index 74ddb7c5a..5ef9243 100644
--- a/media/gpu/ipc/common/media_messages.h
+++ b/media/gpu/ipc/common/media_messages.h
@@ -16,21 +16,11 @@
 #include "media/gpu/ipc/common/media_param_traits.h"
 #include "media/video/jpeg_decode_accelerator.h"
 #include "media/video/video_decode_accelerator.h"
-#include "media/video/video_encode_accelerator.h"
 #include "ui/gfx/ipc/color/gfx_param_traits.h"
 #include "ui/gfx/ipc/gfx_param_traits.h"
 
 #define IPC_MESSAGE_START MediaMsgStart
 
-IPC_STRUCT_BEGIN(AcceleratedVideoEncoderMsg_Encode_Params)
-  IPC_STRUCT_MEMBER(int32_t, frame_id)
-  IPC_STRUCT_MEMBER(base::TimeDelta, timestamp)
-  IPC_STRUCT_MEMBER(base::SharedMemoryHandle, buffer_handle)
-  IPC_STRUCT_MEMBER(uint32_t, buffer_offset)
-  IPC_STRUCT_MEMBER(uint32_t, buffer_size)
-  IPC_STRUCT_MEMBER(bool, force_keyframe)
-IPC_STRUCT_END()
-
 IPC_STRUCT_BEGIN(AcceleratedVideoDecoderHostMsg_PictureReady_Params)
   IPC_STRUCT_MEMBER(int32_t, picture_buffer_id)
   IPC_STRUCT_MEMBER(int32_t, bitstream_buffer_id)
@@ -130,62 +120,3 @@
 // Video decoder has encountered an error.
 IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_ErrorNotification,
                     uint32_t /* Error ID */)
-
-//------------------------------------------------------------------------------
-// Accelerated Video Encoder Messages
-// These messages are sent from the Renderer process to GPU process.
-
-// Create and initialize a hardware video encoder using the specified route_id.
-// Created encoders should be freed with AcceleratedVideoEncoderMsg_Destroy when
-// no longer needed.
-IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_CreateVideoEncoder,
-                           media::CreateVideoEncoderParams,
-                           bool /* succeeded */)
-
-// Queue a video frame to the encoder to encode. |frame_id| will be returned
-// by AcceleratedVideoEncoderHostMsg_NotifyInputDone.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoEncoderMsg_Encode,
-                    AcceleratedVideoEncoderMsg_Encode_Params)
-
-// Queue a buffer to the encoder for use in returning output.  |buffer_id| will
-// be returned by AcceleratedVideoEncoderHostMsg_BitstreamBufferReady.
-IPC_MESSAGE_ROUTED3(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
-                    int32_t /* buffer_id */,
-                    base::SharedMemoryHandle /* buffer_handle */,
-                    uint32_t /* buffer_size */)
-
-// Request a runtime encoding parameter change.
-IPC_MESSAGE_ROUTED2(AcceleratedVideoEncoderMsg_RequestEncodingParametersChange,
-                    uint32_t /* bitrate */,
-                    uint32_t /* framerate */)
-
-//------------------------------------------------------------------------------
-// Accelerated Video Encoder Host Messages
-// These messages are sent from GPU process to Renderer process.
-
-// Notify renderer of the input/output buffer requirements of the encoder.
-IPC_MESSAGE_ROUTED3(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers,
-                    uint32_t /* input_count */,
-                    gfx::Size /* input_coded_size */,
-                    uint32_t /* output_buffer_size */)
-
-// Notify the renderer that the encoder has finished using an input buffer.
-// There is no congruent entry point in the media::VideoEncodeAccelerator
-// interface, in VEA this same done condition is indicated by dropping the
-// reference to the media::VideoFrame passed to VEA::Encode().
-IPC_MESSAGE_ROUTED1(AcceleratedVideoEncoderHostMsg_NotifyInputDone,
-                    int32_t /* frame_id */)
-
-// Notify the renderer that an output buffer has been filled with encoded data.
-IPC_MESSAGE_ROUTED4(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady,
-                    int32_t /* bitstream_buffer_id */,
-                    uint32_t /* payload_size */,
-                    bool /* key_frame */,
-                    base::TimeDelta /* timestamp */)
-
-// Report error condition.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoEncoderHostMsg_NotifyError,
-                    media::VideoEncodeAccelerator::Error /* error */)
-
-// Send destroy request to the encoder.
-IPC_MESSAGE_ROUTED0(AcceleratedVideoEncoderMsg_Destroy)
diff --git a/media/gpu/ipc/service/BUILD.gn b/media/gpu/ipc/service/BUILD.gn
index d66a72d7..5550c3f 100644
--- a/media/gpu/ipc/service/BUILD.gn
+++ b/media/gpu/ipc/service/BUILD.gn
@@ -18,8 +18,6 @@
   sources = [
     "gpu_video_decode_accelerator.cc",
     "gpu_video_decode_accelerator.h",
-    "gpu_video_encode_accelerator.cc",
-    "gpu_video_encode_accelerator.h",
     "media_gpu_channel.cc",
     "media_gpu_channel.h",
     "media_gpu_channel_manager.cc",
diff --git a/media/gpu/ipc/service/gpu_video_encode_accelerator.cc b/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
deleted file mode 100644
index 45cb258..0000000
--- a/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
+++ /dev/null
@@ -1,445 +0,0 @@
-// Copyright 2013 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 "media/gpu/ipc/service/gpu_video_encode_accelerator.h"
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory.h"
-#include "base/numerics/safe_math.h"
-#include "base/sys_info.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "gpu/ipc/service/gpu_channel.h"
-#include "gpu/ipc/service/gpu_channel_manager.h"
-#include "ipc/ipc_message_macros.h"
-#include "media/base/bind_to_current_loop.h"
-#include "media/base/limits.h"
-#include "media/base/video_frame.h"
-#include "media/gpu/gpu_video_accelerator_util.h"
-#include "media/gpu/gpu_video_encode_accelerator_factory.h"
-#include "media/gpu/ipc/common/media_messages.h"
-#include "media/media_features.h"
-
-
-namespace media {
-
-namespace {
-
-void DropSharedMemory(std::unique_ptr<base::SharedMemory> shm) {
-  // Just let |shm| fall out of scope.
-}
-
-}  // anonymous namespace
-
-class GpuVideoEncodeAccelerator::MessageFilter : public IPC::MessageFilter {
- public:
-  MessageFilter(GpuVideoEncodeAccelerator* owner, int32_t host_route_id)
-      : owner_(owner), host_route_id_(host_route_id) {}
-
-  void OnChannelError() override { sender_ = nullptr; }
-
-  void OnChannelClosing() override { sender_ = nullptr; }
-
-  void OnFilterAdded(IPC::Channel* channel) override { sender_ = channel; }
-
-  void OnFilterRemoved() override { owner_->OnFilterRemoved(); }
-
-  bool OnMessageReceived(const IPC::Message& msg) override {
-    if (msg.routing_id() != host_route_id_)
-      return false;
-
-    IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg)
-      IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_Encode, owner_,
-                          GpuVideoEncodeAccelerator::OnEncode)
-      IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
-                          owner_,
-                          GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer)
-      IPC_MESSAGE_FORWARD(
-          AcceleratedVideoEncoderMsg_RequestEncodingParametersChange, owner_,
-          GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange)
-      IPC_MESSAGE_UNHANDLED(return false)
-    IPC_END_MESSAGE_MAP()
-    return true;
-  }
-
-  bool SendOnIOThread(IPC::Message* message) {
-    if (!sender_ || message->is_sync()) {
-      DCHECK(!message->is_sync());
-      delete message;
-      return false;
-    }
-    return sender_->Send(message);
-  }
-
- protected:
-  ~MessageFilter() override = default;
-
- private:
-  GpuVideoEncodeAccelerator* const owner_;
-  const int32_t host_route_id_;
-  // The sender to which this filter was added.
-  IPC::Sender* sender_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(MessageFilter);
-};
-
-GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(
-    int32_t host_route_id,
-    gpu::CommandBufferStub* stub,
-    const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
-    : host_route_id_(host_route_id),
-      stub_(stub),
-      input_format_(PIXEL_FORMAT_UNKNOWN),
-      output_buffer_size_(0),
-      filter_removed_(base::WaitableEvent::ResetPolicy::MANUAL,
-                      base::WaitableEvent::InitialState::NOT_SIGNALED),
-      encoder_worker_thread_("EncoderWorkerThread"),
-      main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      io_task_runner_(io_task_runner),
-      encode_task_runner_(main_task_runner_),
-      weak_this_factory_for_encoder_worker_(this),
-      weak_this_factory_(this) {
-  weak_this_for_encoder_worker_ =
-      weak_this_factory_for_encoder_worker_.GetWeakPtr();
-  weak_this_ = weak_this_factory_.GetWeakPtr();
-  stub_->AddDestructionObserver(this);
-}
-
-GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() {
-  // This class can only be self-deleted from OnWillDestroyStub(), which means
-  // the VEA has already been destroyed in there.
-  DCHECK(!encoder_);
-  DCHECK(!encoder_worker_thread_.IsRunning());
-}
-
-bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format,
-                                           const gfx::Size& input_visible_size,
-                                           VideoCodecProfile output_profile,
-                                           uint32_t initial_bitrate) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  DVLOG(1) << __func__
-           << " input_format=" << VideoPixelFormatToString(input_format)
-           << ", input_visible_size=" << input_visible_size.ToString()
-           << ", output_profile=" << GetProfileName(output_profile)
-           << ", initial_bitrate=" << initial_bitrate;
-  DCHECK(!encoder_);
-
-  if (!stub_->channel()->AddRoute(host_route_id_, stub_->sequence_id(), this)) {
-    DLOG(ERROR) << __func__ << " failed to add route";
-    return false;
-  }
-
-  if (input_visible_size.width() > limits::kMaxDimension ||
-      input_visible_size.height() > limits::kMaxDimension ||
-      input_visible_size.GetArea() > limits::kMaxCanvas) {
-    DLOG(ERROR) << __func__ << "too large input_visible_size "
-                << input_visible_size.ToString();
-    return false;
-  }
-
-  const gpu::GpuPreferences& gpu_preferences =
-      stub_->channel()->gpu_channel_manager()->gpu_preferences();
-
-  encoder_ = GpuVideoEncodeAcceleratorFactory::CreateVEA(
-      input_format, input_visible_size, output_profile, initial_bitrate, this,
-      gpu_preferences);
-  if (!encoder_) {
-    DLOG(ERROR) << __func__ << " Could not create VEA";
-    return false;
-  }
-
-  if (!encoder_worker_thread_.Start()) {
-    encoder_.reset();
-    DLOG(ERROR) << "Failed spawning encoder worker thread.";
-    return false;
-  }
-
-  input_format_ = input_format;
-  input_visible_size_ = input_visible_size;
-  // Attempt to set up performing encoding tasks on IO thread, if supported
-  // by the VEA.
-  if (encoder_->TryToSetupEncodeOnSeparateThread(weak_this_, io_task_runner_)) {
-    filter_ = new MessageFilter(this, host_route_id_);
-    stub_->channel()->AddFilter(filter_.get());
-    encode_task_runner_ = io_task_runner_;
-  }
-  encoder_worker_task_runner_ = encoder_worker_thread_.task_runner();
-  return true;
-}
-
-bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message)
-    IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode)
-    IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
-                        OnUseOutputBitstreamBuffer)
-    IPC_MESSAGE_HANDLER(
-        AcceleratedVideoEncoderMsg_RequestEncodingParametersChange,
-        OnRequestEncodingParametersChange)
-    IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Destroy, OnDestroy)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-bool GpuVideoEncodeAccelerator::Send(IPC::Message* message) {
-  if (filter_ && io_task_runner_->BelongsToCurrentThread()) {
-    return filter_->SendOnIOThread(message);
-  }
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  return stub_->channel()->Send(message);
-}
-
-void GpuVideoEncodeAccelerator::RequireBitstreamBuffers(
-    unsigned int input_count,
-    const gfx::Size& input_coded_size,
-    size_t output_buffer_size) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  if (!Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers(
-          host_route_id_, input_count, input_coded_size, output_buffer_size))) {
-    DLOG(ERROR) << __func__ << " failed.";
-    return;
-  }
-  input_coded_size_ = input_coded_size;
-  output_buffer_size_ = output_buffer_size;
-}
-
-void GpuVideoEncodeAccelerator::BitstreamBufferReady(
-    int32_t bitstream_buffer_id,
-    size_t payload_size,
-    bool key_frame,
-    base::TimeDelta timestamp) {
-  DCHECK(CheckIfCalledOnCorrectThread());
-  if (!Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady(
-          host_route_id_, bitstream_buffer_id, payload_size, key_frame,
-          timestamp))) {
-    DLOG(ERROR) << __func__ << " failed.";
-  }
-}
-
-void GpuVideoEncodeAccelerator::NotifyError(
-    VideoEncodeAccelerator::Error error) {
-  if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_,
-                                                           error))) {
-    DLOG(ERROR) << __func__ << " failed.";
-  }
-}
-
-void GpuVideoEncodeAccelerator::OnWillDestroyStub() {
-  DVLOG(2) << __func__;
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  DCHECK(stub_);
-
-  // The stub is going away, so we have to stop and destroy VEA here before
-  // returning. We cannot destroy the VEA before the IO thread message filter is
-  // removed however, since we cannot service incoming messages with VEA gone.
-  // We cannot simply check for existence of VEA on IO thread though, because
-  // we don't want to synchronize the IO thread with the ChildThread.
-  // So we have to wait for the RemoveFilter callback here instead and remove
-  // the VEA after it arrives and before returning.
-  if (filter_) {
-    stub_->channel()->RemoveFilter(filter_.get());
-    filter_removed_.Wait();
-  }
-
-  // We should stop |encoder_worker_thread_| before releasing |encoder_|, see
-  // https://crbug.com/715759.
-  if (encoder_worker_thread_.IsRunning()) {
-    encoder_worker_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&GpuVideoEncodeAccelerator::DestroyOnEncoderWorker,
-                   weak_this_for_encoder_worker_));
-    encoder_worker_thread_.Stop();
-  }
-
-  stub_->channel()->RemoveRoute(host_route_id_);
-  stub_->RemoveDestructionObserver(this);
-  encoder_.reset();
-  delete this;
-}
-
-// static
-gpu::VideoEncodeAcceleratorSupportedProfiles
-GpuVideoEncodeAccelerator::GetSupportedProfiles(
-    const gpu::GpuPreferences& gpu_preferences) {
-  return GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(
-      GpuVideoEncodeAcceleratorFactory::GetSupportedProfiles(gpu_preferences));
-}
-
-void GpuVideoEncodeAccelerator::OnFilterRemoved() {
-  DVLOG(2) << __func__;
-  DCHECK(io_task_runner_->BelongsToCurrentThread());
-
-  // We're destroying; cancel all callbacks.
-  weak_this_factory_.InvalidateWeakPtrs();
-  filter_removed_.Signal();
-}
-
-void GpuVideoEncodeAccelerator::OnEncode(
-    const AcceleratedVideoEncoderMsg_Encode_Params& params) {
-  DVLOG(3) << __func__ << " frame_id = " << params.frame_id
-           << ", buffer_size=" << params.buffer_size
-           << ", force_keyframe=" << params.force_keyframe;
-  DCHECK(CheckIfCalledOnCorrectThread());
-  DCHECK_EQ(PIXEL_FORMAT_I420, input_format_);
-
-  if (!encoder_)
-    return;
-
-  if (params.frame_id < 0) {
-    DLOG(ERROR) << __func__ << " invalid frame_id=" << params.frame_id;
-    NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
-    return;
-  }
-
-  encoder_worker_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&GpuVideoEncodeAccelerator::CreateEncodeFrameOnEncoderWorker,
-                 weak_this_for_encoder_worker_, params));
-}
-
-void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
-    int32_t buffer_id,
-    base::SharedMemoryHandle buffer_handle,
-    uint32_t buffer_size) {
-  DVLOG(3) << __func__ << " buffer_id=" << buffer_id
-           << ", buffer_size=" << buffer_size;
-  DCHECK(CheckIfCalledOnCorrectThread());
-  if (!encoder_)
-    return;
-  if (buffer_id < 0) {
-    DLOG(ERROR) << __func__ << " invalid buffer_id=" << buffer_id;
-    NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
-    return;
-  }
-  if (buffer_size < output_buffer_size_) {
-    DLOG(ERROR) << __func__ << " buffer too small for buffer_id=" << buffer_id;
-    NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
-    return;
-  }
-  encoder_->UseOutputBitstreamBuffer(
-      BitstreamBuffer(buffer_id, buffer_handle, buffer_size));
-}
-
-void GpuVideoEncodeAccelerator::OnDestroy() {
-  DVLOG(2) << __func__;
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  OnWillDestroyStub();
-}
-
-void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(
-    uint32_t bitrate,
-    uint32_t framerate) {
-  DVLOG(2) << __func__ << " bitrate=" << bitrate << ", framerate=" << framerate;
-  DCHECK(CheckIfCalledOnCorrectThread());
-  if (!encoder_)
-    return;
-  encoder_->RequestEncodingParametersChange(bitrate, framerate);
-}
-
-void GpuVideoEncodeAccelerator::CreateEncodeFrameOnEncoderWorker(
-    const AcceleratedVideoEncoderMsg_Encode_Params& params) {
-  DVLOG(3) << __func__;
-  DCHECK(encoder_worker_task_runner_->BelongsToCurrentThread());
-
-  // Wrap into a SharedMemory in the beginning, so that |params.buffer_handle|
-  // is cleaned properly in case of an early return.
-  std::unique_ptr<base::SharedMemory> shm(
-      new base::SharedMemory(params.buffer_handle, true));
-  const uint32_t aligned_offset =
-      params.buffer_offset % base::SysInfo::VMAllocationGranularity();
-  base::CheckedNumeric<off_t> map_offset = params.buffer_offset;
-  map_offset -= aligned_offset;
-  base::CheckedNumeric<size_t> map_size = params.buffer_size;
-  map_size += aligned_offset;
-
-  if (!map_offset.IsValid() || !map_size.IsValid()) {
-    DLOG(ERROR) << __func__ << "  invalid map_offset or map_size";
-    encode_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&GpuVideoEncodeAccelerator::NotifyError, weak_this_,
-                   VideoEncodeAccelerator::kPlatformFailureError));
-    return;
-  }
-
-  if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
-    DLOG(ERROR) << __func__ << " could not map frame_id=" << params.frame_id;
-    encode_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&GpuVideoEncodeAccelerator::NotifyError, weak_this_,
-                   VideoEncodeAccelerator::kPlatformFailureError));
-    return;
-  }
-
-  uint8_t* shm_memory =
-      reinterpret_cast<uint8_t*>(shm->memory()) + aligned_offset;
-  scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory(
-      input_format_, input_coded_size_, gfx::Rect(input_visible_size_),
-      input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle,
-      params.buffer_offset, params.timestamp);
-  if (!frame) {
-    DLOG(ERROR) << __func__ << " could not create a frame";
-    encode_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&GpuVideoEncodeAccelerator::NotifyError, weak_this_,
-                   VideoEncodeAccelerator::kPlatformFailureError));
-    return;
-  }
-
-  // We wrap |shm| in a callback and add it as a destruction observer, so it
-  // stays alive and mapped until |frame| goes out of scope.
-  frame->AddDestructionObserver(
-      base::Bind(&DropSharedMemory, base::Passed(&shm)));
-  encode_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&GpuVideoEncodeAccelerator::OnEncodeFrameCreated, weak_this_,
-                 params.frame_id, params.force_keyframe, frame));
-}
-
-void GpuVideoEncodeAccelerator::DestroyOnEncoderWorker() {
-  DCHECK(encoder_worker_task_runner_->BelongsToCurrentThread());
-  weak_this_factory_for_encoder_worker_.InvalidateWeakPtrs();
-}
-
-void GpuVideoEncodeAccelerator::OnEncodeFrameCreated(
-    int32_t frame_id,
-    bool force_keyframe,
-    const scoped_refptr<media::VideoFrame>& frame) {
-  DVLOG(3) << __func__;
-  DCHECK(CheckIfCalledOnCorrectThread());
-
-  if (filter_removed_.IsSignaled())
-    return;
-
-  if (!frame) {
-    DLOG(ERROR) << __func__ << " could not create a frame";
-    NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
-    return;
-  }
-
-  frame->AddDestructionObserver(BindToCurrentLoop(
-      base::Bind(&GpuVideoEncodeAccelerator::EncodeFrameFinished,
-                 weak_this_factory_.GetWeakPtr(), frame_id)));
-  encoder_->Encode(frame, force_keyframe);
-}
-
-void GpuVideoEncodeAccelerator::EncodeFrameFinished(int32_t frame_id) {
-  DCHECK(CheckIfCalledOnCorrectThread());
-  if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_,
-                                                               frame_id))) {
-    DLOG(ERROR) << __func__ << " failed.";
-  }
-}
-
-bool GpuVideoEncodeAccelerator::CheckIfCalledOnCorrectThread() {
-  return (filter_ && io_task_runner_->BelongsToCurrentThread()) ||
-         (!filter_ && main_task_runner_->BelongsToCurrentThread());
-}
-
-}  // namespace media
diff --git a/media/gpu/ipc/service/gpu_video_encode_accelerator.h b/media/gpu/ipc/service/gpu_video_encode_accelerator.h
deleted file mode 100644
index 249fd7e..0000000
--- a/media/gpu/ipc/service/gpu_video_encode_accelerator.h
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright 2013 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 MEDIA_GPU_IPC_SERVICE_GPU_VIDEO_ENCODE_ACCELERATOR_H_
-#define MEDIA_GPU_IPC_SERVICE_GPU_VIDEO_ENCODE_ACCELERATOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "gpu/config/gpu_info.h"
-#include "gpu/ipc/service/command_buffer_stub.h"
-#include "ipc/ipc_listener.h"
-#include "media/video/video_encode_accelerator.h"
-#include "ui/gfx/geometry/size.h"
-
-struct AcceleratedVideoEncoderMsg_Encode_Params;
-
-namespace gpu {
-struct GpuPreferences;
-}  // namespace gpu
-
-namespace media {
-
-// This class encapsulates the GPU process view of a VideoEncodeAccelerator,
-// wrapping the platform-specific VideoEncodeAccelerator instance.  It handles
-// IPC coming in from the renderer and passes it to the underlying VEA.
-class GpuVideoEncodeAccelerator
-    : public IPC::Listener,
-      public IPC::Sender,
-      public VideoEncodeAccelerator::Client,
-      public gpu::CommandBufferStub::DestructionObserver {
- public:
-  GpuVideoEncodeAccelerator(
-      int32_t host_route_id,
-      gpu::CommandBufferStub* stub,
-      const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
-  ~GpuVideoEncodeAccelerator() override;
-
-  // Initialize this accelerator with the given parameters and send
-  // |init_done_msg| when complete.
-  bool Initialize(VideoPixelFormat input_format,
-                  const gfx::Size& input_visible_size,
-                  VideoCodecProfile output_profile,
-                  uint32_t initial_bitrate);
-
-  // IPC::Listener implementation
-  bool OnMessageReceived(const IPC::Message& message) override;
-
-  // IPC::Sender implementation
-  bool Send(IPC::Message* message) override;
-
-  // VideoEncodeAccelerator::Client implementation.
-  void RequireBitstreamBuffers(unsigned int input_count,
-                               const gfx::Size& input_coded_size,
-                               size_t output_buffer_size) override;
-  void BitstreamBufferReady(int32_t bitstream_buffer_id,
-                            size_t payload_size,
-                            bool key_frame,
-                            base::TimeDelta timestamp) override;
-  void NotifyError(VideoEncodeAccelerator::Error error) override;
-
-  // gpu::CommandBufferStub::DestructionObserver implementation.
-  void OnWillDestroyStub() override;
-
-  // Static query for supported profiles.  This query calls the appropriate
-  // platform-specific version. The returned supported profiles vector will
-  // not contain duplicates.
-  static gpu::VideoEncodeAcceleratorSupportedProfiles GetSupportedProfiles(
-      const gpu::GpuPreferences& gpu_preferences);
-
- private:
-  // Returns a vector of VEAFactoryFunctions for the current platform.
-  using VEAFactoryFunction =
-      base::Callback<std::unique_ptr<VideoEncodeAccelerator>()>;
-  static std::vector<VEAFactoryFunction> GetVEAFactoryFunctions(
-      const gpu::GpuPreferences& gpu_preferences);
-
-  class MessageFilter;
-
-  // Called on IO thread when |filter_| has been removed.
-  void OnFilterRemoved();
-
-  // IPC handlers, proxying VideoEncodeAccelerator for the renderer
-  // process.
-  void OnEncode(const AcceleratedVideoEncoderMsg_Encode_Params& params);
-  void OnUseOutputBitstreamBuffer(int32_t buffer_id,
-                                  base::SharedMemoryHandle buffer_handle,
-                                  uint32_t buffer_size);
-  void OnRequestEncodingParametersChange(uint32_t bitrate, uint32_t framerate);
-
-  void OnDestroy();
-
-  // Operations that run on encoder worker thread.
-  void CreateEncodeFrameOnEncoderWorker(
-      const AcceleratedVideoEncoderMsg_Encode_Params& params);
-  void DestroyOnEncoderWorker();
-
-  // Completes encode tasks with the received |frame|.
-  void OnEncodeFrameCreated(int32_t frame_id,
-                            bool force_keyframe,
-                            const scoped_refptr<media::VideoFrame>& frame);
-
-  // Notifies renderer that |frame_id| can be reused as input for encode is
-  // completed.
-  void EncodeFrameFinished(int32_t frame_id);
-
-  // Checks that function is called on the correct thread. If MessageFilter is
-  // used, checks if it is called on |io_task_runner_|. If not, checks if it is
-  // called on |main_task_runner_|.
-  bool CheckIfCalledOnCorrectThread();
-
-  // Route ID to communicate with the host.
-  const uint32_t host_route_id_;
-
-  // Unowned pointer to the underlying gpu::CommandBufferStub.  |this| is
-  // registered as a DestuctionObserver of |stub_| and will self-delete when
-  // |stub_| is destroyed.
-  gpu::CommandBufferStub* const stub_;
-
-  // Owned pointer to the underlying VideoEncodeAccelerator.
-  std::unique_ptr<VideoEncodeAccelerator> encoder_;
-
-  // Video encoding parameters.
-  VideoPixelFormat input_format_;
-  gfx::Size input_visible_size_;
-  gfx::Size input_coded_size_;
-  size_t output_buffer_size_;
-
-  // The message filter to run VEA encode methods on IO thread if VEA supports
-  // it.
-  scoped_refptr<MessageFilter> filter_;
-
-  // Used to wait on for |filter_| to be removed, before we can safely
-  // destroy the VEA.
-  base::WaitableEvent filter_removed_;
-
-  // This thread services the operations necessary for encode so that they
-  // wouldn't block |main_task_runner_| or |io_task_runner_|.
-  base::Thread encoder_worker_thread_;
-  scoped_refptr<base::SingleThreadTaskRunner> encoder_worker_task_runner_;
-
-  // GPU main thread task runner.
-  const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
-
-  // GPU IO thread task runner.
-  const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
-  // Task runner used for posting encode tasks. If
-  // TryToSetupEncodeOnSeperateThread() is true, |io_task_runner_| is used,
-  // otherwise |main_thread_task_runner_|.
-  scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner_;
-
-  base::WeakPtr<GpuVideoEncodeAccelerator> weak_this_for_encoder_worker_;
-  base::WeakPtr<GpuVideoEncodeAccelerator> weak_this_;
-
-  // Weak pointer for referring back to |this| on |encoder_worker_task_runner_|.
-  base::WeakPtrFactory<GpuVideoEncodeAccelerator>
-      weak_this_factory_for_encoder_worker_;
-
-  // Weak pointer for VideoFrames that refer back to |this| on
-  // |main_task_runner| or |io_task_runner_|. |io_task_runner_| is used if and
-  // only if |filter_| is applied.
-  base::WeakPtrFactory<GpuVideoEncodeAccelerator> weak_this_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(GpuVideoEncodeAccelerator);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_GPU_IPC_SERVICE_GPU_VIDEO_ENCODE_ACCELERATOR_H_
diff --git a/media/gpu/ipc/service/media_gpu_channel.cc b/media/gpu/ipc/service/media_gpu_channel.cc
index f12ed3b..1b1e2e5 100644
--- a/media/gpu/ipc/service/media_gpu_channel.cc
+++ b/media/gpu/ipc/service/media_gpu_channel.cc
@@ -10,7 +10,6 @@
 #include "ipc/message_filter.h"
 #include "media/gpu/ipc/common/media_messages.h"
 #include "media/gpu/ipc/service/gpu_video_decode_accelerator.h"
-#include "media/gpu/ipc/service/gpu_video_encode_accelerator.h"
 
 namespace media {
 
@@ -28,11 +27,6 @@
                                    reply_message);
   }
 
-  void OnCreateVideoEncoder(const CreateVideoEncoderParams& params,
-                            IPC::Message* reply_message) {
-    channel_->OnCreateVideoEncoder(routing_id_, params, reply_message);
-  }
-
  private:
   MediaGpuChannel* const channel_;
   const int32_t routing_id_;
@@ -101,9 +95,6 @@
     IPC_MESSAGE_FORWARD_DELAY_REPLY(
         GpuCommandBufferMsg_CreateVideoDecoder, &helper,
         MediaGpuChannelDispatchHelper::OnCreateVideoDecoder)
-    IPC_MESSAGE_FORWARD_DELAY_REPLY(
-        GpuCommandBufferMsg_CreateVideoEncoder, &helper,
-        MediaGpuChannelDispatchHelper::OnCreateVideoEncoder)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -134,29 +125,4 @@
   // self-delete during destruction of this stub.
 }
 
-void MediaGpuChannel::OnCreateVideoEncoder(
-    int32_t command_buffer_route_id,
-    const CreateVideoEncoderParams& params,
-    IPC::Message* reply_message) {
-  TRACE_EVENT0("gpu", "MediaGpuChannel::OnCreateVideoEncoder");
-  gpu::CommandBufferStub* stub =
-      channel_->LookupCommandBuffer(command_buffer_route_id);
-  if (!stub) {
-    reply_message->set_reply_error();
-    Send(reply_message);
-    return;
-  }
-  GpuVideoEncodeAccelerator* encoder = new GpuVideoEncodeAccelerator(
-      params.encoder_route_id, stub, stub->channel()->io_task_runner());
-  bool succeeded =
-      encoder->Initialize(params.input_format, params.input_visible_size,
-                          params.output_profile, params.initial_bitrate);
-  GpuCommandBufferMsg_CreateVideoEncoder::WriteReplyParams(reply_message,
-                                                           succeeded);
-  Send(reply_message);
-
-  // encoder is registered as a DestructionObserver of this stub and will
-  // self-delete during destruction of this stub.
-}
-
 }  // namespace media
diff --git a/media/gpu/ipc/service/media_gpu_channel_manager.cc b/media/gpu/ipc/service/media_gpu_channel_manager.cc
index ee0d616..479ebaa 100644
--- a/media/gpu/ipc/service/media_gpu_channel_manager.cc
+++ b/media/gpu/ipc/service/media_gpu_channel_manager.cc
@@ -12,7 +12,6 @@
 #include "ipc/ipc_message_macros.h"
 #include "ipc/param_traits_macros.h"
 #include "media/gpu/ipc/service/gpu_video_decode_accelerator.h"
-#include "media/gpu/ipc/service/gpu_video_encode_accelerator.h"
 #include "media/gpu/ipc/service/media_gpu_channel.h"
 
 namespace media {
diff --git a/media/midi/midi_manager_android.h b/media/midi/midi_manager_android.h
index 0696b9f..6336a834 100644
--- a/media/midi/midi_manager_android.h
+++ b/media/midi/midi_manager_android.h
@@ -18,7 +18,6 @@
 #include "base/time/time.h"
 #include "media/midi/midi_input_port_android.h"
 #include "media/midi/midi_manager.h"
-#include "media/midi/midi_scheduler.h"
 
 namespace midi {
 
diff --git a/media/midi/midi_manager_usb.cc b/media/midi/midi_manager_usb.cc
index 353bb74b..68b0416 100644
--- a/media/midi/midi_manager_usb.cc
+++ b/media/midi/midi_manager_usb.cc
@@ -10,7 +10,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/stringprintf.h"
-#include "media/midi/midi_scheduler.h"
 #include "media/midi/midi_service.h"
 #include "media/midi/task_service.h"
 #include "media/midi/usb_midi_descriptor_parser.h"
diff --git a/media/mojo/interfaces/BUILD.gn b/media/mojo/interfaces/BUILD.gn
index 1c8aed47..b7c7aec 100644
--- a/media/mojo/interfaces/BUILD.gn
+++ b/media/mojo/interfaces/BUILD.gn
@@ -14,6 +14,7 @@
     "audio_output_stream.mojom",
     "audio_parameters.mojom",
     "cdm_proxy.mojom",
+    "cdm_service.mojom",
     "cdm_storage.mojom",
     "content_decryption_module.mojom",
     "decryptor.mojom",
@@ -22,6 +23,7 @@
     "jpeg_decode_accelerator.mojom",
     "media_log.mojom",
     "media_metrics_provider.mojom",
+    "media_service.mojom",
     "media_types.mojom",
     "output_protection.mojom",
     "platform_verification.mojom",
@@ -50,16 +52,15 @@
     "//url/mojo:url_mojom_origin",
   ]
 
-  # TODO(crbug.com/676224): Remove media_service_mac.mojom when we support
-  # EnabledIf attribute in mojom files.
+  # TODO(xhwang): Remove cdm_service_mac.mojom when we support EnabledIf
+  # attribute in mojom files. See https://crbug.com/676224
   if (is_mac) {
-    sources += [ "media_service_mac.mojom" ]
+    sources -= [ "cdm_service.mojom" ]
+    sources += [ "cdm_service_mac.mojom" ]
 
     # TODO(xhwang): Ideally media should not worry about sandbox. Find a way to
     # remove this dependency.
     public_deps += [ "//sandbox/mac/mojom" ]
-  } else {
-    sources += [ "media_service.mojom" ]
   }
 }
 
diff --git a/media/mojo/interfaces/cdm_service.mojom b/media/mojo/interfaces/cdm_service.mojom
new file mode 100644
index 0000000..195c9474
--- /dev/null
+++ b/media/mojo/interfaces/cdm_service.mojom
@@ -0,0 +1,29 @@
+// 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.
+
+module media.mojom;
+
+import "media/mojo/interfaces/interface_factory.mojom";
+import "mojo/common/file_path.mojom";
+import "services/service_manager/public/interfaces/interface_provider.mojom";
+
+// A service to provide media InterfaceFactory to provide CDM service, typically
+// to the media pipeline running in the renderer process. The service itself
+// runs in the CDM (utility) process. The service is always connected from the
+// browser process.
+interface CdmService {
+  // Loads the CDM at |cdm_path| into the process. Must be called before
+  // CreateInterfaceFactory(). Since the client will not know whether LoadCdm()
+  // has been called by a previous CdmService instance, the client should always
+  // call it after service connection. If the CDM is already loaded, this will
+  // be a no-op.
+  LoadCdm(mojo.common.mojom.FilePath cdm_path);
+
+  // Requests an InterfaceFactory. |host_interfaces| can optionally be used to
+  // provide interfaces hosted by the caller to the remote InterfaceFactory
+  // implementation.
+  CreateInterfaceFactory(
+      InterfaceFactory& factory,
+      service_manager.mojom.InterfaceProvider? host_interfaces);
+};
diff --git a/media/mojo/interfaces/media_service_mac.mojom b/media/mojo/interfaces/cdm_service_mac.mojom
similarity index 60%
rename from media/mojo/interfaces/media_service_mac.mojom
rename to media/mojo/interfaces/cdm_service_mac.mojom
index 4ba4b83..af4ac8d 100644
--- a/media/mojo/interfaces/media_service_mac.mojom
+++ b/media/mojo/interfaces/cdm_service_mac.mojom
@@ -12,20 +12,18 @@
 // TODO(xhwang): Merge this file with media_service.mojom once EnabledIf
 // attribute is supported in mojom files. See https://crbug.com/676224
 
-// A service to provide media InterfaceFactory, typically to the media pipeline
-// running in the renderer process. The service itself runs in the process
-// specified by the |mojo_media_host| gn build flag, or in the utility process
-// when this service runs as an standalone CDM service (see gn build flag
-// |enable_standalone_cdm_service| for details). The service is always connected
-// from the browser process.
-// TODO(crbug.com/771791): Separate CdmService from MediaService.
-interface MediaService {
-  // Loads the CDM at |cdm_path| into the process.
-  // Since the client will not know whether LoadCdm() has been called by a
-  // previous MediaService instance, the client should always call it after
-  // interface connection. If the CDM is already loaded, this will be a no-op.
+// A service to provide media InterfaceFactory to provide CDM service, typically
+// to the media pipeline running in the renderer process. The service itself
+// runs in the CDM (utility) process. The service is always connected from the
+// browser process.
+interface CdmService {
+  // Loads the CDM at |cdm_path| into the process. Must be called before
+  // CreateInterfaceFactory(). Since the client will not know whether LoadCdm()
+  // has been called by a previous CdmService instance, the client should always
+  // call it after service connection. If the CDM is already loaded, this will
+  // be a no-op.
   // |token_provider| can be used to get a sandbox seatbelt extension token
-  // synchronously so that the MediaService instance can load the CDM and other
+  // synchronously so that the CdmService instance can load the CDM and other
   // needed files within the Mac sandbox.
   LoadCdm(mojo.common.mojom.FilePath cdm_path,
           SeatbeltExtensionTokenProvider? token_provider);
diff --git a/media/mojo/interfaces/media_service.mojom b/media/mojo/interfaces/media_service.mojom
index b05ee05..306dbe8 100644
--- a/media/mojo/interfaces/media_service.mojom
+++ b/media/mojo/interfaces/media_service.mojom
@@ -5,23 +5,13 @@
 module media.mojom;
 
 import "media/mojo/interfaces/interface_factory.mojom";
-import "mojo/common/file_path.mojom";
 import "services/service_manager/public/interfaces/interface_provider.mojom";
 
 // A service to provide media InterfaceFactory, typically to the media pipeline
 // running in the renderer process. The service itself runs in the process
-// specified by the |mojo_media_host| gn build flag, or in the utility process
-// when this service runs as an standalone CDM service (see gn build flag
-// |enable_standalone_cdm_service| for details). The service is always connected
-// from the browser process.
-// TODO(crbug.com/771791): Separate CdmService from MediaService.
+// specified by the |mojo_media_host| gn build flag. The service is always
+// connected from the browser process.
 interface MediaService {
-  // Loads the CDM at |cdm_path| into the process.
-  // Since the client will not know whether LoadCdm() has been called by a
-  // previous MediaService instance, the client should always call it after
-  // interface connection. If the CDM is already loaded, this will be a no-op.
-  LoadCdm(mojo.common.mojom.FilePath cdm_path);
-
   // Requests an InterfaceFactory. |host_interfaces| can optionally be used to
   // provide interfaces hosted by the caller to the remote InterfaceFactory
   // implementation.
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn
index 2defc60..4e71898 100644
--- a/media/mojo/services/BUILD.gn
+++ b/media/mojo/services/BUILD.gn
@@ -12,6 +12,8 @@
 component("services") {
   output_name = "media_mojo_services"
   sources = [
+    "cdm_service.cc",
+    "cdm_service.h",
     "gpu_mojo_media_client.cc",
     "gpu_mojo_media_client.h",
     "interface_factory_impl.cc",
diff --git a/media/mojo/services/cdm_manifest.json b/media/mojo/services/cdm_manifest.json
index a287a145..96a06dd6 100644
--- a/media/mojo/services/cdm_manifest.json
+++ b/media/mojo/services/cdm_manifest.json
@@ -5,7 +5,7 @@
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": {
-        "media:cdm": [ "media::mojom::MediaService" ]
+        "media:cdm": [ "media::mojom::CdmService" ]
       },
       "requires": {
         "*": [ "app" ]
diff --git a/media/mojo/services/cdm_service.cc b/media/mojo/services/cdm_service.cc
new file mode 100644
index 0000000..27d9f45
--- /dev/null
+++ b/media/mojo/services/cdm_service.cc
@@ -0,0 +1,134 @@
+// 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 "media/mojo/services/cdm_service.h"
+
+#include "base/logging.h"
+#include "media/media_features.h"
+#include "media/mojo/services/interface_factory_impl.h"
+#include "media/mojo/services/mojo_media_client.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
+#include "media/cdm/cdm_module.h"
+#if defined(OS_MACOSX)
+#include <vector>
+#include "sandbox/mac/seatbelt_extension.h"
+#endif  // defined(OS_MACOSX)
+#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
+
+namespace media {
+
+CdmService::CdmService(std::unique_ptr<MojoMediaClient> mojo_media_client)
+    : mojo_media_client_(std::move(mojo_media_client)) {
+  DCHECK(mojo_media_client_);
+  registry_.AddInterface<mojom::CdmService>(
+      base::BindRepeating(&CdmService::Create, base::Unretained(this)));
+}
+
+CdmService::~CdmService() = default;
+
+void CdmService::OnStart() {
+  DVLOG(1) << __func__;
+
+  ref_factory_.reset(new service_manager::ServiceContextRefFactory(
+      base::BindRepeating(&service_manager::ServiceContext::RequestQuit,
+                          base::Unretained(context()))));
+  mojo_media_client_->Initialize(context()->connector());
+}
+
+void CdmService::OnBindInterface(
+    const service_manager::BindSourceInfo& source_info,
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle interface_pipe) {
+  DVLOG(1) << __func__ << ": interface_name = " << interface_name;
+
+  registry_.BindInterface(interface_name, std::move(interface_pipe));
+}
+
+bool CdmService::OnServiceManagerConnectionLost() {
+  interface_factory_bindings_.CloseAllBindings();
+  mojo_media_client_.reset();
+  return true;
+}
+
+void CdmService::Create(mojom::CdmServiceRequest request) {
+  bindings_.AddBinding(this, std::move(request));
+}
+
+#if defined(OS_MACOSX)
+void CdmService::LoadCdm(
+    const base::FilePath& cdm_path,
+    mojom::SeatbeltExtensionTokenProviderPtr token_provider) {
+#else
+void CdmService::LoadCdm(const base::FilePath& cdm_path) {
+#endif  // defined(OS_MACOSX)
+  DVLOG(1) << __func__ << ": cdm_path = " << cdm_path.value();
+
+  // Ignore request if service has already stopped.
+  if (!mojo_media_client_)
+    return;
+
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
+  CdmModule* instance = CdmModule::GetInstance();
+  if (instance->was_initialize_called()) {
+    DCHECK_EQ(cdm_path, instance->GetCdmPath());
+    return;
+  }
+
+#if defined(OS_MACOSX)
+  std::vector<sandbox::SeatbeltExtensionToken> tokens;
+  CHECK(token_provider->GetTokens(&tokens));
+
+  std::vector<std::unique_ptr<sandbox::SeatbeltExtension>> extensions;
+
+  for (auto&& token : tokens) {
+    DVLOG(3) << "token: " << token.token();
+    auto extension = sandbox::SeatbeltExtension::FromToken(std::move(token));
+    if (!extension->Consume()) {
+      DVLOG(1) << "Failed to comsume sandbox seatbelt extension. This could "
+                  "happen if --no-sandbox is specified.";
+    }
+    extensions.push_back(std::move(extension));
+  }
+#endif  // defined(OS_MACOSX)
+
+#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
+  std::vector<CdmHostFilePath> cdm_host_file_paths;
+  mojo_media_client_->AddCdmHostFilePaths(&cdm_host_file_paths);
+  if (!instance->Initialize(cdm_path, cdm_host_file_paths))
+    return;
+#else
+  if (!instance->Initialize(cdm_path))
+    return;
+#endif  // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
+
+  // This may trigger the sandbox to be sealed.
+  mojo_media_client_->EnsureSandboxed();
+
+#if defined(OS_MACOSX)
+  for (auto&& extension : extensions)
+    extension->Revoke();
+#endif  // defined(OS_MACOSX)
+
+  // Always called within the sandbox.
+  instance->InitializeCdmModule();
+#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
+}
+
+void CdmService::CreateInterfaceFactory(
+    mojom::InterfaceFactoryRequest request,
+    service_manager::mojom::InterfaceProviderPtr host_interfaces) {
+  // Ignore request if service has already stopped.
+  if (!mojo_media_client_)
+    return;
+
+  interface_factory_bindings_.AddBinding(
+      std::make_unique<InterfaceFactoryImpl>(
+          std::move(host_interfaces), &media_log_, ref_factory_->CreateRef(),
+          mojo_media_client_.get()),
+      std::move(request));
+}
+
+}  // namespace media
diff --git a/media/mojo/services/cdm_service.h b/media/mojo/services/cdm_service.h
new file mode 100644
index 0000000..e4aa13dc
--- /dev/null
+++ b/media/mojo/services/cdm_service.h
@@ -0,0 +1,80 @@
+// 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 MEDIA_MOJO_SERVICES_MEDIA_SERVICE_H_
+#define MEDIA_MOJO_SERVICES_MEDIA_SERVICE_H_
+
+#include <memory>
+
+#include "build/build_config.h"
+#include "media/base/media_log.h"
+#include "media/mojo/interfaces/interface_factory.mojom.h"
+#include "media/mojo/services/media_mojo_export.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/cpp/service.h"
+#include "services/service_manager/public/cpp/service_context.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
+
+#if defined(OS_MACOSX)
+#include "media/mojo/interfaces/cdm_service_mac.mojom.h"
+#else
+#include "media/mojo/interfaces/cdm_service.mojom.h"
+#endif  // defined(OS_MACOSX)
+
+namespace media {
+
+class MojoMediaClient;
+
+class MEDIA_MOJO_EXPORT CdmService : public service_manager::Service,
+                                     public mojom::CdmService {
+ public:
+  explicit CdmService(std::unique_ptr<MojoMediaClient> mojo_media_client);
+  ~CdmService() final;
+
+ private:
+  // service_manager::Service implementation.
+  void OnStart() final;
+  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
+                       const std::string& interface_name,
+                       mojo::ScopedMessagePipeHandle interface_pipe) override;
+  bool OnServiceManagerConnectionLost() final;
+
+  void Create(mojom::CdmServiceRequest request);
+
+// mojom::CdmService implementation.
+#if defined(OS_MACOSX)
+  void LoadCdm(const base::FilePath& cdm_path,
+               mojom::SeatbeltExtensionTokenProviderPtr token_provider) final;
+#else
+  void LoadCdm(const base::FilePath& cdm_path) final;
+#endif  // defined(OS_MACOSX)
+
+  void CreateInterfaceFactory(
+      mojom::InterfaceFactoryRequest request,
+      service_manager::mojom::InterfaceProviderPtr host_interfaces) final;
+
+  MediaLog media_log_;
+  std::unique_ptr<service_manager::ServiceContextRefFactory> ref_factory_;
+
+  // Note: Since each instance runs on a different thread, do not share a common
+  // MojoMediaClient with other instances to avoid threading issues. Hence using
+  // a unique_ptr here.
+  //
+  // Note: Since |*ref_factory_| is passed to |mojo_media_client_|,
+  // |mojo_media_client_| must be destructed before |ref_factory_|.
+  std::unique_ptr<MojoMediaClient> mojo_media_client_;
+
+  // Note: Since |&media_log_| is passed to bindings, the bindings must be
+  // destructed first.
+  mojo::StrongBindingSet<mojom::InterfaceFactory> interface_factory_bindings_;
+
+  service_manager::BinderRegistry registry_;
+  mojo::BindingSet<mojom::CdmService> bindings_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_MOJO_SERVICES_MEDIA_SERVICE_H_
diff --git a/media/mojo/services/media_service.cc b/media/mojo/services/media_service.cc
index 354032af..f5b61a77 100644
--- a/media/mojo/services/media_service.cc
+++ b/media/mojo/services/media_service.cc
@@ -4,23 +4,12 @@
 
 #include "media/mojo/services/media_service.h"
 
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "media/base/media_log.h"
+#include "base/logging.h"
 #include "media/media_features.h"
 #include "media/mojo/services/interface_factory_impl.h"
 #include "media/mojo/services/mojo_media_client.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/service_manager/public/cpp/connector.h"
 
-#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
-#include "media/cdm/cdm_module.h"
-#if defined(OS_MACOSX)
-#include "sandbox/mac/seatbelt_extension.h"
-#endif  // defined(OS_MACOSX)
-#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
-
 namespace media {
 
 MediaService::MediaService(std::unique_ptr<MojoMediaClient> mojo_media_client)
@@ -60,66 +49,6 @@
   bindings_.AddBinding(this, std::move(request));
 }
 
-#if defined(OS_MACOSX)
-void MediaService::LoadCdm(
-    const base::FilePath& cdm_path,
-    mojom::SeatbeltExtensionTokenProviderPtr token_provider) {
-#else
-void MediaService::LoadCdm(const base::FilePath& cdm_path) {
-#endif  // defined(OS_MACOSX)
-  DVLOG(1) << __func__ << ": cdm_path = " << cdm_path.value();
-
-  // Ignore request if service has already stopped.
-  if (!mojo_media_client_)
-    return;
-
-#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
-  CdmModule* instance = CdmModule::GetInstance();
-  if (instance->was_initialize_called()) {
-    DCHECK_EQ(cdm_path, instance->GetCdmPath());
-    return;
-  }
-
-#if defined(OS_MACOSX)
-  std::vector<sandbox::SeatbeltExtensionToken> tokens;
-  CHECK(token_provider->GetTokens(&tokens));
-
-  std::vector<std::unique_ptr<sandbox::SeatbeltExtension>> extensions;
-
-  for (auto&& token : tokens) {
-    DVLOG(3) << "token: " << token.token();
-    auto extension = sandbox::SeatbeltExtension::FromToken(std::move(token));
-    if (!extension->Consume()) {
-      DVLOG(1) << "Failed to comsume sandbox seatbelt extension. This could "
-                  "happen if --no-sandbox is specified.";
-    }
-    extensions.push_back(std::move(extension));
-  }
-#endif  // defined(OS_MACOSX)
-
-#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
-  std::vector<CdmHostFilePath> cdm_host_file_paths;
-  mojo_media_client_->AddCdmHostFilePaths(&cdm_host_file_paths);
-  if (!instance->Initialize(cdm_path, cdm_host_file_paths))
-    return;
-#else
-  if (!instance->Initialize(cdm_path))
-    return;
-#endif  // BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
-
-  // This may trigger the sandbox to be sealed.
-  mojo_media_client_->EnsureSandboxed();
-
-#if defined(OS_MACOSX)
-  for (auto&& extension : extensions)
-    extension->Revoke();
-#endif  // defined(OS_MACOSX)
-
-  // Always called within the sandbox.
-  instance->InitializeCdmModule();
-#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
-}
-
 void MediaService::CreateInterfaceFactory(
     mojom::InterfaceFactoryRequest request,
     service_manager::mojom::InterfaceProviderPtr host_interfaces) {
@@ -128,7 +57,7 @@
     return;
 
   interface_factory_bindings_.AddBinding(
-      base::MakeUnique<InterfaceFactoryImpl>(
+      std::make_unique<InterfaceFactoryImpl>(
           std::move(host_interfaces), &media_log_, ref_factory_->CreateRef(),
           mojo_media_client_.get()),
       std::move(request));
diff --git a/media/mojo/services/media_service.h b/media/mojo/services/media_service.h
index 41a3a0dc..5219eb2 100644
--- a/media/mojo/services/media_service.h
+++ b/media/mojo/services/media_service.h
@@ -5,16 +5,12 @@
 #ifndef MEDIA_MOJO_SERVICES_MEDIA_SERVICE_H_
 #define MEDIA_MOJO_SERVICES_MEDIA_SERVICE_H_
 
-#include <stdint.h>
-
 #include <memory>
 
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
 #include "build/build_config.h"
 #include "media/base/media_log.h"
 #include "media/mojo/interfaces/interface_factory.mojom.h"
+#include "media/mojo/interfaces/media_service.mojom.h"
 #include "media/mojo/services/media_mojo_export.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/strong_binding_set.h"
@@ -22,13 +18,6 @@
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/cpp/service_context.h"
 #include "services/service_manager/public/cpp/service_context_ref.h"
-#include "url/gurl.h"
-
-#if defined(OS_MACOSX)
-#include "media/mojo/interfaces/media_service_mac.mojom.h"
-#else
-#include "media/mojo/interfaces/media_service.mojom.h"
-#endif  // defined(OS_MACOSX)
 
 namespace media {
 
@@ -50,14 +39,6 @@
 
   void Create(mojom::MediaServiceRequest request);
 
-  // mojom::MediaService implementation.
-#if defined(OS_MACOSX)
-  void LoadCdm(const base::FilePath& cdm_path,
-               mojom::SeatbeltExtensionTokenProviderPtr token_provider) final;
-#else
-  void LoadCdm(const base::FilePath& cdm_path) final;
-#endif  // defined(OS_MACOSX)
-
   void CreateInterfaceFactory(
       mojom::InterfaceFactoryRequest request,
       service_manager::mojom::InterfaceProviderPtr host_interfaces) final;
diff --git a/media/mojo/services/media_service_unittest.cc b/media/mojo/services/media_service_unittest.cc
index 14f35e4..e56ceb3 100644
--- a/media/mojo/services/media_service_unittest.cc
+++ b/media/mojo/services/media_service_unittest.cc
@@ -23,6 +23,7 @@
 #include "media/mojo/interfaces/content_decryption_module.mojom.h"
 #include "media/mojo/interfaces/decryptor.mojom.h"
 #include "media/mojo/interfaces/interface_factory.mojom.h"
+#include "media/mojo/interfaces/media_service.mojom.h"
 #include "media/mojo/interfaces/renderer.mojom.h"
 #include "media/mojo/services/media_interface_provider.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
@@ -32,12 +33,6 @@
 #include "url/gurl.h"
 #include "url/origin.h"
 
-#if defined(OS_MACOSX)
-#include "media/mojo/interfaces/media_service_mac.mojom.h"
-#else
-#include "media/mojo/interfaces/media_service.mojom.h"
-#endif  // defined(OS_MACOSX)
-
 using testing::Exactly;
 using testing::Invoke;
 using testing::InvokeWithoutArgs;
diff --git a/media/test/data/eme_player_js/globals.js b/media/test/data/eme_player_js/globals.js
index 84423e4e..3d9d47b 100644
--- a/media/test/data/eme_player_js/globals.js
+++ b/media/test/data/eme_player_js/globals.js
@@ -49,6 +49,7 @@
 var VERIFY_HOST_FILES_TEST_KEYSYSTEM =
     'org.chromium.externalclearkey.verifycdmhosttest';
 var STORAGE_ID_TEST_KEYSYSTEM = 'org.chromium.externalclearkey.storageidtest';
+var CDM_PROXY_TEST_KEYSYSTEM = 'org.chromium.externalclearkey.cdmproxytest';
 
 // Key system name:value map to show on the document page.
 var KEY_SYSTEMS = {
diff --git a/media/test/data/eme_player_js/player_utils.js b/media/test/data/eme_player_js/player_utils.js
index f32fe91..f317835 100644
--- a/media/test/data/eme_player_js/player_utils.js
+++ b/media/test/data/eme_player_js/player_utils.js
@@ -298,6 +298,7 @@
       case PLATFORM_VERIFICATION_TEST_KEYSYSTEM:
       case VERIFY_HOST_FILES_TEST_KEYSYSTEM:
       case STORAGE_ID_TEST_KEYSYSTEM:
+      case CDM_PROXY_TEST_KEYSYSTEM:
         return UnitTestPlayer;
       default:
         Utils.timeLog(keySystem + ' is not a known key system');
diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md
index fb46a93..6b85ff0a 100644
--- a/mojo/public/cpp/bindings/README.md
+++ b/mojo/public/cpp/bindings/README.md
@@ -441,6 +441,30 @@
 calls are dispatched to the implementation and the connection error handler (if
 registered) won't be called.
 
+### Best practices for dealing with process crashes and callbacks
+A common situation when calling mojo interface methods that take a callback is
+that the caller wants to know if the other endpoint is torn down (e.g. because
+of a crash). In that case, the consumer usually wants to know if the response
+callback won't be run. There are different solutions for this problem, depending
+on how the `InterfacePtr<T>` is held:
+1. The consumer owns the `InterfacePtr<T>`: `set_connection_error_handler`
+   should be used.
+2. The consumer doesn't own the `InterfacePtr<T>`: there are two helpers
+   depending on the behavior that the caller wants. If the caller wants to
+   ensure that an error handler is run, then
+   [**`mojo::WrapCallbackWithDropHandler`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/callback_helpers.h?l=46)
+   should be used. If the caller wants the callback to always be run, then
+   [**`mojo::WrapCallbackWithDefaultInvokeIfNotRun`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/callback_helpers.h?l=40)
+   helper should be used. With both of these helpers, usual callback care should
+   be followed to ensure that the callbacks don't run after the consumer is
+   destructed (e.g. because the owner of the `InterfacePtr<T>` outlives the
+   consumer). This includes using
+   [**`base::WeakPtr`**](https://cs.chromium.org/chromium/src/base/memory/weak_ptr.h?l=5)
+   or
+   [**`base::RefCounted`**](https://cs.chromium.org/chromium/src/base/memory/ref_counted.h?l=246).
+   It should also be noted that with these helpers, the callbacks could be run
+   synchronously while the InterfacePtr<T> is reset or destroyed.
+
 ### A Note About Ordering
 
 As mentioned in the previous section, closing one end of a pipe will eventually
@@ -845,7 +869,7 @@
 A **strong binding** exists as a standalone object which owns its interface
 implementation and automatically cleans itself up when its bound interface
 endpoint detects an error. The
-[**`MakeStrongBinding`**](https://cs.chromim.org/chromium/src//mojo/public/cpp/bindings/strong_binding.h)
+[**`MakeStrongBinding`**](https://cs.chromim.org/chromium/src/mojo/public/cpp/bindings/strong_binding.h)
 function is used to create such a binding.
 .
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index fc79f68..f37dc77 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -2302,9 +2302,7 @@
     "server/web_socket_encoder.cc",
     "server/web_socket_encoder.h",
   ]
-  configs += [
-    "//build/config/compiler:wexit_time_destructors",
-  ]
+  configs += [ "//build/config/compiler:wexit_time_destructors" ]
   deps = [
     ":net",
     "//base",
@@ -2397,6 +2395,7 @@
     "data/ssl/certificates/client_6.pk8",
     "data/ssl/certificates/client_6_ca.pem",
     "data/ssl/certificates/client_root_ca.pem",
+    "data/ssl/certificates/common_name_only.pem",
     "data/ssl/certificates/crit-codeSigning-chain.pem",
     "data/ssl/certificates/crlset_by_intermediate_serial.raw",
     "data/ssl/certificates/crlset_by_leaf_spki.raw",
@@ -2494,6 +2493,7 @@
     "data/ssl/certificates/sha1_2016.pem",
     "data/ssl/certificates/sha1_dec_2015.pem",
     "data/ssl/certificates/sha1_jan_2016.pem",
+    "data/ssl/certificates/sha1_leaf.pem",
     "data/ssl/certificates/spdy_pooling.pem",
     "data/ssl/certificates/start_after_expiry.pem",
     "data/ssl/certificates/subjectAltName_sanity_check.pem",
@@ -2648,9 +2648,7 @@
     "url_request/url_request_test_util.h",
   ]
 
-  configs += [
-    "//build/config:precompiled_headers",
-  ]
+  configs += [ "//build/config:precompiled_headers" ]
 
   public_deps = [
     ":traffic_annotation",
@@ -5296,9 +5294,7 @@
   ]
   net_unfiltered_sources = []
 
-  configs += [
-    "//build/config:precompiled_headers",
-  ]
+  configs += [ "//build/config:precompiled_headers" ]
   defines = []
 
   deps = [
diff --git a/net/data/ssl/certificates/common_name_only.pem b/net/data/ssl/certificates/common_name_only.pem
new file mode 100644
index 0000000..5f7811a0
--- /dev/null
+++ b/net/data/ssl/certificates/common_name_only.pem
@@ -0,0 +1,109 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCp1J9FuvCmfgoP
+pUn3w+iVRBwBOCXlZyzRcfRsiOfEGNnY8gEDNoyccKFHnj5rtJ/kQc9IgcZC2nob
+qUSdHBEhUjKZbDZXOTXlBmpVY3qw0edMgwS9SSmaM5axPXEqJn7KShyzEC+3qux1
+T+gH8DBgwiP2qjM1A6nqf0/QDDms15sKhZJm9Z/MBpbpO/4zPjYSdsADv9sc7uyU
+xRnNp3PQWu/hZjgg9w0tZWOzBaKHTHJLV+wH8frRqwLdHoB+gSIUfmNnGHKe59ia
+rWjGU4l5b4kOVS8e5dSfdvNLbUM8z8dMvRq68fJnCJLkqnV7cehYmi+c6iGvDbkV
+y7vVzfWnAgMBAAECggEALyW5+c/GE1KWVHWcrU4T+axo4eXGj4MvLA4ovyDaxtPn
+VpUItu2j56JVA97okVoZsXKbqxNsCQ9CKv+47qzmDIwXRASIqXpWffhj+MSfQQtk
+3Rbab/optIdx5E6cZgk91cbxZLyvopuu/XprfhiuNY5wEYB6qtMTjug9LhLWyCa3
+N2tTlIi8qMa79HPYcJ3l7en8jXrx+/856hCGGXXNP6H3HP4Kf171tZryDuekJhwt
+pm6chDeFMkvJVa8GflKUxC5aVqhb84apCArvuaP/IXlDf0mEcyToyTjQaHitWtYo
+BqueC3wMU5e5TvfQ3CKutWP3L9fQzU/mzpbEAuMMcQKBgQDUU47C0xwaIhfTyY2V
+j9xDoEyJiRiaw0wUg2WtlNyIfUCOJSFxHeXqCmu1TurBxoNprlWZCf+myBR7hKXV
+XbjRSluo7EFe6qF5ZxfVkTgaggSUmqd65kCDGyWQTZQ4tw+qal6T3TekJOwoAPa0
+ifKfPmzW/uleFwsXRJb5ydNA3QKBgQDMw13gt6s9xSAjvmZwdHdwb7712K4RrcoL
+vrdOI6HEVDYsu2+zJxEtp0koE1Dk5LBUP4VAaDw1ABcx+Qon29mFy/orc8uH0PEu
+SES6kZxr70eKJ67jvgs370m8zM+IJsC4RJ1wu09Q0vsdJ2TZLG5jlQD1no08Ta37
+Wv27zenGUwKBgH7ukPsBj9xDo3D2HlFaFnjLPNZAAliLBlGBF+kEhC6Iim4v3mUs
+VYVrw2Y5jnhXf7pPAVcjNhVzqWMKMsVyaQmdZVyAGLhwliXorsP7M8oNDkX0iskb
+G1gFg5hX+JNLRO9A9dd5uUjE1fU4VkQp78SpYhHJhKO+LOA1HfioYkV1AoGALHAt
+3Iof2M0CN5+nvboY/cbSq6o1xNJxqfDe+U9UWTZpd3XKPRg6ay0F/HOMt9BF0FLk
+yWCVyG7XmdnRcWsOHzJwfaOoxTX8Ua4PdGoLh4UrgnkwRG7HIoGFADt2wraeVp9V
+h9Su1vyi0OXuxg8VefkpdyTMxAybuJQ7wtliZc8CgYEAouBfKjc3xn/jrf++kgie
+taZ+ormKZs2mfTfcEMeQv7Bd7sEUWCoRevdorTlHaw1DKBqFq56Y1v3ppH83C6DH
+5v1+43M6zq7qWGSgf5nbQ1ZBMUR0FMcBujc9JFX52Zc7ScvE1hwMT3lBJut/ln5W
+h1oQd50MoCr4WE39Em4/H3o=
+-----END PRIVATE KEY-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 24 (0x18)
+    Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C=US, ST=California, L=Mountain View, O=Test CA, CN=Test Root CA
+        Validity
+            Not Before: Dec 20 00:00:00 2017 GMT
+            Not After : Dec 20 00:00:00 2020 GMT
+        Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:a9:d4:9f:45:ba:f0:a6:7e:0a:0f:a5:49:f7:c3:
+                    e8:95:44:1c:01:38:25:e5:67:2c:d1:71:f4:6c:88:
+                    e7:c4:18:d9:d8:f2:01:03:36:8c:9c:70:a1:47:9e:
+                    3e:6b:b4:9f:e4:41:cf:48:81:c6:42:da:7a:1b:a9:
+                    44:9d:1c:11:21:52:32:99:6c:36:57:39:35:e5:06:
+                    6a:55:63:7a:b0:d1:e7:4c:83:04:bd:49:29:9a:33:
+                    96:b1:3d:71:2a:26:7e:ca:4a:1c:b3:10:2f:b7:aa:
+                    ec:75:4f:e8:07:f0:30:60:c2:23:f6:aa:33:35:03:
+                    a9:ea:7f:4f:d0:0c:39:ac:d7:9b:0a:85:92:66:f5:
+                    9f:cc:06:96:e9:3b:fe:33:3e:36:12:76:c0:03:bf:
+                    db:1c:ee:ec:94:c5:19:cd:a7:73:d0:5a:ef:e1:66:
+                    38:20:f7:0d:2d:65:63:b3:05:a2:87:4c:72:4b:57:
+                    ec:07:f1:fa:d1:ab:02:dd:1e:80:7e:81:22:14:7e:
+                    63:67:18:72:9e:e7:d8:9a:ad:68:c6:53:89:79:6f:
+                    89:0e:55:2f:1e:e5:d4:9f:76:f3:4b:6d:43:3c:cf:
+                    c7:4c:bd:1a:ba:f1:f2:67:08:92:e4:aa:75:7b:71:
+                    e8:58:9a:2f:9c:ea:21:af:0d:b9:15:cb:bb:d5:cd:
+                    f5:a7
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Subject Key Identifier: 
+                41:E5:87:59:14:3F:3E:99:24:67:DF:F8:B7:59:F6:81:3D:9C:F7:14
+            X509v3 Authority Key Identifier: 
+                keyid:9B:26:0B:8A:98:A9:BB:1D:B9:1F:1C:E3:1A:40:33:ED:8E:17:88:AB
+
+            X509v3 Extended Key Usage: 
+                TLS Web Server Authentication, TLS Web Client Authentication
+    Signature Algorithm: sha256WithRSAEncryption
+         39:41:78:9d:38:e1:d2:7e:92:34:7a:da:32:6c:2d:51:d6:a4:
+         c1:d9:84:5f:24:2e:8f:ce:a8:60:29:ba:01:01:4b:a3:e0:fe:
+         56:9c:5a:0b:8b:9f:b1:b6:55:89:0e:40:8f:09:0c:10:f1:dc:
+         9a:3d:85:7c:ef:83:f9:0e:42:81:89:ac:a4:11:b9:e9:fd:db:
+         58:54:63:51:66:5c:0e:0e:42:68:58:d9:0e:aa:54:70:6d:e7:
+         51:e5:8b:fd:d0:da:dd:7b:b9:97:55:42:42:e7:39:b4:4b:4b:
+         c4:89:90:d1:6e:4b:0a:fd:cc:a8:a3:a7:70:ed:d6:e8:c4:09:
+         80:d7:b0:09:ae:db:d2:4b:4f:0a:ec:73:28:bf:6f:cb:61:bd:
+         ab:5f:9a:2d:81:5e:e0:be:8c:32:d1:24:ea:a3:83:04:b8:81:
+         97:e2:26:91:a2:fa:da:18:fa:54:58:46:d9:38:9b:66:b0:80:
+         1d:a3:55:5b:86:7d:77:ca:0c:ba:e1:e6:c5:8c:e3:08:73:0f:
+         73:b7:8b:42:75:6b:62:6e:bf:73:2d:4c:11:07:b4:b7:a0:72:
+         0d:23:08:4b:65:8e:fd:1d:61:15:e6:d0:a5:ad:31:0b:d4:35:
+         3a:f7:aa:e7:50:38:a2:dc:b0:24:52:9d:86:fc:ce:1a:d8:29:
+         4b:de:82:af
+-----BEGIN CERTIFICATE-----
+MIIDrTCCApWgAwIBAgIBGDANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTE3MTIyMDAw
+MDAwMFoXDTIwMTIyMDAwMDAwMFowYDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh
+bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg
+Q0ExEjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAKnUn0W68KZ+Cg+lSffD6JVEHAE4JeVnLNFx9GyI58QY2djyAQM2jJxw
+oUeePmu0n+RBz0iBxkLaehupRJ0cESFSMplsNlc5NeUGalVjerDR50yDBL1JKZoz
+lrE9cSomfspKHLMQL7eq7HVP6AfwMGDCI/aqMzUDqep/T9AMOazXmwqFkmb1n8wG
+luk7/jM+NhJ2wAO/2xzu7JTFGc2nc9Ba7+FmOCD3DS1lY7MFoodMcktX7Afx+tGr
+At0egH6BIhR+Y2cYcp7n2JqtaMZTiXlviQ5VLx7l1J9280ttQzzPx0y9Grrx8mcI
+kuSqdXtx6FiaL5zqIa8NuRXLu9XN9acCAwEAAaNvMG0wDAYDVR0TAQH/BAIwADAd
+BgNVHQ4EFgQUQeWHWRQ/PpkkZ9/4t1n2gT2c9xQwHwYDVR0jBBgwFoAUmyYLipip
+ux25HxzjGkAz7Y4XiKswHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0G
+CSqGSIb3DQEBCwUAA4IBAQA5QXidOOHSfpI0etoybC1R1qTB2YRfJC6PzqhgKboB
+AUuj4P5WnFoLi5+xtlWJDkCPCQwQ8dyaPYV874P5DkKBiaykEbnp/dtYVGNRZlwO
+DkJoWNkOqlRwbedR5Yv90Nrde7mXVUJC5zm0S0vEiZDRbksK/cyoo6dw7dboxAmA
+17AJrtvSS08K7HMov2/LYb2rX5otgV7gvowy0STqo4MEuIGX4iaRovraGPpUWEbZ
+OJtmsIAdo1Vbhn13ygy64ebFjOMIcw9zt4tCdWtibr9zLUwRB7S3oHINIwhLZY79
+HWEV5tClrTEL1DU696rnUDii3LAkUp2G/M4a2ClL3oKv
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/sha1_leaf.pem b/net/data/ssl/certificates/sha1_leaf.pem
new file mode 100644
index 0000000..598b48d
--- /dev/null
+++ b/net/data/ssl/certificates/sha1_leaf.pem
@@ -0,0 +1,112 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCt5Mpt4Jw+UG9v
+qfdbenxHoJJ8YcG9PZssBRhmA4GIwNGoYqG5D50gMxppUybpdZtQus+FF/lS8v2R
+0+my4D3cgLo+eIebg2oqhz/x5QLQlWsGvcjcn6bTg0INuK9vn9HNqeMQkDotxK9X
+zvcbKazzxzV1K81PGgocpjhj10qdOZoboDu+eTN8bFe13uRNFG13l1nQmU0B6R6n
+BreDtxggA/C9H0x9YjRVyDamxwXe5c1yrye2HZXdxJneEEm+CMUSjKXlpK1it/+U
+1mafGMtrSdl++aspmO3lZ61TUNdSqdSUBGL8azw7AzewvRj48KN8V4EPG7WUvu4a
+CrZpy3O1AgMBAAECggEAcz5ibcliouWZxK4m0YhuXuXqzuXWiP0QHm9OCSWfrirj
+h62+MjBH2LQld9H0wtn/UdRMfY8y3CdPp1qC0dpNBRqG06n7bTP9oyu5VC2K3QN5
+R6F1QcnIvPqLRx6znc2UNLG3Wx3KgNSNxCrUlzradUD7i6i4ywid1PjP/FMNDv6q
+k07xSxc0VpWwkUC0j3uau0qewfnjP3+Toe7au4vHhy+Opyudsu4WETlbhkZq2mlD
+bgUS8/06FOjlf/2tfnElysL2NPvj0sFpm1yUckxZVjiepJ8QfqU46zsxUTqKrtca
+b6kYiJmB30wSxwnsweBhJ6w7UOOV6kmB6scc5OD2IQKBgQDgZESH7yLkqBdY1qFE
+AfWvyMfIe/buB8UNLcicGuSPkjdtCzsXoDgzXxt37RSLFMsPTDBM51KPAzJkWaeM
+Jksbivw/+bEFTyY/AaYreiRHrpIXvLM/mNJFZ514ImZ+mY8YU7nuTZRMn7Ysfs9c
+kHc7r3ET65KOcnXtPVGk6h2rHQKBgQDGY4dc0vWHktGLLqmgIJZHVcojj4NLuX67
+KCj1/DhNFpJhq24MKucxmaOlXXXPgEGTA/JwWnolo1fcT2Vv4LrlgL75SYVHOF71
+2PTIrlM3w6lOJNyzyD3Sjh2wZ87u993P2z6Z/qDWOMTdfD/jvyoU/k1uq6rTxJzy
+SktzfqRveQKBgBwI6vcAzZ870Q7sYeGZTRTVRQCrXEKI/fmTisjWI1A8uGgLSyq8
+fckNTOVC3Zoy0tvqbO5uyEXN5HHdMa206xVZ3AIyNAexx9l/Xz93VykNinskvFBp
+y3uYYngr9BpFHTew3j4Du0+HdL9CaK3r7rmqRbpzaDAb5NfrHVQ5W9ORAoGASfSq
+bnkaHKsnwFnp1A6x1u/tRepnCKCi1MQ42NJobpxef1h30sNfokbjEW9QzsTCLTsI
+csfXxxYoV7GlX9qH8axYBPhaXd1u0PlK71DFJwGiqMXnHIImQcrG2I8qPj1ai/Tw
+VlnsvU82XFbIPm9yEZdnaD1Ill8yHsSBchGg3QkCgYEAxZcgtHjspR9TTzuyl8qm
+gciF8YDwYIIHqOPnVKoC6+EQJf/BJnTU5naf56sa4aMg9eqqNA5eG0aohM1uZJAJ
+TaxkXZ8wTCwFoIh6O05+SD4bHDWvr7Sur1z0HeasYH2OPf/H/N0Xuq10rphCr7dx
+HYbEecCcSPrbEtOR7++xRvA=
+-----END PRIVATE KEY-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 23 (0x17)
+    Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=US, ST=California, L=Mountain View, O=Test CA, CN=Test Root CA
+        Validity
+            Not Before: Dec 20 00:00:00 2017 GMT
+            Not After : Dec 20 00:00:00 2020 GMT
+        Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:ad:e4:ca:6d:e0:9c:3e:50:6f:6f:a9:f7:5b:7a:
+                    7c:47:a0:92:7c:61:c1:bd:3d:9b:2c:05:18:66:03:
+                    81:88:c0:d1:a8:62:a1:b9:0f:9d:20:33:1a:69:53:
+                    26:e9:75:9b:50:ba:cf:85:17:f9:52:f2:fd:91:d3:
+                    e9:b2:e0:3d:dc:80:ba:3e:78:87:9b:83:6a:2a:87:
+                    3f:f1:e5:02:d0:95:6b:06:bd:c8:dc:9f:a6:d3:83:
+                    42:0d:b8:af:6f:9f:d1:cd:a9:e3:10:90:3a:2d:c4:
+                    af:57:ce:f7:1b:29:ac:f3:c7:35:75:2b:cd:4f:1a:
+                    0a:1c:a6:38:63:d7:4a:9d:39:9a:1b:a0:3b:be:79:
+                    33:7c:6c:57:b5:de:e4:4d:14:6d:77:97:59:d0:99:
+                    4d:01:e9:1e:a7:06:b7:83:b7:18:20:03:f0:bd:1f:
+                    4c:7d:62:34:55:c8:36:a6:c7:05:de:e5:cd:72:af:
+                    27:b6:1d:95:dd:c4:99:de:10:49:be:08:c5:12:8c:
+                    a5:e5:a4:ad:62:b7:ff:94:d6:66:9f:18:cb:6b:49:
+                    d9:7e:f9:ab:29:98:ed:e5:67:ad:53:50:d7:52:a9:
+                    d4:94:04:62:fc:6b:3c:3b:03:37:b0:bd:18:f8:f0:
+                    a3:7c:57:81:0f:1b:b5:94:be:ee:1a:0a:b6:69:cb:
+                    73:b5
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Subject Key Identifier: 
+                18:9A:76:1E:86:4C:EF:67:5D:20:7F:24:4C:DC:3F:AE:B5:B5:5C:A1
+            X509v3 Authority Key Identifier: 
+                keyid:9B:26:0B:8A:98:A9:BB:1D:B9:1F:1C:E3:1A:40:33:ED:8E:17:88:AB
+
+            X509v3 Extended Key Usage: 
+                TLS Web Server Authentication, TLS Web Client Authentication
+            X509v3 Subject Alternative Name: 
+                IP Address:127.0.0.1
+    Signature Algorithm: sha1WithRSAEncryption
+         a0:b6:c2:65:a0:9b:25:b7:c9:81:9a:dc:63:aa:ae:6e:f3:8a:
+         62:92:66:6e:ad:3d:a7:fd:26:d4:ea:7b:7c:00:80:2b:73:db:
+         36:86:fe:b1:b5:8a:05:40:d3:3c:6f:1d:11:1b:b2:a0:0d:f6:
+         26:aa:ac:63:62:61:c0:7e:b0:7d:da:73:2c:14:71:41:fd:93:
+         f5:76:cd:21:13:42:df:e5:b0:26:e8:d0:ec:a2:e4:26:b8:ba:
+         e8:bd:49:f9:38:7f:92:1c:a2:7e:8f:b3:d3:e6:0a:51:60:88:
+         c4:ab:08:65:14:53:fd:c3:70:8a:6f:49:99:d7:09:38:00:20:
+         b5:3d:3c:f1:7c:2c:ab:67:4d:df:1d:c2:1e:24:d3:31:60:71:
+         be:b3:85:7e:a7:1e:ce:41:1f:21:58:63:83:3c:e5:91:4a:18:
+         4d:6c:97:13:d5:df:34:c7:22:0a:92:3a:fb:03:3a:b8:62:2b:
+         7e:be:03:fb:39:74:03:1d:f3:c7:55:28:e7:ed:cd:28:75:2b:
+         75:c5:38:b7:fd:da:98:60:61:0a:aa:eb:17:1a:26:e1:74:7e:
+         84:e8:76:bf:15:18:e3:b2:4e:25:41:cb:2b:19:c9:63:6f:aa:
+         8a:58:c7:01:2a:cd:fc:04:ea:63:7f:b3:ed:5d:96:a2:b0:26:
+         63:8d:0d:3f
+-----BEGIN CERTIFICATE-----
+MIIDvzCCAqegAwIBAgIBFzANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHVGVzdCBDQTEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTE3MTIyMDAw
+MDAwMFoXDTIwMTIyMDAwMDAwMFowYDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh
+bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg
+Q0ExEjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAK3kym3gnD5Qb2+p91t6fEegknxhwb09mywFGGYDgYjA0ahiobkPnSAz
+GmlTJul1m1C6z4UX+VLy/ZHT6bLgPdyAuj54h5uDaiqHP/HlAtCVawa9yNyfptOD
+Qg24r2+f0c2p4xCQOi3Er1fO9xsprPPHNXUrzU8aChymOGPXSp05mhugO755M3xs
+V7Xe5E0UbXeXWdCZTQHpHqcGt4O3GCAD8L0fTH1iNFXINqbHBd7lzXKvJ7Ydld3E
+md4QSb4IxRKMpeWkrWK3/5TWZp8Yy2tJ2X75qymY7eVnrVNQ11Kp1JQEYvxrPDsD
+N7C9GPjwo3xXgQ8btZS+7hoKtmnLc7UCAwEAAaOBgDB+MAwGA1UdEwEB/wQCMAAw
+HQYDVR0OBBYEFBiadh6GTO9nXSB/JEzcP661tVyhMB8GA1UdIwQYMBaAFJsmC4qY
+qbsduR8c4xpAM+2OF4irMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAP
+BgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEBBQUAA4IBAQCgtsJloJslt8mBmtxj
+qq5u84pikmZurT2n/SbU6nt8AIArc9s2hv6xtYoFQNM8bx0RG7KgDfYmqqxjYmHA
+frB92nMsFHFB/ZP1ds0hE0Lf5bAm6NDsouQmuLrovUn5OH+SHKJ+j7PT5gpRYIjE
+qwhlFFP9w3CKb0mZ1wk4ACC1PTzxfCyrZ03fHcIeJNMxYHG+s4V+px7OQR8hWGOD
+POWRShhNbJcT1d80xyIKkjr7Azq4Yit+vgP7OXQDHfPHVSjn7c0odSt1xTi3/dqY
+YGEKqusXGibhdH6E6Ha/FRjjsk4lQcsrGcljb6qKWMcBKs38BOpjf7PtXZaisCZj
+jQ0/
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/scripts/ee.cnf b/net/data/ssl/scripts/ee.cnf
index 3d42df1..d5811b9 100644
--- a/net/data/ssl/scripts/ee.cnf
+++ b/net/data/ssl/scripts/ee.cnf
@@ -17,6 +17,9 @@
 O  = Test CA
 CN = 127.0.0.1
 
+[req_no_san]
+basicConstraints = critical, CA:false
+
 [req_duplicate_cn_1]
 O  = Foo
 CN = Duplicate
diff --git a/net/data/ssl/scripts/generate-test-certs.sh b/net/data/ssl/scripts/generate-test-certs.sh
index 031ea77..33ff78c 100755
--- a/net/data/ssl/scripts/generate-test-certs.sh
+++ b/net/data/ssl/scripts/generate-test-certs.sh
@@ -423,6 +423,45 @@
   -extensions req_extensions_with_tls_feature \
   -nodes -config ee.cnf
 
+# SHA-1 certificate issued by locally trusted CA
+openssl req \
+  -config ../scripts/ee.cnf \
+  -newkey rsa:2048 \
+  -text \
+  -keyout out/sha1_leaf.key \
+  -out out/sha1_leaf.req
+CA_NAME="req_ca_dn" \
+  openssl ca \
+    -batch \
+    -extensions user_cert \
+    -startdate 171220000000Z \
+    -enddate   201220000000Z \
+    -in out/sha1_leaf.req \
+    -out out/sha1_leaf.pem \
+    -config ca.cnf \
+    -md sha1
+/bin/sh -c "cat out/sha1_leaf.key out/sha1_leaf.pem \
+    > ../certificates/sha1_leaf.pem"
+
+# Certificate with only a common name (no SAN) issued by a locally trusted CA
+openssl req \
+  -config ../scripts/ee.cnf \
+  -reqexts req_no_san \
+  -newkey rsa:2048 \
+  -text \
+  -keyout out/common_name_only.key \
+  -out out/common_name_only.req
+CA_NAME="req_ca_dn" \
+  openssl ca \
+    -batch \
+    -extensions user_cert \
+    -startdate 171220000000Z \
+    -enddate   201220000000Z \
+    -in out/common_name_only.req \
+    -out out/common_name_only.pem \
+    -config ca.cnf
+/bin/sh -c "cat out/common_name_only.key out/common_name_only.pem \
+    > ../certificates/common_name_only.pem"
 
 # Regenerate CRLSets
 ## Block a leaf cert directly by SPKI
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index 1a966e1..ce7bea0 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -462,8 +462,7 @@
     for (size_t i = 0; i < socket_data_.size(); ++i) {
       EXPECT_TRUE(socket_data_[i]->GetProvider()->AllWriteDataConsumed()) << i;
     }
-    NetTestSuite::SetScopedTaskEnvironment(
-        base::test::ScopedTaskEnvironment::MainThreadType::IO);
+    NetTestSuite::ResetScopedTaskEnvironment();
   }
 
  protected:
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 91f5487..2820679 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -195,6 +195,7 @@
       using_spdy_(false),
       should_reconsider_proxy_(false),
       quic_request_(session_->quic_stream_factory()),
+      expect_on_quic_host_resolution_(false),
       using_existing_quic_session_(false),
       establishing_tunnel_(false),
       was_alpn_negotiated_(false),
@@ -841,9 +842,10 @@
 int HttpStreamFactoryImpl::Job::DoInitConnection() {
   net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_INIT_CONNECTION);
   int result = DoInitConnectionImpl();
-  if (result != ERR_SPDY_SESSION_ALREADY_EXISTS)
+  if (result != ERR_SPDY_SESSION_ALREADY_EXISTS &&
+      !expect_on_quic_host_resolution_) {
     delegate_->OnConnectionInitialized(this, result);
-
+  }
   return result;
 }
 
@@ -913,13 +915,14 @@
                                    net_log_, &net_error_details_, io_callback_);
     if (rv == OK) {
       using_existing_quic_session_ = true;
-    } else {
+    } else if (rv == ERR_IO_PENDING) {
       // There's no available QUIC session. Inform the delegate how long to
       // delay the main job.
-      if (rv == ERR_IO_PENDING) {
-        delegate_->MaybeSetWaitTimeForMainJob(
-            quic_request_.GetTimeDelayForWaitingJob());
-      }
+      delegate_->MaybeSetWaitTimeForMainJob(
+          quic_request_.GetTimeDelayForWaitingJob());
+      expect_on_quic_host_resolution_ =
+          quic_request_.WaitForHostResolution(base::BindRepeating(
+              &Job::OnQuicHostResolution, base::Unretained(this)));
     }
     return rv;
   }
@@ -997,6 +1000,12 @@
       resolution_callback, io_callback_);
 }
 
+void HttpStreamFactoryImpl::Job::OnQuicHostResolution(int result) {
+  DCHECK(expect_on_quic_host_resolution_);
+  expect_on_quic_host_resolution_ = false;
+  delegate_->OnConnectionInitialized(this, result);
+}
+
 int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
   net_log_.EndEvent(NetLogEventType::HTTP_STREAM_JOB_INIT_CONNECTION);
   if (job_type_ == PRECONNECT) {
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h
index 3fdec07..2a4885e 100644
--- a/net/http/http_stream_factory_impl_job.h
+++ b/net/http/http_stream_factory_impl_job.h
@@ -318,6 +318,11 @@
   int StartInternal();
   int DoInitConnectionImpl();
 
+  // If this is a QUIC alt job, then this function is called when host
+  // resolution completes. It's called with the next result after host
+  // resolution, not the result of host resolution itself.
+  void OnQuicHostResolution(int result);
+
   // Each of these methods corresponds to a State value.  Those with an input
   // argument receive the result from the previous state.  If a method returns
   // ERR_IO_PENDING, then the result from OnIOComplete will be passed to the
@@ -464,6 +469,10 @@
 
   QuicStreamRequest quic_request_;
 
+  // Only valid for a QUIC job. Set when a QUIC connection is started. If true,
+  // then OnQuicHostResolution() is expected to be called in the future.
+  bool expect_on_quic_host_resolution_;
+
   // True if this job used an existing QUIC session.
   bool using_existing_quic_session_;
 
diff --git a/net/http/http_stream_factory_impl_job_controller_unittest.cc b/net/http/http_stream_factory_impl_job_controller_unittest.cc
index aaab13fa..28e1429 100644
--- a/net/http/http_stream_factory_impl_job_controller_unittest.cc
+++ b/net/http/http_stream_factory_impl_job_controller_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_mock_time_message_loop_task_runner.h"
 #include "base/test/scoped_task_environment.h"
+#include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/platform_thread.h"
 #include "net/base/test_proxy_delegate.h"
 #include "net/dns/mock_host_resolver.h"
@@ -1363,12 +1364,18 @@
   base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCP) {
-  base::ScopedMockTimeMessageLoopTaskRunner test_task_runner;
-  auto failing_resolver = std::make_unique<MockHostResolver>();
-  failing_resolver->set_ondemand_mode(true);
-  failing_resolver->rules()->AddSimulatedFailure("*google.com");
-  session_deps_.host_resolver = std::move(failing_resolver);
+// Verifies that the main job is not resumed until after the alt job completes
+// host resolution.
+TEST_F(HttpStreamFactoryImplJobControllerTest, HostResolutionHang) {
+  scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner(
+      new base::TestMockTimeTaskRunner());
+  base::TestMockTimeTaskRunner::ScopedContext test_task_runner_context(
+      test_task_runner.get());
+
+  auto hanging_resolver = std::make_unique<MockHostResolver>();
+  hanging_resolver->set_ondemand_mode(true);
+  hanging_resolver->set_synchronous_mode(false);
+  session_deps_.host_resolver = std::move(hanging_resolver);
 
   HttpRequestInfo request_info;
   request_info.method = "GET";
@@ -1376,6 +1383,13 @@
 
   Initialize(request_info);
 
+  // handshake will fail asynchronously after mock data is unpaused.
+  MockQuicData quic_data;
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
+  quic_data.AddRead(ASYNC, ERR_FAILED);
+  quic_data.AddWrite(ASYNC, ERR_FAILED);
+  quic_data.AddSocketDataToFactory(session_deps_.socket_factory.get());
+
   // Enable delayed TCP and set time delay for waiting job.
   QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
   quic_stream_factory->set_require_confirmation(false);
@@ -1388,35 +1402,116 @@
   AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
   SetAlternativeService(request_info, alternative_service);
 
+  // This prevents handshake from immediately succeeding.
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::COLD_START);
+
   request_ =
       job_controller_->Start(&request_delegate_, nullptr, net_log_.bound(),
                              HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
+
   EXPECT_TRUE(job_controller_->main_job());
   EXPECT_TRUE(job_controller_->alternative_job());
-  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+  EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
 
-  // The alternative job stalls as host resolution hangs when creating the QUIC
-  // request and controller should resume the main job after delay.
+  // Since the alt job has not finished host resolution, there should be no
+  // delayed task posted to resume the main job.
+  EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
+  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(50));
+  EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
+
+  // Allow alt job host resolution to complete.
+  session_deps_.host_resolver->ResolveAllPending();
+
+  // Task to resume main job in 15 microseconds should be posted.
   EXPECT_TRUE(test_task_runner->HasPendingTask());
-  EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
+  EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
+  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(14));
   EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
-  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(15));
-  EXPECT_FALSE(test_task_runner->HasPendingTask());
+  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(1));
 
   EXPECT_TRUE(job_controller_->main_job());
   EXPECT_TRUE(job_controller_->alternative_job());
-
-  // |alternative_job| fails but should not report status to Request.
-  EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _)).Times(0);
-
   EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
+  EXPECT_TRUE(JobControllerPeer::main_job_is_resumed(job_controller_));
+
+  // Unpause mock quic data.
+  // Will cause |alternative_job| to fail, but its failure should not be
+  // reported to Request.
+  EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _)).Times(0);
   // OnStreamFailed will post a task to resume the main job immediately but
   // won't call Resume() on the main job since it's been resumed already.
   EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
-  // Now unblock Resolver so that alternate job (and QuicStreamFactory::Job) can
-  // be cleaned up.
-  session_deps_.host_resolver->ResolveAllPending();
-  EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
+  quic_data.GetSequencedSocketData()->Resume();
+  test_task_runner->FastForwardUntilNoTasksRemain();
+  // Alt job should be cleaned up
+  EXPECT_FALSE(job_controller_->alternative_job());
+}
+
+TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCP) {
+  scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner(
+      new base::TestMockTimeTaskRunner());
+  base::TestMockTimeTaskRunner::ScopedContext test_task_runner_context(
+      test_task_runner.get());
+
+  auto immediate_resolver = std::make_unique<MockHostResolver>();
+  immediate_resolver->set_synchronous_mode(true);
+  session_deps_.host_resolver = std::move(immediate_resolver);
+
+  HttpRequestInfo request_info;
+  request_info.method = "GET";
+  request_info.url = GURL("https://www.google.com");
+
+  Initialize(request_info);
+
+  // Handshake will fail asynchronously after mock data is unpaused.
+  MockQuicData quic_data;
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
+  quic_data.AddRead(ASYNC, ERR_FAILED);
+  quic_data.AddWrite(ASYNC, ERR_FAILED);
+  quic_data.AddSocketDataToFactory(session_deps_.socket_factory.get());
+
+  // Enable delayed TCP and set time delay for waiting job.
+  QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
+  quic_stream_factory->set_require_confirmation(false);
+  ServerNetworkStats stats1;
+  stats1.srtt = base::TimeDelta::FromMicroseconds(10);
+  session_->http_server_properties()->SetServerNetworkStats(
+      url::SchemeHostPort(GURL("https://www.google.com")), stats1);
+
+  url::SchemeHostPort server(request_info.url);
+  AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
+  SetAlternativeService(request_info, alternative_service);
+
+  // This prevents handshake from immediately succeeding.
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::COLD_START);
+
+  request_ =
+      job_controller_->Start(&request_delegate_, nullptr, net_log_.bound(),
+                             HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
+
+  EXPECT_TRUE(job_controller_->main_job());
+  EXPECT_TRUE(job_controller_->alternative_job());
+  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+  // Main job is not blocked but hasn't resumed yet; it should resume in 15us.
+  EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
+  EXPECT_FALSE(JobControllerPeer::main_job_is_resumed(job_controller_));
+
+  // Task to resume main job in 15us should be posted.
+  EXPECT_TRUE(test_task_runner->HasPendingTask());
+  EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
+  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(14));
+  EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
+  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(1));
+
+  EXPECT_TRUE(job_controller_->main_job());
+  EXPECT_TRUE(job_controller_->alternative_job());
+  EXPECT_TRUE(JobControllerPeer::main_job_is_resumed(job_controller_));
+
+  // Unpause mock quic data and run all remaining tasks. Alt-job should fail
+  // and be cleaned up.
+  quic_data.GetSequencedSocketData()->Resume();
   test_task_runner->FastForwardUntilNoTasksRemain();
   EXPECT_FALSE(job_controller_->alternative_job());
 }
@@ -1498,8 +1593,7 @@
   // Reset task environment back to the default type.
   // TODO(xunjieli): Remove this temporary workaround once crbug.com/791831 is
   // fixed.
-  NetTestSuite::SetScopedTaskEnvironment(
-      base::test::ScopedTaskEnvironment::MainThreadType::IO);
+  NetTestSuite::ResetScopedTaskEnvironment();
 }
 
 // Test that main job is blocked for kMaxDelayTimeForMainJob(3s) if
@@ -1507,15 +1601,17 @@
 // which would potentially delay the main job for a extremely long time in
 // delayed tcp case.
 TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCPWithLargeSrtt) {
-  // Overrides the main thread's message loop with a mock tick clock so that we
-  // could verify the main job is resumed with appropriate delay.
-  base::ScopedMockTimeMessageLoopTaskRunner test_task_runner;
+  scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner(
+      new base::TestMockTimeTaskRunner());
+  base::TestMockTimeTaskRunner::ScopedContext test_task_runner_context(
+      test_task_runner.get());
+
   // The max delay time should be in sync with .cc file.
   base::TimeDelta kMaxDelayTimeForMainJob = base::TimeDelta::FromSeconds(3);
-  auto failing_resolver = std::make_unique<MockHostResolver>();
-  failing_resolver->set_ondemand_mode(true);
-  failing_resolver->rules()->AddSimulatedFailure("*google.com");
-  session_deps_.host_resolver = std::move(failing_resolver);
+
+  auto immediate_resolver = std::make_unique<MockHostResolver>();
+  immediate_resolver->set_synchronous_mode(true);
+  session_deps_.host_resolver = std::move(immediate_resolver);
 
   HttpRequestInfo request_info;
   request_info.method = "GET";
@@ -1523,7 +1619,14 @@
 
   Initialize(request_info);
 
-  // Enable delayed TCP and set a extremely large time delay for waiting job.
+  // handshake will fail asynchronously after mock data is unpaused.
+  MockQuicData quic_data;
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
+  quic_data.AddRead(ASYNC, ERR_FAILED);
+  quic_data.AddWrite(ASYNC, ERR_FAILED);
+  quic_data.AddSocketDataToFactory(session_deps_.socket_factory.get());
+
+  // Enable delayed TCP and set time delay for waiting job.
   QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
   quic_stream_factory->set_require_confirmation(false);
   ServerNetworkStats stats1;
@@ -1531,47 +1634,53 @@
   session_->http_server_properties()->SetServerNetworkStats(
       url::SchemeHostPort(GURL("https://www.google.com")), stats1);
 
-  // Set a SPDY alternative service for the server.
   url::SchemeHostPort server(request_info.url);
   AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
   SetAlternativeService(request_info, alternative_service);
 
+  // This prevents handshake from immediately succeeding.
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::COLD_START);
+
   request_ =
       job_controller_->Start(&request_delegate_, nullptr, net_log_.bound(),
                              HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
+
   EXPECT_TRUE(job_controller_->main_job());
   EXPECT_TRUE(job_controller_->alternative_job());
-  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+  // Main job is not blocked but hasn't resumed yet; it should resume in 3s.
+  EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
+  EXPECT_FALSE(JobControllerPeer::main_job_is_resumed(job_controller_));
 
-  // The alternative job stalls as host resolution hangs when creating the QUIC
-  // request and controller should resume the main job after delay.
+  // Task to resume main job in 3 seconds should be posted.
   EXPECT_TRUE(test_task_runner->HasPendingTask());
-  EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
-
+  EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
+  test_task_runner->FastForwardBy(kMaxDelayTimeForMainJob -
+                                  base::TimeDelta::FromMicroseconds(1));
   EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
-  // Move forward the task runner with kMaxDelayTimeForMainJob and verify the
-  // main job is resumed.
-  test_task_runner->FastForwardBy(kMaxDelayTimeForMainJob);
-  EXPECT_FALSE(test_task_runner->HasPendingTask());
+  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(1));
 
-  // Now unblock Resolver so that alternate job (and QuicStreamFactory::Job) can
-  // be cleaned up.
-  session_deps_.host_resolver->ResolveAllPending();
-  EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
+  EXPECT_TRUE(job_controller_->main_job());
+  EXPECT_TRUE(job_controller_->alternative_job());
+  EXPECT_TRUE(JobControllerPeer::main_job_is_resumed(job_controller_));
+
+  // Unpause mock quic data and run all remaining tasks. Alt-job  should fail
+  // and be cleaned up.
+  quic_data.GetSequencedSocketData()->Resume();
   test_task_runner->FastForwardUntilNoTasksRemain();
   EXPECT_FALSE(job_controller_->alternative_job());
 }
 
 TEST_F(HttpStreamFactoryImplJobControllerTest,
        ResumeMainJobImmediatelyOnStreamFailed) {
-  // Overrides the main thread's message loop with a mock tick clock so that we
-  // could verify the main job is resumed with appropriate delay.
-  base::ScopedMockTimeMessageLoopTaskRunner test_task_runner;
+  scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner(
+      new base::TestMockTimeTaskRunner());
+  base::TestMockTimeTaskRunner::ScopedContext test_task_runner_context(
+      test_task_runner.get());
 
-  auto failing_resolver = std::make_unique<MockHostResolver>();
-  failing_resolver->set_ondemand_mode(true);
-  failing_resolver->rules()->AddSimulatedFailure("*google.com");
-  session_deps_.host_resolver = std::move(failing_resolver);
+  auto immediate_resolver = std::make_unique<MockHostResolver>();
+  immediate_resolver->set_synchronous_mode(true);
+  session_deps_.host_resolver = std::move(immediate_resolver);
 
   HttpRequestInfo request_info;
   request_info.method = "GET";
@@ -1579,6 +1688,13 @@
 
   Initialize(request_info);
 
+  // handshake will fail asynchronously after mock data is unpaused.
+  MockQuicData quic_data;
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
+  quic_data.AddRead(ASYNC, ERR_FAILED);
+  quic_data.AddWrite(ASYNC, ERR_FAILED);
+  quic_data.AddSocketDataToFactory(session_deps_.socket_factory.get());
+
   // Enable delayed TCP and set time delay for waiting job.
   QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
   quic_stream_factory->set_require_confirmation(false);
@@ -1587,44 +1703,48 @@
   session_->http_server_properties()->SetServerNetworkStats(
       url::SchemeHostPort(GURL("https://www.google.com")), stats1);
 
-  // Set a SPDY alternative service for the server.
   url::SchemeHostPort server(request_info.url);
   AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
   SetAlternativeService(request_info, alternative_service);
 
-  // The alternative job stalls as host resolution hangs when creating the QUIC
-  // request and controller should resume the main job with delay.
-  // OnStreamFailed should resume the main job immediately.
+  // This prevents handshake from immediately succeeding.
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::COLD_START);
+
   request_ =
       job_controller_->Start(&request_delegate_, nullptr, net_log_.bound(),
                              HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
+
   EXPECT_TRUE(job_controller_->main_job());
   EXPECT_TRUE(job_controller_->alternative_job());
-  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+  // Main job is not blocked but hasn't resumed yet; it's scheduled to resume
+  // in 15us.
+  EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
+  EXPECT_FALSE(JobControllerPeer::main_job_is_resumed(job_controller_));
 
+  // Task to resume main job in 15us should be posted.
   EXPECT_TRUE(test_task_runner->HasPendingTask());
-  EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
 
-  // |alternative_job| fails but should not report status to Request.
-  EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _)).Times(0);
-  // Now unblock Resolver to fail the alternate job.
-  session_deps_.host_resolver->ResolveAllPending();
-  EXPECT_EQ(2u, test_task_runner->GetPendingTaskCount());
+  EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
+  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(1));
 
-  // Verify the main job will be resumed immediately.
+  // Now unpause the mock quic data to fail the alt job. This should immediately
+  // resume the main job.
   EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
-  // Execute tasks that have no remaining delay. Tasks with nonzero delay will
-  // remain queued.
-  test_task_runner->RunUntilIdle();
+  quic_data.GetSequencedSocketData()->Resume();
+  test_task_runner->FastForwardBy(base::TimeDelta());
+
+  EXPECT_TRUE(job_controller_->main_job());
+  EXPECT_FALSE(job_controller_->alternative_job());
+  EXPECT_TRUE(JobControllerPeer::main_job_is_resumed(job_controller_));
 
   // Verify there is another task to resume main job with delay but should
   // not call Resume() on the main job as main job has been resumed.
   EXPECT_TRUE(test_task_runner->HasPendingTask());
-  EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
   EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
   test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(15));
-  EXPECT_FALSE(test_task_runner->HasPendingTask());
-  EXPECT_FALSE(job_controller_->alternative_job());
+
+  test_task_runner->FastForwardUntilNoTasksRemain();
 }
 
 // Verifies that the alternative proxy server job is not created if the URL
@@ -1677,24 +1797,32 @@
 // Verifies that the main job is resumed properly after a delay when the
 // alternative proxy server job hangs.
 TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCPAlternativeProxy) {
-  // Overrides the main thread's message loop with a mock tick clock so that we
-  // could verify the main job is resumed with appropriate delay.
-  base::ScopedMockTimeMessageLoopTaskRunner test_task_runner;
+  scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner(
+      new base::TestMockTimeTaskRunner());
+  base::TestMockTimeTaskRunner::ScopedContext test_task_runner_context(
+      test_task_runner.get());
 
-  auto failing_resolver = std::make_unique<MockHostResolver>();
-  failing_resolver->set_ondemand_mode(true);
-  failing_resolver->rules()->AddSimulatedFailure("*myproxy.org");
-  session_deps_.host_resolver = std::move(failing_resolver);
+  auto immediate_resolver = std::make_unique<MockHostResolver>();
+  immediate_resolver->set_synchronous_mode(true);
+  session_deps_.host_resolver = std::move(immediate_resolver);
 
   UseAlternativeProxy();
 
   HttpRequestInfo request_info;
   request_info.method = "GET";
-  request_info.url = GURL("http://mail.example.org/");
+  request_info.url = GURL("http://www.mail.example.org/");
+
   Initialize(request_info);
 
   EXPECT_TRUE(test_proxy_delegate()->alternative_proxy_server().is_quic());
 
+  // Handshake will fail asynchronously after mock data is unpaused.
+  MockQuicData quic_data;
+  quic_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
+  quic_data.AddRead(ASYNC, ERR_FAILED);
+  quic_data.AddWrite(ASYNC, ERR_FAILED);
+  quic_data.AddSocketDataToFactory(session_deps_.socket_factory.get());
+
   // Enable delayed TCP and set time delay for waiting job.
   QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
   quic_stream_factory->set_require_confirmation(false);
@@ -1703,31 +1831,39 @@
   session_->http_server_properties()->SetServerNetworkStats(
       url::SchemeHostPort(GURL("https://myproxy.org")), stats1);
 
+  url::SchemeHostPort server(request_info.url);
+  AlternativeService alternative_service(kProtoQUIC, server.host(), 443);
+  SetAlternativeService(request_info, alternative_service);
+
+  // This prevents handshake from immediately succeeding.
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::COLD_START);
+
   request_ =
       job_controller_->Start(&request_delegate_, nullptr, net_log_.bound(),
                              HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY);
+
   EXPECT_TRUE(job_controller_->main_job());
-  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
   EXPECT_TRUE(job_controller_->alternative_job());
-  // The main job is unblocked but is resumed one message loop iteration later.
+  EXPECT_TRUE(job_controller_->main_job()->is_waiting());
+  // Main job is not blocked but hasn't resumed yet; it should resume in 15us.
   EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
   EXPECT_FALSE(JobControllerPeer::main_job_is_resumed(job_controller_));
-  EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
 
-  // Move forward the delay and verify the main job is resumed.
+  // Task to resume main job in 15us should be posted.
+  EXPECT_TRUE(test_task_runner->HasPendingTask());
+  EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
+  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(14));
   EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1);
-  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(15));
-  EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
+  test_task_runner->FastForwardBy(base::TimeDelta::FromMicroseconds(1));
+
+  EXPECT_TRUE(job_controller_->main_job());
+  EXPECT_TRUE(job_controller_->alternative_job());
   EXPECT_TRUE(JobControllerPeer::main_job_is_resumed(job_controller_));
 
-  test_task_runner->RunUntilIdle();
-  EXPECT_TRUE(test_proxy_delegate()->alternative_proxy_server().is_valid());
-  EXPECT_FALSE(test_task_runner->HasPendingTask());
-
-  // Now unblock Resolver so that alternate job (and QuicStreamFactory::Job) can
-  // be cleaned up.
-  session_deps_.host_resolver->ResolveAllPending();
-  EXPECT_EQ(1u, test_task_runner->GetPendingTaskCount());
+  // Unpause mock quic data and run all remaining tasks. Alt-job should fail
+  // and be cleaned up.
+  quic_data.GetSequencedSocketData()->Resume();
   test_task_runner->FastForwardUntilNoTasksRemain();
   EXPECT_FALSE(job_controller_->alternative_job());
 }
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc
index f66ee474..c76257c 100644
--- a/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -5796,8 +5796,6 @@
 
   mock_quic_data1.AddSocketDataToFactory(&socket_factory_);
 
-  AddHangingSocketData();
-
   QuicTestPacketMaker client_maker2(version_, 0, &clock_, origin2_,
                                     Perspective::IS_CLIENT);
   QuicTestPacketMaker server_maker2(version_, 0, &clock_, origin2_,
@@ -5821,8 +5819,6 @@
 
   mock_quic_data2.AddSocketDataToFactory(&socket_factory_);
 
-  AddHangingSocketData();
-
   SendRequestAndExpectQuicResponse(origin1_);
   SendRequestAndExpectQuicResponse(origin2_);
 
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index 957b720..31798ed 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -317,7 +317,8 @@
 
   ~Job();
 
-  int Run(const CompletionCallback& callback);
+  int Run(const CompletionCallback& host_resolution_callback,
+          const CompletionCallback& callback);
 
   int DoLoop(int rv);
   int DoResolveHost();
@@ -340,6 +341,10 @@
 
   void AddRequest(QuicStreamRequest* request) {
     stream_requests_.insert(request);
+    if (io_state_ == STATE_RESOLVE_HOST ||
+        io_state_ == STATE_RESOLVE_HOST_COMPLETE) {
+      request->ExpectOnHostResolution();
+    }
   }
 
   void RemoveRequest(QuicStreamRequest* request) {
@@ -352,6 +357,10 @@
     return stream_requests_;
   }
 
+  bool IsHostResolutionComplete() const {
+    return io_state_ == STATE_NONE || io_state_ >= STATE_CONNECT;
+  }
+
  private:
   enum IoState {
     STATE_NONE,
@@ -373,6 +382,7 @@
   const NetLogWithSource net_log_;
   int num_sent_client_hellos_;
   QuicChromiumClientSession* session_;
+  CompletionCallback host_resolution_callback_;
   CompletionCallback callback_;
   AddressList address_list_;
   base::TimeTicks dns_resolution_start_time_;
@@ -424,10 +434,14 @@
   // non-null.
 }
 
-int QuicStreamFactory::Job::Run(const CompletionCallback& callback) {
+int QuicStreamFactory::Job::Run(
+    const CompletionCallback& host_resolution_callback,
+    const CompletionCallback& callback) {
   int rv = DoLoop(OK);
-  if (rv == ERR_IO_PENDING)
+  if (rv == ERR_IO_PENDING) {
+    host_resolution_callback_ = host_resolution_callback;
     callback_ = callback;
+  }
 
   return rv > 0 ? OK : rv;
 }
@@ -462,7 +476,12 @@
 }
 
 void QuicStreamFactory::Job::OnIOComplete(int rv) {
+  IoState start_state = io_state_;
   rv = DoLoop(rv);
+  if (start_state == STATE_RESOLVE_HOST_COMPLETE &&
+      !host_resolution_callback_.is_null()) {
+    base::ResetAndReturn(&host_resolution_callback_).Run(rv);
+  }
   if (rv != ERR_IO_PENDING && !callback_.is_null()) {
     base::ResetAndReturn(&callback_).Run(rv);
   }
@@ -500,7 +519,7 @@
 
   // Inform the factory of this resolution, which will set up
   // a session alias, if possible.
-  if (factory_->OnResolution(key_, address_list_))
+  if (factory_->HasMatchingIpSession(key_, address_list_))
     return OK;
 
   io_state_ = STATE_CONNECT;
@@ -567,7 +586,7 @@
   // existing session instead.
   AddressList address(
       session_->connection()->peer_address().impl().socket_address());
-  if (factory_->OnResolution(key_, address)) {
+  if (factory_->HasMatchingIpSession(key_, address)) {
     session_->connection()->CloseConnection(
         QUIC_CONNECTION_IP_POOLED, "An active session exists for the given IP.",
         ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -581,7 +600,7 @@
 }
 
 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory)
-    : factory_(factory) {}
+    : factory_(factory), expect_on_host_resolution_(false) {}
 
 QuicStreamRequest::~QuicStreamRequest() {
   if (factory_ && !callback_.is_null())
@@ -600,6 +619,7 @@
   DCHECK_NE(quic_version, QUIC_VERSION_UNSUPPORTED);
   DCHECK(net_error_details);
   DCHECK(callback_.is_null());
+  DCHECK(host_resolution_callback_.is_null());
   DCHECK(factory_);
 
   net_error_details_ = net_error_details;
@@ -611,13 +631,24 @@
     net_log_ = net_log;
     callback_ = callback;
   } else {
+    DCHECK(!expect_on_host_resolution_);
     factory_ = nullptr;
   }
+
   if (rv == OK)
     DCHECK(session_);
   return rv;
 }
 
+bool QuicStreamRequest::WaitForHostResolution(
+    const CompletionCallback& callback) {
+  DCHECK(host_resolution_callback_.is_null());
+  if (expect_on_host_resolution_) {
+    host_resolution_callback_ = callback;
+  }
+  return expect_on_host_resolution_;
+}
+
 void QuicStreamRequest::SetSession(
     std::unique_ptr<QuicChromiumClientSession::Handle> session) {
   session_ = move(session);
@@ -628,6 +659,18 @@
   base::ResetAndReturn(&callback_).Run(rv);
 }
 
+void QuicStreamRequest::ExpectOnHostResolution() {
+  expect_on_host_resolution_ = true;
+}
+
+void QuicStreamRequest::OnHostResolutionComplete(int rv) {
+  DCHECK(expect_on_host_resolution_);
+  expect_on_host_resolution_ = false;
+  if (!host_resolution_callback_.is_null()) {
+    base::ResetAndReturn(&host_resolution_callback_).Run(rv);
+  }
+}
+
 base::TimeDelta QuicStreamRequest::GetTimeDelayForWaitingJob() const {
   if (!factory_)
     return base::TimeDelta();
@@ -969,8 +1012,11 @@
   std::unique_ptr<Job> job = std::make_unique<Job>(
       this, quic_version, host_resolver_, key, WasQuicRecentlyBroken(server_id),
       priority, cert_verify_flags, net_log);
-  int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
-                               base::Unretained(this), job.get()));
+  int rv = job->Run(
+      base::BindRepeating(&QuicStreamFactory::OnJobHostResolutionComplete,
+                          base::Unretained(this), job.get()),
+      base::BindRepeating(&QuicStreamFactory::OnJobComplete,
+                          base::Unretained(this), job.get()));
   if (rv == ERR_IO_PENDING) {
     job->AddRequest(request);
     active_jobs_[server_id] = std::move(job);
@@ -1013,8 +1059,8 @@
          EstimateServerIdMemoryUsage(server_id_);
 }
 
-bool QuicStreamFactory::OnResolution(const QuicSessionKey& key,
-                                     const AddressList& address_list) {
+bool QuicStreamFactory::HasMatchingIpSession(const QuicSessionKey& key,
+                                             const AddressList& address_list) {
   const QuicServerId& server_id(key.server_id());
   DCHECK(!HasActiveSession(server_id));
   for (const IPEndPoint& address : address_list) {
@@ -1033,6 +1079,14 @@
   return false;
 }
 
+void QuicStreamFactory::OnJobHostResolutionComplete(Job* job, int rv) {
+  auto iter = active_jobs_.find(job->key().server_id());
+  DCHECK(iter != active_jobs_.end());
+  for (auto* request : iter->second->stream_requests()) {
+    request->OnHostResolutionComplete(rv);
+  }
+}
+
 void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
   auto iter = active_jobs_.find(job->key().server_id());
   DCHECK(iter != active_jobs_.end());
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h
index 4d64ebb1..8af3c01 100644
--- a/net/quic/chromium/quic_stream_factory.h
+++ b/net/quic/chromium/quic_stream_factory.h
@@ -119,6 +119,23 @@
               NetErrorDetails* net_error_details,
               const CompletionCallback& callback);
 
+  // This function must be called after Request() returns ERR_IO_PENDING.
+  // Returns true if Request() requires host resolution and it hasn't completed
+  // yet. If true is returned, |callback| will run when host resolution
+  // completes. It will be called with the result after host resolution during
+  // the connection process. For example, if host resolution returns OK and then
+  // crypto handshake returns ERR_IO_PENDING, then |callback| will run with
+  // ERR_IO_PENDING.
+  bool WaitForHostResolution(const CompletionCallback& callback);
+
+  // Tells QuicStreamRequest it should expect OnHostResolutionComplete()
+  // to be called in the future.
+  void ExpectOnHostResolution();
+
+  // Will be called by the associated QuicStreamFactory::Job when host
+  // resolution completes asynchronously after Request().
+  void OnHostResolutionComplete(int rv);
+
   void OnRequestComplete(int rv);
 
   // Helper method that calls |factory_|'s GetTimeDelayForWaitingJob(). It
@@ -145,6 +162,12 @@
   NetErrorDetails* net_error_details_;  // Unowned.
   std::unique_ptr<QuicChromiumClientSession::Handle> session_;
 
+  // Set in Request(). If true, then OnHostResolutionComplete() is expected to
+  // be called in the future.
+  bool expect_on_host_resolution_;
+  // Callback passed to WaitForHostResolution().
+  CompletionCallback host_resolution_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(QuicStreamRequest);
 };
 
@@ -369,7 +392,9 @@
   typedef std::map<QuicServerId, std::unique_ptr<CertVerifierJob>>
       CertVerifierJobMap;
 
-  bool OnResolution(const QuicSessionKey& key, const AddressList& address_list);
+  bool HasMatchingIpSession(const QuicSessionKey& key,
+                            const AddressList& address_list);
+  void OnJobHostResolutionComplete(Job* job, int rv);
   void OnJobComplete(Job* job, int rv);
   void OnCertVerifyJobComplete(CertVerifierJob* job, int rv);
   bool HasActiveSession(const QuicServerId& server_id) const;
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index 989abd3..c9611bd 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -5806,5 +5806,239 @@
             config->max_idle_time_before_crypto_handshake());
 }
 
+// Verify ResultAfterHostResolutionCallback behavior when host resolution
+// succeeds asynchronously, then crypto handshake fails synchronously.
+TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackAsyncSync) {
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  host_resolver_.set_ondemand_mode(true);
+
+  MockQuicData socket_data;
+  socket_data.AddRead(SYNCHRONOUS, ERR_FAILED);
+  socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
+  socket_data.AddSocketDataToFactory(socket_factory_.get());
+
+  QuicStreamRequest request(factory_.get());
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_, version_, privacy_mode_,
+                            DEFAULT_PRIORITY,
+                            /*cert_verify_flags=*/0, url_, net_log_,
+                            &net_error_details_, callback_.callback()));
+
+  TestCompletionCallback host_resolution_callback;
+  EXPECT_TRUE(
+      request.WaitForHostResolution(host_resolution_callback.callback()));
+
+  // |host_resolver_| has not finished host resolution at this point, so
+  // |host_resolution_callback| should not have a result.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(host_resolution_callback.have_result());
+
+  // Allow |host_resolver_| to finish host resolution.
+  // Since the request fails immediately after host resolution (getting
+  // ERR_FAILED from socket reads/writes), |host_resolution_callback| should be
+  // called with ERR_QUIC_PROTOCOL_ERROR since that's the next result in
+  // forming the connection.
+  host_resolver_.ResolveAllPending();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(host_resolution_callback.have_result());
+  EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, host_resolution_callback.WaitForResult());
+
+  // Calling WaitForHostResolution() a second time should return
+  // false since host resolution has finished already.
+  EXPECT_FALSE(
+      request.WaitForHostResolution(host_resolution_callback.callback()));
+
+  EXPECT_TRUE(callback_.have_result());
+  EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
+}
+
+// Verify ResultAfterHostResolutionCallback behavior when host resolution
+// succeeds asynchronously, then crypto handshake fails asynchronously.
+TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackAsyncAsync) {
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  host_resolver_.set_ondemand_mode(true);
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::ZERO_RTT);
+  factory_->set_require_confirmation(true);
+
+  MockQuicData socket_data;
+  socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
+  socket_data.AddRead(ASYNC, ERR_FAILED);
+  socket_data.AddWrite(ASYNC, ERR_FAILED);
+  socket_data.AddSocketDataToFactory(socket_factory_.get());
+
+  QuicStreamRequest request(factory_.get());
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_, version_, privacy_mode_,
+                            DEFAULT_PRIORITY,
+                            /*cert_verify_flags=*/0, url_, net_log_,
+                            &net_error_details_, callback_.callback()));
+
+  TestCompletionCallback host_resolution_callback;
+  EXPECT_TRUE(
+      request.WaitForHostResolution(host_resolution_callback.callback()));
+
+  // |host_resolver_| has not finished host resolution at this point, so
+  // |host_resolution_callback| should not have a result.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(host_resolution_callback.have_result());
+
+  // Allow |host_resolver_| to finish host resolution. Since crypto handshake
+  // will hang after host resolution, |host_resolution_callback| should run with
+  // ERR_IO_PENDING since that's the next result in forming the connection.
+  host_resolver_.ResolveAllPending();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(host_resolution_callback.have_result());
+  EXPECT_EQ(ERR_IO_PENDING, host_resolution_callback.WaitForResult());
+
+  // Calling WaitForHostResolution() a second time should return
+  // false since host resolution has finished already.
+  EXPECT_FALSE(
+      request.WaitForHostResolution(host_resolution_callback.callback()));
+
+  EXPECT_FALSE(callback_.have_result());
+  socket_data.GetSequencedSocketData()->Resume();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(callback_.have_result());
+  EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
+}
+
+// Verify ResultAfterHostResolutionCallback behavior when host resolution
+// succeeds synchronously, then crypto handshake fails synchronously.
+TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackSyncSync) {
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  host_resolver_.set_synchronous_mode(true);
+
+  MockQuicData socket_data;
+  socket_data.AddRead(SYNCHRONOUS, ERR_FAILED);
+  socket_data.AddWrite(SYNCHRONOUS, ERR_FAILED);
+  socket_data.AddSocketDataToFactory(socket_factory_.get());
+
+  QuicStreamRequest request(factory_.get());
+  EXPECT_EQ(
+      ERR_QUIC_PROTOCOL_ERROR,
+      request.Request(host_port_pair_, version_, privacy_mode_,
+                      DEFAULT_PRIORITY, /*cert_verify_flags=*/0, url_, net_log_,
+                      &net_error_details_, callback_.callback()));
+
+  // WaitForHostResolution() should return false since host
+  // resolution has finished already.
+  TestCompletionCallback host_resolution_callback;
+  EXPECT_FALSE(
+      request.WaitForHostResolution(host_resolution_callback.callback()));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(host_resolution_callback.have_result());
+  EXPECT_FALSE(callback_.have_result());
+}
+
+// Verify ResultAfterHostResolutionCallback behavior when host resolution
+// succeeds synchronously, then crypto handshake fails asynchronously.
+TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackSyncAsync) {
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  // Host resolution will succeed synchronously, but Request() as a whole
+  // will fail asynchronously.
+  host_resolver_.set_synchronous_mode(true);
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::ZERO_RTT);
+  factory_->set_require_confirmation(true);
+
+  MockQuicData socket_data;
+  socket_data.AddRead(ASYNC, ERR_IO_PENDING);  // Pause
+  socket_data.AddRead(ASYNC, ERR_FAILED);
+  socket_data.AddWrite(ASYNC, ERR_FAILED);
+  socket_data.AddSocketDataToFactory(socket_factory_.get());
+
+  QuicStreamRequest request(factory_.get());
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      request.Request(host_port_pair_, version_, privacy_mode_,
+                      DEFAULT_PRIORITY, /*cert_verify_flags=*/0, url_, net_log_,
+                      &net_error_details_, callback_.callback()));
+
+  // WaitForHostResolution() should return false since host
+  // resolution has finished already.
+  TestCompletionCallback host_resolution_callback;
+  EXPECT_FALSE(
+      request.WaitForHostResolution(host_resolution_callback.callback()));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(host_resolution_callback.have_result());
+
+  EXPECT_FALSE(callback_.have_result());
+  socket_data.GetSequencedSocketData()->Resume();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(callback_.have_result());
+  EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR, callback_.WaitForResult());
+}
+
+// Verify ResultAfterHostResolutionCallback behavior when host resolution fails
+// synchronously.
+TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackFailSync) {
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  // Host resolution will fail synchronously.
+  host_resolver_.rules()->AddSimulatedFailure(host_port_pair_.host());
+  host_resolver_.set_synchronous_mode(true);
+
+  QuicStreamRequest request(factory_.get());
+  EXPECT_EQ(
+      ERR_NAME_NOT_RESOLVED,
+      request.Request(host_port_pair_, version_, privacy_mode_,
+                      DEFAULT_PRIORITY, /*cert_verify_flags=*/0, url_, net_log_,
+                      &net_error_details_, callback_.callback()));
+
+  // WaitForHostResolution() should return false since host
+  // resolution has failed already.
+  TestCompletionCallback host_resolution_callback;
+  EXPECT_FALSE(
+      request.WaitForHostResolution(host_resolution_callback.callback()));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(host_resolution_callback.have_result());
+}
+
+// Verify ResultAfterHostResolutionCallback behavior when host resolution fails
+// asynchronously.
+TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackFailAsync) {
+  Initialize();
+  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
+  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
+
+  host_resolver_.rules()->AddSimulatedFailure(host_port_pair_.host());
+
+  QuicStreamRequest request(factory_.get());
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      request.Request(host_port_pair_, version_, privacy_mode_,
+                      DEFAULT_PRIORITY, /*cert_verify_flags=*/0, url_, net_log_,
+                      &net_error_details_, callback_.callback()));
+
+  TestCompletionCallback host_resolution_callback;
+  EXPECT_TRUE(
+      request.WaitForHostResolution(host_resolution_callback.callback()));
+
+  // Allow |host_resolver_| to fail host resolution. |host_resolution_callback|
+  // Should run with ERR_NAME_NOT_RESOLVED since that's the error host
+  // resolution failed with.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(host_resolution_callback.have_result());
+  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, host_resolution_callback.WaitForResult());
+
+  EXPECT_TRUE(callback_.have_result());
+  EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback_.WaitForResult());
+}
+
 }  // namespace test
 }  // namespace net
diff --git a/net/socket/udp_socket_posix.h b/net/socket/udp_socket_posix.h
index 699f0b8..fac8d12 100644
--- a/net/socket/udp_socket_posix.h
+++ b/net/socket/udp_socket_posix.h
@@ -129,12 +129,10 @@
   // Writes to the socket.
   // Only usable from the client-side of a UDP socket, after the socket
   // has been connected.
-  // TODO(crbug.com/656607): Remove default value.
   int Write(IOBuffer* buf,
             int buf_len,
             const CompletionCallback& callback,
-            const NetworkTrafficAnnotationTag& traffic_annotation =
-                NO_TRAFFIC_ANNOTATION_BUG_656607);
+            const NetworkTrafficAnnotationTag& traffic_annotation);
 
   // Reads from a socket and receive sender address information.
   // |buf| is the buffer to read data into.
diff --git a/net/test/embedded_test_server/embedded_test_server.cc b/net/test/embedded_test_server/embedded_test_server.cc
index de416f2..5caf5c5 100644
--- a/net/test/embedded_test_server/embedded_test_server.cc
+++ b/net/test/embedded_test_server/embedded_test_server.cc
@@ -281,6 +281,10 @@
       return "localhost_cert.pem";
     case CERT_EXPIRED:
       return "expired_cert.pem";
+    case CERT_COMMON_NAME_ONLY:
+      return "common_name_only.pem";
+    case CERT_SHA1_LEAF:
+      return "sha1_leaf.pem";
   }
 
   return "ok_cert.pem";
diff --git a/net/test/embedded_test_server/embedded_test_server.h b/net/test/embedded_test_server/embedded_test_server.h
index 5d26cf4e..a2d3351 100644
--- a/net/test/embedded_test_server/embedded_test_server.h
+++ b/net/test/embedded_test_server/embedded_test_server.h
@@ -103,6 +103,13 @@
     // Causes the testserver to use a hostname that is a domain
     // instead of an IP.
     CERT_COMMON_NAME_IS_DOMAIN,
+
+    // A certificate that only contains a commonName, rather than also
+    // including a subjectAltName extension.
+    CERT_COMMON_NAME_ONLY,
+
+    // A certificate that is a leaf certificate signed with SHA-1.
+    CERT_SHA1_LEAF,
   };
 
   typedef base::Callback<std::unique_ptr<HttpResponse>(
diff --git a/net/test/net_test_suite.cc b/net/test/net_test_suite.cc
index 8b1a668..792eeab 100644
--- a/net/test/net_test_suite.cc
+++ b/net/test/net_test_suite.cc
@@ -15,6 +15,9 @@
 #endif
 
 namespace {
+base::test::ScopedTaskEnvironment::MainThreadType kDefaultMainThreadType =
+    base::test::ScopedTaskEnvironment::MainThreadType::IO;
+
 NetTestSuite* g_current_net_test_suite = nullptr;
 }  // namespace
 
@@ -46,11 +49,13 @@
   TestSuite::Shutdown();
 }
 
+// static
 base::test::ScopedTaskEnvironment* NetTestSuite::GetScopedTaskEnvironment() {
   DCHECK(g_current_net_test_suite);
   return g_current_net_test_suite->scoped_task_environment_.get();
 }
 
+// static
 void NetTestSuite::SetScopedTaskEnvironment(
     base::test::ScopedTaskEnvironment::MainThreadType type) {
   g_current_net_test_suite->scoped_task_environment_ = nullptr;
@@ -58,6 +63,11 @@
       std::make_unique<base::test::ScopedTaskEnvironment>(type);
 }
 
+// static
+void NetTestSuite::ResetScopedTaskEnvironment() {
+  SetScopedTaskEnvironment(kDefaultMainThreadType);
+}
+
 void NetTestSuite::InitializeTestThread() {
   network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock());
 
@@ -74,5 +84,5 @@
 
   scoped_task_environment_ =
       std::make_unique<base::test::ScopedTaskEnvironment>(
-          base::test::ScopedTaskEnvironment::MainThreadType::IO);
+          kDefaultMainThreadType);
 }
diff --git a/net/test/net_test_suite.h b/net/test/net_test_suite.h
index 9cb4e35..a35a30c9 100644
--- a/net/test/net_test_suite.h
+++ b/net/test/net_test_suite.h
@@ -42,6 +42,10 @@
   static void SetScopedTaskEnvironment(
       base::test::ScopedTaskEnvironment::MainThreadType type);
 
+  // Sets the global ScopedTaskEnvironment to a new environment of the default
+  // type used by NetTestSuite.
+  static void ResetScopedTaskEnvironment();
+
  protected:
   // Called from within Initialize(), but separate so that derived classes
   // can initialize the NetTestSuite instance only and not
diff --git a/ppapi/proxy/BUILD.gn b/ppapi/proxy/BUILD.gn
index 26ae885..5332aa63 100644
--- a/ppapi/proxy/BUILD.gn
+++ b/ppapi/proxy/BUILD.gn
@@ -284,7 +284,7 @@
     ":common",
     "//base",
     "//gpu/command_buffer/client:gles2_implementation",
-    "//gpu/command_buffer/common:gles2_utils",
+    "//gpu/command_buffer/common",
     "//gpu/ipc/common:command_buffer_traits",
     "//media:shared_memory_support",
     "//mojo/edk/system",
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index a65c628..67e9a24 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -1088,15 +1088,14 @@
                     ppapi::HostResource)
 
 // PPB_Graphics3D.
-IPC_SYNC_MESSAGE_ROUTED3_4(
-    PpapiHostMsg_PPBGraphics3D_Create,
-    PP_Instance /* instance */,
-    ppapi::HostResource /* share_context */,
-    gpu::gles2::ContextCreationAttribHelper /* attrib_helper */,
-    ppapi::HostResource /* result */,
-    gpu::Capabilities /* capabilities */,
-    ppapi::proxy::SerializedHandle /* shared_state */,
-    gpu::CommandBufferId /* command_buffer_id */)
+IPC_SYNC_MESSAGE_ROUTED3_4(PpapiHostMsg_PPBGraphics3D_Create,
+                           PP_Instance /* instance */,
+                           ppapi::HostResource /* share_context */,
+                           gpu::ContextCreationAttribs /* attrib_helper */,
+                           ppapi::HostResource /* result */,
+                           gpu::Capabilities /* capabilities */,
+                           ppapi::proxy::SerializedHandle /* shared_state */,
+                           gpu::CommandBufferId /* command_buffer_id */)
 IPC_SYNC_MESSAGE_ROUTED2_0(PpapiHostMsg_PPBGraphics3D_SetGetBuffer,
                            ppapi::HostResource /* context */,
                            int32_t /* transfer_buffer_id */)
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.cc b/ppapi/proxy/ppb_graphics_3d_proxy.cc
index 973e46d..ea77cd1 100644
--- a/ppapi/proxy/ppb_graphics_3d_proxy.cc
+++ b/ppapi/proxy/ppb_graphics_3d_proxy.cc
@@ -168,7 +168,7 @@
     share_gles2 = share_graphics->gles2_impl();
   }
 
-  gpu::gles2::ContextCreationAttribHelper attrib_helper;
+  gpu::ContextCreationAttribs attrib_helper;
   if (attrib_list) {
     for (const int32_t* attr = attrib_list; attr[0] != PP_GRAPHICS3DATTRIB_NONE;
          attr += 2) {
@@ -283,7 +283,7 @@
 void PPB_Graphics3D_Proxy::OnMsgCreate(
     PP_Instance instance,
     HostResource share_context,
-    const gpu::gles2::ContextCreationAttribHelper& attrib_helper,
+    const gpu::ContextCreationAttribs& attrib_helper,
     HostResource* result,
     gpu::Capabilities* capabilities,
     SerializedHandle* shared_state,
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.h b/ppapi/proxy/ppb_graphics_3d_proxy.h
index 4a41114..d686f0ce 100644
--- a/ppapi/proxy/ppb_graphics_3d_proxy.h
+++ b/ppapi/proxy/ppb_graphics_3d_proxy.h
@@ -22,10 +22,8 @@
 #include "ppapi/utility/completion_callback_factory.h"
 
 namespace gpu {
-namespace gles2 {
-struct ContextCreationAttribHelper;
-}
 struct Capabilities;
+struct ContextCreationAttribs;
 }
 
 namespace ppapi {
@@ -92,7 +90,7 @@
  private:
   void OnMsgCreate(PP_Instance instance,
                    HostResource share_context,
-                   const gpu::gles2::ContextCreationAttribHelper& attrib_helper,
+                   const gpu::ContextCreationAttribs& attrib_helper,
                    HostResource* result,
                    gpu::Capabilities* capabilities,
                    SerializedHandle* handle,
diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc
index 5ba34d1..8610a0d 100644
--- a/ppapi/proxy/resource_creation_proxy.cc
+++ b/ppapi/proxy/resource_creation_proxy.cc
@@ -266,7 +266,7 @@
 PP_Resource ResourceCreationProxy::CreateGraphics3DRaw(
     PP_Instance instance,
     PP_Resource share_context,
-    const gpu::gles2::ContextCreationAttribHelper& attrib_helper,
+    const gpu::ContextCreationAttribs& attrib_helper,
     gpu::Capabilities* capabilities,
     base::SharedMemoryHandle* shared_state,
     gpu::CommandBufferId* command_buffer_id) {
diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h
index 1e6a11b..a16df32 100644
--- a/ppapi/proxy/resource_creation_proxy.h
+++ b/ppapi/proxy/resource_creation_proxy.h
@@ -121,7 +121,7 @@
   PP_Resource CreateGraphics3DRaw(
       PP_Instance instance,
       PP_Resource share_context,
-      const gpu::gles2::ContextCreationAttribHelper& attrib_helper,
+      const gpu::ContextCreationAttribs& attrib_helper,
       gpu::Capabilities* capabilities,
       base::SharedMemoryHandle* shared_state,
       gpu::CommandBufferId* command_buffer_id) override;
diff --git a/ppapi/thunk/resource_creation_api.h b/ppapi/thunk/resource_creation_api.h
index 682f680..1b266dcb 100644
--- a/ppapi/thunk/resource_creation_api.h
+++ b/ppapi/thunk/resource_creation_api.h
@@ -36,10 +36,8 @@
 struct PP_Size;
 
 namespace gpu {
-namespace gles2 {
-struct ContextCreationAttribHelper;
-}
 struct Capabilities;
+struct ContextCreationAttribs;
 }
 
 namespace ppapi {
@@ -143,7 +141,7 @@
   virtual PP_Resource CreateGraphics3DRaw(
       PP_Instance instance,
       PP_Resource share_context,
-      const gpu::gles2::ContextCreationAttribHelper& attrib_helper,
+      const gpu::ContextCreationAttribs& attrib_helper,
       gpu::Capabilities* capabilities,
       base::SharedMemoryHandle* shared_state,
       gpu::CommandBufferId* command_buffer_id) = 0;
diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc
index f5eb54b..9333fbfe 100644
--- a/remoting/host/heartbeat_sender.cc
+++ b/remoting/host/heartbeat_sender.cc
@@ -154,7 +154,13 @@
   request_ = iq_sender_->SendIq(
       buzz::STR_SET, directory_bot_jid_, CreateHeartbeatMessage(),
       base::Bind(&HeartbeatSender::OnResponse, base::Unretained(this)));
-  request_->SetTimeout(kHeartbeatResponseTimeout);
+  if (request_) {
+    request_->SetTimeout(kHeartbeatResponseTimeout);
+  } else {
+    // If we failed to send a new heartbeat, call into the handler to determine
+    // whether to retry later or disconnect.
+    OnResponse(nullptr, nullptr);
+  }
   ++sequence_id_;
 }
 
@@ -248,8 +254,9 @@
 
 HeartbeatSender::HeartbeatResult HeartbeatSender::ProcessResponse(
     const buzz::XmlElement* response) {
-  if (!response)
+  if (!response) {
     return HeartbeatResult::TIMEOUT;
+  }
 
   std::string type = response->Attr(buzz::QN_TYPE);
   if (type == buzz::STR_ERROR) {
diff --git a/sandbox/win/src/app_container_test.cc b/sandbox/win/src/app_container_test.cc
index 06ca7885..7167354 100644
--- a/sandbox/win/src/app_container_test.cc
+++ b/sandbox/win/src/app_container_test.cc
@@ -4,24 +4,187 @@
 
 #include <windows.h>
 
-#include "base/strings/string16.h"
+#include <sddl.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/rand_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/win/scoped_handle.h"
+#include "base/win/scoped_process_information.h"
 #include "base/win/windows_version.h"
+#include "sandbox/win/src/app_container_profile.h"
 #include "sandbox/win/src/sync_policy_test.h"
+#include "sandbox/win/src/win_utils.h"
+#include "sandbox/win/tests/common/controller.h"
+#include "sandbox/win/tests/common/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace sandbox {
+
 namespace {
 
 const wchar_t kAppContainerSid[] =
     L"S-1-15-2-3251537155-1984446955-2931258699-841473695-1938553385-"
     L"924012148-2839372144";
 
+std::wstring GenerateRandomPackageName() {
+  return base::StringPrintf(L"%016lX%016lX", base::RandUint64(),
+                            base::RandUint64());
+}
+
+const char* TokenTypeToName(TOKEN_TYPE token_type) {
+  return token_type == ::TokenPrimary ? "Primary Token" : "Impersonation Token";
+}
+
+void CheckToken(HANDLE token,
+                TOKEN_TYPE token_type,
+                PSECURITY_CAPABILITIES security_capabilities,
+                BOOL restricted) {
+  ASSERT_EQ(restricted, ::IsTokenRestricted(token))
+      << TokenTypeToName(token_type);
+
+  DWORD appcontainer;
+  DWORD return_length;
+  ASSERT_TRUE(::GetTokenInformation(token, ::TokenIsAppContainer, &appcontainer,
+                                    sizeof(appcontainer), &return_length))
+      << TokenTypeToName(token_type);
+  ASSERT_TRUE(appcontainer) << TokenTypeToName(token_type);
+  TOKEN_TYPE token_type_real;
+  ASSERT_TRUE(::GetTokenInformation(token, ::TokenType, &token_type_real,
+                                    sizeof(token_type_real), &return_length))
+      << TokenTypeToName(token_type);
+  ASSERT_EQ(token_type_real, token_type) << TokenTypeToName(token_type);
+  if (token_type == ::TokenImpersonation) {
+    SECURITY_IMPERSONATION_LEVEL imp_level;
+    ASSERT_TRUE(::GetTokenInformation(token, ::TokenImpersonationLevel,
+                                      &imp_level, sizeof(imp_level),
+                                      &return_length))
+        << TokenTypeToName(token_type);
+    ASSERT_EQ(imp_level, ::SecurityImpersonation)
+        << TokenTypeToName(token_type);
+  }
+
+  std::unique_ptr<Sid> package_sid;
+  ASSERT_TRUE(GetTokenAppContainerSid(token, &package_sid))
+      << TokenTypeToName(token_type);
+  EXPECT_TRUE(::EqualSid(security_capabilities->AppContainerSid,
+                         package_sid->GetPSID()))
+      << TokenTypeToName(token_type);
+
+  std::vector<SidAndAttributes> capabilities;
+  ASSERT_TRUE(GetTokenGroups(token, ::TokenCapabilities, &capabilities))
+      << TokenTypeToName(token_type);
+
+  ASSERT_EQ(capabilities.size(), security_capabilities->CapabilityCount)
+      << TokenTypeToName(token_type);
+  for (size_t index = 0; index < capabilities.size(); ++index) {
+    EXPECT_EQ(capabilities[index].GetAttributes(),
+              security_capabilities->Capabilities[index].Attributes)
+        << TokenTypeToName(token_type);
+    EXPECT_TRUE(::EqualSid(capabilities[index].GetPSID(),
+                           security_capabilities->Capabilities[index].Sid))
+        << TokenTypeToName(token_type);
+  }
+}
+
+void CheckProcessToken(HANDLE process,
+                       PSECURITY_CAPABILITIES security_capabilities,
+                       bool restricted) {
+  HANDLE token_handle;
+  ASSERT_TRUE(::OpenProcessToken(process, TOKEN_ALL_ACCESS, &token_handle));
+  base::win::ScopedHandle token(token_handle);
+  CheckToken(token_handle, ::TokenPrimary, security_capabilities, restricted);
+}
+
+void CheckThreadToken(HANDLE thread,
+                      PSECURITY_CAPABILITIES security_capabilities,
+                      bool restricted) {
+  HANDLE token_handle;
+  ASSERT_TRUE(::OpenThreadToken(thread, TOKEN_ALL_ACCESS, TRUE, &token_handle));
+  base::win::ScopedHandle token(token_handle);
+  CheckToken(token_handle, ::TokenImpersonation, security_capabilities,
+             restricted);
+}
+
+// Check for LPAC using an access check. We could query for a security attribute
+// but that's undocumented and has the potential to change.
+void CheckLpacToken(HANDLE process) {
+  HANDLE token_handle;
+  ASSERT_TRUE(::OpenProcessToken(process, TOKEN_ALL_ACCESS, &token_handle));
+  base::win::ScopedHandle token(token_handle);
+  ASSERT_TRUE(
+      ::DuplicateToken(token.Get(), ::SecurityImpersonation, &token_handle));
+  token.Set(token_handle);
+  PSECURITY_DESCRIPTOR security_desc_ptr;
+  // AC is AllPackages, S-1-15-2-2 is AllRestrictedPackages. An LPAC token
+  // will get granted access of 2, where as a normal AC token will get 3.
+  ASSERT_TRUE(::ConvertStringSecurityDescriptorToSecurityDescriptor(
+      L"O:SYG:SYD:(A;;0x3;;;WD)(A;;0x1;;;AC)(A;;0x2;;;S-1-15-2-2)",
+      SDDL_REVISION_1, &security_desc_ptr, nullptr));
+  std::unique_ptr<void, LocalFreeDeleter> security_desc(security_desc_ptr);
+  GENERIC_MAPPING generic_mapping = {};
+  PRIVILEGE_SET priv_set = {};
+  DWORD priv_set_length = sizeof(PRIVILEGE_SET);
+  DWORD granted_access;
+  BOOL access_status;
+  ASSERT_TRUE(::AccessCheck(security_desc_ptr, token.Get(), MAXIMUM_ALLOWED,
+                            &generic_mapping, &priv_set, &priv_set_length,
+                            &granted_access, &access_status));
+  ASSERT_TRUE(access_status);
+  ASSERT_EQ(DWORD{2}, granted_access);
+}
+
+class AppContainerProfileTest : public ::testing::Test {
+ public:
+  void SetUp() override {
+    if (base::win::GetVersion() < base::win::VERSION_WIN8)
+      return;
+    package_name_ = GenerateRandomPackageName();
+    broker_services_ = GetBroker();
+    profile_ = AppContainerProfile::Create(package_name_.c_str(), L"Name",
+                                           L"Description");
+    policy_ = broker_services_->CreatePolicy();
+    policy_->SetAppContainerProfile(profile_.get());
+  }
+
+  void TearDown() override {
+    if (scoped_process_info_.IsValid())
+      ::TerminateProcess(scoped_process_info_.process_handle(), 0);
+    if (profile_)
+      AppContainerProfile::Delete(package_name_.c_str());
+  }
+
+ protected:
+  void CreateProcess() {
+    // Get the path to the sandboxed app.
+    wchar_t prog_name[MAX_PATH] = {};
+    ASSERT_NE(DWORD{0}, ::GetModuleFileNameW(nullptr, prog_name, MAX_PATH));
+
+    PROCESS_INFORMATION process_info = {};
+    ResultCode last_warning = SBOX_ALL_OK;
+    DWORD last_error = 0;
+    ResultCode result = broker_services_->SpawnTarget(
+        prog_name, prog_name, policy_, &last_warning, &last_error,
+        &process_info);
+    ASSERT_EQ(SBOX_ALL_OK, result) << "Last Error: " << last_error;
+    scoped_process_info_.Set(process_info);
+  }
+
+  std::wstring package_name_;
+  BrokerServices* broker_services_;
+  scoped_refptr<AppContainerProfile> profile_;
+  scoped_refptr<TargetPolicy> policy_;
+  base::win::ScopedProcessInformation scoped_process_info_;
+};
+
 }  // namespace
 
-namespace sandbox {
 
 TEST(AppContainerTest, DenyOpenEventForLowBox) {
-  if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8)
+  if (base::win::GetVersion() < base::win::VERSION_WIN8)
     return;
 
   TestRunner runner(JOB_UNPROTECTED, USER_UNPROTECTED, USER_UNPROTECTED);
@@ -30,7 +193,7 @@
   // Run test once, this ensures the app container directory exists, we
   // ignore the result.
   runner.RunTest(L"Event_Open f test");
-  base::string16 event_name = L"AppContainerNamedObjects\\";
+  std::wstring event_name = L"AppContainerNamedObjects\\";
   event_name += kAppContainerSid;
   event_name += L"\\test";
 
@@ -41,7 +204,120 @@
   EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"Event_Open f test"));
 }
 
-// TODO(shrikant): Please add some tests to prove usage of lowbox token like
-// socket connection to local server in lock down mode.
+TEST_F(AppContainerProfileTest, CheckIncompatibleOptions) {
+  if (!profile_)
+    return;
+  EXPECT_EQ(SBOX_ERROR_BAD_PARAMS,
+            policy_->SetIntegrityLevel(INTEGRITY_LEVEL_UNTRUSTED));
+  EXPECT_EQ(SBOX_ERROR_BAD_PARAMS, policy_->SetLowBox(kAppContainerSid));
+}
+
+TEST_F(AppContainerProfileTest, NoCapabilities) {
+  if (!profile_)
+    return;
+
+  policy_->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED);
+  policy_->SetJobLevel(JOB_NONE, 0);
+
+  CreateProcess();
+  auto security_capabilities = profile_->GetSecurityCapabilities();
+
+  CheckProcessToken(scoped_process_info_.process_handle(),
+                    security_capabilities.get(), FALSE);
+  CheckThreadToken(scoped_process_info_.thread_handle(),
+                   security_capabilities.get(), FALSE);
+}
+
+TEST_F(AppContainerProfileTest, NoCapabilitiesRestricted) {
+  if (!profile_)
+    return;
+
+  policy_->SetTokenLevel(USER_LOCKDOWN, USER_RESTRICTED_SAME_ACCESS);
+  policy_->SetJobLevel(JOB_NONE, 0);
+
+  CreateProcess();
+  auto security_capabilities = profile_->GetSecurityCapabilities();
+
+  CheckProcessToken(scoped_process_info_.process_handle(),
+                    security_capabilities.get(), TRUE);
+  CheckThreadToken(scoped_process_info_.thread_handle(),
+                   security_capabilities.get(), TRUE);
+}
+
+TEST_F(AppContainerProfileTest, WithCapabilities) {
+  if (!profile_)
+    return;
+
+  profile_->AddCapability(kInternetClient);
+  profile_->AddCapability(kInternetClientServer);
+  policy_->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED);
+  policy_->SetJobLevel(JOB_NONE, 0);
+
+  CreateProcess();
+  auto security_capabilities = profile_->GetSecurityCapabilities();
+
+  CheckProcessToken(scoped_process_info_.process_handle(),
+                    security_capabilities.get(), FALSE);
+  CheckThreadToken(scoped_process_info_.thread_handle(),
+                   security_capabilities.get(), FALSE);
+}
+
+TEST_F(AppContainerProfileTest, WithCapabilitiesRestricted) {
+  if (!profile_)
+    return;
+
+  profile_->AddCapability(kInternetClient);
+  profile_->AddCapability(kInternetClientServer);
+  policy_->SetTokenLevel(USER_LOCKDOWN, USER_RESTRICTED_SAME_ACCESS);
+  policy_->SetJobLevel(JOB_NONE, 0);
+
+  CreateProcess();
+  auto security_capabilities = profile_->GetSecurityCapabilities();
+
+  CheckProcessToken(scoped_process_info_.process_handle(),
+                    security_capabilities.get(), TRUE);
+  CheckThreadToken(scoped_process_info_.thread_handle(),
+                   security_capabilities.get(), TRUE);
+}
+
+TEST_F(AppContainerProfileTest, WithImpersonationCapabilities) {
+  if (!profile_)
+    return;
+
+  profile_->AddCapability(kInternetClient);
+  profile_->AddCapability(kInternetClientServer);
+  profile_->AddImpersonationCapability(kPrivateNetworkClientServer);
+  profile_->AddImpersonationCapability(kPicturesLibrary);
+  policy_->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED);
+  policy_->SetJobLevel(JOB_NONE, 0);
+
+  CreateProcess();
+  auto security_capabilities = profile_->GetSecurityCapabilities();
+
+  CheckProcessToken(scoped_process_info_.process_handle(),
+                    security_capabilities.get(), FALSE);
+  SecurityCapabilities impersonation_security_capabilities(
+      profile_->GetPackageSid(), profile_->GetImpersonationCapabilities());
+  CheckThreadToken(scoped_process_info_.thread_handle(),
+                   &impersonation_security_capabilities, FALSE);
+}
+
+TEST_F(AppContainerProfileTest, NoCapabilitiesLPAC) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN10_RS1)
+    return;
+
+  profile_->SetEnableLowPrivilegeAppContainer(true);
+  policy_->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED);
+  policy_->SetJobLevel(JOB_NONE, 0);
+
+  CreateProcess();
+  auto security_capabilities = profile_->GetSecurityCapabilities();
+
+  CheckProcessToken(scoped_process_info_.process_handle(),
+                    security_capabilities.get(), FALSE);
+  CheckThreadToken(scoped_process_info_.thread_handle(),
+                   security_capabilities.get(), FALSE);
+  CheckLpacToken(scoped_process_info_.process_handle());
+}
 
 }  // namespace sandbox
diff --git a/sandbox/win/src/broker_services.cc b/sandbox/win/src/broker_services.cc
index 525531bc5..ab89995 100644
--- a/sandbox/win/src/broker_services.cc
+++ b/sandbox/win/src/broker_services.cc
@@ -18,6 +18,7 @@
 #include "base/win/scoped_process_information.h"
 #include "base/win/startup_information.h"
 #include "base/win/windows_version.h"
+#include "sandbox/win/src/app_container_profile.h"
 #include "sandbox/win/src/process_mitigations.h"
 #include "sandbox/win/src/sandbox.h"
 #include "sandbox/win/src/sandbox_policy_base.h"
@@ -367,6 +368,20 @@
   if (inherited_handle_list.size())
     ++attribute_count;
 
+  scoped_refptr<AppContainerProfile> profile =
+      policy_base->GetAppContainerProfile();
+  if (profile) {
+    if (base::win::GetVersion() < base::win::VERSION_WIN8)
+      return SBOX_ERROR_BAD_PARAMS;
+    ++attribute_count;
+    if (profile->GetEnableLowPrivilegeAppContainer()) {
+      // LPAC first supported in RS1.
+      if (base::win::GetVersion() < base::win::VERSION_WIN10_RS1)
+        return SBOX_ERROR_BAD_PARAMS;
+      ++attribute_count;
+    }
+  }
+
   if (!startup_info.InitializeProcThreadAttributeList(attribute_count))
     return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;
 
@@ -401,6 +416,28 @@
     inherit_handles = true;
   }
 
+  // Declared here to ensure they stay in scope until after process creation.
+  std::unique_ptr<SecurityCapabilities> security_capabilities;
+  DWORD all_applications_package_policy =
+      PROCESS_CREATION_ALL_APPLICATION_PACKAGES_OPT_OUT;
+
+  if (profile) {
+    security_capabilities = profile->GetSecurityCapabilities();
+    if (!startup_info.UpdateProcThreadAttribute(
+            PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES,
+            security_capabilities.get(), sizeof(SECURITY_CAPABILITIES))) {
+      return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;
+    }
+    if (profile->GetEnableLowPrivilegeAppContainer()) {
+      if (!startup_info.UpdateProcThreadAttribute(
+              PROC_THREAD_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY,
+              &all_applications_package_policy,
+              sizeof(all_applications_package_policy))) {
+        return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;
+      }
+    }
+  }
+
   // Construct the thread pool here in case it is expensive.
   // The thread pool is shared by all the targets
   if (!thread_pool_)
@@ -409,9 +446,10 @@
   // Create the TargetProcess object and spawn the target suspended. Note that
   // Brokerservices does not own the target object. It is owned by the Policy.
   base::win::ScopedProcessInformation process_info;
-  TargetProcess* target =
-      new TargetProcess(std::move(initial_token), std::move(lockdown_token),
-                        job.Get(), thread_pool_.get());
+  TargetProcess* target = new TargetProcess(
+      std::move(initial_token), std::move(lockdown_token), job.Get(),
+      thread_pool_.get(),
+      profile ? profile->GetImpersonationCapabilities() : std::vector<Sid>());
 
   result = target->Create(exe_path, command_line, inherit_handles, startup_info,
                           &process_info, last_error);
diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h
index 29f8705b..4a110fa 100644
--- a/sandbox/win/src/sandbox_policy.h
+++ b/sandbox/win/src/sandbox_policy.h
@@ -14,6 +14,8 @@
 
 namespace sandbox {
 
+class AppContainerProfile;
+
 class TargetPolicy {
  public:
   // Windows subsystems that can have specific rules.
@@ -251,6 +253,9 @@
   // Enable OPM API emulation when in Win32k lockdown.
   virtual bool GetEnableOPMRedirection() = 0;
 
+  // Configure policy to use an AppContainer profile.
+  virtual ResultCode SetAppContainerProfile(AppContainerProfile* profile) = 0;
+
  protected:
   ~TargetPolicy() {}
 };
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc
index 867a549..471fc75a 100644
--- a/sandbox/win/src/sandbox_policy_base.cc
+++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -267,6 +267,8 @@
 }
 
 ResultCode PolicyBase::SetIntegrityLevel(IntegrityLevel integrity_level) {
+  if (_app_container_profile)
+    return SBOX_ERROR_BAD_PARAMS;
   integrity_level_ = integrity_level;
   return SBOX_ALL_OK;
 }
@@ -282,11 +284,11 @@
 }
 
 ResultCode PolicyBase::SetLowBox(const wchar_t* sid) {
-  if (base::win::OSInfo::GetInstance()->version() < base::win::VERSION_WIN8)
+  if (base::win::GetVersion() < base::win::VERSION_WIN8)
     return SBOX_ERROR_UNSUPPORTED;
 
   DCHECK(sid);
-  if (lowbox_sid_)
+  if (lowbox_sid_ || _app_container_profile)
     return SBOX_ERROR_BAD_PARAMS;
 
   if (!ConvertStringSidToSid(sid, &lowbox_sid_))
@@ -594,6 +596,23 @@
   return enable_opm_redirection_;
 }
 
+ResultCode PolicyBase::SetAppContainerProfile(AppContainerProfile* profile) {
+  if (base::win::GetVersion() < base::win::VERSION_WIN8)
+    return SBOX_ERROR_UNSUPPORTED;
+
+  DCHECK(profile);
+  if (lowbox_sid_ || _app_container_profile ||
+      integrity_level_ != INTEGRITY_LEVEL_LAST)
+    return SBOX_ERROR_BAD_PARAMS;
+
+  _app_container_profile = profile;
+  return SBOX_ALL_OK;
+}
+
+scoped_refptr<AppContainerProfile> PolicyBase::GetAppContainerProfile() {
+  return _app_container_profile;
+}
+
 ResultCode PolicyBase::SetupAllInterceptions(TargetProcess* target) {
   InterceptionManager manager(target, relaxed_interceptions_);
 
diff --git a/sandbox/win/src/sandbox_policy_base.h b/sandbox/win/src/sandbox_policy_base.h
index 61a66419..fddea2b 100644
--- a/sandbox/win/src/sandbox_policy_base.h
+++ b/sandbox/win/src/sandbox_policy_base.h
@@ -19,6 +19,7 @@
 #include "base/process/launch.h"
 #include "base/strings/string16.h"
 #include "base/win/scoped_handle.h"
+#include "sandbox/win/src/app_container_profile.h"
 #include "sandbox/win/src/crosscall_server.h"
 #include "sandbox/win/src/handle_closer.h"
 #include "sandbox/win/src/ipc_tags.h"
@@ -72,6 +73,7 @@
   void SetLockdownDefaultDacl() override;
   void SetEnableOPMRedirection() override;
   bool GetEnableOPMRedirection() override;
+  ResultCode SetAppContainerProfile(AppContainerProfile* profile) override;
 
   // Creates a Job object with the level specified in a previous call to
   // SetJobLevel().
@@ -100,6 +102,8 @@
   HANDLE GetStdoutHandle();
   HANDLE GetStderrHandle();
 
+  scoped_refptr<AppContainerProfile> GetAppContainerProfile();
+
   // Returns the list of handles being shared with the target process.
   const base::HandlesToInheritVector& GetHandlesBeingShared();
 
@@ -170,6 +174,8 @@
   base::HandlesToInheritVector handles_to_share_;
   bool enable_opm_redirection_;
 
+  scoped_refptr<AppContainerProfile> _app_container_profile;
+
   DISALLOW_COPY_AND_ASSIGN(PolicyBase);
 };
 
diff --git a/sandbox/win/src/target_process.cc b/sandbox/win/src/target_process.cc
index 4f3e103..72b3e1b 100644
--- a/sandbox/win/src/target_process.cc
+++ b/sandbox/win/src/target_process.cc
@@ -9,18 +9,25 @@
 
 #include <memory>
 #include <utility>
+#include <vector>
 
 #include "base/macros.h"
 #include "base/memory/free_deleter.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/win/startup_information.h"
 #include "base/win/windows_version.h"
 #include "sandbox/win/src/crosscall_client.h"
 #include "sandbox/win/src/crosscall_server.h"
 #include "sandbox/win/src/policy_low_level.h"
+#include "sandbox/win/src/restricted_token_utils.h"
 #include "sandbox/win/src/sandbox_types.h"
+#include "sandbox/win/src/security_capabilities.h"
 #include "sandbox/win/src/sharedmem_ipc_server.h"
+#include "sandbox/win/src/sid.h"
 #include "sandbox/win/src/win_utils.h"
 
+namespace sandbox {
+
 namespace {
 
 void CopyPolicyToTarget(const void* source, size_t size, void* dest) {
@@ -41,9 +48,53 @@
   }
 }
 
-}  // namespace
+bool GetTokenAppContainerSid(HANDLE token_handle,
+                             std::unique_ptr<Sid>* app_container_sid) {
+  std::vector<char> app_container_info(sizeof(TOKEN_APPCONTAINER_INFORMATION) +
+                                       SECURITY_MAX_SID_SIZE);
+  DWORD return_length;
 
-namespace sandbox {
+  if (!::GetTokenInformation(
+          token_handle, TokenAppContainerSid, app_container_info.data(),
+          base::checked_cast<DWORD>(app_container_info.size()),
+          &return_length)) {
+    return false;
+  }
+
+  PTOKEN_APPCONTAINER_INFORMATION info =
+      reinterpret_cast<PTOKEN_APPCONTAINER_INFORMATION>(
+          app_container_info.data());
+  if (!info->TokenAppContainer)
+    return false;
+  *app_container_sid = std::unique_ptr<Sid>(new Sid(info->TokenAppContainer));
+  return true;
+}
+
+bool GetProcessAppContainerSid(HANDLE process,
+                               std::unique_ptr<Sid>* app_container_sid) {
+  HANDLE token_handle;
+  if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle))
+    return false;
+  base::win::ScopedHandle process_token(token_handle);
+
+  return GetTokenAppContainerSid(process_token.Get(), app_container_sid);
+}
+
+bool GetAppContainerImpersonationToken(
+    HANDLE process,
+    HANDLE initial_token,
+    const std::vector<Sid>& capabilities,
+    base::win::ScopedHandle* impersonation_token) {
+  std::unique_ptr<Sid> app_container_sid;
+  if (!GetProcessAppContainerSid(process, &app_container_sid)) {
+    return false;
+  }
+  SecurityCapabilities security_caps(*app_container_sid, capabilities);
+  return CreateLowBoxToken(initial_token, IMPERSONATION, &security_caps,
+                           nullptr, 0, impersonation_token) == ERROR_SUCCESS;
+}
+
+}  // namespace
 
 SANDBOX_INTERCEPT HANDLE g_shared_section;
 SANDBOX_INTERCEPT size_t g_shared_IPC_size;
@@ -52,7 +103,8 @@
 TargetProcess::TargetProcess(base::win::ScopedHandle initial_token,
                              base::win::ScopedHandle lockdown_token,
                              HANDLE job,
-                             ThreadProvider* thread_pool)
+                             ThreadProvider* thread_pool,
+                             const std::vector<Sid>& impersonation_capabilities)
     // This object owns everything initialized here except thread_pool and
     // the job_ handle. The Job handle is closed by BrokerServices and results
     // eventually in a call to our dtor.
@@ -60,7 +112,8 @@
       initial_token_(std::move(initial_token)),
       job_(job),
       thread_pool_(thread_pool),
-      base_address_(nullptr) {}
+      base_address_(nullptr),
+      impersonation_capabilities_(impersonation_capabilities) {}
 
 TargetProcess::~TargetProcess() {
   // Give a chance to the process to die. In most cases the JOB_KILL_ON_CLOSE
@@ -132,14 +185,20 @@
   }
 
   if (initial_token_.IsValid()) {
+    HANDLE impersonation_token = initial_token_.Get();
+    base::win::ScopedHandle app_container_token;
+    if (GetAppContainerImpersonationToken(
+            process_info.process_handle(), impersonation_token,
+            impersonation_capabilities_, &app_container_token)) {
+      impersonation_token = app_container_token.Get();
+    }
+
     // Change the token of the main thread of the new process for the
     // impersonation token with more rights. This allows the target to start;
     // otherwise it will crash too early for us to help.
     HANDLE temp_thread = process_info.thread_handle();
-    if (!::SetThreadToken(&temp_thread, initial_token_.Get())) {
+    if (!::SetThreadToken(&temp_thread, impersonation_token)) {
       *win_error = ::GetLastError();
-      // It might be a security breach if we let the target run outside the job
-      // so kill it before it causes damage.
       ::TerminateProcess(process_info.process_handle(), 0);
       return SBOX_ERROR_SET_THREAD_TOKEN;
     }
@@ -311,8 +370,9 @@
 }
 
 TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) {
-  TargetProcess* target = new TargetProcess(
-      base::win::ScopedHandle(), base::win::ScopedHandle(), nullptr, nullptr);
+  TargetProcess* target =
+      new TargetProcess(base::win::ScopedHandle(), base::win::ScopedHandle(),
+                        nullptr, nullptr, std::vector<Sid>());
   PROCESS_INFORMATION process_info = {};
   process_info.hProcess = process;
   target->sandbox_process_info_.Set(process_info);
diff --git a/sandbox/win/src/target_process.h b/sandbox/win/src/target_process.h
index d4b4b27d..24059c9 100644
--- a/sandbox/win/src/target_process.h
+++ b/sandbox/win/src/target_process.h
@@ -11,6 +11,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <vector>
 
 #include "base/macros.h"
 #include "base/memory/free_deleter.h"
@@ -30,18 +31,19 @@
 namespace sandbox {
 
 class SharedMemIPCServer;
+class Sid;
 class ThreadProvider;
 
 // TargetProcess models a target instance (child process). Objects of this
 // class are owned by the Policy used to create them.
 class TargetProcess {
  public:
-  // The constructor takes ownership of |initial_token|, |lockdown_token|
-  // and |lowbox_token|.
+  // The constructor takes ownership of |initial_token| and |lockdown_token|
   TargetProcess(base::win::ScopedHandle initial_token,
                 base::win::ScopedHandle lockdown_token,
                 HANDLE job,
-                ThreadProvider* thread_pool);
+                ThreadProvider* thread_pool,
+                const std::vector<Sid>& impersonation_capabilities);
   ~TargetProcess();
 
   // TODO(cpu): Currently there does not seem to be a reason to implement
@@ -120,6 +122,8 @@
   void* base_address_;
   // Full name of the target executable.
   std::unique_ptr<wchar_t, base::FreeDeleter> exe_name_;
+  /// List of capability sids for use when impersonating in an AC process.
+  std::vector<Sid> impersonation_capabilities_;
 
   // Function used for testing.
   friend TargetProcess* MakeTestTargetProcess(HANDLE process,
diff --git a/sandbox/win/tests/common/controller.cc b/sandbox/win/tests/common/controller.cc
index 90cd634..27427fd 100644
--- a/sandbox/win/tests/common/controller.cc
+++ b/sandbox/win/tests/common/controller.cc
@@ -13,6 +13,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/unguessable_token.h"
 #include "base/win/windows_version.h"
+#include "sandbox/win/src/app_container_profile.h"
 #include "sandbox/win/src/sandbox_factory.h"
 
 namespace {
@@ -93,27 +94,13 @@
 
 TestRunner::TestRunner(JobLevel job_level,
                        TokenLevel startup_token,
-                       TokenLevel main_token)
+                       TokenLevel main_token,
+                       AppContainerProfile* profile)
     : is_init_(false),
       is_async_(false),
       no_sandbox_(false),
       disable_csrss_(true),
       target_process_id_(0) {
-  Init(job_level, startup_token, main_token);
-}
-
-TestRunner::TestRunner()
-    : is_init_(false),
-      is_async_(false),
-      no_sandbox_(false),
-      disable_csrss_(true),
-      target_process_id_(0) {
-  Init(JOB_LOCKDOWN, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN);
-}
-
-void TestRunner::Init(JobLevel job_level,
-                      TokenLevel startup_token,
-                      TokenLevel main_token) {
   broker_ = NULL;
   policy_ = NULL;
   timeout_ = kDefaultTimeout;
@@ -130,12 +117,24 @@
   if (!policy_)
     return;
 
+  if (profile && policy_->SetAppContainerProfile(profile) != SBOX_ALL_OK) {
+    return;
+  }
+
   policy_->SetJobLevel(job_level, 0);
   policy_->SetTokenLevel(startup_token, main_token);
 
   is_init_ = true;
 }
 
+TestRunner::TestRunner(JobLevel job_level,
+                       TokenLevel startup_token,
+                       TokenLevel main_token)
+    : TestRunner(job_level, startup_token, main_token, nullptr) {}
+
+TestRunner::TestRunner()
+    : TestRunner(JOB_LOCKDOWN, USER_RESTRICTED_SAME_ACCESS, USER_LOCKDOWN) {}
+
 TargetPolicy* TestRunner::GetPolicy() {
   return policy_.get();
 }
diff --git a/sandbox/win/tests/common/controller.h b/sandbox/win/tests/common/controller.h
index 133decd..60c90f2 100644
--- a/sandbox/win/tests/common/controller.h
+++ b/sandbox/win/tests/common/controller.h
@@ -67,12 +67,19 @@
 typedef int (*CommandFunction)(int argc, wchar_t **argv);
 }
 
+class AppContainerProfile;
+
 // Class to facilitate the launch of a test inside the sandbox.
 class TestRunner {
  public:
   TestRunner(JobLevel job_level, TokenLevel startup_token,
              TokenLevel main_token);
 
+  TestRunner(JobLevel job_level,
+             TokenLevel startup_token,
+             TokenLevel main_token,
+             AppContainerProfile* profile);
+
   TestRunner();
 
   ~TestRunner();
@@ -133,11 +140,6 @@
   DWORD process_id() { return target_process_id_; }
 
  private:
-  // Initializes the data in the object. Sets is_init_ to tree if the
-  // function succeeds. This is meant to be called from the constructor.
-  void Init(JobLevel job_level,
-            TokenLevel startup_token,
-            TokenLevel main_token);
 
   // The actual runner.
   int InternalRunTest(const wchar_t* command);
diff --git a/sandbox/win/tests/common/test_utils.cc b/sandbox/win/tests/common/test_utils.cc
index 4ec47bc..9c03ac2 100644
--- a/sandbox/win/tests/common/test_utils.cc
+++ b/sandbox/win/tests/common/test_utils.cc
@@ -7,6 +7,8 @@
 #include <stddef.h>
 #include <winioctl.h>
 
+#include "base/numerics/safe_conversions.h"
+
 typedef struct _REPARSE_DATA_BUFFER {
   ULONG  ReparseTag;
   USHORT  ReparseDataLength;
@@ -71,3 +73,75 @@
 
   return true;
 }
+
+SidAndAttributes::SidAndAttributes(const SID_AND_ATTRIBUTES& sid_and_attributes)
+    : attributes_(sid_and_attributes.Attributes),
+      sid_(sid_and_attributes.Sid) {}
+
+PSID SidAndAttributes::GetPSID() const {
+  return sid_.GetPSID();
+}
+
+DWORD SidAndAttributes::GetAttributes() const {
+  return attributes_;
+}
+
+bool GetTokenAppContainerSid(HANDLE token,
+                             std::unique_ptr<sandbox::Sid>* app_container_sid) {
+  std::vector<char> app_container_info(sizeof(TOKEN_APPCONTAINER_INFORMATION) +
+                                       SECURITY_MAX_SID_SIZE);
+  DWORD return_length;
+
+  if (!::GetTokenInformation(
+          token, TokenAppContainerSid, app_container_info.data(),
+          base::checked_cast<DWORD>(app_container_info.size()),
+          &return_length)) {
+    return false;
+  }
+
+  PTOKEN_APPCONTAINER_INFORMATION info =
+      reinterpret_cast<PTOKEN_APPCONTAINER_INFORMATION>(
+          app_container_info.data());
+  if (!info->TokenAppContainer)
+    return false;
+  *app_container_sid = std::make_unique<sandbox::Sid>(info->TokenAppContainer);
+  return true;
+}
+
+bool GetTokenGroups(HANDLE token,
+                    TOKEN_INFORMATION_CLASS information_class,
+                    std::vector<SidAndAttributes>* token_groups) {
+  if (information_class != ::TokenCapabilities &&
+      information_class != ::TokenGroups &&
+      information_class != ::TokenRestrictedSids) {
+    return false;
+  }
+
+  std::vector<char> groups_buf;
+  if (!GetVariableTokenInformation(token, information_class, &groups_buf))
+    return false;
+
+  PTOKEN_GROUPS groups = reinterpret_cast<PTOKEN_GROUPS>(groups_buf.data());
+
+  if (groups->GroupCount > 0) {
+    token_groups->insert(token_groups->begin(), groups->Groups,
+                         groups->Groups + groups->GroupCount);
+  }
+
+  return true;
+}
+
+bool GetVariableTokenInformation(HANDLE token,
+                                 TOKEN_INFORMATION_CLASS information_class,
+                                 std::vector<char>* information) {
+  DWORD return_length;
+  if (!::GetTokenInformation(token, information_class, nullptr, 0,
+                             &return_length)) {
+    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+      return false;
+  }
+
+  information->resize(return_length);
+  return !!::GetTokenInformation(token, information_class, information->data(),
+                                 return_length, &return_length);
+}
diff --git a/sandbox/win/tests/common/test_utils.h b/sandbox/win/tests/common/test_utils.h
index 9e17660..049321d 100644
--- a/sandbox/win/tests/common/test_utils.h
+++ b/sandbox/win/tests/common/test_utils.h
@@ -7,6 +7,11 @@
 
 #include <windows.h>
 
+#include <memory>
+#include <vector>
+
+#include "sandbox/win/src/sid.h"
+
 // Sets a reparse point. |source| will now point to |target|. Returns true if
 // the call succeeds, false otherwise.
 bool SetReparsePoint(HANDLE source, const wchar_t* target);
@@ -15,5 +20,33 @@
 // succeeds, false otherwise.
 bool DeleteReparsePoint(HANDLE source);
 
+// Class to hold a single Sid with attributes for a group list.
+class SidAndAttributes {
+ public:
+  SidAndAttributes(const SID_AND_ATTRIBUTES& sid_and_attributes);
+
+  PSID GetPSID() const;
+  DWORD GetAttributes() const;
+
+ private:
+  DWORD attributes_;
+  sandbox::Sid sid_;
+};
+
+// Get the App Container sid for a token.
+bool GetTokenAppContainerSid(HANDLE token,
+                             std::unique_ptr<sandbox::Sid>* app_container_sid);
+
+// Get the a list of groups from a token. |information_class| can be one of
+// TokenGroups, TokenRestrictedSids or TokenCapabilites.
+bool GetTokenGroups(HANDLE token,
+                    TOKEN_INFORMATION_CLASS information_class,
+                    std::vector<SidAndAttributes>* groups);
+
+// Get a variable length property from a token.
+bool GetVariableTokenInformation(HANDLE token,
+                                 TOKEN_INFORMATION_CLASS information_class,
+                                 std::vector<char>* information);
+
 #endif  // SANDBOX_TESTS_COMMON_TEST_UTILS_H_
 
diff --git a/services/device/unittest_manifest.json b/services/device/unittest_manifest.json
index d81a595..94c35d9 100644
--- a/services/device/unittest_manifest.json
+++ b/services/device/unittest_manifest.json
@@ -14,6 +14,7 @@
           "device:generic_sensor",
           "device:hid",
           "device:power_monitor",
+          "device:serial",
           "device:vibration",
           "device:wake_lock"
         ]
diff --git a/services/metrics/public/cpp/mojo_ukm_recorder.cc b/services/metrics/public/cpp/mojo_ukm_recorder.cc
index 7dfad5e..d5ed389 100644
--- a/services/metrics/public/cpp/mojo_ukm_recorder.cc
+++ b/services/metrics/public/cpp/mojo_ukm_recorder.cc
@@ -24,14 +24,14 @@
   return std::make_unique<MojoUkmRecorder>(std::move(interface));
 }
 
-void MojoUkmRecorder::UpdateSourceURL(SourceId source_id, const GURL& url) {
-  interface_->UpdateSourceURL(source_id, url.spec());
-}
-
 base::WeakPtr<MojoUkmRecorder> MojoUkmRecorder::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
 
+void MojoUkmRecorder::UpdateSourceURL(SourceId source_id, const GURL& url) {
+  interface_->UpdateSourceURL(source_id, url.spec());
+}
+
 void MojoUkmRecorder::AddEntry(mojom::UkmEntryPtr entry) {
   interface_->AddEntry(std::move(entry));
 }
diff --git a/services/metrics/public/cpp/mojo_ukm_recorder.h b/services/metrics/public/cpp/mojo_ukm_recorder.h
index 5edb070..3616b3f 100644
--- a/services/metrics/public/cpp/mojo_ukm_recorder.h
+++ b/services/metrics/public/cpp/mojo_ukm_recorder.h
@@ -35,9 +35,6 @@
   explicit MojoUkmRecorder(mojom::UkmRecorderInterfacePtr recorder_interface);
   ~MojoUkmRecorder() override;
 
-  // UkmRecorder:
-  void UpdateSourceURL(SourceId source_id, const GURL& url) override;
-
   // Helper for getting the wrapper from a connector.
   static std::unique_ptr<MojoUkmRecorder> Create(
       service_manager::Connector* connector);
@@ -46,6 +43,7 @@
 
  private:
   // UkmRecorder:
+  void UpdateSourceURL(SourceId source_id, const GURL& url) override;
   void AddEntry(mojom::UkmEntryPtr entry) override;
 
   mojom::UkmRecorderInterfacePtr interface_;
diff --git a/services/metrics/public/cpp/ukm_recorder.h b/services/metrics/public/cpp/ukm_recorder.h
index 14c3c39..9260284 100644
--- a/services/metrics/public/cpp/ukm_recorder.h
+++ b/services/metrics/public/cpp/ukm_recorder.h
@@ -19,12 +19,19 @@
 
 class DocumentWritePageLoadMetricsObserver;
 class FromGWSPageLoadMetricsLogger;
+class IOSChromePasswordManagerClient;
+class LocalNetworkRequestsPageLoadMetricsObserver;
+class MediaEngagementSession;
 class PluginInfoHostImpl;
 class ServiceWorkerPageLoadMetricsObserver;
 class SubresourceFilterMetricsObserver;
 class UkmPageLoadMetricsObserver;
 class UseCounterPageLoadMetricsObserver;
-class LocalNetworkRequestsPageLoadMetricsObserver;
+
+namespace autofill {
+class AutofillMetrics;
+class FormStructure;
+}  // namespace autofill
 
 namespace assist_ranker {
 class BasePredictor;
@@ -32,16 +39,26 @@
 
 namespace blink {
 class AutoplayUmaHelper;
+class Document;
 }
 
 namespace cc {
 class UkmManager;
 }
 
+namespace content {
+class WebContentsImpl;
+class PluginServiceImpl;
+}  // namespace content
+
 namespace password_manager {
 class PasswordManagerMetricsRecorder;
 }  // namespace password_manager
 
+namespace payments {
+class JourneyLogger;
+}
+
 namespace previews {
 class PreviewsUKMObserver;
 }
@@ -50,6 +67,16 @@
 class UkmRecorderInterface;
 }
 
+namespace media {
+class MediaMetricsProvider;
+class VideoDecodePerfHistory;
+class WatchTimeRecorder;
+}  // namespace media
+
+namespace translate {
+class TranslateRankerImpl;
+}
+
 namespace ui {
 class LatencyTracker;
 }  // namespace ui
@@ -62,6 +89,7 @@
 
 namespace internal {
 class UkmEntryBuilderBase;
+class SourceUrlRecorderWebContentsObserver;
 }
 
 // This feature controls whether UkmService should be created.
@@ -83,29 +111,38 @@
   // session.
   static SourceId GetNewSourceID();
 
-  // Update the URL on the source keyed to the given source ID. If the source
-  // does not exist, it will create a new UkmSource object.
-  virtual void UpdateSourceURL(SourceId source_id, const GURL& url) = 0;
-
  private:
   friend assist_ranker::BasePredictor;
   friend DelegatingUkmRecorder;
   friend DocumentWritePageLoadMetricsObserver;
   friend FromGWSPageLoadMetricsLogger;
+  friend IOSChromePasswordManagerClient;
   friend LocalNetworkRequestsPageLoadMetricsObserver;
+  friend MediaEngagementSession;
   friend PluginInfoHostImpl;
   friend ServiceWorkerPageLoadMetricsObserver;
   friend SubresourceFilterMetricsObserver;
   friend TestRecordingHelper;
   friend UkmPageLoadMetricsObserver;
   friend UseCounterPageLoadMetricsObserver;
+  friend autofill::AutofillMetrics;
+  friend autofill::FormStructure;
   friend blink::AutoplayUmaHelper;
+  friend blink::Document;
   friend cc::UkmManager;
+  friend content::PluginServiceImpl;
+  friend content::WebContentsImpl;
+  friend internal::SourceUrlRecorderWebContentsObserver;
   friend internal::UkmEntryBuilderBase;
+  friend media::MediaMetricsProvider;
+  friend media::VideoDecodePerfHistory;
+  friend media::WatchTimeRecorder;
   friend metrics::UkmRecorderInterface;
-  friend ui::LatencyTracker;
   friend password_manager::PasswordManagerMetricsRecorder;
+  friend payments::JourneyLogger;
   friend previews::PreviewsUKMObserver;
+  friend translate::TranslateRankerImpl;
+  friend ui::LatencyTracker;
   FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, AddEntryWithEmptyMetrics);
   FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, EntryBuilderAndSerialization);
   FRIEND_TEST_ALL_PREFIXES(UkmServiceTest,
@@ -114,12 +151,17 @@
   FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, PersistAndPurge);
   FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, WhitelistEntryTest);
 
+  // Associates the SourceId with a URL. Most UKM recording code should prefer
+  // to use a shared SourceId that is already associated with a URL, rather
+  // than using this API directly. New uses of this API must be auditted to
+  // maintain privacy constraints.
+  virtual void UpdateSourceURL(SourceId source_id, const GURL& url) = 0;
+
   // Get a new UkmEntryBuilder object for the specified source ID and event,
   // which can get metrics added to.
   //
-  // This API being private is intentional. Any client using UKM needs to
-  // declare itself to be a friend of UkmService and go through code review
-  // process.
+  // This API is deprecated, and new code should prefer using the API from
+  // ukm_builders.h.
   std::unique_ptr<UkmEntryBuilder> GetEntryBuilder(SourceId source_id,
                                                    const char* event_name);
 
diff --git a/services/service_manager/public/cpp/binder_registry.h b/services/service_manager/public/cpp/binder_registry.h
index 77f98ea..ef0a39b 100644
--- a/services/service_manager/public/cpp/binder_registry.h
+++ b/services/service_manager/public/cpp/binder_registry.h
@@ -86,8 +86,20 @@
       it->second->BindInterface(interface_name, std::move(interface_pipe),
                                 args...);
     } else {
-      LOG(ERROR) << "Failed to locate a binder for interface: "
-                 << interface_name;
+#if DCHECK_IS_ON()
+      // While it would not be correct to assert that this never happens (e.g.
+      // a compromised process may request invalid interfaces), we do want to
+      // effectively treat all occurrences of this branch in production code as
+      // bugs that must be fixed. This allows such bugs to be caught in testing
+      // rather than relying on easily overlooked log messages.
+      NOTREACHED() << "Failed to locate a binder for interface \""
+                   << interface_name << "\". You probably need to register "
+                   << "a binder for this interface in the BinderRegistry which "
+                   << "is triggering this assertion.";
+#else
+      LOG(ERROR) << "Failed to locate a binder for interface \""
+                 << interface_name << "\".";
+#endif
     }
   }
 
diff --git a/services/service_manager/service_manager.cc b/services/service_manager/service_manager.cc
index 2d984f8..fabebe1c 100644
--- a/services/service_manager/service_manager.cc
+++ b/services/service_manager/service_manager.cc
@@ -14,6 +14,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/optional.h"
 #include "base/process/process.h"
 #include "base/process/process_handle.h"
 #include "base/stl_util.h"
@@ -141,6 +142,43 @@
   return it->second.find(capability) != it->second.end();
 }
 
+void ReportBlockedInterface(const std::string& source_service_name,
+                            const std::string& target_service_name,
+                            const std::string& target_interface_name) {
+#if DCHECK_IS_ON()
+  // While it would not be correct to assert that this never happens (e.g. a
+  // compromised process may request invalid interfaces), we do want to
+  // effectively treat all occurrences of this branch in production code as
+  // bugs that must be fixed. This crash allows such bugs to be caught in
+  // testing rather than relying on easily overlooked log messages.
+  NOTREACHED()
+#else
+  LOG(ERROR)
+#endif
+      << "The Service Manager prevented service \"" << source_service_name
+      << "\" from binding interface \"" << target_interface_name << "\""
+      << " in target service \"" << target_service_name << "\". You probably "
+      << "need to update one or more service manifests to ensure that \""
+      << target_service_name << "\" exposes \"" << target_interface_name
+      << "\" through a capability and that \"" << source_service_name
+      << "\" requires that capability from the \"" << target_service_name
+      << "\" service.";
+}
+
+void ReportBlockedStartService(const std::string& source_service_name,
+                               const std::string& target_service_name) {
+#if DCHECK_IS_ON()
+  // See the note in ReportBlockedInterface above.
+  NOTREACHED()
+#else
+  LOG(ERROR)
+#endif
+      << "Service \"" << source_service_name << "\" has attempted to manually "
+      << "start service \"" << target_service_name << "\", but it is not "
+      << "sufficiently privileged to do so. You probably need to update one or "
+      << "services' manifests in order to remedy this situation.";
+}
+
 bool AllowsInterface(const Identity& source,
                      const InterfaceProviderSpec& source_spec,
                      const Identity& target,
@@ -150,13 +188,8 @@
       GetInterfacesToExpose(source_spec, target, target_spec);
   bool allowed = (exposed.size() == 1 && exposed.count("*") == 1) ||
                  exposed.count(interface_name) > 0;
-  if (!allowed) {
-    std::stringstream ss;
-    ss << "Connection InterfaceProviderSpec prevented service: "
-       << source.name() << " from binding interface: " << interface_name
-       << " exposed by: " << target.name();
-    LOG(ERROR) << ss.str();
-  }
+  if (!allowed)
+    ReportBlockedInterface(source.name(), target.name(), interface_name);
   return allowed;
 }
 
@@ -419,7 +452,7 @@
                      BindInterfaceCallback callback) override {
     Identity target = in_target;
     mojom::ConnectResult result =
-        ValidateConnectParams(&target, nullptr, nullptr);
+        ValidateConnectParams(&target, nullptr, nullptr, &interface_name);
     if (!Succeeded(result)) {
       std::move(callback).Run(result, Identity());
       return;
@@ -447,7 +480,7 @@
                     StartServiceCallback callback) override {
     Identity target = in_target;
     mojom::ConnectResult result =
-        ValidateConnectParams(&target, nullptr, nullptr);
+        ValidateConnectParams(&target, nullptr, nullptr, nullptr);
     if (!Succeeded(result)) {
       std::move(callback).Run(result, Identity());
       return;
@@ -468,8 +501,8 @@
     Identity target = in_target;
     mojom::ServicePtr service;
     service.Bind(mojom::ServicePtrInfo(std::move(service_handle), 0));
-    mojom::ConnectResult result =
-        ValidateConnectParams(&target, &service, &pid_receiver_request);
+    mojom::ConnectResult result = ValidateConnectParams(
+        &target, &service, &pid_receiver_request, nullptr);
     if (!Succeeded(result)) {
       std::move(callback).Run(result, Identity());
       return;
@@ -514,7 +547,8 @@
   mojom::ConnectResult ValidateConnectParams(
       Identity* target,
       mojom::ServicePtr* service,
-      mojom::PIDReceiverRequest* pid_receiver_request) {
+      mojom::PIDReceiverRequest* pid_receiver_request,
+      const std::string* target_interface_name) {
     if (target->user_id() == mojom::kInheritUserID)
       target->set_user_id(identity_.user_id());
 
@@ -525,7 +559,7 @@
     result = ValidateClientProcessInfo(service, pid_receiver_request, *target);
     if (!Succeeded(result))
       return result;
-    return ValidateConnectionSpec(*target);
+    return ValidateConnectionSpec(*target, target_interface_name);
   }
 
   mojom::ConnectResult ValidateIdentity(const Identity& identity) {
@@ -570,7 +604,9 @@
     return mojom::ConnectResult::SUCCEEDED;
   }
 
-  mojom::ConnectResult ValidateConnectionSpec(const Identity& target) {
+  mojom::ConnectResult ValidateConnectionSpec(
+      const Identity& target,
+      const std::string* target_interface_name) {
     const InterfaceProviderSpec& connection_spec = GetConnectionSpec();
     // TODO(beng): Need to do the following additional policy validation of
     // whether this instance is allowed to connect using:
@@ -605,8 +641,12 @@
             connection_spec.requires.end()) {
       return mojom::ConnectResult::SUCCEEDED;
     }
-    LOG(ERROR) << "InterfaceProviderSpec prevented connection from: "
-               << identity_.name() << " to: " << target.name();
+    if (target_interface_name) {
+      ReportBlockedInterface(identity_.name(), target.name(),
+                             *target_interface_name);
+    } else {
+      ReportBlockedStartService(identity_.name(), target.name());
+    }
     return mojom::ConnectResult::ACCESS_DENIED;
   }
 
@@ -1127,8 +1167,14 @@
   if (!instance)
     return false;
 
-  if ((*params)->HasInterfaceRequestInfo())
+  if ((*params)->HasInterfaceRequestInfo()) {
     instance->CallOnBindInterface(params);
+  } else {
+    // This is a StartService request and the instance is already running.
+    // Make sure the response identity is properly resolved.
+    (*params)->set_response_data(mojom::ConnectResult::SUCCEEDED,
+                                 instance->identity());
+  }
   return true;
 }
 
diff --git a/services/service_manager/tests/connect/connect_unittest.cc b/services/service_manager/tests/connect/connect_unittest.cc
index dede0f15..ac9b319 100644
--- a/services/service_manager/tests/connect/connect_unittest.cc
+++ b/services/service_manager/tests/connect/connect_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/process/process.h"
 #include "base/run_loop.h"
+#include "base/test/gtest_util.h"
 #include "base/test/test_suite.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
@@ -242,9 +243,16 @@
   EXPECT_EQ("", sandbox_type);
 }
 
+#if DCHECK_IS_ON()
+// This test triggers intentional DCHECKs but is not suitable for death testing.
+#define MAYBE_BlockedInterface DISABLED_BlockedInterface
+#else
+#define MAYBE_BlockedInterface BlockedInterface
+#endif
+
 // BlockedInterface should not be exposed to this application because it is not
 // in our CapabilityFilter whitelist.
-TEST_F(ConnectTest, BlockedInterface) {
+TEST_F(ConnectTest, MAYBE_BlockedInterface) {
   base::RunLoop run_loop;
   test::mojom::BlockedInterfacePtr blocked;
   connector()->BindInterface(kTestAppName, &blocked);
@@ -271,12 +279,19 @@
   EXPECT_EQ(resolved_identity.name(), kTestAppAName);
 }
 
+#if DCHECK_IS_ON()
+// This test triggers intentional DCHECKs but is not suitable for death testing.
+#define MAYBE_BlockedPackage DISABLED_BlockedPackage
+#else
+#define MAYBE_BlockedPackage BlockedPackage
+#endif
+
 // Ask the target application to attempt to connect to a third application
 // provided by a package whose id is permitted by the primary target's
 // CapabilityFilter but whose package is not. The connection should be
 // allowed regardless of the target's CapabilityFilter with respect to the
 // package.
-TEST_F(ConnectTest, BlockedPackage) {
+TEST_F(ConnectTest, MAYBE_BlockedPackage) {
   test::mojom::StandaloneAppPtr standalone_app;
   connector()->BindInterface(kTestAppName, &standalone_app);
   base::RunLoop run_loop;
@@ -287,9 +302,16 @@
   EXPECT_EQ("A", title);
 }
 
+#if DCHECK_IS_ON()
+// This test triggers intentional DCHECKs but is not suitable for death testing.
+#define MAYBE_PackagedApp_BlockedInterface DISABLED_PackagedApp_BlockedInterface
+#else
+#define MAYBE_PackagedApp_BlockedInterface PackagedApp_BlockedInterface
+#endif
+
 // BlockedInterface should not be exposed to this application because it is not
 // in our CapabilityFilter whitelist.
-TEST_F(ConnectTest, PackagedApp_BlockedInterface) {
+TEST_F(ConnectTest, MAYBE_PackagedApp_BlockedInterface) {
   base::RunLoop run_loop;
   test::mojom::BlockedInterfacePtr blocked;
   connector()->BindInterface(kTestAppAName, &blocked);
@@ -297,9 +319,16 @@
   run_loop.Run();
 }
 
+#if DCHECK_IS_ON()
+// This test triggers intentional DCHECKs but is not suitable for death testing.
+#define MAYBE_BlockedPackagedApplication DISABLED_BlockedPackagedApplication
+#else
+#define MAYBE_BlockedPackagedApplication BlockedPackagedApplication
+#endif
+
 // Connection to another application provided by the same package, blocked
 // because it's not in the capability filter whitelist.
-TEST_F(ConnectTest, BlockedPackagedApplication) {
+TEST_F(ConnectTest, MAYBE_BlockedPackagedApplication) {
   test::mojom::ConnectTestServicePtr service_b;
   connector()->BindInterface(kTestAppBName, &service_b);
   Connector::TestApi test_api(connector());
@@ -324,7 +353,16 @@
   EXPECT_EQ("CLASS APP", string2);
 }
 
-TEST_F(ConnectTest, ConnectWithoutExplicitClassBlocked) {
+#if DCHECK_IS_ON()
+// This test triggers intentional DCHECKs but is not suitable for death testing.
+#define MAYBE_ConnectWithoutExplicitClassBlocked \
+  DISABLED_ConnectWithoutExplicitClassBlocked
+#else
+#define MAYBE_ConnectWithoutExplicitClassBlocked \
+  ConnectWithoutExplicitClassBlocked
+#endif
+
+TEST_F(ConnectTest, MAYBE_ConnectWithoutExplicitClassBlocked) {
   // We not be able to bind a ClassInterfacePtr since the connect_unittest app
   // does not explicitly request the "class" capability from
   // connect_test_class_app. This test will hang if it is bound.
@@ -392,8 +430,7 @@
 TEST_F(ConnectTest, AllUsersSingleton) {
   // Connect to an instance with an explicitly different user_id. This supplied
   // user id should be ignored by the service manager (which will generate its
-  // own
-  // synthetic user id for all-user singleton instances).
+  // own synthetic user id for all-user singleton instances).
   const std::string singleton_userid = base::GenerateGUID();
   Identity singleton_id(kTestSingletonAppName, singleton_userid);
   connector()->StartService(singleton_id);
diff --git a/services/service_manager/tests/connect/connect_unittests_manifest.json b/services/service_manager/tests/connect/connect_unittests_manifest.json
index f9382b7..5a1e368 100644
--- a/services/service_manager/tests/connect/connect_unittests_manifest.json
+++ b/services/service_manager/tests/connect/connect_unittests_manifest.json
@@ -25,6 +25,7 @@
           "connect_unittests:standalone_app",
           "connect_unittests:user_id_test"
         ],
+        "connect_test_singleton_app": [],
         "service_manager": [
           "service_manager:instance_name",
           "service_manager:user_id"
diff --git a/services/ui/public/cpp/gpu/BUILD.gn b/services/ui/public/cpp/gpu/BUILD.gn
index 943dab1..b310e4c 100644
--- a/services/ui/public/cpp/gpu/BUILD.gn
+++ b/services/ui/public/cpp/gpu/BUILD.gn
@@ -14,7 +14,7 @@
   public_deps = [
     ":internal",
     "//cc",
-    "//gpu/command_buffer/common:gles2_utils",
+    "//gpu/command_buffer/common",
     "//gpu/ipc/client",
     "//gpu/ipc/common",
     "//services/ui/public/interfaces",
diff --git a/services/ui/public/cpp/gpu/context_provider_command_buffer.cc b/services/ui/public/cpp/gpu/context_provider_command_buffer.cc
index 7bb5ba6d..2cf5a04 100644
--- a/services/ui/public/cpp/gpu/context_provider_command_buffer.cc
+++ b/services/ui/public/cpp/gpu/context_provider_command_buffer.cc
@@ -142,7 +142,7 @@
     bool automatic_flushes,
     bool support_locking,
     const gpu::SharedMemoryLimits& memory_limits,
-    const gpu::gles2::ContextCreationAttribHelper& attributes,
+    const gpu::ContextCreationAttribs& attributes,
     ContextProviderCommandBuffer* shared_context_provider,
     command_buffer_metrics::ContextType type)
     : stream_id_(stream_id),
diff --git a/services/ui/public/cpp/gpu/context_provider_command_buffer.h b/services/ui/public/cpp/gpu/context_provider_command_buffer.h
index 132803e..6383e79 100644
--- a/services/ui/public/cpp/gpu/context_provider_command_buffer.h
+++ b/services/ui/public/cpp/gpu/context_provider_command_buffer.h
@@ -19,7 +19,7 @@
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/gpu/raster_context_provider.h"
 #include "gpu/command_buffer/client/shared_memory_limits.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/common/scheduling_priority.h"
 #include "gpu/ipc/common/surface_handle.h"
 #include "services/ui/public/cpp/gpu/command_buffer_metrics.h"
@@ -66,7 +66,7 @@
       bool automatic_flushes,
       bool support_locking,
       const gpu::SharedMemoryLimits& memory_limits,
-      const gpu::gles2::ContextCreationAttribHelper& attributes,
+      const gpu::ContextCreationAttribs& attributes,
       ContextProviderCommandBuffer* shared_context_provider,
       command_buffer_metrics::ContextType type);
 
@@ -141,7 +141,7 @@
   const bool automatic_flushes_;
   const bool support_locking_;
   const gpu::SharedMemoryLimits memory_limits_;
-  const gpu::gles2::ContextCreationAttribHelper attributes_;
+  const gpu::ContextCreationAttribs attributes_;
   const command_buffer_metrics::ContextType context_type_;
 
   scoped_refptr<SharedProviders> shared_providers_;
diff --git a/services/ui/public/cpp/gpu/gpu.cc b/services/ui/public/cpp/gpu/gpu.cc
index e3e366f..9370d3f 100644
--- a/services/ui/public/cpp/gpu/gpu.cc
+++ b/services/ui/public/cpp/gpu/gpu.cc
@@ -284,7 +284,7 @@
   constexpr bool automatic_flushes = false;
   constexpr bool support_locking = false;
 
-  gpu::gles2::ContextCreationAttribHelper attributes;
+  gpu::ContextCreationAttribs attributes;
   attributes.alpha_size = -1;
   attributes.depth_size = 0;
   attributes.stencil_size = 0;
diff --git a/services/ui/public/interfaces/ime/ime.mojom b/services/ui/public/interfaces/ime/ime.mojom
index b9b8169e..0f59599 100644
--- a/services/ui/public/interfaces/ime/ime.mojom
+++ b/services/ui/public/interfaces/ime/ime.mojom
@@ -88,18 +88,14 @@
 // See comments for ui::TextInputMode for more details.
 enum TextInputMode {
   kDefault,
-  kVerbatim,
-  kLatin,
-  kLatinName,
-  kLatinProse,
-  kFullWidthLatin,
-  kKana,
-  kKanaName,
-  kKatakana,
-  kNumeric,
+  kNone,
+  kText,
   kTel,
-  kEmail,
   kUrl,
+  kEmail,
+  kNumeric,
+  kDecimal,
+  kSearch,
 };
 
 // Parameters needed to start an IME session.
diff --git a/services/ui/public/interfaces/ime/ime_struct_traits.cc b/services/ui/public/interfaces/ime/ime_struct_traits.cc
index 5de1835f..0a445971 100644
--- a/services/ui/public/interfaces/ime/ime_struct_traits.cc
+++ b/services/ui/public/interfaces/ime/ime_struct_traits.cc
@@ -110,30 +110,22 @@
   switch (text_input_mode) {
     case ui::TEXT_INPUT_MODE_DEFAULT:
       return ui::mojom::TextInputMode::kDefault;
-    case ui::TEXT_INPUT_MODE_VERBATIM:
-      return ui::mojom::TextInputMode::kVerbatim;
-    case ui::TEXT_INPUT_MODE_LATIN:
-      return ui::mojom::TextInputMode::kLatin;
-    case ui::TEXT_INPUT_MODE_LATIN_NAME:
-      return ui::mojom::TextInputMode::kLatinName;
-    case ui::TEXT_INPUT_MODE_LATIN_PROSE:
-      return ui::mojom::TextInputMode::kLatinProse;
-    case ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN:
-      return ui::mojom::TextInputMode::kFullWidthLatin;
-    case ui::TEXT_INPUT_MODE_KANA:
-      return ui::mojom::TextInputMode::kKana;
-    case ui::TEXT_INPUT_MODE_KANA_NAME:
-      return ui::mojom::TextInputMode::kKanaName;
-    case ui::TEXT_INPUT_MODE_KATAKANA:
-      return ui::mojom::TextInputMode::kKatakana;
-    case ui::TEXT_INPUT_MODE_NUMERIC:
-      return ui::mojom::TextInputMode::kNumeric;
+    case ui::TEXT_INPUT_MODE_NONE:
+      return ui::mojom::TextInputMode::kNone;
+    case ui::TEXT_INPUT_MODE_TEXT:
+      return ui::mojom::TextInputMode::kText;
     case ui::TEXT_INPUT_MODE_TEL:
       return ui::mojom::TextInputMode::kTel;
-    case ui::TEXT_INPUT_MODE_EMAIL:
-      return ui::mojom::TextInputMode::kEmail;
     case ui::TEXT_INPUT_MODE_URL:
       return ui::mojom::TextInputMode::kUrl;
+    case ui::TEXT_INPUT_MODE_EMAIL:
+      return ui::mojom::TextInputMode::kEmail;
+    case ui::TEXT_INPUT_MODE_NUMERIC:
+      return ui::mojom::TextInputMode::kNumeric;
+    case ui::TEXT_INPUT_MODE_DECIMAL:
+      return ui::mojom::TextInputMode::kDecimal;
+    case ui::TEXT_INPUT_MODE_SEARCH:
+      return ui::mojom::TextInputMode::kSearch;
   }
   NOTREACHED();
   return ui::mojom::TextInputMode::kDefault;
@@ -147,41 +139,29 @@
     case ui::mojom::TextInputMode::kDefault:
       *out = ui::TEXT_INPUT_MODE_DEFAULT;
       return true;
-    case ui::mojom::TextInputMode::kVerbatim:
-      *out = ui::TEXT_INPUT_MODE_VERBATIM;
+    case ui::mojom::TextInputMode::kNone:
+      *out = ui::TEXT_INPUT_MODE_NONE;
       return true;
-    case ui::mojom::TextInputMode::kLatin:
-      *out = ui::TEXT_INPUT_MODE_LATIN;
-      return true;
-    case ui::mojom::TextInputMode::kLatinName:
-      *out = ui::TEXT_INPUT_MODE_LATIN_NAME;
-      return true;
-    case ui::mojom::TextInputMode::kLatinProse:
-      *out = ui::TEXT_INPUT_MODE_LATIN_PROSE;
-      return true;
-    case ui::mojom::TextInputMode::kFullWidthLatin:
-      *out = ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN;
-      return true;
-    case ui::mojom::TextInputMode::kKana:
-      *out = ui::TEXT_INPUT_MODE_KANA;
-      return true;
-    case ui::mojom::TextInputMode::kKanaName:
-      *out = ui::TEXT_INPUT_MODE_KANA_NAME;
-      return true;
-    case ui::mojom::TextInputMode::kKatakana:
-      *out = ui::TEXT_INPUT_MODE_KATAKANA;
-      return true;
-    case ui::mojom::TextInputMode::kNumeric:
-      *out = ui::TEXT_INPUT_MODE_NUMERIC;
+    case ui::mojom::TextInputMode::kText:
+      *out = ui::TEXT_INPUT_MODE_TEXT;
       return true;
     case ui::mojom::TextInputMode::kTel:
       *out = ui::TEXT_INPUT_MODE_TEL;
       return true;
+    case ui::mojom::TextInputMode::kUrl:
+      *out = ui::TEXT_INPUT_MODE_URL;
+      return true;
     case ui::mojom::TextInputMode::kEmail:
       *out = ui::TEXT_INPUT_MODE_EMAIL;
       return true;
-    case ui::mojom::TextInputMode::kUrl:
-      *out = ui::TEXT_INPUT_MODE_URL;
+    case ui::mojom::TextInputMode::kNumeric:
+      *out = ui::TEXT_INPUT_MODE_NUMERIC;
+      return true;
+    case ui::mojom::TextInputMode::kDecimal:
+      *out = ui::TEXT_INPUT_MODE_DECIMAL;
+      return true;
+    case ui::mojom::TextInputMode::kSearch:
+      *out = ui::TEXT_INPUT_MODE_SEARCH;
       return true;
   }
   return false;
diff --git a/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc b/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
index bf00aca..812ed1a6 100644
--- a/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
+++ b/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
@@ -124,13 +124,9 @@
 
 TEST_F(IMEStructTraitsTest, TextInputMode) {
   const TextInputMode kTextInputModes[] = {
-      TEXT_INPUT_MODE_DEFAULT,     TEXT_INPUT_MODE_VERBATIM,
-      TEXT_INPUT_MODE_LATIN,       TEXT_INPUT_MODE_LATIN_NAME,
-      TEXT_INPUT_MODE_LATIN_PROSE, TEXT_INPUT_MODE_FULL_WIDTH_LATIN,
-      TEXT_INPUT_MODE_KANA,        TEXT_INPUT_MODE_KANA_NAME,
-      TEXT_INPUT_MODE_KATAKANA,    TEXT_INPUT_MODE_NUMERIC,
-      TEXT_INPUT_MODE_TEL,         TEXT_INPUT_MODE_EMAIL,
-      TEXT_INPUT_MODE_URL,
+      TEXT_INPUT_MODE_DEFAULT, TEXT_INPUT_MODE_NONE,    TEXT_INPUT_MODE_TEXT,
+      TEXT_INPUT_MODE_TEL,     TEXT_INPUT_MODE_URL,     TEXT_INPUT_MODE_EMAIL,
+      TEXT_INPUT_MODE_NUMERIC, TEXT_INPUT_MODE_DECIMAL, TEXT_INPUT_MODE_SEARCH,
   };
 
   mojom::IMEStructTraitsTestPtr proxy = GetTraitsTestProxy();
diff --git a/services/ui/service.cc b/services/ui/service.cc
index 9dd19160..f49ef3c 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -288,13 +288,13 @@
 
     registry_.AddInterface<mojom::Gpu>(
         base::Bind(&Service::BindGpuRequest, base::Unretained(this)));
-    registry_.AddInterface<mojom::VideoDetector>(
-        base::Bind(&Service::BindVideoDetectorRequest, base::Unretained(this)));
 #if defined(OS_CHROMEOS)
     registry_.AddInterface<mojom::Arc>(
         base::Bind(&Service::BindArcRequest, base::Unretained(this)));
 #endif  // defined(OS_CHROMEOS)
   }
+  registry_.AddInterface<mojom::VideoDetector>(
+      base::Bind(&Service::BindVideoDetectorRequest, base::Unretained(this)));
 
   ime_driver_.Init(context()->connector(), test_config_);
 
@@ -556,6 +556,8 @@
 }
 
 void Service::BindVideoDetectorRequest(mojom::VideoDetectorRequest request) {
+  if (!should_host_viz_)
+    return;
   window_server_->video_detector()->AddBinding(std::move(request));
 }
 
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 8217e3c..69e2852 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -241,10 +241,6 @@
 #define SK_SUPPORT_LEGACY_DASH_CULL_PATH
 #endif
 
-#ifndef SK_SUPPORT_LEGACY_SERIALPROCS_REF
-#define SK_SUPPORT_LEGACY_SERIALPROCS_REF
-#endif
-
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
 
 /* In some places Skia can use static initializers for global initialization,
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index a65195e9..772acd78 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -3,7 +3,7 @@
   "AAAAA2 See generate_buildbot_json.py to make changes": {},
   "Linux ChromiumOS Builder": {
     "additional_compile_targets": [
-      "All"
+      "gn_all"
     ]
   },
   "Linux ChromiumOS Tests (dbg)(1)": {
@@ -794,7 +794,7 @@
   },
   "linux-chromeos-rel": {
     "additional_compile_targets": [
-      "All"
+      "gn_all"
     ],
     "gtest_tests": [
       {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index f559ca0..3efe43f 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -4205,8 +4205,7 @@
     "isolated_scripts": [
       {
         "args": [
-          "--xvfb",
-          "--extra-browser-args=--enable-viz"
+          "--xvfb"
         ],
         "isolate_name": "telemetry_perf_unittests",
         "name": "telemetry_perf_unittests",
@@ -4218,6 +4217,18 @@
       },
       {
         "args": [
+          "--xvfb"
+        ],
+        "isolate_name": "telemetry_perf_unittests_viz",
+        "name": "telemetry_perf_unittests_viz",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "hard_timeout": 960,
+          "shards": 12
+        }
+      },
+      {
+        "args": [
           "--extra-browser-args=--enable-viz",
           "--skip=telemetry.internal.actions.scroll_unittest.ScrollActionTest.testWheelScrollDistanceWhileZoomed",
           "--skip=telemetry.internal.backends.chrome_inspector.inspector_page_unittest.InspectorPageTest.testCaptureScreenshot",
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index dfa9f6b..dfc4d88 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -3222,23 +3222,6 @@
       {
         "args": [
           "--use-gpu-in-tests",
-          "--test-launcher-retry-limit=0"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": false,
-          "dimension_sets": [
-            {
-              "gpu": "1002:6613",
-              "os": "Ubuntu"
-            }
-          ]
-        },
-        "test": "angle_end2end_tests",
-        "use_xvfb": false
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests",
           "--test-launcher-retry-limit=0",
           "--no-xvfb"
         ],
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index 60156e2..63c3253 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -215,6 +215,10 @@
 -SSLUIMITMSoftwareEnabledTest.TwoCertErrors_NoMITMSoftwareInterstitial/1
 -SSLUIMITMSoftwareEnabledTest.WrongCertError_NoMITMSoftwareInterstitial/0
 -SSLUIMITMSoftwareEnabledTest.WrongCertError_NoMITMSoftwareInterstitial/1
+-SSLUITest.SHA1IsDefaultDisabled/0
+-SSLUITest.SHA1IsDefaultDisabled/1
+-SSLUITest.CommonNameIsDefaultDisabled/0
+-SSLUITest.CommonNameIsDefaultDisabled/1
 -SSLUITest.TestBadHTTPSDownload/0
 -SSLUITest.TestBadHTTPSDownload/1
 -SSLUITest.TestHTTPSOCSPOk/0
@@ -855,7 +859,7 @@
 -RestartTest.SessionCookies
 
 # Flakes https://logs.chromium.org/v/?s=chromium%2Fbb%2Fchromium.linux%2FLinux_Tests%2F65822%2F%2B%2Frecipes%2Fsteps%2Fnetwork_service_browser_tests%2F0%2Flogs%2FNoSessionRestoreTest.PRE_CookiesClearedOnExit%2F0
--NoSessionRestoreTest.PRE_CookiesClearedOnExit
+-NoSessionRestoreTest.CookiesClearedOnExit
 

 # Flakes https://logs.chromium.org/v/?s=chromium%2Fbb%2Fchromium.linux%2FLinux_Tests%2F65817%2F%2B%2Frecipes%2Fsteps%2Fnetwork_service_browser_tests%2F0%2Flogs%2FRestartTest.CookiesClearedOnExit%2F0

 -RestartTest.CookiesClearedOnExit
diff --git a/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter
index 1705e83..44539ad 100644
--- a/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter
+++ b/testing/buildbot/filters/mojo.fyi.viz.content_browsertests.filter
@@ -46,6 +46,7 @@
 -SitePerProcessBrowserTest.InputEventRouterGesturePreventDefaultTargetMapTest
 -SitePerProcessBrowserTest.InputEventRouterGestureTargetMapTest
 -SitePerProcessBrowserTest.InputEventRouterTouchpadGestureTargetTest
+-SitePerProcessBrowserTest.HitTestNestedFrames
 -SitePerProcessBrowserTest.NavigateCrashedSubframeToSameSite
 -SitePerProcessBrowserTest.NestedSurfaceHitTestTest
 -SitePerProcessBrowserTest.PopupMenuTest
diff --git a/testing/buildbot/filters/viz.browser_tests.filter b/testing/buildbot/filters/viz.browser_tests.filter
index f44cf05..a074ced 100644
--- a/testing/buildbot/filters/viz.browser_tests.filter
+++ b/testing/buildbot/filters/viz.browser_tests.filter
@@ -2,6 +2,7 @@
 -WebViewTests/WebViewFocusTest.TouchFocusesEmbedder/0
 
 # HostFrameSinkManager::CreateRootCompositorFrameSink Crash crbug.com/796575
+-AppWindowApiTest.OnBoundsChangedEvent
 -ForceMaximizeOnFirstRunTest.*TwoRuns
 -ForceMaximizePolicyFalseTest.GeneralFirstRun
 -ShelfAppBrowserTest.LaunchAppFromDisplayWithoutFocus0
@@ -107,6 +108,7 @@
 -GeolocationBrowserTest.NoPromptBeforeStart
 -HostedAppProcessModelTest.IframeNavigationsInsideHostedApp/0
 -IncognitoApiTest.IncognitoYesScript
+-InterstitialAccessibilityBrowserTest.TestSSLInterstitialAccessibility
 -IsolatedAppTest.CookieIsolation
 -IsolatedAppTest.CrossProcessClientRedirect
 -IsolatedAppTest.SubresourceCookieIsolation
@@ -126,7 +128,8 @@
 -OmniboxApiTest.OnInputEntered
 -PageLoadMetricsBrowserTest.*
 -PasswordManagerBrowserTestBase.SlowPageFill
--PaymentRequestModifiersTest.ModifierAppliedIfApplicableSelectedInstrumentWithCreditSupportedType
+-PaymentRequestModifiersTest.*
+-Pepper/ECKEncryptedMediaTest.OutputProtectionTest/0
 -PlatformAppBrowserTest.Isolation
 -PolicyTest.CertificateTransparencyEnforcementDisabledForUrls
 -PolicyTest.SSLErrorOverridingAllowed
@@ -174,8 +177,7 @@
 -WebBluetoothTest.BlocklistShouldBlock
 -WebBluetoothTest.KillSwitchShouldBlock
 -WebBluetoothTest.WebBluetoothAfterCrash
--WebSocketBrowserTest.SecureWebSocketSplitRecords
--WebSocketBrowserTest.WebSocketAppliesHSTS
+-WebSocketBrowserTest.*
 -WebUsbTest.AddRemoveDevice
 -WebUsbTest.AddRemoveDeviceEphemeral
 -WebUsbTest.RequestAndGetDevices
diff --git a/testing/buildbot/filters/viz.content_browsertests.filter b/testing/buildbot/filters/viz.content_browsertests.filter
index f9d917f5..44539ad 100644
--- a/testing/buildbot/filters/viz.content_browsertests.filter
+++ b/testing/buildbot/filters/viz.content_browsertests.filter
@@ -46,6 +46,7 @@
 -SitePerProcessBrowserTest.InputEventRouterGesturePreventDefaultTargetMapTest
 -SitePerProcessBrowserTest.InputEventRouterGestureTargetMapTest
 -SitePerProcessBrowserTest.InputEventRouterTouchpadGestureTargetTest
+-SitePerProcessBrowserTest.HitTestNestedFrames
 -SitePerProcessBrowserTest.NavigateCrashedSubframeToSameSite
 -SitePerProcessBrowserTest.NestedSurfaceHitTestTest
 -SitePerProcessBrowserTest.PopupMenuTest
@@ -58,7 +59,6 @@
 -SitePerProcessBrowserTest.SurfaceHitTestTest
 -SitePerProcessBrowserTest.TwoSubframesCreatePopupMenuWidgetsSimultaneously
 -SitePerProcessBrowserTest.ViewBoundsInNestedFrameTest
--SitePerProcessBrowserTest.HitTestNestedFrames
 
 # Copy Surface timing out http://crbug.com/785257
 -GLAndSoftwareCompositing/CompositingRenderWidgetHostViewBrowserTest.*
diff --git a/testing/buildbot/filters/viz.content_unittests.filter b/testing/buildbot/filters/viz.content_unittests.filter
index e23e36f..a27159f7 100644
--- a/testing/buildbot/filters/viz.content_unittests.filter
+++ b/testing/buildbot/filters/viz.content_unittests.filter
@@ -26,7 +26,9 @@
 -RenderWidgetHostViewChildFrameTest.SwapCompositorFrame
 -RenderWidgetHostViewGuestSurfaceTest.TestGuestSurface
 
+# Not finding the correct target crbug.com/796605
+-RenderWidgetHostInputEventRouterTest.DoNotChangeTargetViewDuringTouchScrollGesture
+
 # TODO(crbug.com/601869): Reflector needs to be rewritten for viz.
--ReflectorImplTest.CheckInvertedOutputSurface
--ReflectorImplTest.CheckNormalOutputSurface
+-ReflectorImplTest.*
 -WebContentsAudioInputStreamTest.MirroringOneStreamAfterTargetChange
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 1f98df4..d70cfb7 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -69,10 +69,6 @@
 # "//testing/scripts/foo.py".
 
 {
-  "All": {
-    "label": "//:All",
-    "type": "additional_compile_target",
-  },
   "All_syzygy": {
     "label": "//:All_syzygy",
     "type": "additional_compile_target",
@@ -469,7 +465,7 @@
     "type": "script",
     "script": "//testing/scripts/run_devtools_check.py",
     "args": [
-        "../../third_party/WebKit/Source/devtools/scripts/buildbot/run_eslint.py",
+        "../../third_party/WebKit/Source/devtools/scripts/lint_javascript.py",
     ],
   },
   "display_unittests": {
@@ -961,6 +957,16 @@
       "-v",
     ],
   },
+  "telemetry_perf_unittests_viz": {
+    "label": "//chrome/test:telemetry_perf_unittests",
+    "type": "script",
+    "script": "//testing/scripts/run_telemetry_as_googletest.py",
+    "args": [
+      "../../tools/perf/run_tests",
+      "-v",
+      '--extra-browser-args=--enable-viz',
+    ],
+  },
   "telemetry_perf_tests": {
     "label": "//chrome/test:telemetry_perf_tests",
     "type": "script",
@@ -1168,7 +1174,7 @@
     "type": "console_test_launcher",
   },
   "vr_testapp": {
-    "label": "//chrome/browser/vr:vr_testapp",
+    "label": "//chrome/browser/vr/testapp:vr_testapp",
     "type": "additional_compile_target",
   },
   "wayland_client_perftests": {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 9bded54..6a94f53 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -990,7 +990,15 @@
     'telemetry_perf_unittests': {
       'args': [
         "--xvfb",
-        '--extra-browser-args=--enable-viz',
+      ],
+      'swarming': {
+        'hard_timeout': 960,
+        'shards': 12,
+      },
+    },
+    'telemetry_perf_unittests_viz': {
+      'args': [
+        "--xvfb",
       ],
       'swarming': {
         'hard_timeout': 960,
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 83bc74e..c40a719 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -573,7 +573,7 @@
     'machines': {
       'Linux ChromiumOS Builder': {
         'additional_compile_targets': [
-          'All',
+          'gn_all',
         ],
       },
       'Linux ChromiumOS Tests (dbg)(1)': {
@@ -598,7 +598,7 @@
       },
       'linux-chromeos-rel': {
         'additional_compile_targets': [
-          'All',
+          'gn_all',
         ],
         'test_suites': {
           'gtest_tests': 'linux_chromeos_rel_gtests',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 2f3a233..d4571b8 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2146,22 +2146,21 @@
         {
             "platforms": [
                 "android",
-                "linux",
-                "win"
+                "win",
+                "mac",
+                "chromeos",
+                "linux"
             ],
             "experiments": [
                 {
                     "name": "Enabled",
                     "params": {
-                        "hanging_request_duration_http_rtt_multiplier": "5",
                         "hanging_request_http_rtt_upper_bound_http_rtt_multiplier": "6",
                         "hanging_request_http_rtt_upper_bound_transport_rtt_multiplier": "8",
-                        "hanging_request_min_duration_msec": "3000",
                         "hanging_request_upper_bound_min_http_rtt_msec": "500",
                         "lower_bound_http_rtt_transport_rtt_multiplier": "1",
                         "rssi_weight_per_signal_strength_level": "0.9",
                         "throughput_hanging_requests_cwnd_size_multiplier": "1",
-                        "throughput_min_requests_in_flight": "5",
                         "upper_bound_http_rtt_transport_rtt_multiplier": "5"
                     }
                 }
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index acc2fe4..4cef0e3 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -293,7 +293,7 @@
 crbug.com/591099 compositing/overflow/overflow-positioning.html [ Failure ]
 crbug.com/591099 compositing/overflow/overflow-scroll-with-local-image-background.html [ Failure ]
 crbug.com/591099 compositing/overflow/overflow-scroll.html [ Failure ]
-crbug.com/591099 compositing/overflow/overflow-with-negative-z-index-child.html [ Failure ]
+crbug.com/591099 compositing/overflow/overflow-with-negative-z-index-child.html [ Failure Pass ]
 crbug.com/591099 compositing/overflow/parent-overflow.html [ Failure ]
 crbug.com/591099 compositing/overflow/remove-overflow-crash2.html [ Failure ]
 crbug.com/714962 compositing/overflow/rtl-overflow.html [ Failure ]
@@ -347,7 +347,6 @@
 crbug.com/591099 compositing/squashing/squash-above-fixed-1.html [ Failure ]
 crbug.com/591099 compositing/squashing/squash-above-fixed-3.html [ Failure ]
 crbug.com/591099 compositing/squashing/squash-onto-distant-relative.html [ Crash ]
-crbug.com/714962 compositing/squashing/squash-overflow-hidden-scrolltop.html [ Failure Pass ]
 crbug.com/591099 compositing/squashing/squash-transform-repainting-transformed-child.html [ Failure ]
 crbug.com/591099 compositing/squashing/squashed-layer-loses-graphicslayer.html [ Failure ]
 crbug.com/591099 compositing/squashing/vertical-writing-mode-squashed.html [ Failure ]
@@ -2216,6 +2215,8 @@
 crbug.com/591099 external/wpt/XMLHttpRequest/send-authentication-prompt-2-manual.htm [ Failure ]
 crbug.com/591099 external/wpt/acid/acid3/test.html [ Crash ]
 crbug.com/591099 external/wpt/compat/webkit-text-fill-color-property-005.html [ Failure Pass ]
+crbug.com/591099 external/wpt/credential-management/federatedcredential-framed-get.sub.https.html [ Crash Pass ]
+crbug.com/591099 external/wpt/credential-management/passwordcredential-framed-get.sub.https.html [ Crash Pass ]
 crbug.com/714962 external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-overflow.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/floats/floats-wrap-bfc-003-left-table.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/CSS2/floats/floats-wrap-bfc-003-right-overflow.xht [ Failure ]
@@ -2225,15 +2226,15 @@
 crbug.com/714962 external/wpt/css/CSS2/linebox/inline-formatting-context-015.xht [ Failure ]
 crbug.com/714962 external/wpt/css/CSS2/linebox/vertical-align-baseline-005a.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-percents-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-non-replaced-width-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-004.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-005.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-007.xht [ Failure ]
+crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-non-replaced-width-001.xht [ Failure Pass ]
+crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-004.xht [ Failure Pass ]
+crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-005.xht [ Failure Pass ]
+crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-007.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/inline-block-zorder-001.xht [ Failure ]
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/inline-block-zorder-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-replaced-height-004.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-replaced-height-005.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-replaced-height-007.xht [ Failure ]
+crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-replaced-height-004.xht [ Failure Pass ]
+crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-replaced-height-005.xht [ Failure Pass ]
+crbug.com/591099 external/wpt/css/CSS2/normal-flow/inline-replaced-height-007.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/inline-table-zorder-001.xht [ Failure ]
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/inline-table-zorder-002.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/max-height-percentage-002.xht [ Failure ]
@@ -2244,7 +2245,7 @@
 crbug.com/714962 external/wpt/css/CSS2/normal-flow/min-height-106.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/root-box-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/positioning/absolute-replaced-height-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/CSS2/positioning/abspos-007.xht [ Failure ]
+crbug.com/591099 external/wpt/css/CSS2/positioning/abspos-007.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/CSS2/positioning/relpos-calcs-004.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/positioning/relpos-calcs-005.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/text/text-decoration-applies-to-015.xht [ Failure ]
@@ -2620,7 +2621,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vrl-018.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vrl-020.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vrl-030.xht [ Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-003.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-003.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-005.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-007.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-009.xht [ Failure Pass ]
@@ -2635,7 +2636,7 @@
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-027.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-029.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-031.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-033.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-033.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-035.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-037.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-039.xht [ Failure Pass ]
@@ -2654,7 +2655,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-065.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-067.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-069.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-071.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-071.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-073.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-075.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-077.xht [ Failure Pass ]
@@ -2765,7 +2766,7 @@
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-062.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-064.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-066.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-068.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-068.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-070.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-072.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-074.xht [ Failure ]
@@ -2946,7 +2947,7 @@
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-005.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-007.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-009.xht [ Failure Pass ]
-crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-011.xht [ Failure ]
+crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-011.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-013.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-015.xht [ Failure Pass ]
 crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-017.xht [ Failure Pass ]
@@ -3022,8 +3023,6 @@
 crbug.com/714962 external/wpt/css/selectors/focus-within-007.html [ Failure ]
 crbug.com/714962 external/wpt/css/selectors/focus-within-008.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001a.xhtml [ Failure ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-rtl-002.xhtml [ Failure Pass ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-rtl-004.xhtml [ Failure Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001b.html [ Failure Pass ]
 crbug.com/714962 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-basic-fieldset-horiz-001.xhtml [ Failure ]
 crbug.com/714962 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-basic-img-horiz-001.xhtml [ Failure ]
@@ -3200,7 +3199,7 @@
 crbug.com/591099 external/wpt/html/dom/documents/resource-metadata-management/document-lastModified-01.html [ Pass ]
 crbug.com/591099 external/wpt/html/dom/interfaces.html [ Timeout ]
 crbug.com/591099 external/wpt/html/editing/focus/tabindex-focus-flag.html [ Crash ]
-crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html [ Timeout ]
+crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html [ Crash Timeout ]
 crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-16le.html [ Crash Timeout ]
 crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/utf-8.html [ Crash Timeout ]
 crbug.com/591099 external/wpt/html/infrastructure/urls/resolving-urls/query-encoding/windows-1251.html [ Crash Timeout ]
@@ -3345,7 +3344,7 @@
 crbug.com/591099 external/wpt/websockets/constructor/011.html?wss [ Pass ]
 crbug.com/591099 external/wpt/websockets/cookies/005.html [ Pass ]
 crbug.com/591099 external/wpt/websockets/cookies/007.html [ Failure Pass ]
-crbug.com/591099 external/wpt/websockets/opening-handshake/005.html [ Failure Pass ]
+crbug.com/591099 external/wpt/websockets/opening-handshake/005.html [ Pass ]
 crbug.com/591099 external/wpt/websockets/unload-a-document/001.html [ Pass ]
 crbug.com/591099 external/wpt/websockets/unload-a-document/001.html?wss [ Pass ]
 crbug.com/591099 external/wpt/webstorage/storage_setitem.html [ Pass Timeout ]
@@ -3374,6 +3373,9 @@
 crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties.html [ Failure ]
 crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand.html [ Failure ]
 crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped.html [ Crash ]
+crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center.html [ Failure ]
+crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left.html [ Failure ]
+crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right.html [ Failure ]
 crbug.com/591099 external/wpt/workers/Worker_terminate_event_queue.htm [ Pass Timeout ]
 crbug.com/591099 fast/animation/scroll-animations/scrolltimeline-currenttime.html [ Failure ]
 crbug.com/591099 fast/autoresize/basic.html [ Failure ]
@@ -3549,9 +3551,9 @@
 crbug.com/591099 fast/block/positioning/complex-positioned-movement-inline-ancestor.html [ Crash ]
 crbug.com/591099 fast/block/positioning/complex-positioned-movement-inline.html [ Crash ]
 crbug.com/591099 fast/block/positioning/fixed-in-abs-height-change.html [ Crash ]
-crbug.com/591099 fast/block/positioning/fixed-positioning-scrollbar-bug.html [ Failure ]
+crbug.com/591099 fast/block/positioning/fixed-positioning-scrollbar-bug.html [ Failure Pass ]
 crbug.com/591099 fast/block/positioning/hittest-on-relative-positioned-children.html [ Failure ]
-crbug.com/591099 fast/block/positioning/inline-block-relposition.html [ Failure ]
+crbug.com/591099 fast/block/positioning/inline-block-relposition.html [ Failure Pass ]
 crbug.com/591099 fast/block/positioning/insert-positioned-in-anonymous-crash.html [ Crash ]
 crbug.com/591099 fast/block/positioning/leftmargin-topmargin.html [ Failure ]
 crbug.com/591099 fast/block/positioning/move-with-auto-width.html [ Failure ]
@@ -3706,7 +3708,6 @@
 crbug.com/714962 fast/canvas/canvas-css-clip-path.html [ Failure ]
 crbug.com/591099 fast/canvas/canvas-drawImage-animated-images.html [ Failure ]
 crbug.com/591099 fast/canvas/canvas-measure-bidi-text.html [ Failure ]
-crbug.com/591099 fast/canvas/canvas-render-layer.html [ Crash Failure Pass ]
 crbug.com/591099 fast/canvas/canvas-shadow-source-in.html [ Failure ]
 crbug.com/714962 fast/canvas/canvas-text-ideographic-space.html [ Failure ]
 crbug.com/714962 fast/canvas/canvas-textMetrics-width.html [ Failure ]
@@ -3715,7 +3716,7 @@
 crbug.com/714962 fast/canvas/image-object-in-canvas.html [ Failure ]
 crbug.com/591099 fast/canvas/patternfill-repeat.html [ Failure ]
 crbug.com/714962 fast/canvas/setWidthResetAfterForcedRender.html [ Crash Failure ]
-crbug.com/591099 fast/clip/001.html [ Failure ]
+crbug.com/591099 fast/clip/001.html [ Failure Pass ]
 crbug.com/591099 fast/clip/004.html [ Failure ]
 crbug.com/591099 fast/clip/009.html [ Failure ]
 crbug.com/591099 fast/clip/010.html [ Failure ]
@@ -3723,7 +3724,7 @@
 crbug.com/591099 fast/clip/012.html [ Failure ]
 crbug.com/591099 fast/clip/013.html [ Failure ]
 crbug.com/591099 fast/clip/014.html [ Failure ]
-crbug.com/591099 fast/clip/nestedTransparencyClip.html [ Failure ]
+crbug.com/591099 fast/clip/nestedTransparencyClip.html [ Failure Pass ]
 crbug.com/591099 fast/clip/outline-overflowClip.html [ Failure ]
 crbug.com/591099 fast/clip/overflow-border-radius-combinations.html [ Failure ]
 crbug.com/591099 fast/clip/overflow-border-radius-composited-parent.html [ Failure ]
@@ -4175,8 +4176,8 @@
 crbug.com/591099 fast/css/sticky/inline-sticky-abspos-child.html [ Crash Failure ]
 crbug.com/714962 fast/css/sticky/replaced-sticky.html [ Failure ]
 crbug.com/714962 fast/css/sticky/sticky-both-sides-bottom-right-constrained.html [ Failure ]
-crbug.com/591099 fast/css/sticky/sticky-top-overflow-scroll-by-fragment.html [ Failure ]
-crbug.com/591099 fast/css/sticky/sticky-vertically-overconstrained.html [ Failure ]
+crbug.com/591099 fast/css/sticky/sticky-top-overflow-scroll-by-fragment.html [ Crash Failure ]
+crbug.com/591099 fast/css/sticky/sticky-vertically-overconstrained.html [ Failure Pass ]
 crbug.com/591099 fast/css/style-outside-head.html [ Failure ]
 crbug.com/591099 fast/css/style-parsed-outside-head.html [ Failure ]
 crbug.com/591099 fast/css/table-text-align-quirk.html [ Failure ]
@@ -4635,7 +4636,7 @@
 crbug.com/591099 fast/forms/calendar-picker/calendar-picker-appearance-zoom125.html [ Failure ]
 crbug.com/714962 fast/forms/calendar-picker/calendar-picker-appearance-zoom200.html [ Failure Timeout ]
 crbug.com/714962 fast/forms/calendar-picker/calendar-picker-appearance.html [ Failure ]
-crbug.com/591099 fast/forms/calendar-picker/calendar-picker-key-operations.html [ Pass Timeout ]
+crbug.com/591099 fast/forms/calendar-picker/calendar-picker-key-operations.html [ Crash Pass Timeout ]
 crbug.com/714962 fast/forms/calendar-picker/calendar-picker-mouse-operations.html [ Failure ]
 crbug.com/714962 fast/forms/calendar-picker/calendar-picker-type-change-onclick.html [ Timeout ]
 crbug.com/714962 fast/forms/calendar-picker/month-picker-appearance-step.html [ Failure ]
@@ -4866,7 +4867,6 @@
 crbug.com/714962 fast/forms/select-popup/popup-menu-appearance-many.html [ Failure ]
 crbug.com/714962 fast/forms/select-popup/popup-menu-appearance-minimum-font.html [ Failure ]
 crbug.com/591099 fast/forms/select-popup/popup-menu-appearance-rtl-default.html [ Failure ]
-crbug.com/591099 fast/forms/select-popup/popup-menu-appearance-rtl.html [ Failure Pass ]
 crbug.com/714962 fast/forms/select-popup/popup-menu-appearance-styled.html [ Failure ]
 crbug.com/714962 fast/forms/select-popup/popup-menu-appearance-transform.html [ Failure ]
 crbug.com/714962 fast/forms/select-popup/popup-menu-appearance-zoom.html [ Failure ]
@@ -5056,7 +5056,7 @@
 crbug.com/714962 fast/forms/textarea/textarea-resize-above-min-size-and-below-initial-size.html [ Failure ]
 crbug.com/714962 fast/forms/textarea/textarea-resize-below-min-intrinsic-size.html [ Failure Timeout ]
 crbug.com/714962 fast/forms/textarea/textarea-resize-below-min-size-zoomed.html [ Failure ]
-crbug.com/714962 fast/forms/textarea/textarea-resize-below-min-size.html [ Failure ]
+crbug.com/714962 fast/forms/textarea/textarea-resize-below-min-size.html [ Failure Timeout ]
 crbug.com/591099 fast/forms/textarea/textarea-resize-orthogonal-containing-block.html [ Failure Timeout ]
 crbug.com/591099 fast/forms/textarea/textarea-scroll-height.html [ Failure ]
 crbug.com/591099 fast/forms/textarea/textarea-scrollbar.html [ Failure ]
@@ -5853,7 +5853,6 @@
 crbug.com/591099 fast/replaced/absolute-position-auto-width-and-left-and-right-and-intrinsic-width-quirks.html [ Failure ]
 crbug.com/591099 fast/replaced/absolute-position-auto-width-and-left-and-right-and-intrinsic-width.html [ Failure ]
 crbug.com/591099 fast/replaced/absolute-position-percentage-height.html [ Failure ]
-crbug.com/591099 fast/replaced/border-radius-clip-content-edge.html [ Failure Pass ]
 crbug.com/591099 fast/replaced/border-radius-clip.html [ Failure ]
 crbug.com/591099 fast/replaced/computed-image-width-with-percent-height-and-fixed-ancestor-vertical-lr.html [ Failure ]
 crbug.com/591099 fast/replaced/computed-image-width-with-percent-height-inside-table-cell-and-fixed-ancestor-vertical-lr.html [ Failure ]
@@ -6203,7 +6202,7 @@
 crbug.com/591099 fast/table/change-row-border-width-floating-container.html [ Failure ]
 crbug.com/591099 fast/table/change-table-border-width.html [ Failure ]
 crbug.com/591099 fast/table/change-tbody-border-width.html [ Failure ]
-crbug.com/591099 fast/table/collapsed-border-overflow-hidden.html [ Failure ]
+crbug.com/591099 fast/table/collapsed-border-overflow-hidden.html [ Failure Pass ]
 crbug.com/591099 fast/table/column-in-inline.html [ Failure ]
 crbug.com/591099 fast/table/dynamic-descendant-percentage-height.html [ Failure ]
 crbug.com/591099 fast/table/empty-table-percent-height.html [ Failure ]
@@ -6353,7 +6352,7 @@
 crbug.com/714962 fast/text/ellipsis-in-justified-text.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-in-relative-inline-right.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-in-relative-inline.html [ Failure ]
-crbug.com/591099 fast/text/ellipsis-ltr-text-in-ltr-flow-underline.html [ Failure ]
+crbug.com/591099 fast/text/ellipsis-ltr-text-in-ltr-flow-underline.html [ Failure Pass ]
 crbug.com/591099 fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-ltr-text-in-rtl-flow-underline.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-ltr-text-in-rtl-flow.html [ Failure ]
@@ -6364,7 +6363,7 @@
 crbug.com/591099 fast/text/ellipsis-platform-font-change.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-rtl-text-in-ltr-flow-underline.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-rtl-text-in-ltr-flow.html [ Failure ]
-crbug.com/591099 fast/text/ellipsis-rtl-text-in-rtl-flow-underline.html [ Failure ]
+crbug.com/591099 fast/text/ellipsis-rtl-text-in-rtl-flow-underline.html [ Failure Pass ]
 crbug.com/591099 fast/text/ellipsis-with-list-marker-in-ltr-flow.html [ Failure ]
 crbug.com/591099 fast/text/ellipsis-with-list-marker-in-rtl-flow.html [ Failure ]
 crbug.com/591099 fast/text/emoji-web-font.html [ Pass ]
@@ -6485,10 +6484,10 @@
 crbug.com/591099 fast/tokenizer/missing-style-end-tag-2.html [ Failure ]
 crbug.com/591099 fast/tokenizer/nested-cached-scripts-and-stylesheet.html [ Failure ]
 crbug.com/591099 fast/tokenizer/script_extra_close.html [ Failure ]
-crbug.com/591099 fast/webgl/texImage-imageBitmap-from-canvas-resize.html [ Failure ]
-crbug.com/591099 fast/webgl/texImage-imageBitmap-from-image-resize.html [ Failure ]
-crbug.com/591099 fast/webgl/texImage-imageBitmap-from-imageData-resize.html [ Failure ]
-crbug.com/591099 fast/webgl/texImage-imageBitmap-from-offscreen-canvas-resize.html [ Failure ]
+crbug.com/591099 fast/webgl/texImage-imageBitmap-from-canvas-resize.html [ Failure Pass ]
+crbug.com/591099 fast/webgl/texImage-imageBitmap-from-image-resize.html [ Failure Pass ]
+crbug.com/591099 fast/webgl/texImage-imageBitmap-from-imageData-resize.html [ Failure Pass ]
+crbug.com/591099 fast/webgl/texImage-imageBitmap-from-offscreen-canvas-resize.html [ Failure Pass ]
 crbug.com/591099 fast/workers/shared-worker-location.html [ Failure ]
 crbug.com/591099 fast/workers/worker-location.html [ Failure ]
 crbug.com/591099 fast/writing-mode/Kusa-Makura-background-canvas.html [ Failure ]
@@ -6650,7 +6649,6 @@
 crbug.com/591099 fullscreen/full-screen-css.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-element-stack.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-iframe-not-allowed.html [ Failure Timeout ]
-crbug.com/591099 fullscreen/full-screen-remove-ancestor-after.html [ Crash Pass ]
 crbug.com/591099 fullscreen/full-screen-ruleset-crash.html [ Crash Pass ]
 crbug.com/591099 fullscreen/full-screen-twice-newapi.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-with-css-reference-filter.html [ Crash ]
@@ -6798,7 +6796,7 @@
 crbug.com/591099 http/tests/csspaint/invalidation-content-image.html [ Timeout ]
 crbug.com/591099 http/tests/devtools/animation/animation-KeyframeEffectReadOnly-crash.js [ Crash Pass ]
 crbug.com/714962 http/tests/devtools/animation/animation-group-matching-animations.js [ Crash Pass ]
-crbug.com/714962 http/tests/devtools/animation/animation-group-matching-transitions.js [ Crash ]
+crbug.com/714962 http/tests/devtools/animation/animation-group-matching-transitions.js [ Crash Pass ]
 crbug.com/591099 http/tests/devtools/animation/animation-timeline.js [ Crash Pass ]
 crbug.com/591099 http/tests/devtools/animation/animation-transition-setTiming-crash.js [ Crash Pass ]
 crbug.com/591099 http/tests/devtools/animation/animation-web-anim-negative-start-time.js [ Crash Pass ]
@@ -6833,9 +6831,8 @@
 crbug.com/714962 http/tests/devtools/elements/edit/undo-set-outer-html-2.js [ Crash ]
 crbug.com/714962 http/tests/devtools/elements/edit/undo-set-outer-html.js [ Crash ]
 crbug.com/591099 http/tests/devtools/elements/elements-delete-inline-style.js [ Crash Pass ]
-crbug.com/591099 http/tests/devtools/elements/elements-inspect-iframe-from-different-domain.js [ Crash Pass Timeout ]
 crbug.com/714962 http/tests/devtools/elements/elements-linkify-attributes.js [ Crash Pass ]
-crbug.com/714962 http/tests/devtools/elements/elements-panel-limited-children.js [ Crash ]
+crbug.com/714962 http/tests/devtools/elements/elements-panel-limited-children.js [ Crash Pass ]
 crbug.com/591099 http/tests/devtools/elements/elements-panel-rewrite-href.js [ Crash Failure Pass ]
 crbug.com/591099 http/tests/devtools/elements/elements-panel-search.js [ Crash Pass ]
 crbug.com/714962 http/tests/devtools/elements/elements-panel-selection-after-delete.js [ Crash ]
@@ -6850,7 +6847,6 @@
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside-scroll.js [ Failure ]
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside.js [ Failure ]
 crbug.com/714962 http/tests/devtools/elements/highlight/highlight-dom-updates.js [ Crash ]
-crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node-scaled.js [ Failure Pass ]
 crbug.com/714962 http/tests/devtools/elements/iframe-load-event.js [ Crash Pass ]
 crbug.com/714962 http/tests/devtools/elements/insert-node.js [ Crash ]
 crbug.com/714962 http/tests/devtools/elements/inspect-pseudo-element.js [ Timeout ]
@@ -6872,7 +6868,7 @@
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-add-new-rule-tab.js [ Crash Failure Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-add-new-rule.js [ Crash Failure Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-cancel-editing.js [ Crash Pass ]
-crbug.com/591099 http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Crash Failure ]
+crbug.com/591099 http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Crash Failure Pass ]
 crbug.com/714962 http/tests/devtools/elements/styles-3/styles-commit-editing.js [ Crash Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Failure Pass ]
 crbug.com/714962 http/tests/devtools/elements/styles-4/styles-live-locations-leak.js [ Crash ]
@@ -6907,7 +6903,6 @@
 crbug.com/591099 http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js [ Timeout ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js [ Timeout ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js [ Timeout ]
-crbug.com/591099 http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.js [ Crash Pass ]
 crbug.com/591099 http/tests/feature-policy-experimental-features/vibrate-allowed-by-container-policy-relocate-and-no-reload.html [ Timeout ]
 crbug.com/591099 http/tests/feature-policy-experimental-features/vibrate-allowed-by-container-policy-relocate-and-reload.html [ Timeout ]
 crbug.com/591099 http/tests/feature-policy-experimental-features/vibrate-allowed-by-container-policy.html [ Timeout ]
@@ -7152,13 +7147,13 @@
 crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-003.htm [ Failure ]
 crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-004.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-007.htm [ Failure Pass ]
-crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-008.htm [ Failure ]
+crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-008.htm [ Failure Pass ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-009.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-010.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-012.htm [ Failure ]
 crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-013.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-014.htm [ Failure ]
-crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-015.htm [ Failure ]
+crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-015.htm [ Failure Pass ]
 crbug.com/591099 ietestcenter/css3/text/textshadow-002.htm [ Failure ]
 crbug.com/714962 ietestcenter/css3/text/textshadow-003.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/text/textshadow-010.htm [ Failure ]
@@ -7266,6 +7261,7 @@
 crbug.com/591099 inspector-protocol/input/dispatchTouchEvent.js [ Pass Timeout ]
 crbug.com/714962 inspector-protocol/layers/paint-profiler.js [ Failure ]
 crbug.com/714962 inspector-protocol/layout-fonts/cjk-ideograph-fallback-by-lang.js [ Failure ]
+crbug.com/591099 inspector-protocol/layout-fonts/fallback-pua-last-resort.js [ Failure ]
 crbug.com/714962 inspector-protocol/layout-fonts/font-style-matching-0.js [ Failure ]
 crbug.com/714962 inspector-protocol/layout-fonts/font-style-matching-1.js [ Failure ]
 crbug.com/714962 inspector-protocol/layout-fonts/font-style-matching-2.js [ Failure ]
@@ -7379,7 +7375,7 @@
 crbug.com/714962 paint/invalidation/caret-outside-block.html [ Failure ]
 crbug.com/714962 paint/invalidation/caret-subpixel.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/caret-ancestor-clip-change.html [ Failure ]
-crbug.com/591099 paint/invalidation/clip/clip-unclip-and-change.html [ Failure ]
+crbug.com/591099 paint/invalidation/clip/clip-unclip-and-change.html [ Failure Pass ]
 crbug.com/591099 paint/invalidation/clip/clip-with-layout-delta.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/clip-with-transform-resize.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/clipped-relative.html [ Failure ]
@@ -7417,7 +7413,7 @@
 crbug.com/591099 paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/layer-repaint-rects.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/layer-repaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/compositing/multi-subsequence-composited.html [ Failure ]
+crbug.com/591099 paint/invalidation/compositing/multi-subsequence-composited.html [ Failure Pass ]
 crbug.com/591099 paint/invalidation/compositing/new-stacking-context.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/opacity-between-absolute.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/opacity-between-absolute2.html [ Failure ]
@@ -7742,7 +7738,7 @@
 crbug.com/591099 paint/invalidation/selection/selected-replaced.html [ Failure ]
 crbug.com/591099 paint/invalidation/selection/selection-after-delete.html [ Failure ]
 crbug.com/591099 paint/invalidation/selection/selection-after-remove.html [ Failure ]
-crbug.com/714962 paint/invalidation/selection/selection-and-text-repaint.html [ Failure ]
+crbug.com/714962 paint/invalidation/selection/selection-and-text-repaint.html [ Failure Pass ]
 crbug.com/591099 paint/invalidation/selection/selection-change-in-iframe-with-relative-parent.html [ Crash Failure ]
 crbug.com/591099 paint/invalidation/selection/selection-clear.html [ Failure ]
 crbug.com/714962 paint/invalidation/selection/selection-in-composited-scrolling-container.html [ Failure ]
@@ -8204,7 +8200,7 @@
 crbug.com/591099 svg/as-background-image/background-image-preserveaspectRatio-support.html [ Failure ]
 crbug.com/591099 svg/as-background-image/background-repeat.html [ Failure ]
 crbug.com/591099 svg/as-background-image/svg-as-background-1.html [ Failure ]
-crbug.com/591099 svg/as-background-image/svg-as-background-2.html [ Failure ]
+crbug.com/591099 svg/as-background-image/svg-as-background-2.html [ Crash Failure ]
 crbug.com/591099 svg/as-background-image/svg-as-background-3.html [ Failure ]
 crbug.com/591099 svg/as-background-image/svg-as-background-5.html [ Failure ]
 crbug.com/591099 svg/as-background-image/svg-as-background-6.html [ Failure ]
@@ -8497,7 +8493,7 @@
 crbug.com/591099 svg/text/bbox-with-glyph-overflow-zoomed.html [ Failure ]
 crbug.com/591099 svg/text/bbox-with-glyph-overflow.html [ Failure ]
 crbug.com/714962 svg/text/columns-do-not-apply.html [ Failure ]
-crbug.com/591099 svg/text/foreignObject-repaint.xml [ Failure ]
+crbug.com/591099 svg/text/foreignObject-repaint.xml [ Crash Failure ]
 crbug.com/591099 svg/text/foreignObject-text-clipping-bug.xml [ Failure ]
 crbug.com/714962 svg/text/layout-inline-children-assert.html [ Failure ]
 crbug.com/591099 svg/text/scaling-font-with-geometric-precision.html [ Failure ]
@@ -8638,7 +8634,7 @@
 crbug.com/714962 tables/mozilla/bugs/bug48827.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug50695-1.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ]
-crbug.com/591099 tables/mozilla/bugs/bug51140.html [ Failure ]
+crbug.com/591099 tables/mozilla/bugs/bug51140.html [ Failure Pass ]
 crbug.com/714962 tables/mozilla/bugs/bug5188.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug53690-2.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug5538.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 afa1c3a..70ac454b 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -229,6 +229,7 @@
 Bug(none) compositing/iframes/composited-parent-iframe.html [ Failure ]
 Bug(none) compositing/iframes/connect-compositing-iframe2.html [ Failure ]
 Bug(none) compositing/iframes/connect-compositing-iframe3.html [ Failure ]
+Bug(none) compositing/iframes/iframe-composited-scrolling-hide-and-show.html [ Failure ]
 Bug(none) compositing/iframes/iframe-resize.html [ Failure ]
 Bug(none) compositing/iframes/iframe-size-from-zero.html [ Failure ]
 Bug(none) compositing/iframes/invisible-nested-iframe-show.html [ Crash Failure ]
@@ -538,25 +539,11 @@
 Bug(none) fast/lists/008.html [ Failure ]
 Bug(none) fast/lists/ol-start-parsing.html [ Failure ]
 Bug(none) fast/lists/olstart.html [ Failure ]
-Bug(none) fast/multicol/balance-breakafter-before-nested-block.html [ Failure ]
-Bug(none) fast/multicol/balance-empty-block-subpixel-column-height.html [ Failure ]
-Bug(none) fast/multicol/balance-float-after-forced-break.html [ Pass Failure ]
-Bug(none) fast/multicol/balance-repeating-table-headers.html [ Failure Crash ]
-Bug(none) fast/multicol/basic-rtl.html [ Failure ]
-Bug(none) fast/multicol/border-radius-clipped-layer-second-column.html [ Failure ]
 Bug(none) fast/multicol/border-radius-clipped-layer.html [ Failure ]
-Bug(none) fast/multicol/client-rects-rtl.html [ Failure ]
-Bug(none) fast/multicol/client-rects.html [ Failure ]
-Bug(none) fast/multicol/column-break-with-balancing.html [ Failure ]
-Bug(none) fast/multicol/column-count-with-rules.html [ Failure ]
-Bug(none) fast/multicol/column-rules.html [ Failure ]
-Bug(none) fast/multicol/columns-shorthand-parsing.html [ Failure ]
 Bug(none) fast/multicol/composited-inner-multicol.html [ Failure ]
 Bug(none) fast/multicol/composited-layer-multiple-fragments-translated.html [ Failure ]
 Bug(none) fast/multicol/composited-layer-multiple-fragments.html [ Failure ]
 Bug(none) fast/multicol/composited-layer-nested.html [ Failure Crash ]
-Bug(none) fast/multicol/composited-layer-single-fragment.html [ Failure ]
-Bug(none) fast/multicol/composited-layer-will-change.html [ Failure ]
 Bug(none) fast/multicol/composited-opacity-2nd-and-3rd-column.html [ Failure ]
 Bug(none) fast/multicol/composited-relpos.html [ Failure ]
 Bug(none) fast/multicol/composited-relpos-clipped.html [ Failure ]
@@ -565,183 +552,15 @@
 Bug(none) fast/multicol/composited-relpos-resize.html [ Failure ]
 Bug(none) fast/multicol/composited-with-child-layer-in-next-column.html [ Failure ]
 Bug(none) fast/multicol/composited-with-overflow-in-next-column.html [ Failure ]
-Bug(none) fast/multicol/doubly-nested-with-top-padding-crossing-row-boundaries.html [ Failure ]
-Bug(none) fast/multicol/relpos-inside-inline-block.html [ Failure ]
-Bug(none) fast/multicol/dynamic/abspos-multicol-with-spanner-becomes-spanner.html [ Failure ]
-Bug(none) fast/multicol/dynamic/add-will-change-transform.html [ Failure ]
-Bug(none) fast/multicol/dynamic/change-spanner-display.html [ Failure ]
-Bug(none) fast/multicol/dynamic/insert-block-among-text-in-anonymous-wrapper.html [ Failure ]
-Bug(none) fast/multicol/dynamic/insert-block-before-spanner-before-content.html [ Failure ]
-Bug(none) fast/multicol/dynamic/insert-block-before-spanner.html [ Failure ]
-Bug(none) fast/multicol/dynamic/insert-block-between-spanners.html [ Failure ]
-Bug(none) fast/multicol/dynamic/insert-block-into-content.html [ Failure ]
-Bug(none) fast/multicol/dynamic/insert-spanner-after-content.html [ Failure ]
-Bug(none) fast/multicol/dynamic/insert-spanner-after-spanner-before-content.html [ Failure ]
-Bug(none) fast/multicol/dynamic/insert-spanner-before-content.html [ Failure ]
-Bug(none) fast/multicol/dynamic/insert-spanner-into-content.html [ Failure ]
-Bug(none) fast/multicol/dynamic/remove-abspos-next-to-spanner.html [ Failure ]
-Bug(none) fast/multicol/dynamic/remove-and-insert-block-after-spanner.html [ Failure ]
-Bug(none) fast/multicol/dynamic/remove-and-insert-block-before-spanner.html [ Failure ]
-Bug(none) fast/multicol/dynamic/remove-and-insert-block-between-spanners.html [ Failure ]
-Bug(none) fast/multicol/dynamic/remove-block-from-content-after-spanner.html [ Failure ]
-Bug(none) fast/multicol/dynamic/remove-block-from-content-before-spanner.html [ Failure ]
-Bug(none) fast/multicol/dynamic/remove-block-from-content-between-spanners.html [ Failure ]
-Bug(none) fast/multicol/dynamic/remove-spanner-in-content.html [ Failure ]
-Bug(none) fast/multicol/dynamic/spanner-after-content-becomes-regular-block.html [ Failure ]
-Bug(none) fast/multicol/dynamic/spanner-becomes-float.html [ Failure ]
-Bug(none) fast/multicol/dynamic/spanner-becomes-regular-block.html [ Failure ]
-Bug(none) fast/multicol/dynamic/spanner-before-content-becomes-regular-block.html [ Failure ]
-Bug(none) fast/multicol/dynamic/spanner-in-content-becomes-regular-block.html [ Failure ]
-Bug(none) fast/multicol/dynamic/static-becomes-relpos-has-abspos.html [ Failure ]
-Bug(none) fast/multicol/fixedpos-child-becomes-static.html [ Failure ]
 Bug(none) fast/multicol/fixedpos-in-transform-at-column-boundary.html [ Crash ]
-Bug(none) fast/multicol/flexbox-starts-at-column-boundary-with-block.html [ Failure ]
-Bug(none) fast/multicol/flexbox-starts-at-column-boundary.html [ Failure ]
-Bug(none) fast/multicol/flexbox.html [ Failure ]
-Bug(none) fast/multicol/flipped-blocks-border-after.html [ Failure ]
-Bug(none) fast/multicol/float-after-break-after.html [ Failure ]
-Bug(none) fast/multicol/float-avoidance.html [ Failure ]
-Bug(none) fast/multicol/float-big-line.html [ Failure ]
-Bug(none) fast/multicol/float-break.html [ Failure ]
-Bug(none) fast/multicol/float-content-break.html [ Failure ]
-Bug(none) fast/multicol/float-edge.html [ Failure ]
-Bug(none) fast/multicol/float-paginate-empty-lines.html [ Failure ]
-Bug(none) fast/multicol/float-paginate.html [ Failure ]
-Bug(none) fast/multicol/forced-break-after-block-with-spanner.html [ Failure ]
-Bug(none) fast/multicol/forced-break-after-empty-block-after-spanner.html [ Failure ]
-Bug(none) fast/multicol/forced-break-after-last-block-before-spanner.html  [ Failure ]
-Bug(none) fast/multicol/forced-break-too-short-column.html [ Failure ]
-Bug(none) fast/multicol/foreignObject.html [ Failure ]
-Bug(none) fast/multicol/inline-block-baseline.html [ Failure ]
-Bug(none) fast/multicol/inner-multicol-in-second-column.html [ Failure ]
 Bug(none) fast/multicol/insane-column-count-and-padding-nested-crash.html [ Crash ]
-Bug(none) fast/multicol/layers-in-multicol.html [ Failure ]
-Bug(none) fast/multicol/layers-split-across-columns.html [ Failure ]
-Bug(none) fast/multicol/line-in-next-row-in-fourth-inner-multicol.html [ Failure ]
-Bug(none) fast/multicol/line-pushed-down-by-float.html [ Failure ]
-Bug(none) fast/multicol/line-too-tall-for-second-outer-row.html [ Failure ]
-Bug(none) fast/multicol/many-lines-overflow-in-single-row-inner.html [ Failure ]
-Bug(none) fast/multicol/margin-collapse.html [ Failure ]
-Bug(none) fast/multicol/mixed-opacity-fixed-test.html [ Failure ]
 Bug(none) fast/multicol/mixed-opacity-test.html [ Failure ]
-Bug(none) fast/multicol/mixed-positioning-stacking-order.html [ Failure ]
-Bug(none) fast/multicol/multicol-on-root-element-quirks.html [ Failure ]
-Bug(none) fast/multicol/multicol-with-child-renderLayer-for-input.html [ Failure ]
-Bug(none) fast/multicol/nested-3-multicols-fixed-height.html [ Failure ]
 Bug(none) fast/multicol/nested-and-unbreakable-crash.html [ Crash ]
-Bug(none) fast/multicol/nested-auto-height-extra-block-inbetween.html [ Failure ]
-Bug(none) fast/multicol/nested-auto-height-short-first-row.html [ Failure ]
-Bug(none) fast/multicol/nested-auto-height.html [ Failure ]
-Bug(none) fast/multicol/nested-balanced-inner-column-count-1-with-forced-break.html [ Failure ]
-Bug(none) fast/multicol/nested-balanced-inner-with-many-breaks-2.html [ Failure ]
-Bug(none) fast/multicol/nested-balanced-inner-with-many-breaks.html [ Failure ]
-Bug(none) fast/multicol/nested-balanced-with-strut-before-first-line.html [ Failure ]
-Bug(none) fast/multicol/nested-columns.html [ Failure ]
-Bug(none) fast/multicol/nested-fixed-height-with-struts.html [ Failure ]
-Bug(none) fast/multicol/nested-outer-fixed-height.html [ Failure ]
-Bug(none) fast/multicol/nested-with-padding.html [ Failure ]
-Bug(none) fast/multicol/nested-with-single-empty-block.html [ Failure ]
-Bug(none) fast/multicol/nested-with-single-tall-line.html [ Failure ]
-Bug(none) fast/multicol/nested-with-tall-block.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/break-before.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/breaks-2-columns-3-no-balancing.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/breaks-2-columns-3.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/breaks-3-columns-3.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/clipping.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/fixed-height-fill-balance-2.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/fixed-height-fill-balance.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/list-item.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/table-cell.html [ Failure ]
-Bug(none) fast/multicol/out-of-flow/abspos-auto-position-on-line-at-boundary.html [ Failure ]
-Bug(none) fast/multicol/out-of-flow/abspos-auto-position-on-line-rtl.html [ Failure ]
-Bug(none) fast/multicol/out-of-flow/abspos-auto-position-on-line.html [ Failure ]
-Bug(none) fast/multicol/out-of-flow/abspos-auto-position-small-on-line-at-boundary.html [ Failure ]
-Bug(none) fast/multicol/out-of-flow/abspos-auto-position.html [ Failure ]
-Bug(none) fast/multicol/out-of-flow/nested-multicol.html [ Failure ]
-Bug(none) fast/multicol/outlines-at-column-boundaries.html [ Failure ]
-Bug(none) fast/multicol/overflow-across-columns.html [ Failure ]
-Bug(none) fast/multicol/overflow-into-columngap.html [ Failure ]
 Bug(none) fast/multicol/overflow-unsplittable.html [ Failure ]
-Bug(none) fast/multicol/paginate-block-replaced.html [ Failure ]
-Bug(none) fast/multicol/percent-height.html [ Failure ]
-Bug(none) fast/multicol/positioned-outside-of-columns.html [ Failure ]
-Bug(none) fast/multicol/positioned-split.html [ Failure ]
-Bug(none) fast/multicol/positive-leading.html [ Failure ]
-Bug(none) fast/multicol/pushed-line-affected-by-float.html [ Failure ]
-Bug(none) fast/multicol/scrollable-basic.html [ Failure ]
-Bug(none) fast/multicol/scrolling-overflow.html [ Failure ]
-Bug(none) fast/multicol/single-line.html [ Failure ]
-Bug(none) fast/multicol/span/abspos-containing-block-outside-spanner.html [ Failure ]
-Bug(none) fast/multicol/span/after-row-with-uneven-height-nested-multicol.html [ Failure ]
-Bug(none) fast/multicol/span/as-inner-multicol.html [ Failure ]
-Bug(none) fast/multicol/span/balance-after-spanner-exact-fit.html [ Failure ]
-Bug(none) fast/multicol/span/balance-after-spanner-extra-height.html [ Failure ]
-Bug(none) fast/multicol/span/balance-after-spanner-some-extra-height.html [ Failure ]
-Bug(none) fast/multicol/span/balance-before-and-after-spanner.html [ Failure ]
-Bug(none) fast/multicol/span/block-with-top-border-and-margin-around-spanner-exact-fit.html [ Failure ]
-Bug(none) fast/multicol/span/block-with-top-border-and-margin-around-spanner-extra-space.html [ Failure ]
-Bug(none) fast/multicol/span/change-multicol-writing-mode.html [ Failure ]
-Bug(none) fast/multicol/span/fill-after-spanner-exact-fit.html [ Failure ]
-Bug(none) fast/multicol/span/fill-after-spanner-extra-height.html [ Failure ]
-Bug(none) fast/multicol/span/float.html [ Failure ]
-Bug(none) fast/multicol/span/in-nested-multicol-with-hard-breaks.html [ Failure ]
-Bug(none) fast/multicol/span/in-nested-multicol-with-soft-breaks-inside.html [ Failure ]
-Bug(none) fast/multicol/span/inside-block-with-fixed-height.html [ Failure ]
-Bug(none) fast/multicol/span/invalid-spanner-in-abspos.html [ Failure ]
 Bug(none) fast/multicol/span/invalid-spanner-in-transform.html [ Failure ]
-Bug(none) fast/multicol/span/nested-multicol.html [ Failure ]
-Bug(none) fast/multicol/span/relpos-spanner-with-abspos-child.html [ Failure ]
-Bug(none) fast/multicol/span/remaining-space-in-last-column.html [ Failure ]
-Bug(none) fast/multicol/span/span-between-text.html [ Failure ]
-Bug(none) fast/multicol/span/spanner-first.html [ Failure ]
-Bug(none) fast/multicol/span/spanner-img.html [ Failure ]
-Bug(none) fast/multicol/span/spanner-with-margin.html [ Failure ]
-Bug(none) fast/multicol/span/spanner-with-relpos-child.html [ Failure ]
-Bug(none) fast/multicol/span/summary-split.html [ Failure ]
-Bug(none) fast/multicol/span/two-rows-then-spanner-then-two-rows.html [ Failure ]
-Bug(none) fast/multicol/span/vertical-lr.html [ Failure ]
-Bug(none) fast/multicol/span/vertical-rl.html [ Failure ]
-Bug(none) fast/multicol/table-caption-and-cells-fixed-width.html [ Failure ]
-Bug(none) fast/multicol/table-caption-and-cells.html [ Failure ]
-Bug(none) fast/multicol/table-caption-with-block.html [ Failure ]
-Bug(none) fast/multicol/table-cell-content-change-with-decorations.html [ Failure ]
-Bug(none) fast/multicol/table-margin-collapse.html [ Failure ]
-Bug(none) fast/multicol/tall-float2.html [ Failure ]
 Bug(none) fast/multicol/transform-with-fixedpos.html [ Crash ]
-Bug(none) fast/multicol/unbreakable-block-too-tall-at-column-start.html [ Failure ]
-Bug(none) fast/multicol/unbreakable-block-too-tall-to-fit.html [ Failure ]
-Bug(none) fast/multicol/under-scroll.html [ Failure ]
-Bug(none) fast/multicol/unsplittable-inline-block.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/column-break-with-balancing.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/column-count-with-rules.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/column-rules.html [ Failure ]
 Bug(none) fast/multicol/vertical-lr/composited-relpos-overlapping-will-change.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/float-avoidance.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/float-big-line.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/float-break.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/float-content-break.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/float-edge.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/float-paginate.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/nested-columns.html [ Failure ]
-Bug(none) fast/multicol/vertical-lr/unsplittable-inline-block.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/abspos-auto-position-on-line.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/column-break-with-balancing.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/column-count-with-rules.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/column-rules.html [ Failure ]
 Bug(none) fast/multicol/vertical-rl/composited-relpos-overlapping-will-change.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/float-avoidance.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/float-big-line.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/float-break.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/float-content-break.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/float-edge.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/float-paginate.html [ Failure ]
-Bug(none) fast/multicol/vertical-rl/unsplittable-inline-block.html [ Failure ]
-Bug(none) fast/multicol/span/outer-column-break-after-inner-spanner.html [ Failure ]
-Bug(none) fast/multicol/span/outer-column-break-after-inner-spanner-and-float.html [ Failure ]
-Bug(none) fast/multicol/span/outer-column-break-after-inner-spanner-2.html [ Failure ]
-Bug(none) fast/multicol/float-margin-at-row-boundary-fixed-multicol-height.html [ Failure ]
-Bug(none) fast/multicol/float-margin-at-row-boundary.html [ Failure ]
 Bug(none) fast/overflow/006.html [ Failure ]
 Bug(none) fast/overflow/007.html [ Failure ]
 Bug(none) fast/overflow/clip-rects-fixed-ancestor.html [ Failure ]
@@ -844,9 +663,6 @@
 Bug(none) paint/invalidation/svg/resize-svg-invalidate-children-2.html [ Failure ]
 Bug(none) paint/invalidation/svg/resize-svg-invalidate-children.html [ Failure ]
 
-# The expectation seems incorrect?
-Bug(none) paint/invalidation/overflow/paged-with-overflowing-block-rl.html [ Failure ]
-
 crbug.com/769942 svg/clip-path/ [ Skip ]
 crbug.com/769942 compositing/overflow/ancestor-with-clip-path.html [ Failure ]
 crbug.com/769942 compositing/overflow/descendant-with-clip-path.html [ Failure ]
@@ -981,15 +797,9 @@
 
 # Wrong invalidation/painting/rasterization for multicol. Different layer tree.
 crbug.com/648274 fast/text/letter-spacing-leading-and-trailing.html [ Failure ]
-crbug.com/648274 paint/invalidation/multicol/column-rules-fixed-height.html [ Failure ]
 crbug.com/648274 paint/invalidation/multicol/multicol-as-paint-container.html [ Failure ]
-crbug.com/648274 paint/invalidation/multicol/multicol-nested.html [ Failure ]
 crbug.com/648274 paint/invalidation/multicol/multicol-repaint.html [ Failure ]
-crbug.com/648274 paint/invalidation/multicol/multicol-with-abspos-in-relpos.html [ Failure ]
-crbug.com/648274 paint/invalidation/multicol/multicol-with-block.html [ Failure ]
 crbug.com/648274 paint/invalidation/multicol/multicol-with-inline.html [ Failure ]
-crbug.com/648274 paint/invalidation/multicol/multicol-with-overflowing-block-rl.html [ Failure ]
-crbug.com/648274 paint/invalidation/multicol/multicol-with-relpos.html [ Failure ]
 crbug.com/648274 paint/invalidation/multicol/multicol-with-text.html [ Failure ]
 
 # Different layer tree about squashing.
@@ -1201,7 +1011,6 @@
 Bug(none) fast/forms/suggestion-picker/time-suggestion-picker-mouse-operations.html [ Failure ]
 Bug(none) fast/forms/suggestion-picker/week-suggestion-picker-mouse-operations.html [ Failure ]
 
-Bug(none) fast/multicol/nested-with-clipped-first-column.html [ Failure ]
 Bug(none) fast/scrolling/absolute-position-behind-scrollbar.html [ Failure ]
 Bug(none) fast/scrolling/fixed-position-behind-scrollbar.html [ Failure Timeout ]
 Bug(none) fast/events/remove-child-onscroll.html [ Timeout ]
@@ -1414,7 +1223,6 @@
 # painting code.
 Bug(700530) svg/text/small-fonts-in-html5.html [ Failure ]
 Bug(700530) compositing/overflow/paint-neg-z-order-descendants-into-scrolling-contents-layer.html [ Failure ]
-Bug(700530) fast/multicol/tall-content-in-inner-with-fixed-height.html [ Failure ]
 
 # The following debug crashes / failures have not been triaged.
 crbug.com/702805 fast/forms/select-popup/popup-menu-appearance-coarse.html [ Crash Timeout Failure ]
@@ -1465,7 +1273,6 @@
 
 crbug.com/719721 virtual/threaded/animations/composited-animation-style-update.html [ Pass Failure ]
 
-Bug(none) paint/pagination/composited-paginated-outlined-box.html [ Failure ]
 Bug(none) paint/pagination/composited-paginated-inline.html [ Failure ]
 
 Bug(none) fast/forms/validation-bubble-appearance-edge.html [ Failure ]
@@ -1655,7 +1462,6 @@
 # different results.
 Bug(none) paint/invalidation/compositing/subpixel-offset-scaled-transform-composited.html [ Failure ]
 
-Bug(none) fast/multicol/balance-fixed-height-unused-space-simple-block.html [ Failure ]
 Bug(none) paint/invalidation/selection/selection-change-in-iframe-with-relative-parent.html [ Failure ]
 Bug(none) paint/invalidation/selection/selection-clear.html [ Failure ]
 Bug(none) paint/invalidation/selection/selection-rl.html [ Failure ]
@@ -1719,15 +1525,46 @@
 Bug(none) svg/W3C-SVG-1.1/text-text-06-t.svg [ Failure ]
 Bug(none) svg/transforms/text-with-pattern-with-svg-transform.svg [ Failure ]
 
-Bug(none) fast/multicol/composited-relpos-2nd-column.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/clipping-overflow-hidden.html [ Failure ]
-Bug(none) fast/multicol/newmulticol/clipping-top-overflow.html [ Failure ]
-Bug(none) fast/multicol/overflow-content.html [ Failure ]
-Bug(none) fast/multicol/scale-transform-text.html [ Failure ]
-
 Bug(none) compositing/rendering-contexts.html [ Failure ]
 Bug(none) compositing/overflow-trumps-transform-style.html [ Failure ]
 
+crbug.com/796768 fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size.html [ Crash ]
+crbug.com/796768 fast/multicol/composited-layer-will-change.html [ Crash ]
+crbug.com/796768 fast/multicol/hit-test-gap-between-pages-flipped.html [ Crash ]
+crbug.com/796768 fast/multicol/hit-test-gap-between-pages.html [ Crash ]
+crbug.com/796768 fast/multicol/multicol-becomes-paged-fixed-height.html [ Crash ]
+crbug.com/796768 fast/multicol/scrollable-basic.html [ Failure Crash ]
+crbug.com/796768 fast/multicol/scrollbar-taller-than-content-box-freeze.html [ Crash ]
+crbug.com/796768 fast/multicol/scrolling-column-rules.html [ Crash ]
+crbug.com/796768 fast/overflow/hidden-html-paged-body.html [ Crash ]
+crbug.com/796768 fast/overflow/scroll-html-paged-body.html [ Crash ]
+crbug.com/796768 fast/pagination/auto-height-with-break.html [ Crash ]
+crbug.com/796768 fast/pagination/break-in-paged-overflow.html [ Crash ]
+crbug.com/796768 fast/pagination/caret-range-outside-paged-x-rtl-vertical-rl.html [ Crash ]
+crbug.com/796768 fast/pagination/caret-range-outside-paged-x-rtl.html [ Crash ]
+crbug.com/796768 fast/pagination/caret-range-outside-paged-x-vertical-rl.html [ Crash ]
+crbug.com/796768 fast/pagination/caret-range-outside-paged-x.html [ Crash ]
+crbug.com/796768 fast/pagination/caret-range-outside-paged-y-rtl-vertical-rl.html [ Crash ]
+crbug.com/796768 fast/pagination/caret-range-outside-paged-y-rtl.html [ Crash ]
+crbug.com/796768 fast/pagination/caret-range-outside-paged-y.html [ Crash ]
+crbug.com/796768 fast/pagination/div-make-paginated.html [ Crash ]
+crbug.com/796768 fast/pagination/div-x-horizontal-tb-ltr.html [ Crash ]
+crbug.com/796768 fast/pagination/div-x-horizontal-tb-rtl.html [ Crash ]
+crbug.com/796768 fast/pagination/div-x-vertical-lr-ltr.html [ Crash ]
+crbug.com/796768 fast/pagination/div-x-vertical-lr-rtl.html [ Crash ]
+crbug.com/796768 fast/pagination/div-x-vertical-rl-ltr.html [ Crash ]
+crbug.com/796768 fast/pagination/div-x-vertical-rl-rtl.html [ Crash ]
+crbug.com/796768 fast/pagination/div-y-horizontal-tb-ltr.html [ Crash ]
+crbug.com/796768 fast/pagination/div-y-horizontal-tb-rtl.html [ Crash ]
+crbug.com/796768 fast/pagination/div-y-vertical-lr-ltr.html [ Crash ]
+crbug.com/796768 fast/pagination/div-y-vertical-lr-rtl.html [ Crash ]
+crbug.com/796768 fast/pagination/div-y-vertical-rl-ltr.html [ Crash ]
+crbug.com/796768 fast/pagination/div-y-vertical-rl-rtl.html [ Crash ]
+crbug.com/796768 fast/pagination/short-pages-tall-content.html [ Crash ]
+crbug.com/796768 fast/text-autosizing/constrained-and-overflow-paged-x-ancestor.html [ Crash ]
+crbug.com/796768 paint/invalidation/overflow/paged-with-overflowing-block-rl.html [ Crash ]
+crbug.com/796768 paint/pagination/composited-paginated-outlined-box.html [ Crash ]
+
 Bug(none) css3/blending/mix-blend-mode-simple.html [ Pass Timeout ]
 Bug(none) css3/blending/mix-blend-mode-simple-text.html [ Pass Timeout ]
 
diff --git a/third_party/WebKit/LayoutTests/LeakExpectations b/third_party/WebKit/LayoutTests/LeakExpectations
index df163903..3b13355 100644
--- a/third_party/WebKit/LayoutTests/LeakExpectations
+++ b/third_party/WebKit/LayoutTests/LeakExpectations
@@ -42,6 +42,10 @@
 crbug.com/762353 external/wpt/beacon/headers/header-referrer-no-referrer.html [ Leak Pass ]
 crbug.com/651742 external/wpt/content-security-policy/connect-src/connect-src-beacon-allowed.sub.html [ Leak Pass ]
 crbug.com/780386 external/wpt/html/dom/reflection-grouping.html [ Leak Pass ]
+crbug.com/796944 [ Linux ] external/wpt/fetch/api/request/request-keepalive-quota.html [ Leak Pass ]
+crbug.com/796944 [ Linux ] virtual/mojo-blobs/external/wpt/fetch/api/request/request-keepalive-quota.html [ Leak Pass ]
+crbug.com/796944 [ Linux ] virtual/outofblink-cors/external/wpt/fetch/api/request/request-keepalive-quota.html [ Leak Pass ]
+crbug.com/796944 [ Linux ] synthetic_gestures/synthetic-pinch-zoom-gesture.html [ Leak Pass ]
 
 # -----------------------------------------------------------------
 # Not revert suspected CL as jam@ request, expected to be fixed soon.
diff --git a/third_party/WebKit/LayoutTests/SmokeTests b/third_party/WebKit/LayoutTests/SmokeTests
index d062dd7..005fbb06 100644
--- a/third_party/WebKit/LayoutTests/SmokeTests
+++ b/third_party/WebKit/LayoutTests/SmokeTests
@@ -888,6 +888,7 @@
 storage/indexeddb/transaction-crash-in-tasks.html
 storage/quota/storageinfo-no-callbacks.html
 storage/quota/storagequota-query-usage.html
+synthetic_gestures/synthetic-pinch-zoom-gesture.html
 svg/animations/animate-stroke-crash.html
 svg/animations/animate-update-crash.xhtml
 svg/animations/dynamic-modify-transform-without-baseval.html
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index abbfdde8..8a3e80a5 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -84,9 +84,7 @@
 crbug.com/771643 virtual/spv175/fast/borders/inline-mask-overlay-image-outset.html [ Failure ]
 crbug.com/771643 virtual/spv175/fast/borders/inline-mask-overlay-image.html [ Failure ]
 crbug.com/771643 virtual/spv175/fast/multicol/border-radius-clipped-layer.html [ Failure ]
-crbug.com/771643 virtual/spv175/fast/multicol/layers-split-across-columns.html [ Failure ]
 crbug.com/771643 virtual/spv175/fast/multicol/mixed-opacity-test.html [ Failure ]
-crbug.com/771643 virtual/spv175/fast/multicol/overflow-across-columns.html [ Failure ]
 crbug.com/771643 virtual/spv175/paint/invalidation/forms/select-option-background-color.html [ Failure ]
 crbug.com/771643 virtual/spv175/paint/invalidation/position/position-change-keeping-geometry.html [ Failure ]
 crbug.com/771643 virtual/spv175/paint/invalidation/svg/absolute-sized-content-with-resources.xhtml [ Failure ]
@@ -768,6 +766,9 @@
 
 crbug.com/788110 [ Linux ] inspector-protocol/layout-fonts/unicode-range-combining-chars-fallback.js [ Pass Failure ]
 
+# Sheriff 2017-12-21
+crbug.com/796926 [ Win10 ] inspector-protocol/layout-fonts/fallback-pua-last-resort.js [ Pass Failure ]
+
 # Run these tests with under virtual/scalefactor... only.
 crbug.com/567837 fast/hidpi/static [ Skip ]
 
@@ -910,6 +911,8 @@
 crbug.com/520737 [ Mac ] external/wpt/css/css-writing-modes/writing-mode-vertical-rl-001.xht [ Failure Pass Timeout ]
 crbug.com/520736 [ Win7 ] media/W3C/video/networkState/networkState_during_progress.html [ Failure Pass ]
 
+# gpuBenchmarking.pinchBy is busted on desktops
+crbug.com/787615 [ Mac Win Linux ] synthetic_gestures/synthetic-pinch-zoom-gesture.html [ Failure Pass ]
 
 crbug.com/522648 fast/events/touch/compositor-touch-hit-rects-iframes.html [ Crash Failure Pass ]
 crbug.com/522648 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-iframes.html [ Crash Failure Pass ]
@@ -942,11 +945,9 @@
 crbug.com/526463 fast/events/wheel/mouse-wheel-scroll-latching.html [ Failure ]
 crbug.com/526463 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Failure Timeout ]
 crbug.com/526463 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Failure Timeout ]
-crbug.com/526463 fast/events/wheel/latched-scroll-node-removed.html [ Failure ]
 crbug.com/526463 virtual/mouseevent_fractional/fast/events/wheel/mouse-wheel-scroll-latching.html [ Failure ]
 crbug.com/526463 virtual/mouseevent_fractional/fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Failure Timeout ]
 crbug.com/526463 virtual/mouseevent_fractional/fast/events/wheel/mainthread-touchpad-fling-latching.html [ Failure Timeout ]
-crbug.com/526463 virtual/mouseevent_fractional/fast/events/wheel/latched-scroll-node-removed.html [ Failure ]
 
 crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/scrollstate-basic.html [ Pass Failure ]
 crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/scrollstate-consume-deltas.html [ Pass Failure ]
@@ -966,22 +967,6 @@
 crbug.com/248938 virtual/threaded/animations/stability/animation-iteration-event-destroy-renderer.html [ Pass Timeout ]
 crbug.com/421283 html/marquee/marquee-scrollamount.html [ Pass Failure ]
 
-crbug.com/595206 http/tests/devtools/console/console-link-to-snippet.js [ Skip ]
-crbug.com/595206 inspector-protocol/console/console-let-const-with-api.js [ Skip ]
-crbug.com/595206 inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name.js [ Skip ]
-crbug.com/595206 inspector-protocol/debugger/setScriptSource.js [ Skip ]
-crbug.com/595206 inspector-protocol/runtime/runtime-await-promise.js [ Skip ]
-crbug.com/595206 inspector-protocol/runtime/runtime-callFunctionOn-async.js [ Skip ]
-crbug.com/595206 inspector-protocol/runtime/runtime-clear-of-command-line-api.js [ Skip ]
-crbug.com/595206 inspector-protocol/runtime/runtime-console-line-and-column.js [ Skip ]
-crbug.com/595206 inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks.js [ Skip ]
-crbug.com/595206 inspector-protocol/runtime/runtime-evaluate-async.js [ Skip ]
-crbug.com/595206 inspector-protocol/runtime/runtime-evaluate-in-default-context.js [ Skip ]
-crbug.com/595206 inspector-protocol/runtime/runtime-get-properties-on-proxy.js [ Skip ]
-crbug.com/595206 inspector-protocol/runtime/runtime-property-on-console-proto.js [ Skip ]
-crbug.com/595206 inspector-protocol/sessions/runtime-evaluate.js [ Skip ]
-crbug.com/595206 inspector-protocol/target/target-send-message.js [ Skip ]
-
 # TODO(oshima): Mac Android are currently not supported.
 crbug.com/567837 [ Mac Android ] virtual/scalefactor200withzoom/fast/hidpi/static [ Skip ]
 
@@ -1813,8 +1798,6 @@
 
 crbug.com/637930 http/tests/media/video-buffered.html [ Pass Failure ]
 
-crbug.com/699096 media/controls-drag-timebar-rendering.html [ Failure ]
-
 crbug.com/613659 external/wpt/quirks-mode/percentage-height-calculation.html [ Failure ]
 crbug.com/613661 external/wpt/quirks-mode/table-cell-nowrap-minimum-width-calculation.html [ Failure ]
 crbug.com/613663 external/wpt/quirks-mode/table-cell-width-calculation.html [ Failure ]
@@ -2040,10 +2023,6 @@
 crbug.com/626703 external/wpt/css/css-fonts/font-features-across-space-1.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-features-across-space-3.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-kerning-03.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-fonts/font-variant-01.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-fonts/font-variant-02.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-fonts/font-variant-03.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-fonts/font-variant-04.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-01.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-02.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-03.html [ Failure ]
@@ -2071,7 +2050,6 @@
 crbug.com/626703 external/wpt/css/css-tables/floats/floats-wrap-bfc-006c.xht [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/line-break/line-break-anywhere-001.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/line-break/line-break-anywhere-002.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-ui/text-overflow-006.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-ui/text-overflow-010.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-ui/text-overflow-021.html [ Failure ]
 crbug.com/626703 external/wpt/css/cssom-view/matchMedia.xht [ Timeout ]
@@ -2400,17 +2378,6 @@
 crbug.com/626703 virtual/outofblink-cors/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ]
 crbug.com/626703 virtual/service-worker-script-streaming/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ]
 crbug.com/626703 [ Win10 ] external/wpt/preload/delaying-onload-link-preload-after-discovery.html [ Timeout ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/outline-004.html [ Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-001.html [ Pass Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-002.html [ Pass Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-003.html [ Pass Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-004.html [ Pass Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-007.html [ Pass Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-013.html [ Pass Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-014.html [ Pass Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-015.html [ Pass Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-016.html [ Pass Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-ui/text-overflow-020.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/box-offsets-rel-pos-vlr-005.xht [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/box-offsets-rel-pos-vrl-004.xht [ Failure ]
 
@@ -2432,6 +2399,18 @@
 crbug.com/794136 [ Win ] external/wpt/css/css-multicol/multicol-rule-stacking-001.xht [ Pass Failure ]
 crbug.com/794136 [ Win ] external/wpt/css/css-multicol/multicol-width-001.xht [ Pass Failure ]
 
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/outline-004.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-001.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-002.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-003.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-004.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-007.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-013.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-014.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-015.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-016.html [ Pass Failure ]
+crbug.com/796733 [ Win ] external/wpt/css/css-ui/text-overflow-020.html [ Pass Failure ]
+
 # This test times out on debug builds, see https://crbug.com/755810
 crbug.com/626703 [ Debug ] external/wpt/html/semantics/tabular-data/processing-model-1/span-limits.html [ Skip ]
 
@@ -2451,8 +2430,6 @@
 
 crbug.com/785940 external/wpt/web-animations/timing-model/timelines/document-timelines.html [ Failure Pass ]
 
-crbug.com/781595 external/wpt/html/dom/documents/resource-metadata-management/document-lastModified-01.html [ Failure ]
-
 crbug.com/655458 external/wpt/workers/constructors/SharedWorker/undefined-arguments.html [ Failure ]
 crbug.com/655458 external/wpt/workers/baseurl/alpha/worker.html [ Failure ]
 crbug.com/655458 external/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html [ Failure ]
@@ -2788,10 +2765,6 @@
 crbug.com/709227 external/wpt/websockets/constructor/002.html?wss [ Failure ]
 crbug.com/709227 external/wpt/websockets/constructor/006.html?wss [ Failure ]
 crbug.com/709227 external/wpt/websockets/constructor/009.html?wss [ Failure ]
-crbug.com/709227 external/wpt/websockets/constructor/010.html [ Failure ]
-crbug.com/709227 external/wpt/websockets/constructor/010.html?wss [ Failure ]
-crbug.com/709227 external/wpt/websockets/constructor/011.html [ Failure ]
-crbug.com/709227 external/wpt/websockets/constructor/011.html?wss [ Failure ]
 crbug.com/709227 external/wpt/websockets/constructor/013.html?wss [ Failure ]
 crbug.com/709227 external/wpt/websockets/constructor/014.html?wss [ Failure ]
 crbug.com/709227 external/wpt/websockets/constructor/016.html?wss [ Failure ]
@@ -2829,8 +2802,6 @@
 crbug.com/709227 external/wpt/websockets/opening-handshake/002.html?wss [ Failure ]
 crbug.com/709227 external/wpt/websockets/opening-handshake/003.html?wss [ Failure ]
 crbug.com/709227 external/wpt/websockets/opening-handshake/005.html [ Failure ]
-crbug.com/709227 external/wpt/websockets/unload-a-document/001.html [ Failure ]
-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 ]
 
@@ -3194,8 +3165,11 @@
 
 # known bug: import() inside set{Timeout,Interval}
 
-# import.meta.url is under development.
-crbug.com/773713 external/wpt/html/semantics/scripting-1/the-script-element/module/import-meta [ Skip ]
+# WIP bug: dynamic import() base URL
+crbug.com/796034 external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html [ Failure ]
+crbug.com/796034 external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html [ Failure ]
+crbug.com/796034 external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html [ Failure ]
+crbug.com/796034 external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html [ Failure ]
 
 # Geolocation tests
 crbug.com/745079 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ]
@@ -3734,3 +3708,5 @@
 # Slight Skia rendering change - drawing zero length line with round caps as circle
 crbug.com/796913 virtual/gpu/fast/canvas/canvas-zero-length-lineCap.html [ NeedsManualRebaseline ]
 
+crbug.com/797138 external/wpt/credential-management/federatedcredential-framed-get.sub.https.html [ Crash ]
+crbug.com/797138 external/wpt/credential-management/passwordcredential-framed-get.sub.https.html [ Crash ]
diff --git a/third_party/WebKit/LayoutTests/editing/execCommand/format_block/format_block_with_nth_child_crash.html b/third_party/WebKit/LayoutTests/editing/execCommand/format_block/format_block_with_nth_child_crash.html
new file mode 100644
index 0000000..d1eab545
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/execCommand/format_block/format_block_with_nth_child_crash.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../assert_selection.js"></script>
+<script>
+selection_test(
+  [
+    '<style>li:nth-child(2){display:table-column-group;}</style>',
+    '<div contenteditable>',
+    '^<li></li>',
+    '<canvas></canvas>',
+    '|</div>'
+  ],
+  'FormatBlock pre',
+  [
+    '<style>li:nth-child(2){display:table-column-group;}</style>',
+    '<div contenteditable>',
+    '<pre></pre>',
+    '<li></li>',
+    '<canvas></canvas>',
+    '</div>'
+  ],
+  'Should not crash');
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 1d747bc..b00822f 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -92463,11 +92463,6 @@
      {}
     ]
    ],
-   "XMLHttpRequest/send-sync-response-event-order-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "XMLHttpRequest/setrequestheader-content-type-expected.txt": [
     [
      {}
@@ -227620,7 +227615,7 @@
    "support"
   ],
   "2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html": [
-   "9208f03b80abcf89354a56f913acf5aeb1b0edfe",
+   "80cf63aa87d02a9618094c822b18c83b235222ae",
    "testharness"
   ],
   "2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidoffset.html": [
@@ -229516,7 +229511,7 @@
    "support"
   ],
   "2dcontext/tools/tests2d.yaml": [
-   "99a4d558b9ad07ae18fa71a6276d0b08db0f49e1",
+   "057e6bc1199bb897e84a0d2ed7efefb616ba978c",
    "support"
   ],
   "2dcontext/tools/tests2dtext.yaml": [
@@ -233499,10 +233494,6 @@
    "bf76cb8987608b7bb9f59627032826d21936f450",
    "testharness"
   ],
-  "XMLHttpRequest/send-sync-response-event-order-expected.txt": [
-   "70c00c61fbfff76b3f6042dac646624464ccb3f0",
-   "support"
-  ],
   "XMLHttpRequest/send-sync-response-event-order.htm": [
    "3e2d0154469dcdf3a04376c2c350dab681ff8fe7",
    "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html
index 7687d0b..7ea349e7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html
@@ -21,6 +21,15 @@
 
 var g = ctx.createLinearGradient(0, 0, 100, 0);
 assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, ""); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)'); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'null'); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'undefined'); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, null); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, undefined); });
+
+var g = ctx.createRadialGradient(0, 0, 0, 100, 0, 0);
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, ""); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)'); });
 assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'null'); });
 assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'undefined'); });
 assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, null); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/2dcontext/tools/tests2d.yaml b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/tools/tests2d.yaml
index 63ffe9d..7da08f9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/2dcontext/tools/tests2d.yaml
+++ b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/tools/tests2d.yaml
@@ -2092,6 +2092,15 @@
   code: |
     var g = ctx.createLinearGradient(0, 0, 100, 0);
     @assert throws SYNTAX_ERR g.addColorStop(0, "");
+    @assert throws SYNTAX_ERR g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)');
+    @assert throws SYNTAX_ERR g.addColorStop(0, 'null');
+    @assert throws SYNTAX_ERR g.addColorStop(0, 'undefined');
+    @assert throws SYNTAX_ERR g.addColorStop(0, null);
+    @assert throws SYNTAX_ERR g.addColorStop(0, undefined);
+
+    var g = ctx.createRadialGradient(0, 0, 0, 100, 0, 0);
+    @assert throws SYNTAX_ERR g.addColorStop(0, "");
+    @assert throws SYNTAX_ERR g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)');
     @assert throws SYNTAX_ERR g.addColorStop(0, 'null');
     @assert throws SYNTAX_ERR g.addColorStop(0, 'undefined');
     @assert throws SYNTAX_ERR g.addColorStop(0, null);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-display/font-display-change-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-display/font-display-change-ref.html
new file mode 100644
index 0000000..e06a559
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-display/font-display-change-ref.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Updating font-display value while loading</title>
+<script>
+
+window.onload = () => {
+    const displayValues = [ 'auto', 'block', 'swap', 'fallback', 'optional' ];
+
+    for (let value of displayValues) {
+        let face = new FontFace(value,
+                                'url("/fonts/Ahem.ttf?pipe=trickle(d5)")',
+                                {display: value});
+        document.fonts.add(face);
+        face.load();
+    }
+
+    setTimeout(() => {
+        document.documentElement.classList.remove("reftest-wait");
+    }, 200);
+};
+
+</script>
+<table>
+  <tr>
+    <th>auto</th>
+    <th>block</th>
+    <th>swap</th>
+    <th>fallback</th>
+    <th>optional</th>
+  </tr>
+  <tr>
+    <td>from auto</td>
+    <td style="font-family: auto">a</td>
+    <td style="font-family: block">a</td>
+    <td style="font-family: swap">a</td>
+    <td style="font-family: fallback">a</td>
+    <td style="font-family: optional">a</td>
+  </tr>
+  <tr>
+    <td>from block</td>
+    <td style="font-family: auto">a</td>
+    <td style="font-family: block">a</td>
+    <td style="font-family: swap">a</td>
+    <td style="font-family: fallback">a</td>
+    <td style="font-family: optional">a</td>
+  </tr>
+  <tr>
+    <td>from swap</td>
+    <td style="font-family: auto">a</td>
+    <td style="font-family: block">a</td>
+    <td style="font-family: swap">a</td>
+    <td style="font-family: fallback">a</td>
+    <td style="font-family: optional">a</td>
+  </tr>
+  <tr>
+    <td>from fallback</td>
+    <td style="font-family: auto">a</td>
+    <td style="font-family: block">a</td>
+    <td style="font-family: swap">a</td>
+    <td style="font-family: fallback">a</td>
+    <td style="font-family: optional">a</td>
+  </tr>
+  <tr>
+    <td>from optional</td>
+    <td style="font-family: auto">a</td>
+    <td style="font-family: block">a</td>
+    <td style="font-family: swap">a</td>
+    <td style="font-family: fallback">a</td>
+    <td style="font-family: optional">a</td>
+  </tr>
+</table>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-display/font-display-change.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-display/font-display-change.html
new file mode 100644
index 0000000..64130ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-display/font-display-change.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Updating font-display value while loading</title>
+<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#font-display-desc">
+<link rel="match" href="font-display-change-ref.html">
+<script>
+
+window.onload = () => {
+    const displayValues = [ 'auto', 'block', 'swap', 'fallback', 'optional' ];
+
+    let updateFuncs = [];
+
+    for (let initialValue of displayValues) {
+        for (let targetValue of displayValues) {
+            let face = new FontFace(initialValue + '-' + targetValue,
+                                    'url("/fonts/Ahem.ttf?pipe=trickle(d5)")',
+                                    {display: initialValue});
+            document.fonts.add(face);
+            face.load();
+            updateFuncs.push(() => {
+                face.display = targetValue;
+            });
+        }
+    }
+
+    setTimeout(() => {
+        for (let update of updateFuncs) {
+            update();
+        }
+        document.documentElement.classList.remove("reftest-wait");
+    }, 200);
+};
+
+</script>
+<table>
+  <tr>
+    <th>auto</th>
+    <th>block</th>
+    <th>swap</th>
+    <th>fallback</th>
+    <th>optional</th>
+  </tr>
+  <tr>
+    <td>from auto</td>
+    <td style="font-family: auto-auto">a</td>
+    <td style="font-family: auto-block">a</td>
+    <td style="font-family: auto-swap">a</td>
+    <td style="font-family: auto-fallback">a</td>
+    <td style="font-family: auto-optional">a</td>
+  </tr>
+  <tr>
+    <td>from block</td>
+    <td style="font-family: block-auto">a</td>
+    <td style="font-family: block-block">a</td>
+    <td style="font-family: block-swap">a</td>
+    <td style="font-family: block-fallback">a</td>
+    <td style="font-family: block-optional">a</td>
+  </tr>
+  <tr>
+    <td>from swap</td>
+    <td style="font-family: swap-auto">a</td>
+    <td style="font-family: swap-block">a</td>
+    <td style="font-family: swap-swap">a</td>
+    <td style="font-family: swap-fallback">a</td>
+    <td style="font-family: swap-optional">a</td>
+  </tr>
+  <tr>
+    <td>from fallback</td>
+    <td style="font-family: fallback-auto">a</td>
+    <td style="font-family: fallback-block">a</td>
+    <td style="font-family: fallback-swap">a</td>
+    <td style="font-family: fallback-fallback">a</td>
+    <td style="font-family: fallback-optional">a</td>
+  </tr>
+  <tr>
+    <td>from optional</td>
+    <td style="font-family: optional-auto">a</td>
+    <td style="font-family: optional-block">a</td>
+    <td style="font-family: optional-swap">a</td>
+    <td style="font-family: optional-fallback">a</td>
+    <td style="font-family: optional-optional">a</td>
+  </tr>
+</table>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements-forms.js b/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements-forms.js
index fc45535..051bc208 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements-forms.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements-forms.js
@@ -1,17 +1,3 @@
-var inputModeKeywords = [
-  "verbatim",
-  "latin",
-  "latin-name",
-  "latin-prose",
-  "full-width-latin",
-  "kana",
-  "kana-name",
-  "katakana",
-  "numeric",
-  "tel",
-  "email",
-  "url",
-];
 var formElements = {
   form: {
     acceptCharset: {type: "string", domAttrName: "accept-charset"},
@@ -52,7 +38,6 @@
     formNoValidate: "boolean",
     formTarget: "string",
     height: {type: "unsigned long", customGetter: true},
-    inputMode: {type: "enum", keywords: inputModeKeywords},
     max: "string",
     maxLength: "limited long",
     min: "string",
@@ -118,7 +103,6 @@
     cols: {type: "limited unsigned long with fallback", defaultVal: 20},
     dirName: "string",
     disabled: "boolean",
-    inputMode: {type: "enum", keywords: inputModeKeywords},
     maxLength: "limited long",
     minLength: "limited long",
     name: "string",
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements-misc.js b/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements-misc.js
index 43cdf5f..df415ae 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements-misc.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements-misc.js
@@ -52,7 +52,9 @@
   },
 
   // Global attributes should exist even on unknown elements
-  undefinedelement: {},
+  undefinedelement: {
+    inputMode: {type: "enum", keywords: ["none", "text", "tel", "url", "email", "numeric", "decimal", "search"]},
+  },
 };
 
 mergeElements(miscElements);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
index f758808..3650855 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 5287 tests; 5166 PASS, 121 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 5263 tests; 5144 PASS, 119 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
 PASS Document interface: attribute domain
 PASS Document interface: attribute referrer
@@ -616,6 +616,7 @@
 FAIL HTMLElement interface: attribute onpaste assert_own_property: expected property "onpaste" missing
 PASS HTMLElement interface: attribute contentEditable
 PASS HTMLElement interface: attribute isContentEditable
+PASS HTMLElement interface: attribute inputMode
 PASS HTMLElement must be primary interface of document.createElement("noscript")
 PASS Stringification of document.createElement("noscript")
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "title" with the proper type
@@ -701,6 +702,7 @@
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "onpaste" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "contentEditable" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "isContentEditable" with the proper type
+PASS HTMLElement interface: document.createElement("noscript") must inherit property "inputMode" with the proper type
 PASS HTMLUnknownElement interface: existence and properties of interface object
 PASS HTMLUnknownElement interface object length
 PASS HTMLUnknownElement interface object name
@@ -2082,7 +2084,6 @@
 PASS HTMLInputElement interface: attribute formTarget
 PASS HTMLInputElement interface: attribute height
 PASS HTMLInputElement interface: attribute indeterminate
-FAIL HTMLInputElement interface: attribute inputMode assert_own_property: expected property "inputMode" missing
 PASS HTMLInputElement interface: attribute list
 PASS HTMLInputElement interface: attribute max
 PASS HTMLInputElement interface: attribute maxLength
@@ -2140,7 +2141,6 @@
 PASS HTMLInputElement interface: document.createElement("input") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: document.createElement("input") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: document.createElement("input") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: document.createElement("input") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: document.createElement("input") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: document.createElement("input") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: document.createElement("input") must inherit property "maxLength" with the proper type
@@ -2204,7 +2204,6 @@
 PASS HTMLInputElement interface: createInput("text") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("text") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("text") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("text") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("text") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("text") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("text") must inherit property "maxLength" with the proper type
@@ -2268,7 +2267,6 @@
 PASS HTMLInputElement interface: createInput("hidden") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("hidden") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("hidden") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("hidden") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("hidden") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("hidden") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("hidden") must inherit property "maxLength" with the proper type
@@ -2332,7 +2330,6 @@
 PASS HTMLInputElement interface: createInput("search") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("search") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("search") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("search") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("search") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("search") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("search") must inherit property "maxLength" with the proper type
@@ -2396,7 +2393,6 @@
 PASS HTMLInputElement interface: createInput("tel") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("tel") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("tel") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("tel") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("tel") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("tel") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("tel") must inherit property "maxLength" with the proper type
@@ -2460,7 +2456,6 @@
 PASS HTMLInputElement interface: createInput("url") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("url") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("url") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("url") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("url") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("url") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("url") must inherit property "maxLength" with the proper type
@@ -2524,7 +2519,6 @@
 PASS HTMLInputElement interface: createInput("email") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("email") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("email") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("email") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("email") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("email") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("email") must inherit property "maxLength" with the proper type
@@ -2588,7 +2582,6 @@
 PASS HTMLInputElement interface: createInput("password") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("password") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("password") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("password") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("password") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("password") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("password") must inherit property "maxLength" with the proper type
@@ -2652,7 +2645,6 @@
 PASS HTMLInputElement interface: createInput("date") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("date") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("date") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("date") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("date") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("date") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("date") must inherit property "maxLength" with the proper type
@@ -2716,7 +2708,6 @@
 PASS HTMLInputElement interface: createInput("month") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("month") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("month") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("month") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("month") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("month") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("month") must inherit property "maxLength" with the proper type
@@ -2780,7 +2771,6 @@
 PASS HTMLInputElement interface: createInput("week") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("week") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("week") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("week") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("week") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("week") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("week") must inherit property "maxLength" with the proper type
@@ -2844,7 +2834,6 @@
 PASS HTMLInputElement interface: createInput("time") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("time") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("time") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("time") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("time") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("time") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("time") must inherit property "maxLength" with the proper type
@@ -2908,7 +2897,6 @@
 PASS HTMLInputElement interface: createInput("datetime-local") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("datetime-local") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("datetime-local") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("datetime-local") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("datetime-local") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("datetime-local") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("datetime-local") must inherit property "maxLength" with the proper type
@@ -2972,7 +2960,6 @@
 PASS HTMLInputElement interface: createInput("number") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("number") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("number") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("number") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("number") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("number") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("number") must inherit property "maxLength" with the proper type
@@ -3036,7 +3023,6 @@
 PASS HTMLInputElement interface: createInput("range") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("range") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("range") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("range") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("range") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("range") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("range") must inherit property "maxLength" with the proper type
@@ -3100,7 +3086,6 @@
 PASS HTMLInputElement interface: createInput("color") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("color") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("color") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("color") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("color") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("color") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("color") must inherit property "maxLength" with the proper type
@@ -3164,7 +3149,6 @@
 PASS HTMLInputElement interface: createInput("checkbox") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("checkbox") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("checkbox") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("checkbox") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("checkbox") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("checkbox") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("checkbox") must inherit property "maxLength" with the proper type
@@ -3228,7 +3212,6 @@
 PASS HTMLInputElement interface: createInput("radio") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("radio") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("radio") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("radio") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("radio") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("radio") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("radio") must inherit property "maxLength" with the proper type
@@ -3292,7 +3275,6 @@
 PASS HTMLInputElement interface: createInput("file") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("file") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("file") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("file") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("file") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("file") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("file") must inherit property "maxLength" with the proper type
@@ -3356,7 +3338,6 @@
 PASS HTMLInputElement interface: createInput("submit") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("submit") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("submit") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("submit") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("submit") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("submit") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("submit") must inherit property "maxLength" with the proper type
@@ -3420,7 +3401,6 @@
 PASS HTMLInputElement interface: createInput("image") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("image") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("image") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("image") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("image") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("image") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("image") must inherit property "maxLength" with the proper type
@@ -3484,7 +3464,6 @@
 PASS HTMLInputElement interface: createInput("reset") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("reset") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("reset") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("reset") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("reset") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("reset") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("reset") must inherit property "maxLength" with the proper type
@@ -3548,7 +3527,6 @@
 PASS HTMLInputElement interface: createInput("button") must inherit property "formTarget" with the proper type
 PASS HTMLInputElement interface: createInput("button") must inherit property "height" with the proper type
 PASS HTMLInputElement interface: createInput("button") must inherit property "indeterminate" with the proper type
-PASS HTMLInputElement interface: createInput("button") must inherit property "inputMode" with the proper type
 PASS HTMLInputElement interface: createInput("button") must inherit property "list" with the proper type
 PASS HTMLInputElement interface: createInput("button") must inherit property "max" with the proper type
 PASS HTMLInputElement interface: createInput("button") must inherit property "maxLength" with the proper type
@@ -3765,7 +3743,6 @@
 PASS HTMLTextAreaElement interface: attribute dirName
 PASS HTMLTextAreaElement interface: attribute disabled
 PASS HTMLTextAreaElement interface: attribute form
-FAIL HTMLTextAreaElement interface: attribute inputMode assert_own_property: expected property "inputMode" missing
 PASS HTMLTextAreaElement interface: attribute maxLength
 PASS HTMLTextAreaElement interface: attribute minLength
 PASS HTMLTextAreaElement interface: attribute name
@@ -3800,7 +3777,6 @@
 PASS HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "dirName" with the proper type
 PASS HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "disabled" with the proper type
 PASS HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "form" with the proper type
-PASS HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "inputMode" with the proper type
 PASS HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "maxLength" with the proper type
 PASS HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "minLength" with the proper type
 PASS HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "name" with the proper type
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-forms-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-forms-expected.txt
index f3d7dc5..0f9591e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-forms-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-forms-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 7041 tests; 6731 PASS, 310 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 6725 tests; 6675 PASS, 50 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS form.title: 32 tests
 PASS form.lang: 32 tests
 PASS form.dir: 62 tests
@@ -63,162 +63,6 @@
 PASS input.formNoValidate: 33 tests
 PASS input.formTarget: 32 tests
 PASS input.height: 9 tests
-PASS input.inputMode: 3 tests
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
 PASS input.max: 32 tests
 PASS input.maxLength: 61 tests
 PASS input.min: 32 tests
@@ -339,162 +183,6 @@
 PASS textarea.cols: 59 tests
 PASS textarea.dirName: 32 tests
 PASS textarea.disabled: 33 tests
-PASS textarea.inputMode: 3 tests
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
-NOTRUN test
 PASS textarea.maxLength: 61 tests
 PASS textarea.minLength: 61 tests
 PASS textarea.name: 32 tests
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-misc-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-misc-expected.txt
index 9740c7d5..720e06b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-misc-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/reflection-misc-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 3615 tests; 3601 PASS, 14 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 3727 tests; 3713 PASS, 14 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS html.title: 32 tests
 PASS html.lang: 32 tests
 PASS html.dir: 62 tests
@@ -118,5 +118,6 @@
 PASS undefinedelement.hidden: 33 tests
 PASS undefinedelement.accessKey: 32 tests
 PASS undefinedelement.tabIndex: 24 tests
+PASS undefinedelement.inputMode: 112 tests
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic-expected.txt
deleted file mode 100644
index 2c67ac7..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL setTimeout should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/imports-a.js?label=setTimeout"
-PASS eval should successfully import
-PASS Function should successfully import
-FAIL reflected-inline-event-handlers should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/imports-a.js?label=reflected-inline-event-handlers"
-FAIL inline-event-handlers-UA-code should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/imports-a.js?label=inline-event-handlers-UA-code"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module-expected.txt
deleted file mode 100644
index 2c67ac7..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL setTimeout should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/imports-a.js?label=setTimeout"
-PASS eval should successfully import
-PASS Function should successfully import
-FAIL reflected-inline-event-handlers should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/imports-a.js?label=reflected-inline-event-handlers"
-FAIL inline-event-handlers-UA-code should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/imports-a.js?label=inline-event-handlers-UA-code"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic-expected.txt
deleted file mode 100644
index d2d6c0f..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL setTimeout should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=setTimeout"
-FAIL eval should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=eval"
-FAIL the Function constructor should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=the%20Function%20constructor"
-FAIL reflected inline event handlers should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=reflected%20inline%20event%20handlers"
-FAIL inline event handlers triggered via UA code should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=inline%20event%20handlers%20triggered%20via%20UA%20code"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module-expected.txt
deleted file mode 100644
index 81414c53..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL setTimeout should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=setTimeout"
-PASS eval should successfully import
-PASS the Function constructor should successfully import
-FAIL reflected inline event handlers should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=reflected%20inline%20event%20handlers"
-FAIL inline event handlers triggered via UA code should successfully import promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/dynamic-import/imports-a.js?label=inline%20event%20handlers%20triggered%20via%20UA%20code"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl
index 7d4fe774..e272fb8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl
@@ -816,7 +816,6 @@
   [CEReactions] attribute DOMString formTarget;
   [CEReactions] attribute unsigned long height;
   attribute boolean indeterminate;
-  [CEReactions] attribute DOMString inputMode;
   readonly attribute HTMLElement? list;
   [CEReactions] attribute DOMString max;
   [CEReactions] attribute long maxLength;
@@ -960,7 +959,6 @@
   [CEReactions] attribute DOMString dirName;
   [CEReactions] attribute boolean disabled;
   readonly attribute HTMLFormElement? form;
-  [CEReactions] attribute DOMString inputMode;
   [CEReactions] attribute long maxLength;
   [CEReactions] attribute long minLength;
   [CEReactions] attribute DOMString name;
@@ -1455,6 +1453,7 @@
 interface mixin ElementContentEditable {
   [CEReactions] attribute DOMString contentEditable;
   readonly attribute boolean isContentEditable;
+  [CEReactions] attribute DOMString inputMode;
 };
 
 [Exposed=Window,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
index 5b964ac..6d8971f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
+++ b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
@@ -148,7 +148,6 @@
 SET TIMEOUT: css/selectors/selector-placeholder-shown-type-change-003.html
 SET TIMEOUT: css/selectors/selector-read-write-type-change-002.html
 SET TIMEOUT: css/selectors/selector-required-type-change-002.html
-SET TIMEOUT: css/css-fonts/font-display/font-display.html
 SET TIMEOUT: encrypted-media/polyfill/chrome-polyfill.js
 SET TIMEOUT: encrypted-media/polyfill/clearkey-polyfill.js
 SET TIMEOUT: encrypted-media/scripts/playback-temporary-events.js
@@ -304,6 +303,9 @@
 GENERATE_TESTS: shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html
 
 # Intentional use of setTimeout
+SET TIMEOUT: css/css-fonts/font-display/font-display.html
+SET TIMEOUT: css/css-fonts/font-display/font-display-change.html
+SET TIMEOUT: css/css-fonts/font-display/font-display-change-ref.html
 SET TIMEOUT: html/browsers/windows/auxiliary-browsing-contexts/resources/close-opener.html
 SET TIMEOUT: html/dom/documents/dom-tree-accessors/Document.currentScript.html
 SET TIMEOUT: html/webappapis/timers/*
@@ -970,4 +972,4 @@
 WEB-PLATFORM.TEST: webdriver/tests/cookies/add_cookie.py
 WEB-PLATFORM.TEST: webdriver/tests/cookies/get_named_cookie.py
 WEB-PLATFORM.TEST: webrtc/RTCPeerConnection-getIdentityAssertion.html
-WEB-PLATFORM.TEST: webrtc/identity-helper.js
\ No newline at end of file
+WEB-PLATFORM.TEST: webrtc/identity-helper.js
diff --git a/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null-expected.txt
index 1f6081f9..8f59ea3 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null-expected.txt
@@ -276,7 +276,6 @@
 
 TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTextAreaElement.defaultValue]
 TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTextAreaElement.dirName]
-TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTextAreaElement.inputMode]
 TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTextAreaElement.name]
 TEST SUCCEEDED: The value was the string 'null'. [tested HTMLTextAreaElement.placeholder]
 TEST SUCCEEDED: The value was the empty string. [tested HTMLTextAreaElement.value]
diff --git a/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null.html b/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null.html
index a5d26ce..f8aa398e 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/element-attribute-js-null.html
@@ -625,7 +625,6 @@
                     attributes: [
                         {name: 'defaultValue', expectedNull: 'null'},
                         {name: 'dirName', expectedNull: 'null'},
-                        {name: 'inputMode', expectedNull: 'null'},
                         {name: 'name', expectedNull: 'null'},
                         {name: 'placeholder', expectedNull: 'null'},
                         {name: 'value', expectedNull: ''},
diff --git a/third_party/WebKit/LayoutTests/fast/forms/input-inputmode-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/input-inputmode-expected.txt
deleted file mode 100644
index 466b53f..0000000
--- a/third_party/WebKit/LayoutTests/fast/forms/input-inputmode-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-Tests the behavior of .inputMode of HTMLInputElement.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS input.inputMode is ""
-PASS input.inputMode is "0"
-PASS input.inputMode is "abc"
-PASS input.getAttribute("inputmode") is "foo"
-PASS input.getAttribute("inputmode") is ""
-Setting null to inputMode:
-PASS input.inputMode is "null"
-PASS input.getAttribute("inputmode") is "null"
-PASS input.inputMode is "null"
-Setting undefined to inputMode:
-PASS input.inputMode is "undefined"
-PASS input.getAttribute("inputmode") is "undefined"
-PASS input.inputMode is "undefined"
-Setting non-string to inputMode:
-PASS input.inputMode is "256"
-PASS input.getAttribute("inputmode") is "256"
-PASS input.inputMode is "256"
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/forms/input-inputmode.html b/third_party/WebKit/LayoutTests/fast/forms/input-inputmode.html
deleted file mode 100644
index 4ffb5658..0000000
--- a/third_party/WebKit/LayoutTests/fast/forms/input-inputmode.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
-<body>
-<script>
-description('Tests the behavior of .inputMode of HTMLInputElement.');
-
-var input = document.createElement('input');
-
-// .inputMode just reflect the corresponding attributes.
-input.type = 'text';
-shouldBe('input.inputMode', '""');
-input.setAttribute('inputmode', '0');
-shouldBe('input.inputMode', '"0"');
-input.setAttribute('inputmode', 'abc');
-shouldBe('input.inputMode', '"abc"');
-
-input.inputMode = 'foo';
-shouldBe('input.getAttribute("inputmode")', '"foo"');
-
-input.inputMode = '';
-shouldBe('input.getAttribute("inputmode")', '""');
-
-// Null.
-debug('Setting null to inputMode:');
-input.inputMode = null;
-shouldBe('input.inputMode', '"null"');
-shouldBe('input.getAttribute("inputmode")', '"null"');
-input.setAttribute('inputmode', null);
-shouldBe('input.inputMode', '"null"');
-
-// Undefined.
-debug('Setting undefined to inputMode:');
-input.inputMode = undefined;
-shouldBe('input.inputMode', '"undefined"');
-shouldBe('input.getAttribute("inputmode")', '"undefined"');
-input.setAttribute('inputmode', undefined);
-shouldBe('input.inputMode', '"undefined"');
-
-// Non-string.
-debug('Setting non-string to inputMode:');
-input.inputMode = 256;
-shouldBe('input.inputMode', '"256"');
-shouldBe('input.getAttribute("inputmode")', '"256"');
-input.setAttribute('inputmode', 256);
-shouldBe('input.inputMode', '"256"');
-
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-inputmode-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-inputmode-expected.txt
deleted file mode 100644
index fbb5dc7..0000000
--- a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-inputmode-expected.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-Tests the behavior of .inputMode of HTMLTextAreaElement.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS textarea.inputMode is ""
-PASS textarea.inputMode is "0"
-PASS textarea.inputMode is "abc"
-PASS textarea.getAttribute("inputmode") is "foo"
-PASS textarea.getAttribute("inputmode") is ""
-Setting null to inputMode:
-PASS textarea.inputMode is "null"
-PASS textarea.getAttribute("inputmode") is "null"
-PASS textarea.inputMode is "null"
-Setting undefined to inputMode:
-PASS textarea.inputMode is "undefined"
-PASS textarea.getAttribute("inputmode") is "undefined"
-PASS textarea.inputMode is "undefined"
-Setting non-string to inputMode:
-PASS textarea.inputMode is "256"
-PASS textarea.getAttribute("inputmode") is "256"
-PASS textarea.inputMode is "256"
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-inputmode.html b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-inputmode.html
deleted file mode 100644
index ee8a96583..0000000
--- a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-inputmode.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<script src="../../../resources/js-test.js"></script>
-</head>
-<body>
-<script>
-description('Tests the behavior of .inputMode of HTMLTextAreaElement.');
-
-var textarea = document.createElement('textarea');
-
-// .inputMode just reflect the corresponding attributes.
-textarea.type = 'text';
-shouldBe('textarea.inputMode', '""');
-textarea.setAttribute('inputmode', '0');
-shouldBe('textarea.inputMode', '"0"');
-textarea.setAttribute('inputmode', 'abc');
-shouldBe('textarea.inputMode', '"abc"');
-
-textarea.inputMode = 'foo';
-shouldBe('textarea.getAttribute("inputmode")', '"foo"');
-
-textarea.inputMode = '';
-shouldBe('textarea.getAttribute("inputmode")', '""');
-
-// Null.
-debug('Setting null to inputMode:');
-textarea.inputMode = null;
-shouldBe('textarea.inputMode', '"null"');
-shouldBe('textarea.getAttribute("inputmode")', '"null"');
-textarea.setAttribute('inputmode', null);
-shouldBe('textarea.inputMode', '"null"');
-
-// Undefined.
-debug('Setting undefined to inputMode:');
-textarea.inputMode = undefined;
-shouldBe('textarea.inputMode', '"undefined"');
-shouldBe('textarea.getAttribute("inputmode")', '"undefined"');
-textarea.setAttribute('inputmode', undefined);
-shouldBe('textarea.inputMode', '"undefined"');
-
-// Non-string.
-debug('Setting non-string to inputMode:');
-textarea.inputMode = 256;
-shouldBe('textarea.inputMode', '"256"');
-shouldBe('textarea.getAttribute("inputmode")', '"256"');
-textarea.setAttribute('inputmode', 256);
-shouldBe('textarea.inputMode', '"256"');
-
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/column-rules-fixed-height-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/column-rules-fixed-height-expected.txt
new file mode 100644
index 0000000..346475f5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/column-rules-fixed-height-expected.txt
@@ -0,0 +1,58 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutMultiColumnSet (anonymous)",
+          "rect": [8, 52, 525, 315],
+          "reason": "style change"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [110, 52, 106, 315],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [110, 52, 106, 315],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [8, 0, 103, 367],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [8, 0, 103, 367],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [215, 52, 103, 315],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [215, 52, 103, 315],
+          "reason": "chunk uncacheable"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutMultiColumnSet (anonymous)",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-abspos-in-relpos-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-abspos-in-relpos-expected.txt
new file mode 100644
index 0000000..8047484
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-abspos-in-relpos-expected.txt
@@ -0,0 +1,36 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (positioned) DIV id='target'",
+          "rect": [508, 28, 80, 20],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (positioned) DIV id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-block-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-block-expected.txt
new file mode 100644
index 0000000..8ee40c3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-block-expected.txt
@@ -0,0 +1,36 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [488, 8, 80, 20],
+          "reason": "chunk uncacheable"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='target'",
+      "reason": "style change"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "style change"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-overflowing-block-rl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-overflowing-block-rl-expected.txt
new file mode 100644
index 0000000..8d1148b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-overflowing-block-rl-expected.txt
@@ -0,0 +1,57 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [8, 8, 792, 167],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [8, 8, 792, 167],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [0, 341, 508, 167],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [0, 341, 508, 167],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [8, 174, 500, 168],
+          "reason": "chunk uncacheable"
+        },
+        {
+          "object": "LayoutMultiColumnFlowThread (anonymous)",
+          "rect": [8, 174, 500, 168],
+          "reason": "chunk uncacheable"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow DIV id='elm'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='elm'",
+      "reason": "style change"
+    },
+    {
+      "object": "LayoutBlockFlow DIV id='elm'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-relpos-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-relpos-expected.txt
new file mode 100644
index 0000000..42721fa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/multicol/multicol-with-relpos-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (relative positioned) DIV id='target'",
+          "rect": [508, 28, 150, 20],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutBlockFlow (relative positioned) DIV id='target'",
+      "reason": "style change"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-limited-run.js b/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-limited-run.js
index 6a8010a..2b72d6d8 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-limited-run.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-limited-run.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-(async function(testRunner) {
+(async function() {
   TestRunner.addResult('Tests that audits panel works when only performance category is selected.\n');
 
   await TestRunner.loadModule('audits2_test_runner');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-prevent-run.js b/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-prevent-run.js
index 27b1c87..1f84837 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-prevent-run.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-prevent-run.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-(async function(testRunner) {
+(async function() {
   // about:blank never fires a load event so just wait until we see the URL change
   function navigateToAboutBlankAndWait() {
     var listenerPromise = new Promise(resolve => {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-successful-run.js b/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-successful-run.js
index ba76594..f3290c1 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-successful-run.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/audits2/audits2-successful-run.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-(async function(testRunner) {
+(async function() {
   TestRunner.addResult('Tests that audits panel works.\n');
 
   await TestRunner.loadModule('audits2_test_runner');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/bindings-main-frame-navigated-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/bindings-main-frame-navigated-expected.txt
index 6d63e03..177bc9b46 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/bindings-main-frame-navigated-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/bindings-main-frame-navigated-expected.txt
@@ -33,7 +33,6 @@
 [-] http://127.0.0.1:8000/devtools/bindings/resources/sourcemap-typescript.ts
 [-] http://127.0.0.1:8000/devtools/resources/inspected-page.html
 [-] _test_attachFrame.js
-Workspace: 2 uiSourceCodes.
-[+] debugger:///VM[XXX] empty-page.html
+Workspace: 1 uiSourceCodes.
 [+] http://127.0.0.1:8000/devtools/bindings/resources/empty-page.html
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/resources/empty-page.html b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/resources/empty-page.html
index cb29953..1be32cad 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/resources/empty-page.html
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/bindings/resources/empty-page.html
@@ -1,15 +1,3 @@
 <html>
-<script>
-window.onload = function()
-{
-    function notifyFrontend()
-    {
-        TestRunner.pageLoaded();
-    }
-    testRunner.dumpAsText();
-    testRunner.waitUntilDone();
-    testRunner.evaluateInWebInspector(42, "(" + notifyFrontend + ")()");
-}
-</script>
 <p>empty page</p>
 </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-time-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-time-expected.txt
index bf580720..410eec6 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-time-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-time-expected.txt
@@ -1,7 +1,7 @@
 console.time / console.timeEnd tests.
 
-console-time.js:16 default: <time>
-console-time.js:18 42: <time>
-console-time.js:20 239: <time>
-console-time.js:22 [object Object]: <time>
+console-time.js:14 default: <time>
+console-time.js:16 42: <time>
+console-time.js:18 239: <time>
+console-time.js:20 [object Object]: <time>
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-time.js b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-time.js
index bfc47cc1..8132343 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-time.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/console-time.js
@@ -8,8 +8,6 @@
   await TestRunner.loadModule('console_test_runner');
   await TestRunner.showPanel('console');
   await TestRunner.evaluateInPagePromise(`
-    testRunner.setDumpConsoleMessages(false);
-
     function testFunction()
     {
       console.time();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/device-orientation-success-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/device-orientation-success-expected.txt
index 556c46d..07cf3e3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/device-orientation-success-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/device-orientation-success-expected.txt
@@ -6,7 +6,7 @@
 Running: setOverride
 
 Running: clearOverride
-device-orientation-success.js:23 alpha: 1.1 beta: 2.2 gamma: 3.3
-device-orientation-success.js:23 alpha: 20 beta: 30 gamma: 40
-device-orientation-success.js:23 alpha: 1.1 beta: 2.2 gamma: 3.3
+device-orientation-success.js:22 alpha: 1.1 beta: 2.2 gamma: 3.3
+device-orientation-success.js:22 alpha: 20 beta: 30 gamma: 40
+device-orientation-success.js:22 alpha: 1.1 beta: 2.2 gamma: 3.3
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/device-orientation-success.js b/third_party/WebKit/LayoutTests/http/tests/devtools/device-orientation-success.js
index 0a9d3798..a183eba2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/device-orientation-success.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/device-orientation-success.js
@@ -13,8 +13,7 @@
 
       function setup()
       {
-          if (window.testRunner)
-              testRunner.setMockDeviceOrientation(true, mockAlpha, true, mockBeta, true, mockGamma, absolute);
+          testRunner.setMockDeviceOrientation(true, mockAlpha, true, mockBeta, true, mockGamma, absolute);
           window.addEventListener("deviceorientation", handler, false);
       }
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/elements/styles-3/styles-change-node-while-editing-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/styles-3/styles-change-node-while-editing-expected.txt
index 02eec8f6..6a79117 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/elements/styles-3/styles-change-node-while-editing-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/elements/styles-3/styles-change-node-while-editing-expected.txt
@@ -1,6 +1,5 @@
 Tests that changing selected node while editing style does update styles sidebar.
 
-Text
 [expanded] 
 element.style { ()
     color: red;
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/resources/without-indexed-db.html b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/resources/without-indexed-db.html
index dbcfd91..4617c6e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/resources/without-indexed-db.html
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/resources/without-indexed-db.html
@@ -1,15 +1,3 @@
 <html>
-<script>
-window.onload = function()
-{
-    function notifyFrontend()
-    {
-        TestRunner.pageLoaded();
-    }
-    testRunner.dumpAsText();
-    testRunner.waitUntilDone();
-    testRunner.evaluateInWebInspector(0, "(" + notifyFrontend + ")()");
-}
-</script>
 <p>Page without Indexed DB.</p>
 </html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/transaction-promise-console.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/transaction-promise-console.js
index 1382978..339259f 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/transaction-promise-console.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/transaction-promise-console.js
@@ -10,9 +10,6 @@
     // Note: every test that uses a storage API must manually clean-up state from previous tests.
   await ApplicationTestRunner.resetState();
 
-  testRunner.waitUntilDone();
-  testRunner.showWebInspector();
-
   var dbname = location.href;
   indexedDB.deleteDatabase(dbname).onsuccess = function() {
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/input-event-warning.js b/third_party/WebKit/LayoutTests/http/tests/devtools/input-event-warning.js
index 0676255..b18368048 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/input-event-warning.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/input-event-warning.js
@@ -47,8 +47,6 @@
           }
           var deadline = performance.now() + 100;
           while (performance.now() < deadline) {};
-          if (window.testRunner)
-              window.testRunner.setDumpConsoleMessages(false);
           for (var event of events)
               target.dispatchEvent(event);
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain-expected.txt
new file mode 100644
index 0000000..3478cf5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain-expected.txt
@@ -0,0 +1,7 @@
+Test that computing the initiator graph works for service worker request.
+
+
+http://127.0.0.1:8000/devtools/service-workers/resources/network-fetch-worker.js
+Initiators http://127.0.0.1:8000/devtools/service-workers/resources/network-fetch-worker.js
+Initiated http://127.0.0.1:8000/devtools/service-workers/resources/network-fetch-worker.js
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain.js
new file mode 100644
index 0000000..125b58b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-initiator-chain.js
@@ -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.
+
+(async function() {
+  TestRunner.addResult(`Test that computing the initiator graph works for service worker request.\n`);
+  await TestRunner.loadModule('network_test_runner');
+  await TestRunner.loadModule('application_test_runner');
+  await TestRunner.showPanel('network');
+
+  NetworkTestRunner.recordNetwork();
+  let scope = 'http://127.0.0.1:8000/devtools/service-workers/resources/';
+  await ApplicationTestRunner.registerServiceWorker('../service-workers/resources/network-fetch-worker.js', scope);
+
+  var requests = NetworkTestRunner.networkRequests();
+  requests.forEach((request) => {
+    TestRunner.addResult('\n' + request.url());
+    var graph = NetworkLog.networkLog.initiatorGraphForRequest(request);
+    TestRunner.addResult('Initiators ' + Array.from(graph.initiators).map(request => request._url));
+    TestRunner.addResult('Initiated ' + Array.from(graph.initiated).map(request => request._url));
+  });
+
+  TestRunner.completeTest();
+})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/ping.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/ping.js
index e8997dc..316b835 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/ping.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/ping.js
@@ -8,8 +8,7 @@
   await TestRunner.showPanel('network');
   await TestRunner.loadHTML(`<a id="pingLink" href="#" ping="ping.js">ping</a>`);
   await TestRunner.evaluateInPagePromise(`
-      if (window.testRunner)
-          testRunner.overridePreference("WebKitHyperlinkAuditingEnabled", 1);
+      testRunner.overridePreference("WebKitHyperlinkAuditingEnabled", 1);
       function navigateLink()
       {
           var evt = document.createEvent("MouseEvents");
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/overrides/files-save-without-hash.js b/third_party/WebKit/LayoutTests/http/tests/devtools/overrides/files-save-without-hash.js
index bf437276..e017f474 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/overrides/files-save-without-hash.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/overrides/files-save-without-hash.js
@@ -33,8 +33,8 @@
         Workspace.Workspace.Events.UISourceCodeAdded, Workspace.workspace,
         uiSourceCode => uiSourceCode.url().startsWith('http'));
     if (!networkUISourceCode) {
-      testRunner.addResult('ERROR: No uiSourceCode');
-      testRunner.completeTest();
+      TestRunner.addResult('ERROR: No uiSourceCode');
+      TestRunner.completeTest();
       return;
     }
     TestRunner.addResult('Found network UISourceCode: ' + networkUISourceCode.url());
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/ensure-filesystem-create-files-doesnt-emit-change-first.js b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/ensure-filesystem-create-files-doesnt-emit-change-first.js
index 750f035..a2054a0d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/ensure-filesystem-create-files-doesnt-emit-change-first.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/persistence/ensure-filesystem-create-files-doesnt-emit-change-first.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-(async function(testRunner) {
+(async function() {
   TestRunner.addResult(`Verify that fs.createFile is creating UISourceCode atomically with content`);
   await TestRunner.loadModule('bindings_test_runner');
 
@@ -19,4 +19,4 @@
 
   var fsWorkspaceBinding = Workspace.workspace.project(folderLocation);
   fsWorkspaceBinding.createFile('', 'test.txt', 'file content');
-})(window.testRunner)
\ No newline at end of file
+})()
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resources/screen-orientation-resource.html b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/screen-orientation-resource.html
index 5db6988..b34b4a5c 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/resources/screen-orientation-resource.html
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resources/screen-orientation-resource.html
@@ -1,9 +1,6 @@
 <html>
 <script>
-if (window.testRunner) {
-    window.testRunner.disableMockScreenOrientation();
-    window.testRunner.setDumpConsoleMessages(false);
-}
+window.testRunner.disableMockScreenOrientation();
 
 var windowOrientationChangeEvent = false;
 var screenOrientationChangeEvent = false;
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/document-write-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/document-write-expected.txt
index ba4d0e0..612209d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/document-write-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/document-write-expected.txt
@@ -5,7 +5,7 @@
 VM:1 Line 1 in document.write
 VM:4 Line 4 in document.write
 document-write.html:7 Line 7
-document-write.html:25 Line 25
+document-write.html:22 Line 22
 VM:1 script element
 VM:1 document.write from onload
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/console-log-before-frame-navigation.html b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/console-log-before-frame-navigation.html
index 53b4d730..7c332f0e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/console-log-before-frame-navigation.html
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/console-log-before-frame-navigation.html
@@ -5,12 +5,6 @@
 window.addEventListener("message", receiveMessage, false);
 
 function receiveMessage(event) {
-    if (event.data != "frameReloaded") {
-        testFailed("Unexpected message: " + event.data);
-        if (window.testRunner)
-            testRunner.notifyDone();
-        return;
-    }
     testRunner.inspectSecondaryWindow();
 }
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/document-write.html b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/document-write.html
index 4773aab..5a9de10 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/document-write.html
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/document-write.html
@@ -10,9 +10,6 @@
 
 function onload()
 {
-    if (window.testRunner)
-        testRunner.dumpAsText();
-
     var script = document.createElement("script");
     script.textContent = "console.log(\"script element\")";
     document.head.appendChild(script);
@@ -22,7 +19,7 @@
 
 </script>
 </head>
-<body onload="console.log('Line 25'); onload();">
+<body onload="console.log('Line 22'); onload();">
 <p>
 Tests that console reports zero line number for scripts generated with document.write. See https://bugs.webkit.org/show_bug.cgi?id=71099.
 </p>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/shadow-dom-rules.html b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/shadow-dom-rules.html
index 12b7f99..7d51298 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/shadow-dom-rules.html
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/resources/shadow-dom-rules.html
@@ -4,8 +4,6 @@
 
 function createShadowRoot()
 {
-    if (window.testRunner)
-        testRunner.waitUntilDone();
     var template = document.querySelector('#tmpl');
     var root = document.querySelector('#host').createShadowRoot();
     root.appendChild(template.content.cloneNode(true));
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/console-timeline.js b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/console-timeline.js
index da6130e..90925f5 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/console-timeline.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/console-timeline.js
@@ -8,8 +8,6 @@
   await TestRunner.loadModule('performance_test_runner');
   await TestRunner.showPanel('timeline');
   await TestRunner.evaluateInPagePromise(`
-      testRunner.setDumpConsoleMessages(false);
-
       function startStopTimeline()
       {
           console.timeStamp("timestamp 0");
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-script-module-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-script-module-expected.txt
index d8b2e556..9ac0a31 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-script-module-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-script-module-expected.txt
@@ -3,13 +3,13 @@
 v8.compileModule Properties:
 {
     data : {
-        fileName : .../devtools/tracing/
+        fileName : .../devtools/resources/inspected-page.html
     }
     endTime : <number>
     startTime : <number>
     type : "v8.compileModule"
 }
-Text details for v8.compileModule: (index)
+Text details for v8.compileModule: inspected-page.html
 v8.evaluateModule Properties:
 {
     data : {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-time/timeline-time.js b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-time/timeline-time.js
index 76a8c7b..962d59f 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-time/timeline-time.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-time/timeline-time.js
@@ -7,8 +7,6 @@
   await TestRunner.loadModule('performance_test_runner');
   await TestRunner.showPanel('timeline');
   await TestRunner.evaluateInPagePromise(`
-      testRunner.setDumpConsoleMessages(false);
-
       function simpleConsoleTime()
       {
           console.time("a");
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/console/console-let-const-with-api-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/console/console-let-const-with-api-expected.txt
index 4ad4ce64..834265c 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/console/console-let-const-with-api-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/console/console-let-const-with-api-expected.txt
@@ -3,7 +3,7 @@
 second 'let a = 1;' result: wasThrown = true
 exception message: Uncaught SyntaxError: Identifier 'a' has already been declared
     at <anonymous>:1:1
-{"result":{"type":"number","value":42}}
+{"result":{"type":"number","value":42,"description":"42"}}
 function $(selector, [startNode]) { [Command Line API] }
 function $$(selector, [startNode]) { [Command Line API] }
 function $x(xpath, [startNode]) { [Command Line API] }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name-expected.txt
index 98c447c..38b54a7 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/debugger-scope-skip-variables-with-empty-name-expected.txt
@@ -7,6 +7,7 @@
             isOwn : true
             name : a
             value : {
+                description : 2
                 type : number
                 value : 2
             }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-disconnect-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-disconnect-expected.txt
new file mode 100644
index 0000000..d9c58d1c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-disconnect-expected.txt
@@ -0,0 +1,2 @@
+Tests disconnect inside pause on setInnerHTML breakpoint.
+
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-disconnect.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-disconnect.js
new file mode 100644
index 0000000..0f96c40d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/domdebugger-setInnerHTML-disconnect.js
@@ -0,0 +1,18 @@
+(async function(testRunner) {
+  var {page, session, dp} = await testRunner.startHTML(`
+    <div id='divUnderTest'></div>
+  `, `Tests disconnect inside pause on setInnerHTML breakpoint.`);
+
+  dp.Debugger.enable();
+  dp.DOM.enable();
+  dp.DOMDebugger.enable();
+  dp.DOMDebugger.setInstrumentationBreakpoint({eventName: 'Element.setInnerHTML'});
+  dp.Runtime.evaluate({expression: `
+    (function modifyHTML() {
+      document.getElementById('divUnderTest').innerHTML = 'innerHTML';
+    })()
+  ` });
+  var messageObject = await dp.Debugger.oncePaused();
+  await session.disconnect();
+  testRunner.completeTest();
+})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource-expected.txt
index 16281b0..8381592c 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource-expected.txt
@@ -1,7 +1,7 @@
 Tests setScriptSource functionality.
-Function evaluate: {"type":"number","value":6}
+Function evaluate: {"type":"number","value":6,"description":"6"}
 PASS, result value: 6
-Function evaluate: {"type":"number","value":8}
+Function evaluate: {"type":"number","value":8,"description":"8"}
 PASS, result value: 8
 Has error reported: PASS
 Reported error is a compile error: PASS
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-await-promise-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-await-promise-expected.txt
index f2d99da..e31ec1b6 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-await-promise-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-await-promise-expected.txt
@@ -3,6 +3,7 @@
 Running test: testResolvedPromise
 {
     result : {
+        description : 239
         type : number
         value : 239
     }
@@ -21,22 +22,6 @@
         }
         exceptionId : 0
         lineNumber : 0
-        stackTrace : {
-            callFrames : [
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 8
-                        functionName : 
-                        lineNumber : 0
-                        scriptId : <number>
-                        url : 
-                    }
-                ]
-                description : Promise.reject
-            }
-        }
         text : Uncaught (in promise)
     }
     result : {
@@ -52,38 +37,17 @@
     exceptionDetails : {
         columnNumber : 0
         exception : {
+            description : 239
             objectId : <number>
             type : number
             value : 239
         }
         exceptionId : 0
         lineNumber : 0
-        stackTrace : {
-            callFrames : [
-            ]
-            parent : {
-                callFrames : [
-                    [0] : {
-                        columnNumber : 6
-                        functionName : rejectPromise
-                        lineNumber : 14
-                        scriptId : <number>
-                        url : 
-                    }
-                    [1] : {
-                        columnNumber : 0
-                        functionName : 
-                        lineNumber : 0
-                        scriptId : <number>
-                        url : 
-                    }
-                ]
-                description : Promise.reject
-            }
-        }
         text : Uncaught (in promise)
     }
     result : {
+        description : 239
         type : number
         value : 239
     }
@@ -92,6 +56,7 @@
 Running test: testPendingPromise
 {
     result : {
+        description : 239
         type : number
         value : 239
     }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-callFunctionOn-async-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-callFunctionOn-async-expected.txt
index d45b87d..19b6e61 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-callFunctionOn-async-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-callFunctionOn-async-expected.txt
@@ -61,6 +61,7 @@
 Running test: testFunctionReturnNotPromise
 {
     result : {
+        description : 239
         type : number
         value : 239
     }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-clear-of-command-line-api-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-clear-of-command-line-api-expected.txt
index 25529c6..db9f0d6 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-clear-of-command-line-api-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-clear-of-command-line-api-expected.txt
@@ -2,12 +2,14 @@
 
 {
     result : {
+        description : 15
         type : number
         value : 15
     }
 }
 {
     result : {
+        description : 0
         type : number
         value : 0
     }
@@ -15,18 +17,21 @@
 setPropertyForMethod()
 {
     result : {
+        description : 14
         type : number
         value : 14
     }
 }
 {
     result : {
+        description : 0
         type : number
         value : 0
     }
 }
 {
     result : {
+        description : 42
         type : number
         value : 42
     }
@@ -34,18 +39,21 @@
 defineValuePropertyForMethod()
 {
     result : {
+        description : 14
         type : number
         value : 14
     }
 }
 {
     result : {
+        description : 0
         type : number
         value : 0
     }
 }
 {
     result : {
+        description : 42
         type : number
         value : 42
     }
@@ -53,18 +61,21 @@
 definePropertiesForMethod()
 {
     result : {
+        description : 14
         type : number
         value : 14
     }
 }
 {
     result : {
+        description : 0
         type : number
         value : 0
     }
 }
 {
     result : {
+        description : 42
         type : number
         value : 42
     }
@@ -72,18 +83,21 @@
 defineAccessorPropertyForMethod()
 {
     result : {
+        description : 14
         type : number
         value : 14
     }
 }
 {
     result : {
+        description : 0
         type : number
         value : 0
     }
 }
 {
     result : {
+        description : 42
         type : number
         value : 42
     }
@@ -91,18 +105,21 @@
 redefineGetOwnPropertyDescriptors()
 {
     result : {
+        description : 14
         type : number
         value : 14
     }
 }
 {
     result : {
+        description : 0
         type : number
         value : 0
     }
 }
 {
     result : {
+        description : 42
         type : number
         value : 42
     }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-line-and-column-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-line-and-column-expected.txt
index 92bd363a7..e298f8c1c 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-line-and-column-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-line-and-column-expected.txt
@@ -4,6 +4,7 @@
     params : {
         args : [
             [0] : {
+                description : 239
                 type : number
                 value : 239
             }
@@ -29,6 +30,7 @@
     params : {
         args : [
             [0] : {
+                description : 239
                 type : number
                 value : 239
             }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks-expected.txt
index 343c1e0f..5a234ec7 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-console-log-doesnt-run-microtasks-expected.txt
@@ -1,13 +1,16 @@
 Check that console.log doesn't run microtasks.
 {
+    description : 42
     type : number
     value : 42
 }
 {
+    description : 43
     type : number
     value : 43
 }
 {
+    description : 239
     type : number
     value : 239
 }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-evaluate-async-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-evaluate-async-expected.txt
index 674f3e7..8153c1e 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-evaluate-async-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-evaluate-async-expected.txt
@@ -3,6 +3,7 @@
 Running test: testResolvedPromise
 {
     result : {
+        description : 239
         type : number
         value : 239
     }
@@ -13,6 +14,7 @@
     exceptionDetails : {
         columnNumber : 0
         exception : {
+            description : 239
             objectId : <number>
             type : number
             value : 239
@@ -23,6 +25,7 @@
         text : Uncaught (in promise)
     }
     result : {
+        description : 239
         type : number
         value : 239
     }
@@ -60,6 +63,7 @@
     exceptionDetails : {
         columnNumber : 0
         exception : {
+            description : 239
             objectId : <number>
             type : number
             value : 239
@@ -70,6 +74,7 @@
         text : Uncaught
     }
     result : {
+        description : 239
         type : number
         value : 239
     }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-evaluate-in-default-context-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-evaluate-in-default-context-expected.txt
index adbdc0e..f34c8bb 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-evaluate-in-default-context-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-evaluate-in-default-context-expected.txt
@@ -3,6 +3,7 @@
     id : <number>
     result : {
         result : {
+            description : 42
             type : number
             value : 42
         }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-get-properties-on-proxy-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-get-properties-on-proxy-expected.txt
index 05fdc13..151ea38 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-get-properties-on-proxy-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-get-properties-on-proxy-expected.txt
@@ -1,6 +1,7 @@
 Check that while Runtime.getProperties call on proxy object no user defined trap will be executed.
 {
     result : {
+        description : 0
         type : number
         value : 0
     }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-property-on-console-proto-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-property-on-console-proto-expected.txt
index b69fcbc7..ca6bbf9 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-property-on-console-proto-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-property-on-console-proto-expected.txt
@@ -3,6 +3,7 @@
     id : <number>
     result : {
         result : {
+            description : 0
             type : number
             value : 0
         }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/sessions/runtime-evaluate-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/sessions/runtime-evaluate-expected.txt
index 8fa1b52e..eb588a3 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/sessions/runtime-evaluate-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/sessions/runtime-evaluate-expected.txt
@@ -4,6 +4,7 @@
     id : <number>
     result : {
         result : {
+            description : 42
             type : number
             value : 42
         }
@@ -14,6 +15,7 @@
     id : <number>
     result : {
         result : {
+            description : 42
             type : number
             value : 42
         }
@@ -24,6 +26,7 @@
     id : <number>
     result : {
         result : {
+            description : 42
             type : number
             value : 42
         }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/target/target-send-message-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/target/target-send-message-expected.txt
index 83a2770..f43ed949 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/target/target-send-message-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/target/target-send-message-expected.txt
@@ -6,7 +6,7 @@
 JSON without method property..
 {"error":{"code":-32600,"message":"Message must have string 'method' property"}}
 JSON without id property..
-{"error":{"code":-32600,"message":"Message must have integer 'id' porperty"}}
+{"error":{"code":-32600,"message":"Message must have integer 'id' property"}}
 Valid JSON..
-{"id":1,"result":{"result":{"type":"number","value":42}}}
+{"id":1,"result":{"result":{"type":"number","value":42,"description":"42"}}}
 
diff --git a/third_party/WebKit/LayoutTests/mojo/bind-interface.html b/third_party/WebKit/LayoutTests/mojo/bind-interface.html
index a4bfbcc88..f068eac2 100644
--- a/third_party/WebKit/LayoutTests/mojo/bind-interface.html
+++ b/third_party/WebKit/LayoutTests/mojo/bind-interface.html
@@ -19,15 +19,6 @@
 }, "can bind interfaces");
 
 promise_test(() => {
-  let helper = new content.mojom.MojoLayoutTestHelperPtr;
-  Mojo.bindInterface("totally not a valid interface name",
-                     mojo.makeRequest(helper).handle);
-  return helper.reverse("doesn't matter").then(
-      reply => assert_unreached("request should not succeed"),
-      e => {});
-}, "bindInterface failure closes the request pipe");
-
-promise_test(() => {
   let helperImpl = new TestHelperImpl;
   let interceptor =
       new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name);
@@ -46,7 +37,7 @@
   });
 }, "can intercept calls to bindInterface");
 
-promise_test(() => {
+promise_test(async () => {
   // Intercept this interface at "context" scope to check that it is being
   // requested at "process" scope.
   let helperImpl = new TestHelperImpl;
@@ -64,9 +55,11 @@
 
   const kTestMessage = "hello world.";
   const kExpectedReply = ".dlrow olleh";
-  return helper.reverse(kTestMessage).then(reply => {
+  await helper.reverse(kTestMessage).then(reply => {
     assert_equals(reply.reversed, kExpectedReply);
   });
+
+  interceptor.stop();
 }, "can request interfaces at process scope");
 
 promise_test(() => {
@@ -90,9 +83,8 @@
 }, "can intercept interfaces at process scope");
 
 test(() => {
-  const kTestInterfaceName = "foo::mojom::Ba1r";
-  let a = new MojoInterfaceInterceptor(kTestInterfaceName);
-  let b = new MojoInterfaceInterceptor(kTestInterfaceName);
+  let a = new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name);
+  let b = new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name);
   a.oninterfacerequest = () => {};
   b.oninterfacerequest = () => {};
   a.start();
@@ -101,9 +93,10 @@
 }, "interface interceptors are mutually exclusive");
 
 test(() => {
-  const kTestInterfaceName = "foo::mojom::Ba1r";
-  let a = new MojoInterfaceInterceptor(kTestInterfaceName, "process");
-  let b = new MojoInterfaceInterceptor(kTestInterfaceName, "process");
+  let a = new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name,
+                                       "process");
+  let b = new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name,
+                                       "process");
   a.oninterfacerequest = () => {};
   b.oninterfacerequest = () => {};
   a.start();
@@ -111,11 +104,10 @@
   a.stop();
 }, "process scope interface interceptors are mutually exclusive");
 
-test(async t => {
-  const kTestInterfaceName = "foo::mojom::Bar";
-
+promise_test(async t => {
   // First check that the interceptor can be started and intercepts requests.
-  let interceptor = new MojoInterfaceInterceptor(kTestInterfaceName);
+  let interceptor =
+      new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name);
   let promise = new Promise(resolve => {
     interceptor.oninterfacerequest = e => {
       resolve(e.handle);
@@ -124,7 +116,7 @@
   interceptor.start();
 
   let pipe = Mojo.createMessagePipe();
-  Mojo.bindInterface(kTestInterfaceName, pipe.handle0);
+  Mojo.bindInterface(content.mojom.MojoLayoutTestHelper.name, pipe.handle0);
   let interceptedHandle = await promise;
   assert_true(interceptedHandle instanceof MojoHandle);
   interceptedHandle.close();
@@ -133,21 +125,24 @@
   // Stop the interceptor and make another request.
   interceptor.stop();
 
-  pipe = Mojo.createMessagePipe();
+  let helper = new content.mojom.MojoLayoutTestHelperPtr;
   interceptor.oninterfacerequest = t.step_func(() => {
     assert_unreached("unexpected 'interfacerequest' event after stop");
   });
-  promise = new Promise(resolve => {
-    let watcher = pipe.handle1.watch({peerClosed: true}, () => {
-      watcher.cancel();  // Necessary to avoid a DCHECK when handle1 is closed.
-      resolve();
-    });
+  Mojo.bindInterface(content.mojom.MojoLayoutTestHelper.name,
+                     mojo.makeRequest(helper).handle);
+
+  // Enusre that the interface is functioning, i.e. the request definitely was
+  // not intercepted.
+  await helper.reverse("abc").then(reply => {
+    assert_equals(reply.reversed, "cba");
   });
-  Mojo.bindInterface(kTestInterfaceName, pipe.handle0);
-  await promise;
   pipe.handle1.close();
 
-  interceptor = new MojoInterfaceInterceptor(kTestInterfaceName);
+  // And ensure that we can start a new interceptor for the same interface since
+  // the previous one was stopped.
+  interceptor =
+      new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name);
   interceptor.oninterfacerequest = e => {};
   interceptor.start();
   interceptor.stop();
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/update-visual-rects-after-compositing-change-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/update-visual-rects-after-compositing-change-expected.txt
deleted file mode 100644
index 07571311..0000000
--- a/third_party/WebKit/LayoutTests/paint/invalidation/update-visual-rects-after-compositing-change-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-gone!
-Summary
-Harness status: OK
-
-Found 1 tests
-
-1 Pass
-Details
-Result	Test Name	Message
-Pass	Untitled	
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/update-visual-rects-after-compositing-change.html b/third_party/WebKit/LayoutTests/paint/invalidation/update-visual-rects-after-compositing-change.html
index faa4c0a..b860013 100644
--- a/third_party/WebKit/LayoutTests/paint/invalidation/update-visual-rects-after-compositing-change.html
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/update-visual-rects-after-compositing-change.html
@@ -13,42 +13,31 @@
   </div>
 </div>
 <script src="../../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <script>
 
+var t = async_test();
+
 function runTest() {
   var content = document.createElement("span");
   var div = document.createElement("div");
   div.appendChild(content);
   div.id = "child";
   target.replaceChild(div, child);
-  requestAnimationFrame(checkResult);
+  requestAnimationFrame(t.step_func_done(checkResult));
 }
 
 function checkResult() {
-  if (window.internals) {
-    var clientRect = window.internals.visualRect(myspan.firstChild);
-    test(function() {
-      // Check that the visual rect for the child has been initialized
-      // to a non-zero (and hence presumably correct) size.
-      assert_true(clientRect.width > 0);
-      assert_true(clientRect.height > 0);
-    });
-  }
-  if (window.testRunner)
-    testRunner.notifyDone();
-}
-
-if (window.testRunner) {
-  window.testRunner.waitUntilDone();
-  window.testRunner.dumpAsText();
+  var clientRect = window.internals.visualRect(myspan.firstChild);
+  // Check that the visual rect for the child has been initialized
+  // to a non-zero (and hence presumably correct) size.
+  assert_true(clientRect.width > 0);
+  assert_true(clientRect.height > 0);
 }
 
 onload = function() {
   requestAnimationFrame(function() {
-    requestAnimationFrame(function() {
-      runTest();
-    });
+    requestAnimationFrame(t.step_func(runTest));
   });
 }
 </script>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/unicode-fallback-font-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/unicode-fallback-font-expected.png
index 09d4a7c..3d9191e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/unicode-fallback-font-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/unicode-fallback-font-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/synthetic_gestures/synthetic-pinch-zoom-gesture.html b/third_party/WebKit/LayoutTests/synthetic_gestures/synthetic-pinch-zoom-gesture.html
new file mode 100644
index 0000000..2bb48cd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/synthetic_gestures/synthetic-pinch-zoom-gesture.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<style>
+  body, html {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+  }
+  div {
+    background-color: green;
+    width: 100px;
+    height: 100px;
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    margin-left: -50px;
+    margin-top: -50px;
+  }
+</style>
+
+<script>
+  const kScaleEpsilon = 0.0001;
+  const kOffsetEpsilon = 1;
+
+  const t = async_test(
+      "This tests that gpuBenchmarking.pinchBy is relatively accurate.");
+
+  function performZoom(scale, anchorX, anchorY, speed, callback) {
+    chrome.gpuBenchmarking.pinchBy(scale, anchorX, anchorY, callback, speed);
+  }
+
+  const centerX = window.innerWidth / 2;
+  const centerY = window.innerHeight / 2;
+
+  // TODO(bokan): Add more variations (speed, anchor location, etc.) but it's
+  // difficult right now as pinchBy is badly broken on desktops:
+  // https://crbug.com/787615.
+  const tests = [
+    { starting_scale: 1, scale: 3, speed: 1000, msg: "Zooming in quickly has correct " },
+    { starting_scale: 3, scale: 0.5, speed: 1000, msg: "Zooming out quickly has correct " },
+    { starting_scale: 1, scale: 3, speed: 100, msg: "Zooming in slowly has correct " },
+    { starting_scale: 4, scale: 0.5, speed: 100, msg: "Zooming out slowly has correct " },
+    { starting_scale: 1, scale: 3, speed: 50000, msg: "Zooming in instantly has correct " },
+    { starting_scale: 4, scale: 0.5, speed: 50000, msg: "Zooming out instantly has correct " },
+  ];
+
+  function runTest(testCase) {
+    return new Promise((resolve, reject) => {
+      window.internals.setPageScaleFactor(testCase.starting_scale);
+      window.internals.setVisualViewportOffset(
+          window.innerWidth * (1 - (1 / testCase.starting_scale)) / 2,
+          window.innerHeight * (1 - (1 / testCase.starting_scale)) / 2);
+
+      chrome.gpuBenchmarking.pinchBy(testCase.scale, centerX, centerY, () => {
+        t.step(() => {
+            const expectedScale = testCase.starting_scale * testCase.scale;
+            assert_approx_equals(
+                window.visualViewport.scale,
+                expectedScale,
+                kScaleEpsilon,
+                testCase.msg + " page scale factor.");
+            assert_approx_equals(
+                window.visualViewport.offsetLeft,
+                window.innerWidth * (1 - (1 / expectedScale)) / 2,
+                kOffsetEpsilon,
+                testCase.msg + " visual viewport offsetLeft.");
+            assert_approx_equals(
+                window.visualViewport.offsetTop,
+                window.innerHeight * (1 - (1 / expectedScale)) / 2,
+                kOffsetEpsilon,
+                testCase.msg + " visual viewport offsetTop.");
+        });
+        resolve();
+      }, testCase.speed);
+    });
+  }
+
+  async function runAllTestCases() {
+    for (const testCase of tests) {
+      await runTest(testCase);
+    }
+    t.done();
+  }
+
+  addEventListener('load', runAllTestCases);
+</script>
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorldTest.cpp b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorldTest.cpp
index 8a4ae04..eacb6d5 100644
--- a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorldTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorldTest.cpp
@@ -82,8 +82,8 @@
   worlds.clear();
 
   thread->ShutdownOnBackingThread();
-  main_thread_task_runner->PostTask(FROM_HERE,
-                                    CrossThreadBind(&testing::ExitRunLoop));
+  PostCrossThreadTask(*main_thread_task_runner, FROM_HERE,
+                      CrossThreadBind(&testing::ExitRunLoop));
 }
 
 TEST(DOMWrapperWorldTest, Basic) {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.cpp
index 388051c6..7bca09e 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.cpp
@@ -25,7 +25,8 @@
 
 ScriptModule ScriptModule::Compile(v8::Isolate* isolate,
                                    const String& source,
-                                   const String& file_name,
+                                   const KURL& source_url,
+                                   const KURL& base_url,
                                    const ScriptFetchOptions& options,
                                    AccessControlStatus access_control_status,
                                    const TextPosition& text_position,
@@ -33,11 +34,9 @@
   v8::TryCatch try_catch(isolate);
   v8::Local<v8::Module> module;
 
-  // TODO(kouhei): plumb base url to here.
-  KURL wrong_base_url(file_name);
-  if (!V8ScriptRunner::CompileModule(
-           isolate, source, file_name, access_control_status, text_position,
-           ReferrerScriptInfo(wrong_base_url, options))
+  if (!V8ScriptRunner::CompileModule(isolate, source, source_url,
+                                     access_control_status, text_position,
+                                     ReferrerScriptInfo(base_url, options))
            .ToLocal(&module)) {
     DCHECK(try_catch.HasCaught());
     exception_state.RethrowV8Exception(try_catch.Exception());
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h
index 7d147c1..cfde621a 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h
@@ -35,7 +35,8 @@
  public:
   static ScriptModule Compile(v8::Isolate*,
                               const String& source,
-                              const String& file_name,
+                              const KURL& source_url,
+                              const KURL& base_url,
                               const ScriptFetchOptions&,
                               AccessControlStatus,
                               const TextPosition&,
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptModuleTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptModuleTest.cpp
index 8fa61399..923cacd34 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptModuleTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptModuleTest.cpp
@@ -83,8 +83,9 @@
 
 TEST(ScriptModuleTest, compileSuccess) {
   V8TestingScope scope;
+  const KURL js_url("https://example.com/foo.js");
   ScriptModule module = ScriptModule::Compile(
-      scope.GetIsolate(), "export const a = 42;", "foo.js",
+      scope.GetIsolate(), "export const a = 42;", js_url, js_url,
       ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module.IsNull());
@@ -92,8 +93,9 @@
 
 TEST(ScriptModuleTest, compileFail) {
   V8TestingScope scope;
+  const KURL js_url("https://example.com/foo.js");
   ScriptModule module = ScriptModule::Compile(
-      scope.GetIsolate(), "123 = 456", "foo.js", ScriptFetchOptions(),
+      scope.GetIsolate(), "123 = 456", js_url, js_url, ScriptFetchOptions(),
       kSharableCrossOrigin, TextPosition::MinimumPosition(),
       scope.GetExceptionState());
   ASSERT_TRUE(module.IsNull());
@@ -102,17 +104,19 @@
 
 TEST(ScriptModuleTest, equalAndHash) {
   V8TestingScope scope;
+  const KURL js_url_a("https://example.com/a.js");
+  const KURL js_url_b("https://example.com/b.js");
 
   ScriptModule module_null;
   ScriptModule module_a = ScriptModule::Compile(
-      scope.GetIsolate(), "export const a = 'a';", "a.js", ScriptFetchOptions(),
-      kSharableCrossOrigin, TextPosition::MinimumPosition(),
-      ASSERT_NO_EXCEPTION);
+      scope.GetIsolate(), "export const a = 'a';", js_url_a, js_url_a,
+      ScriptFetchOptions(), kSharableCrossOrigin,
+      TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module_a.IsNull());
   ScriptModule module_b = ScriptModule::Compile(
-      scope.GetIsolate(), "export const b = 'b';", "b.js", ScriptFetchOptions(),
-      kSharableCrossOrigin, TextPosition::MinimumPosition(),
-      ASSERT_NO_EXCEPTION);
+      scope.GetIsolate(), "export const b = 'b';", js_url_b, js_url_b,
+      ScriptFetchOptions(), kSharableCrossOrigin,
+      TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module_b.IsNull());
   Vector<char> module_deleted_buffer(sizeof(ScriptModule));
   ScriptModule& module_deleted =
@@ -150,9 +154,10 @@
 
 TEST(ScriptModuleTest, moduleRequests) {
   V8TestingScope scope;
+  const KURL js_url("https://example.com/foo.js");
   ScriptModule module = ScriptModule::Compile(
       scope.GetIsolate(), "import 'a'; import 'b'; export const c = 'c';",
-      "foo.js", ScriptFetchOptions(), kSharableCrossOrigin,
+      js_url, js_url, ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module.IsNull());
 
@@ -168,8 +173,9 @@
 
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
+  const KURL js_url("https://example.com/foo.js");
   ScriptModule module = ScriptModule::Compile(
-      scope.GetIsolate(), "export const a = 42;", "foo.js",
+      scope.GetIsolate(), "export const a = 42;", js_url, js_url,
       ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module.IsNull());
@@ -187,23 +193,26 @@
 
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
+  const KURL js_url_a("https://example.com/a.js");
   ScriptModule module_a = ScriptModule::Compile(
-      scope.GetIsolate(), "export const a = 'a';", "foo.js",
+      scope.GetIsolate(), "export const a = 'a';", js_url_a, js_url_a,
       ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module_a.IsNull());
   resolver->PushScriptModule(module_a);
 
+  const KURL js_url_b("https://example.com/b.js");
   ScriptModule module_b = ScriptModule::Compile(
-      scope.GetIsolate(), "export const b = 'b';", "foo.js",
+      scope.GetIsolate(), "export const b = 'b';", js_url_b, js_url_b,
       ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module_b.IsNull());
   resolver->PushScriptModule(module_b);
 
+  const KURL js_url_c("https://example.com/c.js");
   ScriptModule module = ScriptModule::Compile(
       scope.GetIsolate(), "import 'a'; import 'b'; export const c = 123;",
-      "c.js", ScriptFetchOptions(), kSharableCrossOrigin,
+      js_url_c, js_url_c, ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module.IsNull());
   ScriptValue exception = module.Instantiate(scope.GetScriptState());
@@ -227,8 +236,9 @@
 
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
+  const KURL js_url_f("https://example.com/failure.js");
   ScriptModule module_failure = ScriptModule::Compile(
-      scope.GetIsolate(), "nonexistent_function()", "failure.js",
+      scope.GetIsolate(), "nonexistent_function()", js_url_f, js_url_f,
       ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module_failure.IsNull());
@@ -239,9 +249,10 @@
 
   resolver->PushScriptModule(module_failure);
 
+  const KURL js_url_c("https://example.com/c.js");
   ScriptModule module = ScriptModule::Compile(
-      scope.GetIsolate(), "import 'failure'; export const c = 123;", "c.js",
-      ScriptFetchOptions(), kSharableCrossOrigin,
+      scope.GetIsolate(), "import 'failure'; export const c = 123;", js_url_c,
+      js_url_c, ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), scope.GetExceptionState());
   ASSERT_FALSE(module.IsNull());
   ASSERT_TRUE(module.Instantiate(scope.GetScriptState()).IsEmpty());
@@ -260,9 +271,10 @@
   auto modulator = new ScriptModuleTestModulator();
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
+  const KURL js_url("https://example.com/foo.js");
   ScriptModule module = ScriptModule::Compile(
-      scope.GetIsolate(), "export const a = 42; window.foo = 'bar';", "foo.js",
-      ScriptFetchOptions(), kSharableCrossOrigin,
+      scope.GetIsolate(), "export const a = 42; window.foo = 'bar';", js_url,
+      js_url, ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module.IsNull());
   ScriptValue exception = module.Instantiate(scope.GetScriptState());
@@ -292,8 +304,9 @@
   auto modulator = new ScriptModuleTestModulator();
   Modulator::SetModulator(scope.GetScriptState(), modulator);
 
+  const KURL js_url("https://example.com/foo.js");
   ScriptModule module = ScriptModule::Compile(
-      scope.GetIsolate(), "throw 'bar';", "foo.js", ScriptFetchOptions(),
+      scope.GetIsolate(), "throw 'bar';", js_url, js_url, ScriptFetchOptions(),
       kSharableCrossOrigin, TextPosition::MinimumPosition(),
       ASSERT_NO_EXCEPTION);
   ASSERT_FALSE(module.IsNull());
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp
index e5f1d97..01e6783 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.cpp
@@ -80,12 +80,4 @@
   visitor->Trace(streamer_);
 }
 
-KURL ScriptSourceCode::Url() const {
-  return url_;
-}
-
-String ScriptSourceCode::SourceMapUrl() const {
-  return source_map_url_;
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h
index 1abc1d7..69ed2a04 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptSourceCode.h
@@ -71,13 +71,13 @@
 
   const String& Source() const { return source_; }
   CachedMetadataHandler* CacheHandler() const { return cache_handler_; }
-  KURL Url() const;
+  const KURL& Url() const { return url_; }
   int StartLine() const { return start_position_.line_.OneBasedInt(); }
   const TextPosition& StartPosition() const { return start_position_; }
   ScriptSourceLocationType SourceLocationType() const {
     return source_location_type_;
   }
-  String SourceMapUrl() const;
+  const String& SourceMapUrl() const { return source_map_url_; }
 
   ScriptStreamer* Streamer() const { return streamer_; }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
index a0b644da..cdc7be35 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamer.cpp
@@ -360,9 +360,9 @@
 
   // notifyFinished might already be called, or it might be called in the
   // future (if the parsing finishes earlier because of a parse error).
-  loading_task_runner_->PostTask(
-      FROM_HERE, CrossThreadBind(&ScriptStreamer::StreamingComplete,
-                                 WrapCrossThreadPersistent(this)));
+  PostCrossThreadTask(*loading_task_runner_, FROM_HERE,
+                      CrossThreadBind(&ScriptStreamer::StreamingComplete,
+                                      WrapCrossThreadPersistent(this)));
 
   // The task might delete ScriptStreamer, so it's not safe to do anything
   // after posting it. Note that there's no way to guarantee that this
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerThread.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerThread.cpp
index e2c3194..309535d0 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerThread.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptStreamerThread.cpp
@@ -38,7 +38,8 @@
   MutexLocker locker(mutex_);
   DCHECK(!running_task_);
   running_task_ = true;
-  PlatformThread().GetWebTaskRunner()->PostTask(FROM_HERE, std::move(task));
+  PostCrossThreadTask(*PlatformThread().GetWebTaskRunner(), FROM_HERE,
+                      std::move(task));
 }
 
 void ScriptStreamerThread::TaskDone() {
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
index c78f41c..6a07d04 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -574,20 +574,19 @@
     }
   }
 
-  void SetProtection(void* data, size_t length, Protection protection) {
-    CHECK(SetProtection(protection, data, length));
-  }
-
-  bool SetProtection(Protection protection, void* data, size_t length) {
+  void SetProtection(void* data,
+                     size_t length,
+                     Protection protection) override {
     switch (protection) {
       case Protection::kNoAccess:
-        return WTF::SetSystemPagesAccess(data, length, WTF::PageInaccessible);
+        CHECK(WTF::SetSystemPagesAccess(data, length, WTF::PageInaccessible));
+        return;
       case Protection::kReadWrite:
-        return WTF::SetSystemPagesAccess(data, length, WTF::PageReadWrite);
+        CHECK(WTF::SetSystemPagesAccess(data, length, WTF::PageReadWrite));
+        return;
       default:
         NOTREACHED();
     }
-    return false;
   }
 };
 
diff --git a/third_party/WebKit/Source/build/scripts/templates/ProbeSink.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/ProbeSink.h.tmpl
index 3a8da14..4edf707 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ProbeSink.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/ProbeSink.h.tmpl
@@ -43,7 +43,7 @@
 {% set class_name = agent | agent_name_to_class %}
 {% set getter_name = class_name | to_lower_case %}
   bool has{{class_name}}s() const { return !m_{{getter_name}}s.IsEmpty(); }
-  const HeapHashSet<Member<{{class_name}}>>& {{getter_name}}s() const { return m_{{getter_name}}s; }
+  const HeapListHashSet<Member<{{class_name}}>>& {{getter_name}}s() const { return m_{{getter_name}}s; }
   void add{{class_name}}({{class_name}}* agent);
   void remove{{class_name}}({{class_name}}* agent);
 
@@ -57,7 +57,7 @@
 {% for agent in agents %}
 {% set class_name = agent | agent_name_to_class %}
 {% set getter_name = class_name | to_lower_case %}
-  HeapHashSet<Member<{{class_name}}>> m_{{getter_name}}s;
+  HeapListHashSet<Member<{{class_name}}>> m_{{getter_name}}s;
 {% endfor %}
 
   // Number of sinks with an enabled agent of each type, used to keep
diff --git a/third_party/WebKit/Source/core/animation/CompositorMutatorImpl.cpp b/third_party/WebKit/Source/core/animation/CompositorMutatorImpl.cpp
index 652947f..6bebac0 100644
--- a/third_party/WebKit/Source/core/animation/CompositorMutatorImpl.cpp
+++ b/third_party/WebKit/Source/core/animation/CompositorMutatorImpl.cpp
@@ -35,10 +35,10 @@
   std::unique_ptr<CompositorMutatorClient> mutator_client;
   WaitableEvent done_event;
   if (WebThread* compositor_thread = Platform::Current()->CompositorThread()) {
-    compositor_thread->GetWebTaskRunner()->PostTask(
-        FROM_HERE, CrossThreadBind(&CreateCompositorMutatorClient,
-                                   CrossThreadUnretained(&mutator_client),
-                                   CrossThreadUnretained(&done_event)));
+    PostCrossThreadTask(*compositor_thread->GetWebTaskRunner(), FROM_HERE,
+                        CrossThreadBind(&CreateCompositorMutatorClient,
+                                        CrossThreadUnretained(&mutator_client),
+                                        CrossThreadUnretained(&done_event)));
   } else {
     CreateCompositorMutatorClient(&mutator_client, &done_event);
   }
diff --git a/third_party/WebKit/Source/core/css/CSSFontFace.cpp b/third_party/WebKit/Source/core/css/CSSFontFace.cpp
index 0bb53e9..b882825 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFace.cpp
+++ b/third_party/WebKit/Source/core/css/CSSFontFace.cpp
@@ -75,6 +75,12 @@
   return true;
 }
 
+void CSSFontFace::SetDisplay(FontDisplay value) {
+  for (auto& source : sources_) {
+    source->SetDisplay(value);
+  }
+}
+
 size_t CSSFontFace::ApproximateBlankCharacterCount() const {
   if (!sources_.IsEmpty() && sources_.front()->IsInBlockPeriod() &&
       segmented_font_face_)
@@ -82,7 +88,7 @@
   return 0;
 }
 
-bool CSSFontFace::DidBecomeVisibleFallback(RemoteFontFaceSource* source) {
+bool CSSFontFace::FallbackVisibilityChanged(RemoteFontFaceSource* source) {
   if (!IsValid() || source != sources_.front())
     return false;
   if (segmented_font_face_)
diff --git a/third_party/WebKit/Source/core/css/CSSFontFace.h b/third_party/WebKit/Source/core/css/CSSFontFace.h
index a9088f9..552dff86 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFace.h
+++ b/third_party/WebKit/Source/core/css/CSSFontFace.h
@@ -32,6 +32,7 @@
 #include "core/css/CSSFontFaceSource.h"
 #include "core/css/CSSSegmentedFontFace.h"
 #include "core/css/FontFace.h"
+#include "core/css/FontFaceSource.h"
 #include "platform/fonts/SegmentedFontData.h"
 #include "platform/fonts/UnicodeRangeSet.h"
 #include "platform/wtf/Deque.h"
@@ -66,10 +67,11 @@
   size_t ApproximateBlankCharacterCount() const;
 
   void AddSource(CSSFontFaceSource*);
+  void SetDisplay(FontDisplay);
 
   void DidBeginLoad();
   bool FontLoaded(RemoteFontFaceSource*);
-  bool DidBecomeVisibleFallback(RemoteFontFaceSource*);
+  bool FallbackVisibilityChanged(RemoteFontFaceSource*);
 
   scoped_refptr<SimpleFontData> GetFontData(const FontDescription&);
 
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceSource.h b/third_party/WebKit/Source/core/css/CSSFontFaceSource.h
index e78293b..1ad58e1d 100644
--- a/third_party/WebKit/Source/core/css/CSSFontFaceSource.h
+++ b/third_party/WebKit/Source/core/css/CSSFontFaceSource.h
@@ -40,6 +40,15 @@
 class FontDescription;
 class SimpleFontData;
 
+enum FontDisplay {
+  kFontDisplayAuto,
+  kFontDisplayBlock,
+  kFontDisplaySwap,
+  kFontDisplayFallback,
+  kFontDisplayOptional,
+  kFontDisplayEnumMax
+};
+
 class CORE_EXPORT CSSFontFaceSource
     : public GarbageCollectedFinalized<CSSFontFaceSource> {
  public:
@@ -55,6 +64,7 @@
 
   virtual bool IsLocalFontAvailable(const FontDescription&) { return false; }
   virtual void BeginLoadIfNeeded() {}
+  virtual void SetDisplay(FontDisplay) {}
 
   virtual bool IsInBlockPeriod() const { return false; }
   virtual bool IsInFailurePeriod() const { return false; }
diff --git a/third_party/WebKit/Source/core/css/FontFace.cpp b/third_party/WebKit/Source/core/css/FontFace.cpp
index c62fe5b..4a1193c 100644
--- a/third_party/WebKit/Source/core/css/FontFace.cpp
+++ b/third_party/WebKit/Source/core/css/FontFace.cpp
@@ -71,9 +71,11 @@
 
 namespace blink {
 
-static const CSSValue* ParseCSSValue(const ExecutionContext* context,
-                                     const String& value,
-                                     AtRuleDescriptorID descriptor_id) {
+namespace {
+
+const CSSValue* ParseCSSValue(const ExecutionContext* context,
+                              const String& value,
+                              AtRuleDescriptorID descriptor_id) {
   CSSParserContext* parser_context =
       context->IsDocument() ? CSSParserContext::Create(*ToDocument(context))
                             : CSSParserContext::Create(*context);
@@ -81,6 +83,43 @@
                                                          *parser_context);
 }
 
+FontDisplay CSSValueToFontDisplay(const CSSValue* value) {
+  if (value && value->IsIdentifierValue()) {
+    switch (ToCSSIdentifierValue(value)->GetValueID()) {
+      case CSSValueAuto:
+        return kFontDisplayAuto;
+      case CSSValueBlock:
+        return kFontDisplayBlock;
+      case CSSValueSwap:
+        return kFontDisplaySwap;
+      case CSSValueFallback:
+        return kFontDisplayFallback;
+      case CSSValueOptional:
+        return kFontDisplayOptional;
+      default:
+        break;
+    }
+  }
+  return kFontDisplayAuto;
+}
+
+CSSFontFace* CreateCSSFontFace(FontFace* font_face,
+                               const CSSValue* unicode_range) {
+  Vector<UnicodeRange> ranges;
+  if (const CSSValueList* range_list = ToCSSValueList(unicode_range)) {
+    unsigned num_ranges = range_list->length();
+    for (unsigned i = 0; i < num_ranges; i++) {
+      const CSSUnicodeRangeValue& range =
+          ToCSSUnicodeRangeValue(range_list->Item(i));
+      ranges.push_back(UnicodeRange(range.From(), range.To()));
+    }
+  }
+
+  return new CSSFontFace(font_face, ranges);
+}
+
+}  // namespace
+
 FontFace* FontFace::Create(ExecutionContext* context,
                            const AtomicString& family,
                            StringOrArrayBufferOrArrayBufferView& source,
@@ -320,6 +359,8 @@
       break;
     case AtRuleDescriptorID::FontDisplay:
       display_ = value;
+      if (css_font_face_)
+        css_font_face_->SetDisplay(CSSValueToFontDisplay(display_.Get()));
       break;
     default:
       NOTREACHED();
@@ -648,41 +689,6 @@
   return 0;
 }
 
-static FontDisplay CSSValueToFontDisplay(const CSSValue* value) {
-  if (value && value->IsIdentifierValue()) {
-    switch (ToCSSIdentifierValue(value)->GetValueID()) {
-      case CSSValueAuto:
-        return kFontDisplayAuto;
-      case CSSValueBlock:
-        return kFontDisplayBlock;
-      case CSSValueSwap:
-        return kFontDisplaySwap;
-      case CSSValueFallback:
-        return kFontDisplayFallback;
-      case CSSValueOptional:
-        return kFontDisplayOptional;
-      default:
-        break;
-    }
-  }
-  return kFontDisplayAuto;
-}
-
-static CSSFontFace* CreateCSSFontFace(FontFace* font_face,
-                                      const CSSValue* unicode_range) {
-  Vector<UnicodeRange> ranges;
-  if (const CSSValueList* range_list = ToCSSValueList(unicode_range)) {
-    unsigned num_ranges = range_list->length();
-    for (unsigned i = 0; i < num_ranges; i++) {
-      const CSSUnicodeRangeValue& range =
-          ToCSSUnicodeRangeValue(range_list->Item(i));
-      ranges.push_back(UnicodeRange(range.From(), range.To()));
-    }
-  }
-
-  return new CSSFontFace(font_face, ranges);
-}
-
 bool ContextAllowsDownload(ExecutionContext* context) {
   if (!context) {
     return false;
diff --git a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
index 8d3650f..312b7713 100644
--- a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
+++ b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
@@ -25,19 +25,68 @@
 
 namespace blink {
 
+namespace {
+
+RemoteFontFaceSource::DisplayPeriod ComputePeriod(
+    FontDisplay displayValue,
+    RemoteFontFaceSource::Phase phase,
+    bool is_intervention_triggered) {
+  switch (displayValue) {
+    case kFontDisplayAuto:
+      if (is_intervention_triggered)
+        return RemoteFontFaceSource::kSwapPeriod;
+    // Fall through.
+    case kFontDisplayBlock:
+      switch (phase) {
+        case RemoteFontFaceSource::kNoLimitExceeded:
+        case RemoteFontFaceSource::kShortLimitExceeded:
+          return RemoteFontFaceSource::kBlockPeriod;
+        case RemoteFontFaceSource::kLongLimitExceeded:
+          return RemoteFontFaceSource::kSwapPeriod;
+      }
+
+    case kFontDisplaySwap:
+      return RemoteFontFaceSource::kSwapPeriod;
+
+    case kFontDisplayFallback:
+      switch (phase) {
+        case RemoteFontFaceSource::kNoLimitExceeded:
+          return RemoteFontFaceSource::kBlockPeriod;
+        case RemoteFontFaceSource::kShortLimitExceeded:
+          return RemoteFontFaceSource::kSwapPeriod;
+        case RemoteFontFaceSource::kLongLimitExceeded:
+          return RemoteFontFaceSource::kFailurePeriod;
+      }
+
+    case kFontDisplayOptional:
+      switch (phase) {
+        case RemoteFontFaceSource::kNoLimitExceeded:
+          return RemoteFontFaceSource::kBlockPeriod;
+        case RemoteFontFaceSource::kShortLimitExceeded:
+        case RemoteFontFaceSource::kLongLimitExceeded:
+          return RemoteFontFaceSource::kFailurePeriod;
+      }
+
+    case kFontDisplayEnumMax:
+      NOTREACHED();
+      break;
+  }
+  NOTREACHED();
+  return RemoteFontFaceSource::kSwapPeriod;
+}
+
+}  // namespace
+
 RemoteFontFaceSource::RemoteFontFaceSource(CSSFontFace* css_font_face,
                                            FontSelector* font_selector,
                                            FontDisplay display)
     : face_(css_font_face),
       font_selector_(font_selector),
       display_(display),
-      period_(display == kFontDisplaySwap ? kSwapPeriod : kBlockPeriod),
-      is_intervention_triggered_(false) {
+      phase_(kNoLimitExceeded),
+      is_intervention_triggered_(ShouldTriggerWebFontsIntervention()) {
   DCHECK(face_);
-  if (ShouldTriggerWebFontsIntervention()) {
-    is_intervention_triggered_ = true;
-    period_ = kSwapPeriod;
-  }
+  period_ = ComputePeriod(display_, phase_, is_intervention_triggered_);
 }
 
 RemoteFontFaceSource::~RemoteFontFaceSource() = default;
@@ -90,42 +139,43 @@
 void RemoteFontFaceSource::FontLoadShortLimitExceeded(FontResource*) {
   if (IsLoaded())
     return;
-
-  if (display_ == kFontDisplayFallback)
-    SwitchToSwapPeriod();
-  else if (display_ == kFontDisplayOptional)
-    SwitchToFailurePeriod();
+  phase_ = kShortLimitExceeded;
+  UpdatePeriod();
 }
 
 void RemoteFontFaceSource::FontLoadLongLimitExceeded(FontResource*) {
   if (IsLoaded())
     return;
-
-  if (display_ == kFontDisplayBlock ||
-      (!is_intervention_triggered_ && display_ == kFontDisplayAuto))
-    SwitchToSwapPeriod();
-  else if (display_ == kFontDisplayFallback)
-    SwitchToFailurePeriod();
+  phase_ = kLongLimitExceeded;
+  UpdatePeriod();
 
   histograms_.LongLimitExceeded();
 }
 
-void RemoteFontFaceSource::SwitchToSwapPeriod() {
-  DCHECK_EQ(period_, kBlockPeriod);
-  period_ = kSwapPeriod;
-
-  PruneTable();
-  if (face_->DidBecomeVisibleFallback(this))
-    font_selector_->FontFaceInvalidated();
-
-  histograms_.RecordFallbackTime();
+void RemoteFontFaceSource::SetDisplay(FontDisplay display) {
+  // TODO(ksakamoto): If the font is loaded and in the failure period,
+  // changing it to block or swap period should update the font rendering
+  // using the loaded font.
+  if (IsLoaded())
+    return;
+  display_ = display;
+  UpdatePeriod();
 }
 
-void RemoteFontFaceSource::SwitchToFailurePeriod() {
-  if (period_ == kBlockPeriod)
-    SwitchToSwapPeriod();
-  DCHECK_EQ(period_, kSwapPeriod);
-  period_ = kFailurePeriod;
+void RemoteFontFaceSource::UpdatePeriod() {
+  DisplayPeriod new_period =
+      ComputePeriod(display_, phase_, is_intervention_triggered_);
+
+  // Fallback font is invisible iff the font is loading and in the block period.
+  // Invalidate the font if its fallback visibility has changed.
+  if (IsLoading() && period_ != new_period &&
+      (period_ == kBlockPeriod || new_period == kBlockPeriod)) {
+    PruneTable();
+    if (face_->FallbackVisibilityChanged(this))
+      font_selector_->FontFaceInvalidated();
+    histograms_.RecordFallbackTime();
+  }
+  period_ = new_period;
 }
 
 bool RemoteFontFaceSource::ShouldTriggerWebFontsIntervention() {
diff --git a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h
index 95a41c5..58e349a 100644
--- a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h
+++ b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h
@@ -15,21 +15,15 @@
 class FontSelector;
 class FontCustomPlatformData;
 
-enum FontDisplay {
-  kFontDisplayAuto,
-  kFontDisplayBlock,
-  kFontDisplaySwap,
-  kFontDisplayFallback,
-  kFontDisplayOptional,
-  kFontDisplayEnumMax
-};
-
 class RemoteFontFaceSource final : public CSSFontFaceSource,
                                    public FontResourceClient {
   USING_PRE_FINALIZER(RemoteFontFaceSource, Dispose);
   USING_GARBAGE_COLLECTED_MIXIN(RemoteFontFaceSource);
 
  public:
+  enum Phase { kNoLimitExceeded, kShortLimitExceeded, kLongLimitExceeded };
+  // Periods of the Font Display Timeline.
+  // https://drafts.csswg.org/css-fonts-4/#font-display-timeline
   enum DisplayPeriod { kBlockPeriod, kSwapPeriod, kFailurePeriod };
 
   RemoteFontFaceSource(CSSFontFace*, FontSelector*, FontDisplay);
@@ -41,6 +35,7 @@
   bool IsValid() const override;
 
   void BeginLoadIfNeeded() override;
+  void SetDisplay(FontDisplay) override;
 
   void NotifyFinished(Resource*) override;
   void FontLoadShortLimitExceeded(FontResource*) override;
@@ -114,8 +109,7 @@
     DataSource data_source_;
   };
 
-  void SwitchToSwapPeriod();
-  void SwitchToFailurePeriod();
+  void UpdatePeriod();
   bool ShouldTriggerWebFontsIntervention();
   bool IsLowPriorityLoadingAllowedForRemoteFont() const override;
 
@@ -126,7 +120,8 @@
   // |nullptr| if font is not loaded or failed to decode.
   scoped_refptr<FontCustomPlatformData> custom_font_data_;
 
-  const FontDisplay display_;
+  FontDisplay display_;
+  Phase phase_;
   DisplayPeriod period_;
   FontLoadHistograms histograms_;
   bool is_intervention_triggered_;
diff --git a/third_party/WebKit/Source/core/css/threaded/MultiThreadedTestUtil.h b/third_party/WebKit/Source/core/css/threaded/MultiThreadedTestUtil.h
index d28c89b..64e32bc 100644
--- a/third_party/WebKit/Source/core/css/threaded/MultiThreadedTestUtil.h
+++ b/third_party/WebKit/Source/core/css/threaded/MultiThreadedTestUtil.h
@@ -65,26 +65,27 @@
       WebTaskRunner* task_runner =
           threads[i]->PlatformThread().GetWebTaskRunner();
 
-      task_runner->PostTask(FROM_HERE,
-                            CrossThreadBind(
-                                [](WebThreadSupportingGC* thread) {
-                                  thread->InitializeOnThread();
-                                },
-                                CrossThreadUnretained(threads[i].get())));
+      PostCrossThreadTask(*task_runner, FROM_HERE,
+                          CrossThreadBind(
+                              [](WebThreadSupportingGC* thread) {
+                                thread->InitializeOnThread();
+                              },
+                              CrossThreadUnretained(threads[i].get())));
 
       for (int j = 0; j < callbacks_per_thread_; ++j) {
-        task_runner->PostTask(FROM_HERE,
-                              CrossThreadBind(function, parameters...));
+        PostCrossThreadTask(*task_runner, FROM_HERE,
+                            CrossThreadBind(function, parameters...));
       }
 
-      task_runner->PostTask(
-          FROM_HERE, CrossThreadBind(
-                         [](WebThreadSupportingGC* thread, WaitableEvent* w) {
-                           thread->ShutdownOnThread();
-                           w->Signal();
-                         },
-                         CrossThreadUnretained(threads[i].get()),
-                         CrossThreadUnretained(waits[i].get())));
+      PostCrossThreadTask(
+          *task_runner, FROM_HERE,
+          CrossThreadBind(
+              [](WebThreadSupportingGC* thread, WaitableEvent* w) {
+                thread->ShutdownOnThread();
+                w->Signal();
+              },
+              CrossThreadUnretained(threads[i].get()),
+              CrossThreadUnretained(waits[i].get())));
     }
 
     for (int i = 0; i < num_threads_; ++i) {
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index cf10279b..81f45c2 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -608,6 +608,7 @@
       visually_ordered_(false),
       ready_state_(kComplete),
       parsing_state_(kFinishedParsing),
+      goto_anchor_needed_after_stylesheets_load_(false),
       contains_validity_style_rules_(false),
       contains_plugins_(false),
       ignore_destructive_write_count_(0),
@@ -2386,6 +2387,9 @@
   if (frame_view->NeedsLayout())
     frame_view->UpdateLayout();
 
+  if (goto_anchor_needed_after_stylesheets_load_)
+    frame_view->ProcessUrlFragment(url_);
+
   if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean)
     Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean);
 
@@ -3265,6 +3269,12 @@
         (!GetLayoutViewItem().FirstChild() ||
          GetLayoutViewItem().NeedsLayout()))
       View()->UpdateLayout();
+
+    // TODO(bokan): This is a temporary fix to https://crbug.com/788486.
+    // There's some better cleanups that should be done to follow-up:
+    // https://crbug.com/795381.
+    if (View() && goto_anchor_needed_after_stylesheets_load_)
+      View()->ProcessUrlFragment(url_);
   }
 
   load_event_progress_ = kLoadEventCompleted;
@@ -6383,12 +6393,11 @@
 
 void Document::AddConsoleMessage(ConsoleMessage* console_message) {
   if (!IsContextThread()) {
-    GetTaskRunner(TaskType::kUnthrottled)
-        ->PostTask(FROM_HERE, CrossThreadBind(&RunAddConsoleMessageTask,
-                                              console_message->Source(),
-                                              console_message->Level(),
-                                              console_message->Message(),
-                                              WrapCrossThreadPersistent(this)));
+    PostCrossThreadTask(
+        *GetTaskRunner(TaskType::kUnthrottled), FROM_HERE,
+        CrossThreadBind(&RunAddConsoleMessageTask, console_message->Source(),
+                        console_message->Level(), console_message->Message(),
+                        WrapCrossThreadPersistent(this)));
     return;
   }
 
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 265076e..e3f059e 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -479,6 +479,13 @@
     return *style_engine_.Get();
   }
 
+  bool GotoAnchorNeededAfterStylesheetsLoad() {
+    return goto_anchor_needed_after_stylesheets_load_;
+  }
+  void SetGotoAnchorNeededAfterStylesheetsLoad(bool b) {
+    goto_anchor_needed_after_stylesheets_load_ = b;
+  }
+
   void ScheduleUseShadowTreeUpdate(SVGUseElement&);
   void UnscheduleUseShadowTreeUpdate(SVGUseElement&);
 
@@ -1635,6 +1642,7 @@
   DocumentReadyState ready_state_;
   ParsingState parsing_state_;
 
+  bool goto_anchor_needed_after_stylesheets_load_;
   bool is_dns_prefetch_enabled_;
   bool have_explicitly_disabled_dns_prefetch_;
   bool contains_validity_style_rules_;
diff --git a/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp b/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
index bf01c7e..86b55da 100644
--- a/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
@@ -123,9 +123,15 @@
   bool was_end_of_paragraph =
       IsEndOfParagraph(CreateVisiblePosition(last_paragraph_in_block_node));
 
-  MoveParagraphWithClones(CreateVisiblePosition(start),
-                          CreateVisiblePosition(end), block_element,
-                          outer_block, editing_state);
+  const VisiblePosition& start_of_paragraph_to_move =
+      CreateVisiblePosition(start);
+  const VisiblePosition& end_of_paragraph_to_move = CreateVisiblePosition(end);
+  // execCommand/format_block/format_block_with_nth_child_crash.html reaches
+  // here.
+  ABORT_EDITING_COMMAND_IF(start_of_paragraph_to_move.IsNull());
+  ABORT_EDITING_COMMAND_IF(end_of_paragraph_to_move.IsNull());
+  MoveParagraphWithClones(start_of_paragraph_to_move, end_of_paragraph_to_move,
+                          block_element, outer_block, editing_state);
   if (editing_state->IsAborted())
     return;
 
diff --git a/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
index 70389c2f..7f2e751d 100644
--- a/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
@@ -1291,30 +1291,22 @@
 
   if (mode.IsEmpty())
     return kWebTextInputModeDefault;
-  if (mode == InputModeNames::verbatim)
-    return kWebTextInputModeVerbatim;
-  if (mode == InputModeNames::latin)
-    return kWebTextInputModeLatin;
-  if (mode == InputModeNames::latin_name)
-    return kWebTextInputModeLatinName;
-  if (mode == InputModeNames::latin_prose)
-    return kWebTextInputModeLatinProse;
-  if (mode == InputModeNames::full_width_latin)
-    return kWebTextInputModeFullWidthLatin;
-  if (mode == InputModeNames::kana)
-    return kWebTextInputModeKana;
-  if (mode == InputModeNames::kana_name)
-    return kWebTextInputModeKanaName;
-  if (mode == InputModeNames::katakana)
-    return kWebTextInputModeKataKana;
-  if (mode == InputModeNames::numeric)
-    return kWebTextInputModeNumeric;
+  if (mode == InputModeNames::none)
+    return kWebTextInputModeNone;
+  if (mode == InputModeNames::text)
+    return kWebTextInputModeText;
   if (mode == InputModeNames::tel)
     return kWebTextInputModeTel;
-  if (mode == InputModeNames::email)
-    return kWebTextInputModeEmail;
   if (mode == InputModeNames::url)
     return kWebTextInputModeUrl;
+  if (mode == InputModeNames::email)
+    return kWebTextInputModeEmail;
+  if (mode == InputModeNames::numeric)
+    return kWebTextInputModeNumeric;
+  if (mode == InputModeNames::decimal)
+    return kWebTextInputModeDecimal;
+  if (mode == InputModeNames::search)
+    return kWebTextInputModeSearch;
   return kWebTextInputModeDefault;
 }
 
diff --git a/third_party/WebKit/Source/core/editing/ime/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/ime/InputMethodControllerTest.cpp
index 44fb904..5b7cf26 100644
--- a/third_party/WebKit/Source/core/editing/ime/InputMethodControllerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/ime/InputMethodControllerTest.cpp
@@ -2383,16 +2383,10 @@
 }
 
 TEST_F(InputMethodControllerTest, InputModeOfFocusedElement) {
-  InsertHTMLElement("<input id='a' inputmode='KataKana'>", "a")->focus();
-  EXPECT_EQ(kWebTextInputModeKataKana,
-            Controller().InputModeOfFocusedElement());
+  InsertHTMLElement("<input id='a' inputmode='decimal'>", "a")->focus();
+  EXPECT_EQ(kWebTextInputModeDecimal, Controller().InputModeOfFocusedElement());
 
-  // U+212A + "atakana"
-  InsertHTMLElement(
-      "<input id='b' inputmode='\xE2\x84\xAA"
-      "atakana'>",
-      "b")
-      ->focus();
+  InsertHTMLElement("<input id='b' inputmode='foo'>", "b")->focus();
   EXPECT_EQ(kWebTextInputModeDefault, Controller().InputModeOfFocusedElement());
 }
 
diff --git a/third_party/WebKit/Source/core/editing/input_mode_names.json5 b/third_party/WebKit/Source/core/editing/input_mode_names.json5
index da84b65..e210b74 100644
--- a/third_party/WebKit/Source/core/editing/input_mode_names.json5
+++ b/third_party/WebKit/Source/core/editing/input_mode_names.json5
@@ -5,17 +5,13 @@
   },
 
   data: [
-    "verbatim",
-    "latin",
-    "latin-name",
-    "latin-prose",
-    "full-width-latin",
-    "kana",
-    "kana-name",
-    "katakana",
-    "numeric",
+    "none",
+    "text",
     "tel",
-    "email",
     "url",
+    "email",
+    "numeric",
+    "decimal",
+    "search",
   ],
 }
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp
index e6cdf80d..afdfc921 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.cpp
@@ -73,13 +73,13 @@
   state_ = State::kInactive;
   if (cold_mode_timer_.IsActive())
     cold_mode_timer_.Stop();
-  if (idle_callback_handle_ != kInvalidHandle)
-    GetFrame().GetDocument()->CancelIdleCallback(idle_callback_handle_);
+  if (idle_callback_handle_ != kInvalidHandle && IsAvailable())
+    GetDocument().CancelIdleCallback(idle_callback_handle_);
   idle_callback_handle_ = kInvalidHandle;
 }
 
 void IdleSpellCheckCallback::SetNeedsInvocation() {
-  if (!IsSpellCheckingEnabled()) {
+  if (!IsSpellCheckingEnabled() || !IsAvailable()) {
     Deactivate();
     return;
   }
@@ -93,14 +93,13 @@
   }
 
   if (state_ == State::kColdModeRequested) {
-    GetFrame().GetDocument()->CancelIdleCallback(idle_callback_handle_);
+    GetDocument().CancelIdleCallback(idle_callback_handle_);
     idle_callback_handle_ = kInvalidHandle;
   }
 
   IdleRequestOptions options;
   options.setTimeout(kHotModeRequestTimeoutMS);
-  idle_callback_handle_ =
-      GetFrame().GetDocument()->RequestIdleCallback(this, options);
+  idle_callback_handle_ = GetDocument().RequestIdleCallback(this, options);
   state_ = State::kHotModeRequested;
 }
 
@@ -127,13 +126,13 @@
   DCHECK(RuntimeEnabledFeatures::IdleTimeColdModeSpellCheckingEnabled());
   DCHECK_EQ(State::kColdModeTimerStarted, state_);
 
-  if (!IsSpellCheckingEnabled()) {
+  if (!IsSpellCheckingEnabled() || !IsAvailable()) {
     Deactivate();
     return;
   }
 
   idle_callback_handle_ =
-      GetFrame().GetDocument()->RequestIdleCallback(this, IdleRequestOptions());
+      GetDocument().RequestIdleCallback(this, IdleRequestOptions());
   state_ = State::kColdModeRequested;
 }
 
@@ -141,7 +140,7 @@
   TRACE_EVENT0("blink", "IdleSpellCheckCallback::hotModeInvocation");
 
   // TODO(xiaochengh): Figure out if this has any performance impact.
-  GetFrame().GetDocument()->UpdateStyleAndLayout();
+  GetDocument().UpdateStyleAndLayout();
 
   HotModeSpellCheckRequester requester(GetSpellCheckRequester());
 
@@ -160,22 +159,17 @@
     // The ending selection stored in undo stack can be invalid, disconnected
     // or have been moved to another document, so we should check its validity
     // before using it.
-    if (!step->EndingSelection().IsValidFor(*GetFrame().GetDocument()))
+    if (!step->EndingSelection().IsValidFor(GetDocument()))
       continue;
     requester.CheckSpellingAt(step->EndingSelection().Extent());
   }
 }
 
 void IdleSpellCheckCallback::invoke(IdleDeadline* deadline) {
-  // TODO(xiaochengh): IdleSpellCheckCallback should get Document via
-  // SynchronousMutationObserver::GetContext().
-  if (!GetFrame().GetDocument() || !GetFrame().GetDocument()->IsActive())
-    return;
-
   DCHECK_NE(idle_callback_handle_, kInvalidHandle);
   idle_callback_handle_ = kInvalidHandle;
 
-  if (!IsSpellCheckingEnabled()) {
+  if (!IsSpellCheckingEnabled() || !IsAvailable()) {
     Deactivate();
     return;
   }
@@ -223,7 +217,7 @@
       break;
     case State::kHotModeRequested:
     case State::kColdModeRequested:
-      GetFrame().GetDocument()->CancelIdleCallback(idle_callback_handle_);
+      GetDocument().CancelIdleCallback(idle_callback_handle_);
       invoke(deadline);
       break;
     case State::kInactive:
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.h b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.h
index 07d93471..7435bfb7 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.h
+++ b/third_party/WebKit/Source/core/editing/spellcheck/IdleSpellCheckCallback.h
@@ -68,6 +68,15 @@
 
   LocalFrame& GetFrame() const { return *frame_; }
 
+  // Returns whether there is an active document to work on.
+  bool IsAvailable() const { return LifecycleContext(); }
+
+  // Return the document to work on. Callable only when IsAvailable() is true.
+  Document& GetDocument() const {
+    DCHECK(IsAvailable());
+    return *LifecycleContext();
+  }
+
   // Returns whether spell checking is globally enabled.
   bool IsSpellCheckingEnabled() const;
 
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
index 5f57800b..9be275b 100644
--- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
@@ -1137,4 +1137,11 @@
   virtual_time_pauser_ = std::move(virtual_time_pauser);
 }
 
+String LocalFrameClientImpl::evaluateInInspectorOverlayForTesting(
+    const String& script) {
+  if (WebDevToolsAgentImpl* devtools = DevToolsAgent())
+    return devtools->EvaluateInOverlayForTesting(script);
+  return g_empty_string;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h
index c990cc4..561226b 100644
--- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h
+++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.h
@@ -261,6 +261,8 @@
 
   void SetVirtualTimePauser(WebScopedVirtualTimePauser) override;
 
+  String evaluateInInspectorOverlayForTesting(const String& script) override;
+
  private:
   explicit LocalFrameClientImpl(WebLocalFrameImpl*);
 
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp
index 7a6fcab..b06907b3 100644
--- a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp
@@ -577,9 +577,8 @@
   return false;
 }
 
-WebString WebDevToolsAgentImpl::EvaluateInWebInspectorOverlay(
-    const WebString& script) {
-  WebString result;
+String WebDevToolsAgentImpl::EvaluateInOverlayForTesting(const String& script) {
+  String result;
   for (auto& it : overlay_agents_)
     result = it.value->EvaluateInOverlayForTest(script);
   return result;
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.h b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.h
index f7b5353..35f3761 100644
--- a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.h
+++ b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.h
@@ -87,6 +87,7 @@
   void RootLayerCleared();
   bool CacheDisabled();
   void DetachAllSessionsForTesting();
+  String EvaluateInOverlayForTesting(const String& script);
 
   // WebDevToolsAgent implementation.
   void Attach(int session_id) override;
@@ -98,7 +99,6 @@
                                   const WebString& message) override;
   void InspectElementAt(int session_id, const WebPoint&) override;
   void FailedToRequestDevTools(int session_id) override;
-  WebString EvaluateInWebInspectorOverlay(const WebString& script) override;
 
  private:
   WebDevToolsAgentImpl(WebLocalFrameImpl*,
diff --git a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
index 8e94749..dae516b 100644
--- a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
@@ -163,6 +163,7 @@
 #include "public/web/WebViewClient.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/common/page/launching_process_state.h"
 #include "v8/include/v8.h"
 
 using blink::URLTestHelpers::ToKURL;
@@ -197,6 +198,18 @@
         ->UnregisterAllURLsAndClearMemoryCache();
   }
 
+  void DisableRendererSchedulerThrottling() {
+    // Make sure that the RendererScheduler is foregrounded to avoid getting
+    // throttled.
+    if (kLaunchingProcessIsBackgrounded) {
+      Platform::Current()
+          ->CurrentThread()
+          ->Scheduler()
+          ->GetRendererSchedulerForTest()
+          ->SetRendererBackgrounded(false);
+    }
+  }
+
   void RegisterMockedHttpURLLoad(const std::string& file_name) {
     RegisterMockedURLLoadFromBase(base_url_, file_name);
   }
@@ -497,6 +510,7 @@
 }
 
 TEST_P(ParameterizedWebFrameTest, RequestExecuteV8FunctionWhileSuspended) {
+  DisableRendererSchedulerThrottling();
   RegisterMockedHttpURLLoad("foo.html");
 
   FrameTestHelpers::WebViewHelper web_view_helper;
@@ -531,6 +545,7 @@
 
 TEST_P(ParameterizedWebFrameTest,
        RequestExecuteV8FunctionWhileSuspendedWithUserGesture) {
+  DisableRendererSchedulerThrottling();
   RegisterMockedHttpURLLoad("foo.html");
 
   FrameTestHelpers::WebViewHelper web_view_helper;
diff --git a/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp
index 1f866a0..7c44847 100644
--- a/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.cpp
@@ -328,7 +328,7 @@
   return true;
 }
 
-void WebPagePopupImpl::PostMessage(const String& message) {
+void WebPagePopupImpl::PostMessageToPopup(const String& message) {
   if (!page_)
     return;
   ScriptForbiddenScope::AllowUserAgentScript allow_script;
diff --git a/third_party/WebKit/Source/core/exported/WebPagePopupImpl.h b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.h
index c6b23d8..1bfc743a 100644
--- a/third_party/WebKit/Source/core/exported/WebPagePopupImpl.h
+++ b/third_party/WebKit/Source/core/exported/WebPagePopupImpl.h
@@ -38,9 +38,6 @@
 #include "platform/wtf/RefCounted.h"
 #include "public/web/WebPagePopup.h"
 
-// To avoid conflicts with the CreateWindow macro from the Windows SDK...
-#undef PostMessage
-
 namespace blink {
 
 class CompositorAnimationHost;
@@ -72,7 +69,7 @@
   void CompositeAndReadbackAsync(
       WebCompositeAndReadbackAsyncCallback*) override;
   WebPoint PositionRelativeToOwner() override;
-  void PostMessage(const String& message) override;
+  void PostMessageToPopup(const String& message) override;
   void Cancel();
 
   // PageWidgetEventHandler functions.
diff --git a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
index 48d52885b..4c468fed 100644
--- a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
@@ -193,12 +193,11 @@
   // The HTML spec requires to queue a connect event using the DOM manipulation
   // task source.
   // https://html.spec.whatwg.org/multipage/workers.html#shared-workers-and-the-sharedworker-interface
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kDOMManipulation)
-      ->PostTask(FROM_HERE, CrossThreadBind(
-                                &WebSharedWorkerImpl::ConnectTaskOnWorkerThread,
-                                WTF::CrossThreadUnretained(this),
-                                WTF::Passed(std::move(web_channel))));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE,
+      CrossThreadBind(&WebSharedWorkerImpl::ConnectTaskOnWorkerThread,
+                      WTF::CrossThreadUnretained(this),
+                      WTF::Passed(std::move(web_channel))));
 }
 
 void WebSharedWorkerImpl::ConnectTaskOnWorkerThread(
diff --git a/third_party/WebKit/Source/core/exported/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
index dc8057d..0f984b0 100644
--- a/third_party/WebKit/Source/core/exported/WebViewTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
@@ -876,36 +876,22 @@
                 "input_mode_default.html");
   TestInputMode(WebTextInputMode::kWebTextInputModeDefault,
                 "input_mode_default_unknown.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeVerbatim,
-                "input_mode_default_verbatim.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeVerbatim,
-                "input_mode_type_text_verbatim.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeVerbatim,
-                "input_mode_type_search_verbatim.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeDefault,
-                "input_mode_type_url_verbatim.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeLatin,
-                "input_mode_type_latin.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeLatinName,
-                "input_mode_type_latin_name.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeLatinProse,
-                "input_mode_type_latin_prose.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeFullWidthLatin,
-                "input_mode_type_full_width_latin.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeKana,
-                "input_mode_type_kana.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeKanaName,
-                "input_mode_type_kana_name.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeKataKana,
-                "input_mode_type_kata_kana.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeNumeric,
-                "input_mode_type_numeric.html");
+  TestInputMode(WebTextInputMode::kWebTextInputModeNone,
+                "input_mode_type_none.html");
+  TestInputMode(WebTextInputMode::kWebTextInputModeText,
+                "input_mode_type_text.html");
   TestInputMode(WebTextInputMode::kWebTextInputModeTel,
                 "input_mode_type_tel.html");
-  TestInputMode(WebTextInputMode::kWebTextInputModeEmail,
-                "input_mode_type_email.html");
   TestInputMode(WebTextInputMode::kWebTextInputModeUrl,
                 "input_mode_type_url.html");
+  TestInputMode(WebTextInputMode::kWebTextInputModeEmail,
+                "input_mode_type_email.html");
+  TestInputMode(WebTextInputMode::kWebTextInputModeNumeric,
+                "input_mode_type_numeric.html");
+  TestInputMode(WebTextInputMode::kWebTextInputModeDecimal,
+                "input_mode_type_decimal.html");
+  TestInputMode(WebTextInputMode::kWebTextInputModeSearch,
+                "input_mode_type_search.html");
 }
 
 TEST_P(WebViewTest, TextInputInfoWithReplacedElements) {
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameClient.h b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
index 1b1a697..ceea9ab 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameClient.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
@@ -386,6 +386,8 @@
 
   virtual void SetVirtualTimePauser(
       WebScopedVirtualTimePauser virtual_time_pauser) {}
+
+  virtual String evaluateInInspectorOverlayForTesting(const String& script) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index 411a4d0..5167d58a 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -120,7 +120,6 @@
 #include "platform/graphics/compositing/PaintArtifactCompositor.h"
 #include "platform/graphics/paint/CullRect.h"
 #include "platform/graphics/paint/PaintController.h"
-#include "platform/graphics/paint/ScopedPaintChunkProperties.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
 #include "platform/instrumentation/tracing/TracedValue.h"
 #include "platform/json/JSONValues.h"
@@ -240,7 +239,6 @@
       needs_intersection_observation_(false),
       needs_forced_compositing_update_(false),
       scroll_gesture_region_is_dirty_(false),
-      needs_focus_on_fragment_(false),
       main_thread_scrolling_reasons_(0),
       paint_frame_count_(0),
       unique_id_(NewUniqueObjectId()) {
@@ -1918,6 +1916,14 @@
                                               UrlFragmentBehavior behavior) {
   DCHECK(frame_->GetDocument());
 
+  if (behavior == kUrlFragmentScroll &&
+      !frame_->GetDocument()->IsRenderingReady()) {
+    frame_->GetDocument()->SetGotoAnchorNeededAfterStylesheetsLoad(true);
+    return false;
+  }
+
+  frame_->GetDocument()->SetGotoAnchorNeededAfterStylesheetsLoad(false);
+
   Element* anchor_node = frame_->GetDocument()->FindAnchor(name);
 
   // Setting to null will clear the current target.
@@ -1928,12 +1934,12 @@
             ToSVGSVGElementOrNull(frame_->GetDocument()->documentElement())) {
       svg->SetupInitialView(name, anchor_node);
       if (!anchor_node)
-        return false;
+        return true;
     }
     // If this is not the top-level frame, then don't scroll to the
     // anchor position.
     if (!frame_->IsMainFrame())
-      return false;
+      behavior = kUrlFragmentDontScroll;
   }
 
   // Implement the rule that "" and "top" both mean top of page as in other
@@ -1942,33 +1948,46 @@
       !(name.IsEmpty() || DeprecatedEqualIgnoringCase(name, "top")))
     return false;
 
-  if (behavior == kUrlFragmentDontScroll)
-    return true;
-
-  if (!anchor_node) {
-    fragment_anchor_ = frame_->GetDocument();
-    needs_focus_on_fragment_ = false;
-  } else {
-    fragment_anchor_ = anchor_node;
-    needs_focus_on_fragment_ = true;
+  if (behavior == kUrlFragmentScroll) {
+    SetFragmentAnchor(anchor_node ? static_cast<Node*>(anchor_node)
+                                  : frame_->GetDocument());
   }
 
-  // If rendering is blocked, we'll necessarily have a layout to kick off the
-  // scroll and focus.
-  if (frame_->GetDocument()->IsRenderingReady()) {
-    frame_->GetDocument()->UpdateStyleAndLayoutTree();
-
-    // If layout is needed, we will scroll in performPostLayoutTasks. Otherwise,
-    // scroll and focus immediately.
-    if (NeedsLayout())
-      UpdateLayout();
-    else
-      ScrollAndFocusFragmentAnchor();
+  // If the anchor accepts keyboard focus and fragment scrolling is allowed,
+  // move focus there to aid users relying on keyboard navigation.
+  // If anchorNode is not focusable or fragment scrolling is not allowed,
+  // clear focus, which matches the behavior of other browsers.
+  if (anchor_node) {
+    frame_->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
+    if (behavior == kUrlFragmentScroll && anchor_node->IsFocusable()) {
+      anchor_node->focus();
+    } else {
+      if (behavior == kUrlFragmentScroll) {
+        frame_->GetDocument()->SetSequentialFocusNavigationStartingPoint(
+            anchor_node);
+      }
+      frame_->GetDocument()->ClearFocusedElement();
+    }
   }
-
   return true;
 }
 
+void LocalFrameView::SetFragmentAnchor(Node* anchor_node) {
+  DCHECK(anchor_node);
+  fragment_anchor_ = anchor_node;
+
+  // We need to update the layout tree before scrolling.
+  frame_->GetDocument()->UpdateStyleAndLayoutTree();
+
+  // If layout is needed, we will scroll in performPostLayoutTasks. Otherwise,
+  // scroll immediately.
+  LayoutViewItem layout_view_item = this->GetLayoutViewItem();
+  if (!layout_view_item.IsNull() && layout_view_item.NeedsLayout())
+    UpdateLayout();
+  else
+    ScrollToFragmentAnchor();
+}
+
 void LocalFrameView::ClearFragmentAnchor() {
   fragment_anchor_ = nullptr;
 }
@@ -2443,7 +2462,7 @@
       });
 }
 
-void LocalFrameView::ScrollAndFocusFragmentAnchor() {
+void LocalFrameView::ScrollToFragmentAnchor() {
   Node* anchor_node = fragment_anchor_;
   if (!anchor_node)
     return;
@@ -2486,22 +2505,6 @@
 
     if (AXObjectCache* cache = frame_->GetDocument()->ExistingAXObjectCache())
       cache->HandleScrolledToAnchor(anchor_node);
-
-    // If the anchor accepts keyboard focus and fragment scrolling is allowed,
-    // move focus there to aid users relying on keyboard navigation.
-    // If anchorNode is not focusable or fragment scrolling is not allowed,
-    // clear focus, which matches the behavior of other browsers.
-    if (needs_focus_on_fragment_) {
-      if (anchor_node->IsElementNode() &&
-          ToElement(anchor_node)->IsFocusable()) {
-        ToElement(anchor_node)->focus();
-      } else {
-        frame_->GetDocument()->SetSequentialFocusNavigationStartingPoint(
-            anchor_node);
-        frame_->GetDocument()->ClearFocusedElement();
-      }
-      needs_focus_on_fragment_ = false;
-    }
   }
 
   // The fragment anchor should only be maintained while the frame is still
@@ -2628,7 +2631,7 @@
 
   // If we're restoring a scroll position from history, that takes precedence
   // over scrolling to the anchor in the URL.
-  ScrollAndFocusFragmentAnchor();
+  ScrollToFragmentAnchor();
   GetFrame().Loader().RestoreScrollPositionAndViewState();
   SendResizeEventIfNeeded();
 }
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h
index e52d3b5..204cc74 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -352,8 +352,8 @@
   enum UrlFragmentBehavior { kUrlFragmentScroll, kUrlFragmentDontScroll };
   // Updates the fragment anchor element based on URL's fragment identifier.
   // Updates corresponding ':target' CSS pseudo class on the anchor element.
-  // If |UrlFragmentScroll| is passed in sets the the anchor element so that it
-  // will be focused and scrolled into view during layout. The scroll offset is
+  // If |UrlFragmentScroll| is passed in then makes the anchor element
+  // focused and also visible by scrolling to it. The scroll offset is
   // maintained during the frame loading process.
   void ProcessUrlFragment(const KURL&,
                           UrlFragmentBehavior = kUrlFragmentScroll);
@@ -1103,7 +1103,7 @@
 
   bool ProcessUrlFragmentHelper(const String&, UrlFragmentBehavior);
   void SetFragmentAnchor(Node*);
-  void ScrollAndFocusFragmentAnchor();
+  void ScrollToFragmentAnchor();
   void DidScrollTimerFired(TimerBase*);
 
   void UpdateLayersAndCompositingAfterScrollIfNeeded();
@@ -1323,8 +1323,6 @@
   bool needs_forced_compositing_update_;
   bool scroll_gesture_region_is_dirty_;
 
-  bool needs_focus_on_fragment_;
-
   Member<ElementVisibilityObserver> visibility_observer_;
 
   IntRect remote_viewport_intersection_;
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.idl b/third_party/WebKit/Source/core/html/HTMLElement.idl
index 3e2e9989..6cc1edb 100644
--- a/third_party/WebKit/Source/core/html/HTMLElement.idl
+++ b/third_party/WebKit/Source/core/html/HTMLElement.idl
@@ -43,7 +43,7 @@
     // https://html.spec.whatwg.org/#contenteditable
     [CEReactions, CustomElementCallbacks, RaisesException=Setter] attribute DOMString contentEditable;
     [ImplementedAs=isContentEditableForBinding] readonly attribute boolean isContentEditable;
-    [RuntimeEnabled=InputModeAttribute, CEReactions, Reflect] attribute DOMString inputMode;
+    [RuntimeEnabled=InputModeAttribute, CEReactions, Reflect, ReflectOnly=("none","text","tel","url","email","numeric","decimal","search")] attribute DOMString inputMode;
 
     // CSSOM View Module
     // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
index 10677ab..0853388 100644
--- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
@@ -389,11 +389,10 @@
   if (IsMainThread()) {
     CreateBlobAndReturnResult();
   } else {
-    context_->GetTaskRunner(TaskType::kCanvasBlobSerialization)
-        ->PostTask(
-            FROM_HERE,
-            CrossThreadBind(&CanvasAsyncBlobCreator::CreateBlobAndReturnResult,
-                            WrapCrossThreadPersistent(this)));
+    PostCrossThreadTask(
+        *context_->GetTaskRunner(TaskType::kCanvasBlobSerialization), FROM_HERE,
+        CrossThreadBind(&CanvasAsyncBlobCreator::CreateBlobAndReturnResult,
+                        WrapCrossThreadPersistent(this)));
   }
 
   SignalAlternativeCodePathFinishedForTesting();
@@ -440,19 +439,19 @@
   DCHECK(mime_type_ == kMimeTypeWebp);
 
   if (!EncodeImage(quality)) {
-    parent_frame_task_runner_->Get(TaskType::kCanvasBlobSerialization)
-        ->PostTask(
-            FROM_HERE,
-            CrossThreadBind(&CanvasAsyncBlobCreator::CreateNullAndReturnResult,
-                            WrapCrossThreadPersistent(this)));
+    PostCrossThreadTask(
+        *parent_frame_task_runner_->Get(TaskType::kCanvasBlobSerialization),
+        FROM_HERE,
+        CrossThreadBind(&CanvasAsyncBlobCreator::CreateNullAndReturnResult,
+                        WrapCrossThreadPersistent(this)));
     return;
   }
 
-  parent_frame_task_runner_->Get(TaskType::kCanvasBlobSerialization)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&CanvasAsyncBlobCreator::CreateBlobAndReturnResult,
-                          WrapCrossThreadPersistent(this)));
+  PostCrossThreadTask(
+      *parent_frame_task_runner_->Get(TaskType::kCanvasBlobSerialization),
+      FROM_HERE,
+      CrossThreadBind(&CanvasAsyncBlobCreator::CreateBlobAndReturnResult,
+                      WrapCrossThreadPersistent(this)));
 }
 
 bool CanvasAsyncBlobCreator::InitializeEncoder(double quality) {
diff --git a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
index 1256e6e2..c149dd7f 100644
--- a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
+++ b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
@@ -549,7 +549,7 @@
       OwnerElement().GetDocument().View());
   AddProperty("anchorRectInScreen", anchor_rect_in_screen, data.get());
   PagePopupClient::AddString("}\n", data.get());
-  popup_->PostMessage(String::FromUTF8(data->Data(), data->size()));
+  popup_->PostMessageToPopup(String::FromUTF8(data->Data(), data->size()));
 }
 
 void InternalPopupMenu::DisconnectClient() {
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
index 28d85693..2dcb150 100644
--- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
@@ -353,8 +353,8 @@
   if (IsMainThread()) {
     WTF::Bind(std::move(function), std::forward<Ps>(parameters)...).Run();
   } else {
-    loading_task_runner_->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *loading_task_runner_, FROM_HERE,
         CrossThreadBind(std::move(function), std::forward<Ps>(parameters)...));
   }
 }
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
index 22cd3f6e..88d95f28 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmap.cpp
@@ -971,11 +971,11 @@
   }
   scoped_refptr<WebTaskRunner> task_runner =
       Platform::Current()->MainThread()->GetWebTaskRunner();
-  task_runner->PostTask(
-      FROM_HERE, CrossThreadBind(&ResolvePromiseOnOriginalThread,
-                                 WrapCrossThreadPersistent(resolver),
-                                 std::move(skia_image), origin_clean,
-                                 WTF::Passed(std::move(parsed_options))));
+  PostCrossThreadTask(*task_runner, FROM_HERE,
+                      CrossThreadBind(&ResolvePromiseOnOriginalThread,
+                                      WrapCrossThreadPersistent(resolver),
+                                      std::move(skia_image), origin_clean,
+                                      WTF::Passed(std::move(parsed_options))));
 }
 
 ScriptPromise ImageBitmap::CreateAsync(ImageElementBase* image,
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
index 472b6a5f..d2302d3 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
@@ -329,8 +329,8 @@
   if (decoder) {
     frame = ImageBitmap::GetSkImageFromDecoder(std::move(decoder));
   }
-  task_runner->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *task_runner, FROM_HERE,
       CrossThreadBind(&ImageBitmapFactories::ImageBitmapLoader::
                           ResolvePromiseOnOriginalThread,
                       WrapCrossThreadPersistent(this), std::move(frame)));
diff --git a/third_party/WebKit/Source/core/layout/BUILD.gn b/third_party/WebKit/Source/core/layout/BUILD.gn
index c71fcdb..44de20c 100644
--- a/third_party/WebKit/Source/core/layout/BUILD.gn
+++ b/third_party/WebKit/Source/core/layout/BUILD.gn
@@ -347,8 +347,8 @@
     "ng/inline/ng_inline_box_state.h",
     "ng/inline/ng_inline_break_token.cc",
     "ng/inline/ng_inline_break_token.h",
-    "ng/inline/ng_inline_fragment_iterator.cc",
-    "ng/inline/ng_inline_fragment_iterator.h",
+    "ng/inline/ng_inline_fragment_traversal.cc",
+    "ng/inline/ng_inline_fragment_traversal.h",
     "ng/inline/ng_inline_item.cc",
     "ng/inline/ng_inline_item.h",
     "ng/inline/ng_inline_item_result.cc",
diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.cpp b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
index ec693b0d..3bb7cde5 100644
--- a/third_party/WebKit/Source/core/layout/LayoutInline.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
@@ -34,7 +34,7 @@
 #include "core/layout/LayoutView.h"
 #include "core/layout/api/LineLayoutBoxModel.h"
 #include "core/layout/line/InlineTextBox.h"
-#include "core/layout/ng/inline/ng_inline_fragment_iterator.h"
+#include "core/layout/ng/inline/ng_inline_fragment_traversal.h"
 #include "core/layout/ng/layout_ng_block_flow.h"
 #include "core/paint/BoxPainter.h"
 #include "core/paint/InlinePainter.h"
@@ -984,7 +984,8 @@
   if (const NGPhysicalBoxFragment* box_fragment =
           EnclosingBlockFlowFragmentOf(*this)) {
     LayoutRect result;
-    NGInlineFragmentIterator children(*box_fragment, this);
+    auto children =
+        NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, this);
     for (const auto& child : children) {
       NGPhysicalOffset left_top =
           child.fragment->Offset() + child.offset_to_container_box;
@@ -1130,7 +1131,8 @@
   if (const NGPhysicalBoxFragment* box_fragment =
           EnclosingBlockFlowFragmentOf(*this)) {
     NGPhysicalOffsetRect result;
-    NGInlineFragmentIterator children(*box_fragment, this);
+    auto children =
+        NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, this);
     for (const auto& child : children) {
       NGPhysicalOffsetRect child_rect =
           child.fragment->VisualRectWithContents();
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.cpp b/third_party/WebKit/Source/core/layout/LayoutText.cpp
index e8999db6..7f9f8092 100644
--- a/third_party/WebKit/Source/core/layout/LayoutText.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutText.cpp
@@ -45,7 +45,7 @@
 #include "core/layout/line/EllipsisBox.h"
 #include "core/layout/line/GlyphOverflow.h"
 #include "core/layout/line/InlineTextBox.h"
-#include "core/layout/ng/inline/ng_inline_fragment_iterator.h"
+#include "core/layout/ng/inline/ng_inline_fragment_traversal.h"
 #include "core/layout/ng/inline/ng_inline_node.h"
 #include "core/layout/ng/inline/ng_offset_mapping.h"
 #include "core/layout/ng/layout_ng_block_flow.h"
@@ -1805,7 +1805,8 @@
   if (const NGPhysicalBoxFragment* box_fragment =
           EnclosingBlockFlowFragment()) {
     NGPhysicalOffsetRect bounding_box;
-    NGInlineFragmentIterator children(*box_fragment, this);
+    auto children =
+        NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, this);
     for (const auto& child : children)
       bounding_box.Unite(child.RectInContainerBox());
     return bounding_box.ToLayoutRect();
diff --git a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
index 75833f9..757064f2 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineFlowBox.cpp
@@ -98,49 +98,28 @@
       text_box->GetLineLayoutItem().StyleRef(IsFirstLineStyle());
   if (!text_box->GetEmphasisMarkPosition(style, emphasis_mark_position))
     return false;
-  if (IsHorizontal()) {
-    return emphasis_mark_position == TextEmphasisPosition::kOverRight ||
-           emphasis_mark_position == TextEmphasisPosition::kOverLeft;
-  }
-  if (style.IsFlippedLinesWritingMode()) {
-    return emphasis_mark_position == TextEmphasisPosition::kOverLeft ||
-           emphasis_mark_position == TextEmphasisPosition::kUnderLeft;
-  }
-  if (style.IsFlippedBlocksWritingMode()) {
-    return emphasis_mark_position == TextEmphasisPosition::kOverRight ||
-           emphasis_mark_position == TextEmphasisPosition::kUnderRight;
-  }
-  return false;
+  LineLogicalSide side = style.GetTextEmphasisLineLogicalSide();
+  if (IsHorizontal() || !style.IsFlippedLinesWritingMode())
+    return side == LineLogicalSide::kOver;
+  return side == LineLogicalSide::kUnder;
 }
 
 inline bool InlineFlowBox::HasEmphasisMarkOver(
     const InlineTextBox* text_box) const {
+  const auto& style =
+      text_box->GetLineLayoutItem().StyleRef(IsFirstLineStyle());
   TextEmphasisPosition emphasis_mark_position;
-  if (!text_box->GetEmphasisMarkPosition(
-          text_box->GetLineLayoutItem().StyleRef(IsFirstLineStyle()),
-          emphasis_mark_position))
-    return false;
-
-  return IsHorizontal()
-             ? emphasis_mark_position == TextEmphasisPosition::kOverRight ||
-                   emphasis_mark_position == TextEmphasisPosition::kOverLeft
-             : emphasis_mark_position == TextEmphasisPosition::kOverRight ||
-                   emphasis_mark_position == TextEmphasisPosition::kUnderRight;
+  return text_box->GetEmphasisMarkPosition(style, emphasis_mark_position) &&
+         style.GetTextEmphasisLineLogicalSide() == LineLogicalSide::kOver;
 }
 
 inline bool InlineFlowBox::HasEmphasisMarkUnder(
     const InlineTextBox* text_box) const {
+  const auto& style =
+      text_box->GetLineLayoutItem().StyleRef(IsFirstLineStyle());
   TextEmphasisPosition emphasis_mark_position;
-  if (!text_box->GetEmphasisMarkPosition(
-          text_box->GetLineLayoutItem().StyleRef(IsFirstLineStyle()),
-          emphasis_mark_position))
-    return false;
-
-  return IsHorizontal()
-             ? emphasis_mark_position == TextEmphasisPosition::kUnderRight ||
-                   emphasis_mark_position == TextEmphasisPosition::kUnderLeft
-             : emphasis_mark_position == TextEmphasisPosition::kOverLeft ||
-                   emphasis_mark_position == TextEmphasisPosition::kUnderLeft;
+  return text_box->GetEmphasisMarkPosition(style, emphasis_mark_position) &&
+         style.GetTextEmphasisLineLogicalSide() == LineLogicalSide::kUnder;
 }
 
 void InlineFlowBox::AddToLine(InlineBox* child) {
diff --git a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
index 8171902b..cb4312d 100644
--- a/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
+++ b/third_party/WebKit/Source/core/layout/line/InlineTextBox.cpp
@@ -518,12 +518,7 @@
 
   emphasis_position = style.GetTextEmphasisPosition();
   // Ruby text is always over, so it cannot suppress emphasis marks under.
-  if ((IsHorizontal() &&
-       (emphasis_position == TextEmphasisPosition::kUnderRight ||
-        emphasis_position == TextEmphasisPosition::kUnderLeft)) ||
-      (!IsHorizontal() &&
-       (emphasis_position == TextEmphasisPosition::kOverLeft ||
-        emphasis_position == TextEmphasisPosition::kUnderLeft)))
+  if (style.GetTextEmphasisLineLogicalSide() != LineLogicalSide::kOver)
     return true;
 
   LineLayoutBox containing_block = GetLineLayoutItem().ContainingBlock();
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_iterator.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal.cc
similarity index 93%
rename from third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_iterator.cc
rename to third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal.cc
index a251a62..be7851e 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_iterator.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal.cc
@@ -2,9 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(xiaochengh): Rename this file into ng_inline_fragment_traversal.cc
-
-#include "core/layout/ng/inline/ng_inline_fragment_iterator.h"
+#include "core/layout/ng/inline/ng_inline_fragment_traversal.h"
 
 #include "core/layout/LayoutObject.h"
 #include "core/layout/ng/ng_physical_box_fragment.h"
@@ -114,12 +112,6 @@
 
 }  // namespace
 
-NGInlineFragmentIterator::NGInlineFragmentIterator(
-    const NGPhysicalBoxFragment& box,
-    const LayoutObject* layout_object) {
-  results_ = NGInlineFragmentTraversal::SelfFragmentsOf(box, layout_object);
-}
-
 // static
 Vector<Result, 1> NGInlineFragmentTraversal::SelfFragmentsOf(
     const NGPhysicalContainerFragment& container,
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_iterator.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal.h
similarity index 66%
rename from third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_iterator.h
rename to third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal.h
index 431309e..bf8cbf1 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_iterator.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal.h
@@ -2,10 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NGInlineFragmentIterator_h
-#define NGInlineFragmentIterator_h
-
-// TODO(xiaochengh): Rename this file into ng_inline_fragment_traversal.h
+#ifndef NGInlineFragmentTraversal_h
+#define NGInlineFragmentTraversal_h
 
 #include "core/CoreExport.h"
 #include "core/layout/ng/ng_physical_fragment.h"
@@ -15,7 +13,6 @@
 namespace blink {
 
 class LayoutObject;
-class NGPhysicalBoxFragment;
 class NGPhysicalContainerFragment;
 
 // Utility class for traversing the physical fragment tree.
@@ -52,28 +49,6 @@
       const LayoutObject* target);
 };
 
-// TODO(xiaochengh): Convert clients of NGInlineFragmentIterator to use
-// NGInlineFragmentTraversal::SelfFragmentsOf().
-
-// Iterate through inline descendant fragments.
-class CORE_EXPORT NGInlineFragmentIterator {
-  STACK_ALLOCATED();
-
- public:
-  // Create an iterator that returns inline fragments produced from the
-  // specified LayoutObject.
-  NGInlineFragmentIterator(const NGPhysicalBoxFragment&,
-                           const LayoutObject* filter);
-
-  using Results = Vector<NGPhysicalFragmentWithOffset, 1>;
-
-  Results::const_iterator begin() const { return results_.begin(); }
-  Results::const_iterator end() const { return results_.end(); }
-
- private:
-  Results results_;
-};
-
 }  // namespace blink
 
-#endif  // NGInlineFragmentIterator_h
+#endif  // NGInlineFragmentTraversal_h
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal_test.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal_test.cc
index 47d90fa..6f8aa36 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_fragment_traversal_test.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 "core/layout/ng/inline/ng_inline_fragment_iterator.h"
+#include "core/layout/ng/inline/ng_inline_fragment_traversal.h"
 
 #include "core/layout/ng/inline/ng_physical_text_fragment.h"
 #include "core/layout/ng/ng_layout_test.h"
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index d0b2f4b..bf7aeaf 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -189,31 +189,17 @@
   BidiReorder();
   box_states_->UpdateAfterReorder(&line_box_);
   LayoutUnit inline_size = box_states_->ComputeInlinePositions(&line_box_);
+  const NGLineHeightMetrics& line_box_metrics =
+      box_states_->LineBoxState().metrics;
 
   // Handle out-of-flow positioned objects. They need inline offsets for their
   // static positions.
-  bool has_fragments = false;
-  for (auto& child : line_box_) {
-    if (child.out_of_flow_positioned_box) {
-      NGBlockNode node(ToLayoutBox(child.out_of_flow_positioned_box));
-      container_builder_.AddInlineOutOfFlowChildCandidate(
-          node, NGLogicalOffset(child.offset.inline_offset, LayoutUnit()),
-          line_info->BaseDirection(), child.out_of_flow_containing_box);
-      child.out_of_flow_positioned_box = child.out_of_flow_containing_box =
-          nullptr;
-    } else if (!has_fragments) {
-      has_fragments = child.HasFragment();
-    }
-  }
-
-  if (!has_fragments) {
+  if (!PlaceOutOfFlowObjects(*line_info, line_box_metrics)) {
     // If we have out-of-flow objects but nothing else, we don't have line box
     // metrics nor BFC offset. Exit early.
     return;
   }
 
-  const NGLineHeightMetrics& line_box_metrics =
-      box_states_->LineBoxState().metrics;
   DCHECK(!line_box_metrics.IsEmpty());
 
   NGBfcOffset line_bfc_offset(line_info->LineBfcOffset());
@@ -345,6 +331,39 @@
                      item_result->inline_size, item.BidiLevel());
 }
 
+// Place all out-of-flow objects in |line_box_| and clear them.
+// @return whether |line_box_| has any in-flow fragments.
+bool NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
+    const NGLineInfo& line_info,
+    const NGLineHeightMetrics& line_box_metrics) {
+  bool has_fragments = false;
+  for (auto& child : line_box_) {
+    if (LayoutObject* box = child.out_of_flow_positioned_box) {
+      // The static position is at the line-top. Ignore the block_offset.
+      NGLogicalOffset static_offset(child.offset.inline_offset, LayoutUnit());
+
+      // If a block-level box appears in the middle of a line, move the static
+      // position to where the next block will be placed.
+      if (static_offset.inline_offset &&
+          !box->StyleRef().IsOriginalDisplayInlineType()) {
+        static_offset.inline_offset = LayoutUnit();
+        if (!line_box_metrics.IsEmpty())
+          static_offset.block_offset = line_box_metrics.LineHeight();
+      }
+
+      container_builder_.AddInlineOutOfFlowChildCandidate(
+          NGBlockNode(ToLayoutBox(box)), static_offset,
+          line_info.BaseDirection(), child.out_of_flow_containing_box);
+
+      child.out_of_flow_positioned_box = child.out_of_flow_containing_box =
+          nullptr;
+    } else if (!has_fragments) {
+      has_fragments = child.HasFragment();
+    }
+  }
+  return has_fragments;
+}
+
 // Place a list marker.
 void NGInlineLayoutAlgorithm::PlaceListMarker(const NGInlineItem& item,
                                               NGInlineItemResult* item_result,
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h
index 3abeb89..4064780 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.h
@@ -69,6 +69,7 @@
   void PlaceLayoutResult(NGInlineItemResult*,
                          NGInlineBoxState*,
                          LayoutUnit inline_offset = LayoutUnit());
+  bool PlaceOutOfFlowObjects(const NGLineInfo&, const NGLineHeightMetrics&);
   void PlaceListMarker(const NGInlineItem&,
                        NGInlineItemResult*,
                        const NGLineInfo&);
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
index 750a58e..fc33c54 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
@@ -777,11 +777,21 @@
   item_index_ = saved_item_index;
   offset_ = saved_offset;
 
+  // Ellipsis should not have text decorations. Reset if it's set.
+  scoped_refptr<const ComputedStyle> style = &line_info->LineStyle();
+  if (style->TextDecorationsInEffect() != TextDecoration::kNone) {
+    scoped_refptr<ComputedStyle> ellipsis_style =
+        ComputedStyle::CreateAnonymousStyleWithDisplay(*style,
+                                                       EDisplay::kInline);
+    ellipsis_style->ResetTextDecoration();
+    ellipsis_style->ClearAppliedTextDecorations();
+    style = std::move(ellipsis_style);
+  }
+
   // The ellipsis should appear at the logical end of the line.
   // This is stored seprately from other results so that it can be appended
   // after bidi reorder.
-  line_info->SetLineEndShapeResult(std::move(shape_result),
-                                   &line_info->LineStyle());
+  line_info->SetLineEndShapeResult(std::move(shape_result), style);
 }
 
 void NGLineBreaker::SetCurrentStyle(const ComputedStyle& style) {
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.cc
index 2c5566e..d4a3322 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.cc
@@ -14,36 +14,47 @@
   if (!shape_result_)
     return {};
 
-  // TODO(kojii): Copying InlineTextBox logic from
-  // InlineFlowBox::ComputeOverflow().
-  //
-  // InlineFlowBox::ComputeOverflow() computes GlpyhOverflow first
-  // (ComputeGlyphOverflow) then AddTextBoxVisualOverflow(). We probably don't
-  // have to keep these two steps separated.
-
-  // Glyph bounds is in logical coordinate, origin at the baseline.
-  FloatRect visual_float_rect = shape_result_->Bounds();
+  // Glyph bounds is in logical coordinate, origin at the alphabetic baseline.
+  LayoutRect visual_rect = EnclosingLayoutRect(shape_result_->Bounds());
 
   // Make the origin at the logical top of this fragment.
-  // ShapeResult::Bounds() is in logical coordinate with alphabetic baseline.
   const ComputedStyle& style = Style();
-  const SimpleFontData* font_data = style.GetFont().PrimaryFont();
-  visual_float_rect.SetY(
-      visual_float_rect.Y() +
-      font_data->GetFontMetrics().FixedAscent(kAlphabeticBaseline));
-
-  // TODO(kojii): Copying from AddTextBoxVisualOverflow()
-  if (float stroke_width = style.TextStrokeWidth()) {
-    visual_float_rect.Inflate(stroke_width / 2.0f);
+  const Font& font = style.GetFont();
+  const SimpleFontData* font_data = font.PrimaryFont();
+  if (font_data) {
+    visual_rect.SetY(visual_rect.Y() + font_data->GetFontMetrics().FixedAscent(
+                                           kAlphabeticBaseline));
   }
 
-  // TODO(kojii): Implement emphasis marks.
+  if (float stroke_width = style.TextStrokeWidth()) {
+    visual_rect.Inflate(LayoutUnit::FromFloatCeil(stroke_width / 2.0f));
+  }
+
+  if (style.GetTextEmphasisMark() != TextEmphasisMark::kNone) {
+    LayoutUnit emphasis_mark_height =
+        LayoutUnit(font.EmphasisMarkHeight(style.TextEmphasisMarkString()));
+    DCHECK_GT(emphasis_mark_height, LayoutUnit());
+    if (style.GetTextEmphasisLineLogicalSide() == LineLogicalSide::kOver) {
+      visual_rect.ShiftYEdgeTo(
+          std::min(visual_rect.Y(), -emphasis_mark_height));
+    } else {
+      LayoutUnit logical_height =
+          style.IsHorizontalWritingMode() ? Size().height : Size().width;
+      visual_rect.ShiftMaxYEdgeTo(
+          std::max(visual_rect.MaxY(), logical_height + emphasis_mark_height));
+    }
+  }
 
   if (ShadowList* text_shadow = style.TextShadow()) {
-    // TODO(kojii): Implement text shadow.
+    LayoutRectOutsets text_shadow_logical_outsets =
+        LayoutRectOutsets(text_shadow->RectOutsetsIncludingOriginal())
+            .LineOrientationOutsets(style.GetWritingMode());
+    text_shadow_logical_outsets.ClampNegativeToZero();
+    visual_rect.Expand(text_shadow_logical_outsets);
   }
 
-  LayoutRect visual_rect = EnclosingLayoutRect(visual_float_rect);
+  visual_rect = LayoutRect(EnclosingIntRect(visual_rect));
+
   switch (LineOrientation()) {
     case NGLineOrientation::kHorizontal:
       return NGPhysicalOffsetRect(visual_rect);
@@ -58,4 +69,10 @@
   return {};
 }
 
+bool NGPhysicalTextFragment::IsLineBreak() const {
+  // TODO(xiaochengh): Introduce and set a text fragment type flag in fragment
+  // builder, instead of check text content string.
+  return Text() == "\n";
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.h
index cc45f2d..8f31942 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_physical_text_fragment.h
@@ -106,6 +106,8 @@
                                    TextShapeResult()};
   }
 
+  bool IsLineBreak() const;
+
  private:
   // The text of NGInlineNode; i.e., of a parent block. The text for this
   // fragment is a substring(start_offset_, end_offset_) of this string.
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
index ccd59bf0..253074c 100644
--- a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
+++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
@@ -5,7 +5,7 @@
 #include "core/layout/ng/layout_ng_block_flow.h"
 
 #include "core/layout/LayoutAnalyzer.h"
-#include "core/layout/ng/inline/ng_inline_fragment_iterator.h"
+#include "core/layout/ng/inline/ng_inline_fragment_traversal.h"
 #include "core/layout/ng/inline/ng_inline_node_data.h"
 #include "core/layout/ng/ng_fragment_builder.h"
 #include "core/layout/ng/ng_length_utils.h"
@@ -218,7 +218,8 @@
   // Investigate why.
   if (!box_fragment)
     return false;
-  NGInlineFragmentIterator children(*box_fragment, layout_object);
+  auto children =
+      NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, layout_object);
   for (const auto& child : children) {
     NGPhysicalOffsetRect child_visual_rect = child.fragment->SelfVisualRect();
     visual_rect->Unite(child_visual_rect + child.offset_to_container_box);
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.cc b/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.cc
index 4a4f47a9..5d2c38f 100644
--- a/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.cc
+++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "core/layout/HitTestLocation.h"
-#include "core/layout/ng/inline/ng_inline_fragment_iterator.h"
 #include "core/layout/ng/inline/ng_inline_node_data.h"
 #include "core/layout/ng/ng_constraint_space.h"
 #include "core/layout/ng/ng_layout_result.h"
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
index b75c4ab..cd230ac 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
@@ -6,7 +6,7 @@
 
 #include "core/layout/LayoutObject.h"
 #include "core/layout/ng/inline/ng_inline_break_token.h"
-#include "core/layout/ng/inline/ng_inline_fragment_iterator.h"
+#include "core/layout/ng/inline/ng_inline_fragment_traversal.h"
 #include "core/layout/ng/inline/ng_inline_node.h"
 #include "core/layout/ng/inline/ng_physical_line_box_fragment.h"
 #include "core/layout/ng/ng_block_break_token.h"
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.h b/third_party/WebKit/Source/core/loader/EmptyClients.h
index 334600c..7abed33d 100644
--- a/third_party/WebKit/Source/core/loader/EmptyClients.h
+++ b/third_party/WebKit/Source/core/loader/EmptyClients.h
@@ -373,6 +373,9 @@
 
   void AnnotatedRegionsChanged() override {}
   String GetInstrumentationToken() override { return g_empty_string; };
+  String evaluateInInspectorOverlayForTesting(const String& script) override {
+    return g_empty_string;
+  }
 
  protected:
   EmptyLocalFrameClient() = default;
diff --git a/third_party/WebKit/Source/core/loader/InteractiveDetectorTest.cpp b/third_party/WebKit/Source/core/loader/InteractiveDetectorTest.cpp
index e808383..3565017 100644
--- a/third_party/WebKit/Source/core/loader/InteractiveDetectorTest.cpp
+++ b/third_party/WebKit/Source/core/loader/InteractiveDetectorTest.cpp
@@ -432,8 +432,8 @@
   detector->OnFirstMeaningfulPaintDetected(t0 + 3.0);
 
   // Post a task with 6 seconds duration.
-  platform_->CurrentThread()->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *platform_->CurrentThread()->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(
           &InteractiveDetectorTestWithDummyPage::DummyTaskWithDuration,
           CrossThreadUnretained(this), 6.0));
@@ -456,8 +456,8 @@
   detector->OnFirstMeaningfulPaintDetected(t0 + 3.0);
 
   // Long task 1.
-  platform_->CurrentThread()->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *platform_->CurrentThread()->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(
           &InteractiveDetectorTestWithDummyPage::DummyTaskWithDuration,
           CrossThreadUnretained(this), 0.1));
@@ -469,8 +469,8 @@
   EXPECT_EQ(detector->GetInteractiveTime(), long_task_1_end_time);
 
   // Long task 2.
-  platform_->CurrentThread()->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *platform_->CurrentThread()->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(
           &InteractiveDetectorTestWithDummyPage::DummyTaskWithDuration,
           CrossThreadUnretained(this), 0.1));
diff --git a/third_party/WebKit/Source/core/loader/PingLoader.cpp b/third_party/WebKit/Source/core/loader/PingLoader.cpp
index 4774a65..2d21f14 100644
--- a/third_party/WebKit/Source/core/loader/PingLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/PingLoader.cpp
@@ -172,24 +172,9 @@
   AtomicString content_type_;
 };
 
-// Decide if a beacon with the given size is allowed to go ahead
-// given some overall allowance limit.
-bool AllowBeaconWithSize(int allowance, unsigned long long size) {
-  // If a negative allowance is supplied, no size constraint is imposed.
-  if (allowance < 0)
-    return true;
-
-  if (static_cast<unsigned long long>(allowance) < size)
-    return false;
-
-  return true;
-}
-
 bool SendBeaconCommon(LocalFrame* frame,
-                      int allowance,
                       const KURL& url,
-                      const Beacon& beacon,
-                      size_t& beacon_size) {
+                      const Beacon& beacon) {
   if (!frame->GetDocument())
     return false;
 
@@ -200,12 +185,6 @@
     return true;
   }
 
-  unsigned long long size = beacon.size();
-  if (!AllowBeaconWithSize(allowance, size))
-    return false;
-
-  beacon_size = size;
-
   ResourceRequest request(url);
   request.SetHTTPMethod(HTTPNames::POST);
   request.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=0");
@@ -318,39 +297,31 @@
 }
 
 bool PingLoader::SendBeacon(LocalFrame* frame,
-                            int allowance,
                             const KURL& beacon_url,
-                            const String& data,
-                            size_t& beacon_size) {
+                            const String& data) {
   BeaconString beacon(data);
-  return SendBeaconCommon(frame, allowance, beacon_url, beacon, beacon_size);
+  return SendBeaconCommon(frame, beacon_url, beacon);
 }
 
 bool PingLoader::SendBeacon(LocalFrame* frame,
-                            int allowance,
                             const KURL& beacon_url,
-                            DOMArrayBufferView* data,
-                            size_t& beacon_size) {
+                            DOMArrayBufferView* data) {
   BeaconDOMArrayBufferView beacon(data);
-  return SendBeaconCommon(frame, allowance, beacon_url, beacon, beacon_size);
+  return SendBeaconCommon(frame, beacon_url, beacon);
 }
 
 bool PingLoader::SendBeacon(LocalFrame* frame,
-                            int allowance,
                             const KURL& beacon_url,
-                            FormData* data,
-                            size_t& beacon_size) {
+                            FormData* data) {
   BeaconFormData beacon(data);
-  return SendBeaconCommon(frame, allowance, beacon_url, beacon, beacon_size);
+  return SendBeaconCommon(frame, beacon_url, beacon);
 }
 
 bool PingLoader::SendBeacon(LocalFrame* frame,
-                            int allowance,
                             const KURL& beacon_url,
-                            Blob* data,
-                            size_t& beacon_size) {
+                            Blob* data) {
   BeaconBlob beacon(data);
-  return SendBeaconCommon(frame, allowance, beacon_url, beacon, beacon_size);
+  return SendBeaconCommon(frame, beacon_url, beacon);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/PingLoader.h b/third_party/WebKit/Source/core/loader/PingLoader.h
index 1997757a..af96198 100644
--- a/third_party/WebKit/Source/core/loader/PingLoader.h
+++ b/third_party/WebKit/Source/core/loader/PingLoader.h
@@ -77,14 +77,10 @@
   // The last argument is guaranteed to be set to the size of payload if
   // these method return true. If these method returns false, the value
   // shouldn't be used.
-  static bool SendBeacon(LocalFrame*, int, const KURL&, const String&, size_t&);
-  static bool SendBeacon(LocalFrame*,
-                         int,
-                         const KURL&,
-                         DOMArrayBufferView*,
-                         size_t&);
-  static bool SendBeacon(LocalFrame*, int, const KURL&, Blob*, size_t&);
-  static bool SendBeacon(LocalFrame*, int, const KURL&, FormData*, size_t&);
+  static bool SendBeacon(LocalFrame*, const KURL&, const String&);
+  static bool SendBeacon(LocalFrame*, const KURL&, DOMArrayBufferView*);
+  static bool SendBeacon(LocalFrame*, const KURL&, Blob*);
+  static bool SendBeacon(LocalFrame*, const KURL&, FormData*);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/PingLoaderTest.cpp b/third_party/WebKit/Source/core/loader/PingLoaderTest.cpp
index 4858f45..6448d1a 100644
--- a/third_party/WebKit/Source/core/loader/PingLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/PingLoaderTest.cpp
@@ -155,9 +155,7 @@
   KURL ping_url("https://localhost/bar.html");
   URLTestHelpers::RegisterMockedURLLoad(
       ping_url, testing::CoreTestDataPath("bar.html"), "text/html");
-  size_t size = 0;
-  PingLoader::SendBeacon(&page_holder_->GetFrame(), 123, ping_url, "hello",
-                         size);
+  PingLoader::SendBeacon(&page_holder_->GetFrame(), ping_url, "hello");
   Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
   const ResourceRequest& request = client_->PingRequest();
   ASSERT_FALSE(request.IsNull());
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
index 4dcd1a8..c6c47033 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
@@ -263,8 +263,8 @@
   void CreateLoader(ThreadableLoaderClient* client) override {
     std::unique_ptr<WaitableEvent> completion_event =
         std::make_unique<WaitableEvent>();
-    worker_loading_task_runner_->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *worker_loading_task_runner_, FROM_HERE,
         CrossThreadBind(&WorkerThreadableLoaderTestHelper::WorkerCreateLoader,
                         CrossThreadUnretained(this),
                         CrossThreadUnretained(client),
@@ -275,11 +275,12 @@
   void StartLoader(const ResourceRequest& request) override {
     std::unique_ptr<WaitableEvent> completion_event =
         std::make_unique<WaitableEvent>();
-    worker_loading_task_runner_->PostTask(
-        FROM_HERE, CrossThreadBind(
-                       &WorkerThreadableLoaderTestHelper::WorkerStartLoader,
-                       CrossThreadUnretained(this),
-                       CrossThreadUnretained(completion_event.get()), request));
+    PostCrossThreadTask(
+        *worker_loading_task_runner_, FROM_HERE,
+        CrossThreadBind(&WorkerThreadableLoaderTestHelper::WorkerStartLoader,
+                        CrossThreadUnretained(this),
+                        CrossThreadUnretained(completion_event.get()),
+                        request));
     completion_event->Wait();
   }
 
@@ -311,8 +312,8 @@
 
     std::unique_ptr<WaitableEvent> completion_event =
         std::make_unique<WaitableEvent>();
-    worker_loading_task_runner_->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *worker_loading_task_runner_, FROM_HERE,
         CrossThreadBind(&WorkerThreadableLoaderTestHelper::WorkerCallCheckpoint,
                         CrossThreadUnretained(this),
                         CrossThreadUnretained(completion_event.get()), n));
@@ -338,26 +339,26 @@
     worker_loading_task_runner_ =
         worker_thread_->GetTaskRunner(TaskType::kInternalTest);
 
-    worker_loading_task_runner_->PostTask(FROM_HERE,
-                                          CrossThreadBind(&SetUpMockURLs));
+    PostCrossThreadTask(*worker_loading_task_runner_, FROM_HERE,
+                        CrossThreadBind(&SetUpMockURLs));
     WaitForWorkerThreadSignal();
   }
 
   void OnServeRequests() override {
     testing::RunPendingTasks();
-    worker_loading_task_runner_->PostTask(
-        FROM_HERE, CrossThreadBind(&ServeAsynchronousRequests));
+    PostCrossThreadTask(*worker_loading_task_runner_, FROM_HERE,
+                        CrossThreadBind(&ServeAsynchronousRequests));
     WaitForWorkerThreadSignal();
   }
 
   void OnTearDown() override {
-    worker_loading_task_runner_->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *worker_loading_task_runner_, FROM_HERE,
         CrossThreadBind(&WorkerThreadableLoaderTestHelper::ClearLoader,
                         CrossThreadUnretained(this)));
     WaitForWorkerThreadSignal();
-    worker_loading_task_runner_->PostTask(
-        FROM_HERE, CrossThreadBind(&UnregisterAllURLsAndClearMemoryCache));
+    PostCrossThreadTask(*worker_loading_task_runner_, FROM_HERE,
+                        CrossThreadBind(&UnregisterAllURLsAndClearMemoryCache));
     WaitForWorkerThreadSignal();
 
     worker_thread_->Terminate();
@@ -413,8 +414,8 @@
 
   void WaitForWorkerThreadSignal() {
     WaitableEvent event;
-    worker_loading_task_runner_->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *worker_loading_task_runner_, FROM_HERE,
         CrossThreadBind(&WaitableEvent::Signal, CrossThreadUnretained(&event)));
     event.Wait();
   }
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
index e943087..ee4c802 100644
--- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -245,7 +245,6 @@
   DCHECK(!user_agent.IsNull());
   request.SetHTTPUserAgent(AtomicString(user_agent));
 
-  request.OverrideLoadingIPCType(WebURLRequest::LoadingIPCType::kMojo);
   WrappedResourceRequest webreq(request);
   web_context_->WillSendRequest(webreq);
 }
diff --git a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
index 8bea1587..c9f23ae 100644
--- a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
@@ -78,12 +78,14 @@
   void ForwardTask(const base::Location& location,
                    CrossThreadClosure task) override {
     DCHECK(IsMainThread());
-    worker_loading_task_runner_->PostTask(location, std::move(task));
+    PostCrossThreadTask(*worker_loading_task_runner_, location,
+                        std::move(task));
   }
   void ForwardTaskWithDoneSignal(const base::Location& location,
                                  CrossThreadClosure task) override {
     DCHECK(IsMainThread());
-    worker_loading_task_runner_->PostTask(location, std::move(task));
+    PostCrossThreadTask(*worker_loading_task_runner_, location,
+                        std::move(task));
   }
   void Abort() override { DCHECK(IsMainThread()); }
 
@@ -236,18 +238,17 @@
   WorkerThread* worker_thread = worker_global_scope_->GetThread();
   scoped_refptr<WebTaskRunner> worker_loading_task_runner =
       worker_global_scope_->GetTaskRunner(TaskType::kUnspecedLoading);
-  parent_frame_task_runners_->Get(TaskType::kUnspecedLoading)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(
-              &MainThreadLoaderHolder::CreateAndStart,
-              WrapCrossThreadPersistent(this),
-              WrapCrossThreadPersistent(worker_thread->GetLoadingContext()),
-              std::move(worker_loading_task_runner),
-              WrapCrossThreadPersistent(
-                  worker_thread->GetWorkerThreadLifecycleContext()),
-              request, threadable_loader_options_, resource_loader_options_,
-              event_with_tasks));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kUnspecedLoading), FROM_HERE,
+      CrossThreadBind(
+          &MainThreadLoaderHolder::CreateAndStart,
+          WrapCrossThreadPersistent(this),
+          WrapCrossThreadPersistent(worker_thread->GetLoadingContext()),
+          std::move(worker_loading_task_runner),
+          WrapCrossThreadPersistent(
+              worker_thread->GetWorkerThreadLifecycleContext()),
+          request, threadable_loader_options_, resource_loader_options_,
+          event_with_tasks));
 
   event_with_tasks->Wait();
 
@@ -272,19 +273,19 @@
   DCHECK(!IsMainThread());
   if (!main_thread_loader_holder_)
     return;
-  parent_frame_task_runners_->Get(TaskType::kUnspecedLoading)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&MainThreadLoaderHolder::OverrideTimeout,
-                          main_thread_loader_holder_, timeout_milliseconds));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kUnspecedLoading), FROM_HERE,
+      CrossThreadBind(&MainThreadLoaderHolder::OverrideTimeout,
+                      main_thread_loader_holder_, timeout_milliseconds));
 }
 
 void WorkerThreadableLoader::Cancel() {
   DCHECK(!IsMainThread());
   if (main_thread_loader_holder_) {
-    parent_frame_task_runners_->Get(TaskType::kUnspecedLoading)
-        ->PostTask(FROM_HERE, CrossThreadBind(&MainThreadLoaderHolder::Cancel,
-                                              main_thread_loader_holder_));
+    PostCrossThreadTask(
+        *parent_frame_task_runners_->Get(TaskType::kUnspecedLoading), FROM_HERE,
+        CrossThreadBind(&MainThreadLoaderHolder::Cancel,
+                        main_thread_loader_holder_));
     main_thread_loader_holder_ = nullptr;
   }
 
@@ -314,10 +315,10 @@
   DCHECK(main_thread_loader_holder);
   if (!client_) {
     // The thread is terminating.
-    parent_frame_task_runners_->Get(TaskType::kUnspecedLoading)
-        ->PostTask(FROM_HERE, CrossThreadBind(&MainThreadLoaderHolder::Cancel,
-                                              WrapCrossThreadPersistent(
-                                                  main_thread_loader_holder)));
+    PostCrossThreadTask(
+        *parent_frame_task_runners_->Get(TaskType::kUnspecedLoading), FROM_HERE,
+        CrossThreadBind(&MainThreadLoaderHolder::Cancel,
+                        WrapCrossThreadPersistent(main_thread_loader_holder)));
     return;
   }
 
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp
index 03819b4..05a3436 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoader.cpp
@@ -203,9 +203,9 @@
   // Step 10. "Let module script be the result of creating a module script given
   // source text, module map settings object, response's url, and options."
   // [spec text]
-  module_script_ = ModuleScript::Create(params->GetSourceText(), modulator_,
-                                        params->GetResponseUrl(), options_,
-                                        params->GetAccessControlStatus());
+  module_script_ = ModuleScript::Create(
+      params->GetSourceText(), modulator_, params->GetResponseUrl(),
+      params->GetResponseUrl(), options_, params->GetAccessControlStatus());
 
   AdvanceState(State::kFinished);
 }
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
index c68c1774..3fcef5cba7 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
@@ -82,15 +82,16 @@
   ScriptState* GetScriptState() override { return script_state_.get(); }
 
   ScriptModule CompileModule(const String& script,
-                             const String& url_str,
+                             const KURL& source_url,
+                             const KURL& base_url,
                              const ScriptFetchOptions& options,
                              AccessControlStatus access_control_status,
                              const TextPosition& position,
                              ExceptionState& exception_state) override {
     ScriptState::Scope scope(script_state_.get());
-    return ScriptModule::Compile(script_state_->GetIsolate(), script, url_str,
-                                 options, access_control_status, position,
-                                 exception_state);
+    return ScriptModule::Compile(
+        script_state_->GetIsolate(), script, source_url, base_url, options,
+        access_control_status, position, exception_state);
   }
 
   void SetModuleRequests(const Vector<String>& requests) {
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp
index 1098c4f..3335f7e3 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp
@@ -82,7 +82,7 @@
     source_text.Append("export default 'grapes';");
 
     ScriptModule script_module = ScriptModule::Compile(
-        script_state_->GetIsolate(), source_text.ToString(), url.GetString(),
+        script_state_->GetIsolate(), source_text.ToString(), url, url,
         ScriptFetchOptions(), kSharableCrossOrigin,
         TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
     auto* module_script = ModuleScript::CreateForTest(this, script_module, url);
diff --git a/third_party/WebKit/Source/core/messaging/MessagePort.cpp b/third_party/WebKit/Source/core/messaging/MessagePort.cpp
index ee273945..d941449 100644
--- a/third_party/WebKit/Source/core/messaging/MessagePort.cpp
+++ b/third_party/WebKit/Source/core/messaging/MessagePort.cpp
@@ -109,9 +109,9 @@
   if (AtomicTestAndSetToOne(&pending_dispatch_task_))
     return;
 
-  task_runner_->PostTask(FROM_HERE,
-                         CrossThreadBind(&MessagePort::DispatchMessages,
-                                         WrapCrossThreadPersistent(this)));
+  PostCrossThreadTask(*task_runner_, FROM_HERE,
+                      CrossThreadBind(&MessagePort::DispatchMessages,
+                                      WrapCrossThreadPersistent(this)));
 }
 
 void MessagePort::start() {
diff --git a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp
index 28f9ed4..49b6790 100644
--- a/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp
+++ b/third_party/WebKit/Source/core/mojo/MojoWatcher.cpp
@@ -154,8 +154,8 @@
   // dispatch a |MOJO_RESULT_CANCELLED| notification. That is always the last
   // notification received by this callback.
   MojoWatcher* watcher = reinterpret_cast<MojoWatcher*>(context);
-  watcher->task_runner_->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *watcher->task_runner_, FROM_HERE,
       CrossThreadBind(&MojoWatcher::RunReadyCallback,
                       WrapCrossThreadWeakPersistent(watcher), result));
 }
diff --git a/third_party/WebKit/Source/core/page/PagePopup.h b/third_party/WebKit/Source/core/page/PagePopup.h
index 2a07f5141..a8497811 100644
--- a/third_party/WebKit/Source/core/page/PagePopup.h
+++ b/third_party/WebKit/Source/core/page/PagePopup.h
@@ -33,9 +33,6 @@
 
 #include "platform/wtf/Forward.h"
 
-// To avoid conflicts with the CreateWindow macro from the Windows SDK...
-#undef PostMessage
-
 namespace blink {
 
 class AXObject;
@@ -47,7 +44,7 @@
  public:
   virtual AXObject* RootAXObject() = 0;
   virtual void SetWindowRect(const IntRect&) = 0;
-  virtual void PostMessage(const String& message) = 0;
+  virtual void PostMessageToPopup(const String& message) = 0;
 
  protected:
   virtual ~PagePopup() {}
diff --git a/third_party/WebKit/Source/core/paint/AdjustPaintOffsetScope.cpp b/third_party/WebKit/Source/core/paint/AdjustPaintOffsetScope.cpp
index e56826d..82f735c 100644
--- a/third_party/WebKit/Source/core/paint/AdjustPaintOffsetScope.cpp
+++ b/third_party/WebKit/Source/core/paint/AdjustPaintOffsetScope.cpp
@@ -13,14 +13,16 @@
   if (box.HasSelfPaintingLayer())
     return false;
 
-  const auto* paint_properties = box.FirstFragment().PaintProperties();
+  const auto* fragment = old_paint_info_.FragmentToPaint(box);
+  if (!fragment)
+    return false;
+  const auto* paint_properties = fragment->PaintProperties();
   if (!paint_properties || !paint_properties->PaintOffsetTranslation())
     return false;
 
-  DCHECK(box.FirstFragment().LocalBorderBoxProperties());
+  DCHECK(fragment->LocalBorderBoxProperties());
   contents_properties_.emplace(old_paint_info_.context.GetPaintController(),
-                               *box.FirstFragment().LocalBorderBoxProperties(),
-                               box);
+                               *fragment->LocalBorderBoxProperties(), box);
 
   new_paint_info_.emplace(old_paint_info_);
   new_paint_info_->UpdateCullRect(
diff --git a/third_party/WebKit/Source/core/paint/AdjustPaintOffsetScope.h b/third_party/WebKit/Source/core/paint/AdjustPaintOffsetScope.h
index 446e66dd..7ca7be4 100644
--- a/third_party/WebKit/Source/core/paint/AdjustPaintOffsetScope.h
+++ b/third_party/WebKit/Source/core/paint/AdjustPaintOffsetScope.h
@@ -12,8 +12,6 @@
 
 namespace blink {
 
-class ScopedPaintChunkProperties;
-
 class AdjustPaintOffsetScope {
   STACK_ALLOCATED();
 
diff --git a/third_party/WebKit/Source/core/paint/BlockPainter.cpp b/third_party/WebKit/Source/core/paint/BlockPainter.cpp
index d1f182a1..7e88403 100644
--- a/third_party/WebKit/Source/core/paint/BlockPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/BlockPainter.cpp
@@ -179,8 +179,8 @@
   // crbug.com/753124 in the future where the scrolling element's border is hit
   // test differently if composited.
 
-  const auto& fragment = layout_block_.FirstFragment();
-  const auto* properties = fragment.PaintProperties();
+  const auto* fragment = paint_info.FragmentToPaint(layout_block_);
+  const auto* properties = fragment ? fragment->PaintProperties() : nullptr;
 
   // Without RootLayerScrolling, the LayoutView will not create scroll paint
   // properties and will rely on the LocalFrameView providing a scroll
@@ -211,7 +211,7 @@
     // properties so that the scroll hit test is not clipped or scrolled.
     ScopedPaintChunkProperties scroll_hit_test_properties(
         paint_info.context.GetPaintController(),
-        *fragment.LocalBorderBoxProperties(), layout_block_);
+        *fragment->LocalBorderBoxProperties(), layout_block_);
     ScrollHitTestDisplayItem::Record(paint_info.context, layout_block_,
                                      DisplayItem::kScrollHitTest,
                                      properties->ScrollTranslation());
@@ -266,22 +266,24 @@
     Optional<ScrollRecorder> scroll_recorder;
     Optional<PaintInfo> scrolled_paint_info;
     if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-      const auto* object_properties =
-          layout_block_.FirstFragment().PaintProperties();
-      auto* scroll_translation =
-          object_properties ? object_properties->ScrollTranslation() : nullptr;
-      if (scroll_translation) {
-        scoped_scroll_property.emplace(
-            paint_info.context.GetPaintController(), scroll_translation,
-            layout_block_, DisplayItem::PaintPhaseToDrawingType(paint_phase));
-        scrolled_paint_info.emplace(paint_info);
-        if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
-          scrolled_paint_info->UpdateCullRectForScrollingContents(
-              EnclosingIntRect(layout_block_.OverflowClipRect(paint_offset)),
-              scroll_translation->Matrix().ToAffineTransform());
-        } else {
-          scrolled_paint_info->UpdateCullRect(
-              scroll_translation->Matrix().ToAffineTransform());
+      if (const auto* fragment = paint_info.FragmentToPaint(layout_block_)) {
+        const auto* object_properties = fragment->PaintProperties();
+        auto* scroll_translation = object_properties
+                                       ? object_properties->ScrollTranslation()
+                                       : nullptr;
+        if (scroll_translation) {
+          scoped_scroll_property.emplace(
+              paint_info.context.GetPaintController(), scroll_translation,
+              layout_block_, DisplayItem::PaintPhaseToDrawingType(paint_phase));
+          scrolled_paint_info.emplace(paint_info);
+          if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+            scrolled_paint_info->UpdateCullRectForScrollingContents(
+                EnclosingIntRect(layout_block_.OverflowClipRect(paint_offset)),
+                scroll_translation->Matrix().ToAffineTransform());
+          } else {
+            scrolled_paint_info->UpdateCullRect(
+                scroll_translation->Matrix().ToAffineTransform());
+          }
         }
       }
     } else if (layout_block_.HasOverflowClip()) {
diff --git a/third_party/WebKit/Source/core/paint/BoxClipper.cpp b/third_party/WebKit/Source/core/paint/BoxClipper.cpp
index 423ae19..2966aae 100644
--- a/third_party/WebKit/Source/core/paint/BoxClipper.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxClipper.cpp
@@ -44,12 +44,16 @@
     return;
 
   if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    const auto* properties = box_.FirstFragment().PaintProperties();
-    if (properties && properties->OverflowClip()) {
-      scoped_clip_property_.emplace(paint_info.context.GetPaintController(),
-                                    properties->OverflowClip(), box,
-                                    paint_info.DisplayItemTypeForClipping());
-    }
+    const auto* fragment = paint_info.FragmentToPaint(box_);
+    if (!fragment)
+      return;
+    const auto* properties = fragment->PaintProperties();
+    if (!properties || !properties->OverflowClip())
+      return;
+
+    scoped_clip_property_.emplace(paint_info.context.GetPaintController(),
+                                  properties->OverflowClip(), box,
+                                  paint_info.DisplayItemTypeForClipping());
     return;
   }
 
diff --git a/third_party/WebKit/Source/core/paint/BoxPainter.cpp b/third_party/WebKit/Source/core/paint/BoxPainter.cpp
index a449679..514f100 100644
--- a/third_party/WebKit/Source/core/paint/BoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPainter.cpp
@@ -65,10 +65,12 @@
                 paint_info.context.GetPaintController()
                     .CurrentPaintChunkProperties()
                     .backface_hidden);
-      scoped_scroll_property.emplace(
-          paint_info.context.GetPaintController(),
-          layout_box_.FirstFragment().ContentsProperties(), layout_box_,
-          DisplayItem::PaintPhaseToScrollType(paint_info.phase));
+      if (const auto* fragment = paint_info.FragmentToPaint(layout_box_)) {
+        scoped_scroll_property.emplace(
+            paint_info.context.GetPaintController(),
+            fragment->ContentsProperties(), layout_box_,
+            DisplayItem::PaintPhaseToScrollType(paint_info.phase));
+      }
     }
 
     // The background painting code assumes that the borders are part of the
diff --git a/third_party/WebKit/Source/core/paint/PaintInfo.h b/third_party/WebKit/Source/core/paint/PaintInfo.h
index a8cfbe4..3b5a76b 100644
--- a/third_party/WebKit/Source/core/paint/PaintInfo.h
+++ b/third_party/WebKit/Source/core/paint/PaintInfo.h
@@ -28,6 +28,7 @@
 #define PaintInfo_h
 
 #include "core/CoreExport.h"
+#include "core/layout/LayoutObject.h"
 // TODO(jchaffraix): Once we unify PaintBehavior and PaintLayerFlags, we should
 // move PaintLayerFlags to PaintPhase and rename it. Thus removing the need for
 // this #include "core/paint/PaintLayerPaintingInfo.h"
@@ -54,16 +55,18 @@
   USING_FAST_MALLOC(PaintInfo);
 
  public:
-  PaintInfo(GraphicsContext& new_context,
+  PaintInfo(GraphicsContext& context,
             const IntRect& cull_rect,
-            PaintPhase new_phase,
+            PaintPhase phase,
             GlobalPaintFlags global_paint_flags,
             PaintLayerFlags paint_flags,
-            const LayoutBoxModelObject* new_paint_container = nullptr)
-      : context(new_context),
-        phase(new_phase),
+            const LayoutBoxModelObject* paint_container = nullptr,
+            const LayoutPoint& pagination_offset = LayoutPoint())
+      : context(context),
+        phase(phase),
         cull_rect_(cull_rect),
-        paint_container_(new_paint_container),
+        paint_container_(paint_container),
+        pagination_offset_(pagination_offset),
         paint_flags_(paint_flags),
         global_paint_flags_(global_paint_flags) {}
 
@@ -73,6 +76,7 @@
         phase(copy_other_fields_from.phase),
         cull_rect_(copy_other_fields_from.cull_rect_),
         paint_container_(copy_other_fields_from.paint_container_),
+        pagination_offset_(copy_other_fields_from.pagination_offset_),
         paint_flags_(copy_other_fields_from.paint_flags_),
         global_paint_flags_(copy_other_fields_from.global_paint_flags_) {}
 
@@ -128,6 +132,20 @@
                                           local_to_parent_transform);
   }
 
+  // Returns the fragment of the current painting object matching the current
+  // layer fragment.
+  const FragmentData* FragmentToPaint(const LayoutObject& object) const {
+    for (const auto* fragment = &object.FirstFragment(); fragment;
+         fragment = fragment->NextFragment()) {
+      // TODO(chrishtr): This technique is fragile and need improvement.
+      if (fragment->PaginationOffset() == pagination_offset_)
+        return fragment;
+    }
+    // No fragment of the current painting object matches the layer fragment,
+    // which means the object should not paint in this fragment.
+    return nullptr;
+  }
+
   // FIXME: Introduce setters/getters at some point. Requires a lot of changes
   // throughout layout/.
   GraphicsContext& context;
@@ -139,6 +157,10 @@
   // The box model object that originates the current painting.
   const LayoutBoxModelObject* paint_container_;
 
+  // The pagination offset of the current fragment of the self-painting
+  // PaintLayer which initiated the current painting.
+  LayoutPoint pagination_offset_;
+
   const PaintLayerFlags paint_flags_;
   const GlobalPaintFlags global_paint_flags_;
 
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
index 83e0b44..3d981339 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -157,7 +157,7 @@
     GraphicsContext& context,
     const PaintLayerPaintingInfo& painting_info,
     PaintLayerFlags paint_flags,
-    FragmentPolicy fragment_policy) {
+    const PaintLayerFragment* fragment) {
   DCHECK(paint_layer_.IsSelfPaintingLayer() ||
          paint_layer_.HasSelfPaintingLayerDescendant());
 
@@ -165,7 +165,7 @@
       paint_flags & ~(kPaintLayerAppliedTransform);
   local_paint_flags |= kPaintLayerPaintingCompositingAllPhases;
   return PaintLayerContents(context, painting_info, local_paint_flags,
-                            fragment_policy);
+                            fragment);
 }
 
 static bool ShouldCreateSubsequence(const PaintLayer& paint_layer,
@@ -262,6 +262,8 @@
     return;
   // Paint properties for transforms, composited layers or LayoutView is already
   // taken care of.
+  // TODO(wangxianzhu): Also use this for PaintsWithTransform() and remove
+  // PaintLayerWithTransform() for SPv175.
   if (&paint_layer_ == painting_info.root_layer ||
       paint_layer_.PaintsWithTransform(painting_info.GetGlobalPaintFlags()) ||
       paint_layer_.PaintsIntoOwnOrGroupedBacking(
@@ -314,7 +316,7 @@
     GraphicsContext& context,
     const PaintLayerPaintingInfo& painting_info_arg,
     PaintLayerFlags paint_flags_arg,
-    FragmentPolicy fragment_policy) {
+    const PaintLayerFragment* fragment) {
   PaintLayerFlags paint_flags = paint_flags_arg;
   PaintResult result = kFullyPainted;
 
@@ -473,17 +475,20 @@
       respect_overflow_clip = kIgnoreOverflowClip;
     }
 
-    // TODO(trchen): We haven't decided how to handle visual fragmentation with
-    // SPv2.  Related thread
-    // https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuWFf-mxM
-    if (fragment_policy == kForceSingleFragment ||
-        RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+    if (fragment) {
+      // We are painting a single specified fragment.
+      // TODO(wangxianzhu): we could use |fragment| directly, but because
+      // the value of |fragment| is for SPv175 only for descendants to find the
+      // correct fragment state, we don't bother to modify SPv1 code with
+      // the risk of regressions. Eventually we will remove the whole
+      // PaintLayerWithTransform() path.
       paint_layer_for_fragments->AppendSingleFragmentIgnoringPagination(
           layer_fragments, local_painting_info.root_layer,
           local_painting_info.paint_dirty_rect, kUncachedClipRects,
           PaintLayer::kUseGeometryMapper, kIgnorePlatformOverlayScrollbarSize,
           respect_overflow_clip, &offset_from_root,
           local_painting_info.sub_pixel_accumulation);
+      layer_fragments[0].fragment_data = fragment->fragment_data;
     } else if (paint_layer_.GetLayoutObject()
                    .IsFixedPositionObjectInPagedMedia()) {
       PaintLayerFragments single_fragment;
@@ -774,6 +779,7 @@
     // path, when the transform has been applied.
     PaintLayerFragment fragment;
     fragment.background_rect = painting_info.paint_dirty_rect;
+    fragment.fragment_data = &paint_layer_.GetLayoutObject().FirstFragment();
     if (is_fixed_position_object_in_paged_media) {
       RepeatFixedPositionObjectInPages(fragment, painting_info,
                                        layer_fragments);
@@ -812,7 +818,7 @@
       }
     }
     if (PaintFragmentByApplyingTransform(context, painting_info, paint_flags,
-                                         fragment.pagination_offset) ==
+                                         fragment) ==
         kMayBeClippedByPaintDirtyRect)
       result = kMayBeClippedByPaintDirtyRect;
   }
@@ -823,13 +829,13 @@
     GraphicsContext& context,
     const PaintLayerPaintingInfo& painting_info,
     PaintLayerFlags paint_flags,
-    const LayoutPoint& fragment_translation) {
+    const PaintLayerFragment& fragment) {
   // This involves subtracting out the position of the layer in our current
   // coordinate space, but preserving the accumulated error for sub-pixel
   // layout.
   LayoutPoint delta;
   paint_layer_.ConvertToLayerCoords(painting_info.root_layer, delta);
-  delta.MoveBy(fragment_translation);
+  delta.MoveBy(fragment.pagination_offset);
   delta += painting_info.sub_pixel_accumulation;
   IntPoint rounded_delta = RoundedIntPoint(delta);
 
@@ -866,7 +872,7 @@
   }
 
   return PaintLayerContentsCompositingAllPhases(
-      context, transformed_painting_info, paint_flags, kForceSingleFragment);
+      context, transformed_painting_info, paint_flags, &fragment);
 }
 
 PaintResult PaintLayerPainter::PaintChildren(
@@ -1089,7 +1095,10 @@
   }
   PaintInfo paint_info(context, PixelSnappedIntRect(new_cull_rect), phase,
                        painting_info.GetGlobalPaintFlags(), paint_flags,
-                       &painting_info.root_layer->GetLayoutObject());
+                       &painting_info.root_layer->GetLayoutObject(),
+                       fragment.fragment_data
+                           ? fragment.fragment_data->PaginationOffset()
+                           : LayoutPoint());
 
   paint_layer_.GetLayoutObject().Paint(paint_info, paint_offset);
 }
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
index 7849e87e..07b3afb 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
@@ -28,28 +28,27 @@
   STACK_ALLOCATED();
 
  public:
-  enum FragmentPolicy { kAllowMultipleFragments, kForceSingleFragment };
-
   PaintLayerPainter(PaintLayer& paint_layer) : paint_layer_(paint_layer) {}
 
-  // The paint() method paints the layers that intersect the damage rect from
+  // The Paint() method paints the layers that intersect the damage rect from
   // back to front.  paint() assumes that the caller will clip to the bounds of
   // damageRect if necessary.
   void Paint(GraphicsContext&,
              const LayoutRect& damage_rect,
              const GlobalPaintFlags = kGlobalPaintNormalPhase,
              PaintLayerFlags = 0);
-  // paint() assumes that the caller will clip to the bounds of the painting
+  // Paint() assumes that the caller will clip to the bounds of the painting
   // dirty if necessary.
   PaintResult Paint(GraphicsContext&,
                     const PaintLayerPaintingInfo&,
                     PaintLayerFlags);
-  // paintLayerContents() assumes that the caller will clip to the bounds of the
-  // painting dirty rect if necessary.
+  // PaintLayerContents() assumes that the caller will clip to the bounds of the
+  // painting dirty rect if necessary. If PaintLayerFragment is not nullptr,
+  // only the specified fragment will be painted.
   PaintResult PaintLayerContents(GraphicsContext&,
                                  const PaintLayerPaintingInfo&,
                                  PaintLayerFlags,
-                                 FragmentPolicy = kAllowMultipleFragments);
+                                 const PaintLayerFragment* = nullptr);
 
   void PaintOverlayScrollbars(GraphicsContext&,
                               const LayoutRect& damage_rect,
@@ -74,15 +73,14 @@
       GraphicsContext&,
       const PaintLayerPaintingInfo&,
       PaintLayerFlags,
-      FragmentPolicy = kAllowMultipleFragments);
+      const PaintLayerFragment* = nullptr);
   PaintResult PaintLayerWithTransform(GraphicsContext&,
                                       const PaintLayerPaintingInfo&,
                                       PaintLayerFlags);
-  PaintResult PaintFragmentByApplyingTransform(
-      GraphicsContext&,
-      const PaintLayerPaintingInfo&,
-      PaintLayerFlags,
-      const LayoutPoint& fragment_translation);
+  PaintResult PaintFragmentByApplyingTransform(GraphicsContext&,
+                                               const PaintLayerPaintingInfo&,
+                                               PaintLayerFlags,
+                                               const PaintLayerFragment&);
 
   PaintResult PaintChildren(unsigned children_to_visit,
                             GraphicsContext&,
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index 265e46bb..62e09fe 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -150,6 +150,11 @@
     full_context.fragments.push_back(PaintPropertyTreeBuilderFragmentContext());
 
   PaintPropertyTreeBuilderFragmentContext& context = full_context.fragments[0];
+
+  context.current.containing_block_changed_under_filter = false;
+  context.absolute_position.containing_block_changed_under_filter = false;
+  context.fixed_position.containing_block_changed_under_filter = false;
+
   if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
     // With root layer scrolling, the LayoutView (a LayoutObject) properties are
     // updated like other objects (see updatePropertiesAndContextForSelf and
@@ -1216,6 +1221,20 @@
   }
 }
 
+static inline bool ContextsDiffer(
+    const PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext& a,
+    const PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext& b) {
+  if (a.clip != b.clip)
+    return true;
+  if (a.transform != b.transform)
+    return true;
+  if (a.paint_offset != b.paint_offset)
+    return true;
+  if (a.scroll != b.scroll)
+    return true;
+  return false;
+}
+
 void FragmentPaintPropertyTreeBuilder::UpdateOutOfFlowContext() {
   if (!object_.IsBoxModelObject() && !properties_)
     return;
@@ -1223,8 +1242,9 @@
   if (object_.IsLayoutBlock())
     context_.paint_offset_for_float = context_.current.paint_offset;
 
-  if (object_.CanContainAbsolutePositionObjects())
+  if (object_.CanContainAbsolutePositionObjects()) {
     context_.absolute_position = context_.current;
+  }
 
   if (object_.IsLayoutView()) {
     if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
@@ -1232,6 +1252,7 @@
       const auto* initial_fixed_scroll = context_.fixed_position.scroll;
 
       context_.fixed_position = context_.current;
+      context_.fixed_position.containing_block_changed_under_filter = false;
 
       // Fixed position transform and scroll nodes should not be affected.
       context_.fixed_position.transform = initial_fixed_transform;
@@ -1269,6 +1290,14 @@
     }
   }
 
+  if (NeedsFilter(object_)) {
+    if (ContextsDiffer(context_.current, context_.absolute_position))
+      context_.absolute_position.containing_block_changed_under_filter = true;
+
+    if (ContextsDiffer(context_.current, context_.fixed_position))
+      context_.fixed_position.containing_block_changed_under_filter = true;
+  }
+
   if (object_.NeedsPaintPropertyUpdate() ||
       full_context_.force_subtree_update) {
     if (properties_) {
@@ -1403,12 +1432,18 @@
         // relative to that transform, and hence the fixed-position element.
         if (context_.fixed_position.fixed_position_children_fixed_to_root)
           context_.current.paint_offset_root = &box_model_object;
+
         break;
       default:
         NOTREACHED();
     }
   }
 
+  if (context_.current.containing_block_changed_under_filter) {
+    UseCounter::Count(object_.GetDocument(),
+                      WebFeature::kFilterAsContainingBlockMayChangeOutput);
+  }
+
   if (object_.IsBox()) {
     // TODO(pdr): Several calls in this function walk back up the tree to
     // calculate containers (e.g., physicalLocation, offsetForInFlowPosition*).
@@ -1416,6 +1451,7 @@
     // PaintPropertyTreeBuilderFragmentContext instead of recomputing them.
     context_.current.paint_offset.MoveBy(
         ToLayoutBox(object_).PhysicalLocation());
+
     // This is a weird quirk that table cells paint as children of table rows,
     // but their location have the row's location baked-in.
     // Similar adjustment is done in LayoutTableCell::offsetFromContainer().
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
index d9aff961..ab38de87 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
@@ -48,6 +48,12 @@
     // be updated whenever |transform| is; flattening only needs to happen
     // to immediate children.
     bool should_flatten_inherited_transform = false;
+
+    // True if making filter a containing block for all descendants would
+    // change this context to a different one. This is used only for
+    // use-counting.
+    bool containing_block_changed_under_filter = false;
+
     // Rendering context for 3D sorting. See
     // TransformPaintPropertyNode::renderingContextId.
     unsigned rendering_context_id = 0;
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index 3d52a94..50ab160 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -3606,6 +3606,12 @@
 }
 
 TEST_P(PaintPropertyTreeBuilderTest, CompositedUnderMultiColumn) {
+  // TODO(crbug.com/796768): Currently this test crashes for SPv2 when mapping
+  // layer clip rects from one fragment to another. May need to adjust fragment
+  // clip hierarchy to fix the crash.
+  if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+    return;
+
   SetBodyInnerHTML(R"HTML(
     <style>body { margin: 0; }</style>
     <div id='multicol' style='columns:3; column-fill:auto; column-gap: 0;
@@ -4290,6 +4296,115 @@
             scroll_properties->PaintOffsetTranslation()->Matrix());
 }
 
+TEST_P(PaintPropertyTreeBuilderTest, FilterContainingBlockUseCounterRelPos) {
+  SetBodyInnerHTML(
+      "<div style='filter:blur(2px)'>"
+      "  <div id=target style='position:relative'></div>"
+      "</div>");
+
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
+TEST_P(PaintPropertyTreeBuilderTest, FilterContainingBlockUseCounterAbsPos) {
+  SetBodyInnerHTML(
+      "<div style='filter:blur(2px)'>"
+      "  <div id=target style='position:absolute'></div>"
+      "</div>");
+
+  EXPECT_TRUE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
+TEST_P(PaintPropertyTreeBuilderTest, FilterContainingBlockUseCounterStickyPos) {
+  SetBodyInnerHTML(
+      "<div style='filter:blur(2px)'>"
+      "  <div id=target style='position:sticky'></div>"
+      "</div>");
+
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
+TEST_P(PaintPropertyTreeBuilderTest, FilterContainingBlockUseCounterFixedPos) {
+  SetBodyInnerHTML(
+      "<div style='filter:blur(2px)'>"
+      "  <div id=target style='position:fixed'></div>"
+      "</div>");
+
+  EXPECT_TRUE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
+TEST_P(PaintPropertyTreeBuilderTest,
+       FilterContainingBlockUseCounterAbsPosAbsPos) {
+  SetBodyInnerHTML(
+      "<div style='filter:blur(2px); position:absolute'>"
+      "  <div id=target style='position:absolute'></div>"
+      "</div>");
+
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
+TEST_P(PaintPropertyTreeBuilderTest,
+       FilterContainingBlockUseCounterAbsPosFixedPos) {
+  SetBodyInnerHTML(
+      "<div style='filter:blur(2px); position:absolute'>"
+      "  <div id=target style='position:fixed'></div>"
+      "</div>"
+      "<div style='width: 10px; height: 1000px'></div>");
+
+  EXPECT_TRUE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
+TEST_P(PaintPropertyTreeBuilderTest,
+       FilterContainingBlockUseCounterFixedPosFixedPos) {
+  SetBodyInnerHTML(
+      "<div style='filter:blur(2px); position:fixed'>"
+      "  <div id=target style='position:fixed'></div>"
+      "</div>");
+
+  EXPECT_TRUE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
+TEST_P(PaintPropertyTreeBuilderTest,
+       FilterContainingBlockUseCounterFixedPosTransform) {
+  SetBodyInnerHTML(
+      "<div style='filter:blur(2px); transform: translateX(0)'>"
+      "  <div id=target style='position:fixed'></div>"
+      "</div>");
+
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
+// The body and html elements are special and won't affect change of
+// containing block for filter.
+TEST_P(PaintPropertyTreeBuilderTest,
+       FilterContainingBlockUseCounterFixedPosUnderFilteredBody) {
+  SetBodyInnerHTML(
+      "<body style='filter:blur(2px);'>"
+      "  <div id=target style='position:fixed'></div>"
+      "</body>");
+
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
+TEST_P(PaintPropertyTreeBuilderTest,
+       FilterContainingBlockUseCounterFixedPosUnderFilteredHTML) {
+  SetBodyInnerHTML(
+      "<html style='filter:blur(2px);'>"
+      "  <div id=target style='position:fixed'></div>"
+      "</html>");
+
+  EXPECT_FALSE(UseCounter::IsCounted(
+      GetDocument(), WebFeature::kFilterAsContainingBlockMayChangeOutput));
+}
+
 TEST_P(PaintPropertyTreeBuilderTest, CompositedLayerPaintOffsetTranslation) {
   SetBodyInnerHTML(R"HTML(
     <style>#target { position: absolute; top: 50px; left: 60px }</style>
diff --git a/third_party/WebKit/Source/core/paint/ReplacedPainter.cpp b/third_party/WebKit/Source/core/paint/ReplacedPainter.cpp
index 8d6a090..e302a2ee 100644
--- a/third_party/WebKit/Source/core/paint/ReplacedPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/ReplacedPainter.cpp
@@ -91,13 +91,15 @@
         completely_clipped_out = true;
       } else if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
         if (!layout_replaced_.IsSVGRoot()) {
-          const auto* properties =
-              layout_replaced_.FirstFragment().PaintProperties();
-          DCHECK(properties && properties->InnerBorderRadiusClip());
-          chunk_properties.emplace(
-              local_paint_info.context.GetPaintController(),
-              properties->InnerBorderRadiusClip(), layout_replaced_,
-              DisplayItem::PaintPhaseToDrawingType(local_paint_info.phase));
+          if (const auto* fragment =
+                  paint_info.FragmentToPaint(layout_replaced_)) {
+            const auto* properties = fragment->PaintProperties();
+            DCHECK(properties && properties->InnerBorderRadiusClip());
+            chunk_properties.emplace(
+                local_paint_info.context.GetPaintController(),
+                properties->InnerBorderRadiusClip(), layout_replaced_,
+                DisplayItem::PaintPhaseToDrawingType(local_paint_info.phase));
+          }
         }
       } else if (ShouldApplyViewportClip(layout_replaced_)) {
         // Push a clip if we have a border radius, since we want to round the
diff --git a/third_party/WebKit/Source/core/script/DynamicModuleResolverTest.cpp b/third_party/WebKit/Source/core/script/DynamicModuleResolverTest.cpp
index bc0f451..c559983 100644
--- a/third_party/WebKit/Source/core/script/DynamicModuleResolverTest.cpp
+++ b/third_party/WebKit/Source/core/script/DynamicModuleResolverTest.cpp
@@ -197,7 +197,7 @@
 
   ScriptModule record = ScriptModule::Compile(
       scope.GetIsolate(), "export const foo = 'hello';", TestReferrerURL(),
-      ScriptFetchOptions(), kSharableCrossOrigin,
+      TestReferrerURL(), ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ModuleScript* module_script =
       ModuleScript::CreateForTest(modulator, record, TestDependencyURL());
@@ -280,7 +280,7 @@
 
   ScriptModule record = ScriptModule::Compile(
       scope.GetIsolate(), "throw Error('bar')", TestReferrerURL(),
-      ScriptFetchOptions(), kSharableCrossOrigin,
+      TestReferrerURL(), ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ModuleScript* module_script =
       ModuleScript::CreateForTest(modulator, record, TestDependencyURL());
@@ -318,7 +318,7 @@
 
   ScriptModule record = ScriptModule::Compile(
       scope.GetIsolate(), "export const foo = 'hello';", TestDependencyURL(),
-      ScriptFetchOptions(), kSharableCrossOrigin,
+      TestDependencyURL(), ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   ModuleScript* module_script =
       ModuleScript::CreateForTest(modulator, record, TestDependencyURL());
diff --git a/third_party/WebKit/Source/core/script/Modulator.h b/third_party/WebKit/Source/core/script/Modulator.h
index 1f14e34..c958aaa3 100644
--- a/third_party/WebKit/Source/core/script/Modulator.h
+++ b/third_party/WebKit/Source/core/script/Modulator.h
@@ -129,7 +129,8 @@
   virtual bool HasValidContext() = 0;
 
   virtual ScriptModule CompileModule(const String& script,
-                                     const String& url_str,
+                                     const KURL& source_url,
+                                     const KURL& base_url,
                                      const ScriptFetchOptions&,
                                      AccessControlStatus,
                                      const TextPosition&,
diff --git a/third_party/WebKit/Source/core/script/ModulatorImplBase.cpp b/third_party/WebKit/Source/core/script/ModulatorImplBase.cpp
index 096090f..96220e9 100644
--- a/third_party/WebKit/Source/core/script/ModulatorImplBase.cpp
+++ b/third_party/WebKit/Source/core/script/ModulatorImplBase.cpp
@@ -119,7 +119,8 @@
 
 ScriptModule ModulatorImplBase::CompileModule(
     const String& provided_source,
-    const String& url_str,
+    const KURL& source_url,
+    const KURL& base_url,
     const ScriptFetchOptions& options,
     AccessControlStatus access_control_status,
     const TextPosition& position,
@@ -139,9 +140,9 @@
 
   // Step 5. Let result be ParseModule(script source, realm, script).
   ScriptState::Scope scope(script_state_.get());
-  return ScriptModule::Compile(script_state_->GetIsolate(), script_source,
-                               url_str, options, access_control_status,
-                               position, exception_state);
+  return ScriptModule::Compile(
+      script_state_->GetIsolate(), script_source, source_url, base_url, options,
+      access_control_status, position, exception_state);
 }
 
 ScriptValue ModulatorImplBase::InstantiateModule(ScriptModule script_module) {
diff --git a/third_party/WebKit/Source/core/script/ModulatorImplBase.h b/third_party/WebKit/Source/core/script/ModulatorImplBase.h
index 2fd6d03d..4dfc168 100644
--- a/third_party/WebKit/Source/core/script/ModulatorImplBase.h
+++ b/third_party/WebKit/Source/core/script/ModulatorImplBase.h
@@ -66,7 +66,8 @@
                           ScriptPromiseResolver*) override;
   ModuleImportMeta HostGetImportMetaProperties(ScriptModule) const override;
   ScriptModule CompileModule(const String& script,
-                             const String& url_str,
+                             const KURL& source_url,
+                             const KURL& base_url,
                              const ScriptFetchOptions&,
                              AccessControlStatus,
                              const TextPosition&,
diff --git a/third_party/WebKit/Source/core/script/ModuleScript.cpp b/third_party/WebKit/Source/core/script/ModuleScript.cpp
index c2548ff9..dd4871a 100644
--- a/third_party/WebKit/Source/core/script/ModuleScript.cpp
+++ b/third_party/WebKit/Source/core/script/ModuleScript.cpp
@@ -13,6 +13,7 @@
 
 ModuleScript* ModuleScript::Create(const String& source_text,
                                    Modulator* modulator,
+                                   const KURL& source_url,
                                    const KURL& base_url,
                                    const ScriptFetchOptions& options,
                                    AccessControlStatus access_control_status,
@@ -41,7 +42,7 @@
 
   // Delegate to Modulator::CompileModule to process Steps 3-5.
   ScriptModule result = modulator->CompileModule(
-      source_text, base_url.GetString(), options, access_control_status,
+      source_text, source_url, base_url, options, access_control_status,
       start_position, exception_state);
 
   // CreateInternal processes Steps 4 and 8-10.
diff --git a/third_party/WebKit/Source/core/script/ModuleScript.h b/third_party/WebKit/Source/core/script/ModuleScript.h
index 83f0d54d..0b419a9 100644
--- a/third_party/WebKit/Source/core/script/ModuleScript.h
+++ b/third_party/WebKit/Source/core/script/ModuleScript.h
@@ -28,6 +28,7 @@
   static ModuleScript* Create(
       const String& source_text,
       Modulator*,
+      const KURL& source_url,
       const KURL& base_url,
       const ScriptFetchOptions&,
       AccessControlStatus,
diff --git a/third_party/WebKit/Source/core/script/ScriptLoader.cpp b/third_party/WebKit/Source/core/script/ScriptLoader.cpp
index 54ecc84..9a2de59e 100644
--- a/third_party/WebKit/Source/core/script/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/script/ScriptLoader.cpp
@@ -508,11 +508,12 @@
         //     source text, settings, base URL, cryptographic nonce,
         //     parser state, and module script credentials mode."
         // TODO(kouhei,hiroshige): Update spec refs to use ScriptFetchOptions.
+        const KURL& source_url = element_document.Url();
         Modulator* modulator = Modulator::From(
             ToScriptStateForMainWorld(context_document->GetFrame()));
         ModuleScript* module_script = ModuleScript::Create(
-            element_->TextFromChildren(), modulator, base_url, options,
-            kSharableCrossOrigin, position);
+            element_->TextFromChildren(), modulator, source_url, base_url,
+            options, kSharableCrossOrigin, position);
 
         // 2. "If this returns null, set the script's script to null and abort
         //     these substeps; the script is ready."
diff --git a/third_party/WebKit/Source/core/script/ScriptModuleResolverImplTest.cpp b/third_party/WebKit/Source/core/script/ScriptModuleResolverImplTest.cpp
index 1895132..420654b4 100644
--- a/third_party/WebKit/Source/core/script/ScriptModuleResolverImplTest.cpp
+++ b/third_party/WebKit/Source/core/script/ScriptModuleResolverImplTest.cpp
@@ -66,9 +66,10 @@
 
 ModuleScript* CreateReferrerModuleScript(Modulator* modulator,
                                          V8TestingScope& scope) {
+  KURL js_url("https://example.com/referrer.js");
   ScriptModule referrer_record = ScriptModule::Compile(
-      scope.GetIsolate(), "import './target.js'; export const a = 42;",
-      "referrer.js", ScriptFetchOptions(), kSharableCrossOrigin,
+      scope.GetIsolate(), "import './target.js'; export const a = 42;", js_url,
+      js_url, ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   KURL referrer_url("https://example.com/referrer.js");
   auto* referrer_module_script =
@@ -79,8 +80,9 @@
 ModuleScript* CreateTargetModuleScript(Modulator* modulator,
                                        V8TestingScope& scope,
                                        bool has_parse_error = false) {
+  KURL js_url("https://example.com/target.js");
   ScriptModule record = ScriptModule::Compile(
-      scope.GetIsolate(), "export const pi = 3.14;", "target.js",
+      scope.GetIsolate(), "export const pi = 3.14;", js_url, js_url,
       ScriptFetchOptions(), kSharableCrossOrigin,
       TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
   KURL url("https://example.com/target.js");
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index 3b563d7e..28c47d91 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -1359,6 +1359,26 @@
   return g_null_atom;
 }
 
+LineLogicalSide ComputedStyle::GetTextEmphasisLineLogicalSide() const {
+  TextEmphasisPosition position = GetTextEmphasisPosition();
+  if (IsHorizontalWritingMode()) {
+    return position == TextEmphasisPosition::kOverRight ||
+                   position == TextEmphasisPosition::kOverLeft
+               ? LineLogicalSide::kOver
+               : LineLogicalSide::kUnder;
+  }
+  if (GetWritingMode() != WritingMode::kSidewaysLr) {
+    return position == TextEmphasisPosition::kOverRight ||
+                   position == TextEmphasisPosition::kUnderRight
+               ? LineLogicalSide::kOver
+               : LineLogicalSide::kUnder;
+  }
+  return position == TextEmphasisPosition::kOverLeft ||
+                 position == TextEmphasisPosition::kUnderLeft
+             ? LineLogicalSide::kOver
+             : LineLogicalSide::kUnder;
+}
+
 CSSAnimationData& ComputedStyle::AccessAnimations() {
   if (!AnimationsInternal())
     SetAnimationsInternal(CSSAnimationData::Create());
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 397c0252..900753764 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -876,6 +876,7 @@
     SetTextEmphasisMarkInternal(mark);
   }
   const AtomicString& TextEmphasisMarkString() const;
+  LineLogicalSide GetTextEmphasisLineLogicalSide() const;
 
   // -webkit-text-emphasis-color (aka -epub-text-emphasis-color)
   void SetTextEmphasisColor(const StyleColor& color) {
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index ee2174f..beceb82f 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -253,6 +253,11 @@
   kUnderLeft,
 };
 
+enum class LineLogicalSide {
+  kOver,
+  kUnder,
+};
+
 }  // namespace blink
 
 #endif  // ComputedStyleConstants_h
diff --git a/third_party/WebKit/Source/core/testing/DummyModulator.cpp b/third_party/WebKit/Source/core/testing/DummyModulator.cpp
index 1cebd79..e7c3c1c 100644
--- a/third_party/WebKit/Source/core/testing/DummyModulator.cpp
+++ b/third_party/WebKit/Source/core/testing/DummyModulator.cpp
@@ -113,7 +113,8 @@
 }
 
 ScriptModule DummyModulator::CompileModule(const String& script,
-                                           const String& url_str,
+                                           const KURL& source_url,
+                                           const KURL& base_url,
                                            const ScriptFetchOptions&,
                                            AccessControlStatus,
                                            const TextPosition&,
diff --git a/third_party/WebKit/Source/core/testing/DummyModulator.h b/third_party/WebKit/Source/core/testing/DummyModulator.h
index b942bb8..40efd27 100644
--- a/third_party/WebKit/Source/core/testing/DummyModulator.h
+++ b/third_party/WebKit/Source/core/testing/DummyModulator.h
@@ -54,7 +54,8 @@
                           ScriptPromiseResolver*) override;
   ModuleImportMeta HostGetImportMetaProperties(ScriptModule) const override;
   ScriptModule CompileModule(const String& script,
-                             const String& url_str,
+                             const KURL& source_url,
+                             const KURL& base_url,
                              const ScriptFetchOptions&,
                              AccessControlStatus,
                              const TextPosition&,
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index d0e4d221..d5abfd5 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -3547,6 +3547,13 @@
   CHECK(false) << "Intentional crash";
 }
 
+String Internals::evaluateInInspectorOverlay(const String& script) {
+  LocalFrame* frame = GetFrame();
+  if (frame && frame->Client())
+    return frame->Client()->evaluateInInspectorOverlayForTesting(script);
+  return g_empty_string;
+}
+
 void Internals::setIsLowEndDevice(bool is_low_end_device) {
   MemoryCoordinator::SetIsLowEndDeviceForTesting(is_low_end_device);
 }
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h
index 86e25acb..1163b65 100644
--- a/third_party/WebKit/Source/core/testing/Internals.h
+++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -588,6 +588,9 @@
   // Intentional crash.
   void crash();
 
+  // Exposed for testing of inspector overlay.
+  String evaluateInInspectorOverlay(const String& script);
+
   // Overrides if the device is low-end (low on memory).
   void setIsLowEndDevice(bool);
   // Returns if the device is low-end.
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl
index d4f286f2..460cc88b 100644
--- a/third_party/WebKit/Source/core/testing/Internals.idl
+++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -399,6 +399,8 @@
 
     void crash();
 
+    DOMString evaluateInInspectorOverlay(DOMString script);
+    
     void setIsLowEndDevice(boolean isLowEndDevice);
     boolean isLowEndDevice();
 
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_default_verbatim.html b/third_party/WebKit/Source/core/testing/data/input_mode_default_verbatim.html
deleted file mode 100644
index 0106ee3..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_default_verbatim.html
+++ /dev/null
@@ -1 +0,0 @@
-<input inputmode="Verbatim" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_textarea_verbatim.html b/third_party/WebKit/Source/core/testing/data/input_mode_textarea_verbatim.html
deleted file mode 100644
index 89f8978..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_textarea_verbatim.html
+++ /dev/null
@@ -1 +0,0 @@
-<textarea inputmode="Verbatim" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_decimal.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_decimal.html
new file mode 100644
index 0000000..a80852e
--- /dev/null
+++ b/third_party/WebKit/Source/core/testing/data/input_mode_type_decimal.html
@@ -0,0 +1 @@
+<input inputmode="decimal" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_full_width_latin.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_full_width_latin.html
deleted file mode 100644
index 2261828..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_full_width_latin.html
+++ /dev/null
@@ -1 +0,0 @@
-<input inputmode="full-width-latin" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_kana.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_kana.html
deleted file mode 100644
index 3efaa15d..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_kana.html
+++ /dev/null
@@ -1 +0,0 @@
-<input inputmode="kana" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_kana_name.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_kana_name.html
deleted file mode 100644
index 645d984..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_kana_name.html
+++ /dev/null
@@ -1 +0,0 @@
-<input inputmode="kana-name" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_kata_kana.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_kata_kana.html
deleted file mode 100644
index b6474a7..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_kata_kana.html
+++ /dev/null
@@ -1 +0,0 @@
-<input inputmode="katakana" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_latin.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_latin.html
deleted file mode 100644
index 0cd6df5..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_latin.html
+++ /dev/null
@@ -1 +0,0 @@
-<input inputmode="latin" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_latin_name.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_latin_name.html
deleted file mode 100644
index f846930..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_latin_name.html
+++ /dev/null
@@ -1 +0,0 @@
-<input inputmode="latin-name" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_latin_prose.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_latin_prose.html
deleted file mode 100644
index dd912e2b..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_latin_prose.html
+++ /dev/null
@@ -1 +0,0 @@
-<input inputmode="latin-prose" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_none.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_none.html
new file mode 100644
index 0000000..f494660
--- /dev/null
+++ b/third_party/WebKit/Source/core/testing/data/input_mode_type_none.html
@@ -0,0 +1 @@
+<input inputmode="none" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_search.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_search.html
new file mode 100644
index 0000000..5738060
--- /dev/null
+++ b/third_party/WebKit/Source/core/testing/data/input_mode_type_search.html
@@ -0,0 +1 @@
+<input inputmode="search" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_search_verbatim.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_search_verbatim.html
deleted file mode 100644
index 5c41bf3..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_search_verbatim.html
+++ /dev/null
@@ -1 +0,0 @@
-<input type="search" inputmode="verbatim" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_text.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_text.html
new file mode 100644
index 0000000..279cf90
--- /dev/null
+++ b/third_party/WebKit/Source/core/testing/data/input_mode_type_text.html
@@ -0,0 +1 @@
+<input inputmode="text" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_text_verbatim.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_text_verbatim.html
deleted file mode 100644
index f4d7552..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_text_verbatim.html
+++ /dev/null
@@ -1 +0,0 @@
-<input type="text" inputmode="verbatim" />
diff --git a/third_party/WebKit/Source/core/testing/data/input_mode_type_url_verbatim.html b/third_party/WebKit/Source/core/testing/data/input_mode_type_url_verbatim.html
deleted file mode 100644
index 550fec6..0000000
--- a/third_party/WebKit/Source/core/testing/data/input_mode_type_url_verbatim.html
+++ /dev/null
@@ -1 +0,0 @@
-<input type="url" inputmode="verbatim" />
diff --git a/third_party/WebKit/Source/core/testing/v8/WebCoreTestSupport.cpp b/third_party/WebKit/Source/core/testing/v8/WebCoreTestSupport.cpp
index 6f1e376..5705590 100644
--- a/third_party/WebKit/Source/core/testing/v8/WebCoreTestSupport.cpp
+++ b/third_party/WebKit/Source/core/testing/v8/WebCoreTestSupport.cpp
@@ -30,7 +30,7 @@
 #include "core/dom/Document.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/frame/LocalFrame.h"
-#include "core/origin_trials/OriginTrialContext.h"
+#include "core/origin_trials/origin_trials.h"
 #include "core/testing/InternalSettings.h"
 #include "core/testing/Internals.h"
 #include "core/testing/WorkerInternals.h"
@@ -92,11 +92,9 @@
 
   blink::ExecutionContext* execution_context =
       blink::ExecutionContext::From(script_state);
-  const blink::OriginTrialContext* originTrialContext =
-      blink::OriginTrialContext::From(execution_context);
 
   if (type == &blink::V8OriginTrialsTest::wrapperTypeInfo) {
-    if (originTrialContext && originTrialContext->IsTrialEnabled("Frobulate")) {
+    if (blink::OriginTrials::originTrialsSampleAPIEnabled(execution_context)) {
       blink::V8OriginTrialsTest::installOriginTrialsSampleAPI(
           script_state->GetIsolate(), script_state->World(),
           v8::Local<v8::Object>(), prototype_object, interface_object);
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
index 6a958118..97a4a6aa 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
@@ -80,9 +80,9 @@
         WTF::Passed(std::move(queued_task.message)),
         WTF::Passed(std::move(queued_task.channels)),
         CrossThreadUnretained(GetWorkerThread()), queued_task.stack_id);
-    GetWorkerThread()
-        ->GetTaskRunner(TaskType::kPostedMessage)
-        ->PostTask(FROM_HERE, std::move(task));
+    PostCrossThreadTask(
+        *GetWorkerThread()->GetTaskRunner(TaskType::kPostedMessage), FROM_HERE,
+        std::move(task));
   }
   queued_early_tasks_.clear();
 }
@@ -101,9 +101,9 @@
         CrossThreadUnretained(&WorkerObjectProxy()), std::move(message),
         WTF::Passed(std::move(channels)),
         CrossThreadUnretained(GetWorkerThread()), stack_id);
-    GetWorkerThread()
-        ->GetTaskRunner(TaskType::kPostedMessage)
-        ->PostTask(FROM_HERE, std::move(task));
+    PostCrossThreadTask(
+        *GetWorkerThread()->GetTaskRunner(TaskType::kPostedMessage), FROM_HERE,
+        std::move(task));
   } else {
     // GetWorkerThread() returns nullptr while the worker thread is being
     // created. In that case, push events into the queue and dispatch them in
@@ -164,13 +164,11 @@
   // The HTML spec requires to queue an error event using the DOM manipulation
   // task source.
   // https://html.spec.whatwg.org/multipage/workers.html#runtime-script-errors-2
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kDOMManipulation)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(
-                     &DedicatedWorkerObjectProxy::ProcessUnhandledException,
-                     CrossThreadUnretained(worker_object_proxy_.get()),
-                     exception_id, CrossThreadUnretained(GetWorkerThread())));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE,
+      CrossThreadBind(&DedicatedWorkerObjectProxy::ProcessUnhandledException,
+                      CrossThreadUnretained(worker_object_proxy_.get()),
+                      exception_id, CrossThreadUnretained(GetWorkerThread())));
 }
 
 void DedicatedWorkerMessagingProxy::Trace(blink::Visitor* visitor) {
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerObjectProxy.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerObjectProxy.cpp
index 070812e..602552b 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerObjectProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerObjectProxy.cpp
@@ -65,13 +65,11 @@
     scoped_refptr<SerializedScriptValue> message,
     Vector<MessagePortChannel> channels,
     const v8_inspector::V8StackTraceId& stack_id) {
-  GetParentFrameTaskRunners()
-      ->Get(TaskType::kPostedMessage)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(
-                     &DedicatedWorkerMessagingProxy::PostMessageToWorkerObject,
-                     messaging_proxy_weak_ptr_, std::move(message),
-                     WTF::Passed(std::move(channels)), stack_id));
+  PostCrossThreadTask(
+      *GetParentFrameTaskRunners()->Get(TaskType::kPostedMessage), FROM_HERE,
+      CrossThreadBind(&DedicatedWorkerMessagingProxy::PostMessageToWorkerObject,
+                      messaging_proxy_weak_ptr_, std::move(message),
+                      WTF::Passed(std::move(channels)), stack_id));
 }
 
 void DedicatedWorkerObjectProxy::ProcessMessageFromWorkerObject(
@@ -102,13 +100,11 @@
     const String& error_message,
     std::unique_ptr<SourceLocation> location,
     int exception_id) {
-  GetParentFrameTaskRunners()
-      ->Get(TaskType::kUnspecedTimer)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&DedicatedWorkerMessagingProxy::DispatchErrorEvent,
-                          messaging_proxy_weak_ptr_, error_message,
-                          WTF::Passed(location->Clone()), exception_id));
+  PostCrossThreadTask(
+      *GetParentFrameTaskRunners()->Get(TaskType::kUnspecedTimer), FROM_HERE,
+      CrossThreadBind(&DedicatedWorkerMessagingProxy::DispatchErrorEvent,
+                      messaging_proxy_weak_ptr_, error_message,
+                      WTF::Passed(location->Clone()), exception_id));
 }
 
 void DedicatedWorkerObjectProxy::DidCreateWorkerGlobalScope(
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
index 0ead576e..ab40ced2 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
@@ -48,9 +48,9 @@
   void CountFeature(WebFeature feature) {
     EXPECT_TRUE(IsCurrentThread());
     GlobalScope()->CountFeature(feature);
-    GetParentFrameTaskRunners()
-        ->Get(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
+    PostCrossThreadTask(
+        *GetParentFrameTaskRunners()->Get(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(&testing::ExitRunLoop));
   }
 
   // Emulates deprecated API use on DedicatedWorkerGlobalScope.
@@ -63,9 +63,9 @@
     String console_message = GetConsoleMessageStorage()->at(0)->Message();
     EXPECT_TRUE(console_message.Contains("deprecated"));
 
-    GetParentFrameTaskRunners()
-        ->Get(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
+    PostCrossThreadTask(
+        *GetParentFrameTaskRunners()->Get(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(&testing::ExitRunLoop));
   }
 
   void TestTaskRunner() {
@@ -73,9 +73,9 @@
     scoped_refptr<WebTaskRunner> task_runner =
         GlobalScope()->GetTaskRunner(TaskType::kInternalTest);
     EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
-    GetParentFrameTaskRunners()
-        ->Get(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
+    PostCrossThreadTask(
+        *GetParentFrameTaskRunners()->Get(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(&testing::ExitRunLoop));
   }
 };
 
@@ -224,23 +224,19 @@
   // API use on the DedicatedWorkerGlobalScope should be recorded in UseCounter
   // on the Document.
   EXPECT_FALSE(UseCounter::IsCounted(GetDocument(), kFeature1));
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&DedicatedWorkerThreadForTest::CountFeature,
-                          CrossThreadUnretained(GetWorkerThread()), kFeature1));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&DedicatedWorkerThreadForTest::CountFeature,
+                      CrossThreadUnretained(GetWorkerThread()), kFeature1));
   testing::EnterRunLoop();
   EXPECT_TRUE(UseCounter::IsCounted(GetDocument(), kFeature1));
 
   // API use should be reported to the Document only one time. See comments in
   // DedicatedWorkerObjectProxyForTest::CountFeature.
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&DedicatedWorkerThreadForTest::CountFeature,
-                          CrossThreadUnretained(GetWorkerThread()), kFeature1));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&DedicatedWorkerThreadForTest::CountFeature,
+                      CrossThreadUnretained(GetWorkerThread()), kFeature1));
   testing::EnterRunLoop();
 
   // This feature is randomly selected from Deprecation::deprecationMessage().
@@ -249,23 +245,19 @@
   // Deprecated API use on the DedicatedWorkerGlobalScope should be recorded in
   // UseCounter on the Document.
   EXPECT_FALSE(UseCounter::IsCounted(GetDocument(), kFeature2));
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&DedicatedWorkerThreadForTest::CountDeprecation,
-                          CrossThreadUnretained(GetWorkerThread()), kFeature2));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&DedicatedWorkerThreadForTest::CountDeprecation,
+                      CrossThreadUnretained(GetWorkerThread()), kFeature2));
   testing::EnterRunLoop();
   EXPECT_TRUE(UseCounter::IsCounted(GetDocument(), kFeature2));
 
   // API use should be reported to the Document only one time. See comments in
   // DedicatedWorkerObjectProxyForTest::CountDeprecation.
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&DedicatedWorkerThreadForTest::CountDeprecation,
-                          CrossThreadUnretained(GetWorkerThread()), kFeature2));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&DedicatedWorkerThreadForTest::CountDeprecation,
+                      CrossThreadUnretained(GetWorkerThread()), kFeature2));
   testing::EnterRunLoop();
 }
 
@@ -273,11 +265,10 @@
   const String source_code = "// Do nothing";
   WorkerMessagingProxy()->StartWithSourceCode(source_code);
 
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(&DedicatedWorkerThreadForTest::TestTaskRunner,
-                                 CrossThreadUnretained(GetWorkerThread())));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&DedicatedWorkerThreadForTest::TestTaskRunner,
+                      CrossThreadUnretained(GetWorkerThread())));
   testing::EnterRunLoop();
 }
 
diff --git a/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.cpp b/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.cpp
index 4fc3e1e..99a19cf 100644
--- a/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/SharedWorkerReportingProxy.cpp
@@ -25,10 +25,10 @@
 
 void SharedWorkerReportingProxy::CountFeature(WebFeature feature) {
   DCHECK(!IsMainThread());
-  parent_frame_task_runners_->Get(TaskType::kUnspecedTimer)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(&WebSharedWorkerImpl::CountFeature,
-                                 CrossThreadUnretained(worker_), feature));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kUnspecedTimer), FROM_HERE,
+      CrossThreadBind(&WebSharedWorkerImpl::CountFeature,
+                      CrossThreadUnretained(worker_), feature));
 }
 
 void SharedWorkerReportingProxy::CountDeprecation(WebFeature feature) {
@@ -61,27 +61,26 @@
   DCHECK(!IsMainThread());
   // The TaskType of Inspector tasks need to be Unthrottled because they need to
   // run even on a suspended page.
-  parent_frame_task_runners_->Get(TaskType::kUnthrottled)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&WebSharedWorkerImpl::PostMessageToPageInspector,
-                          CrossThreadUnretained(worker_), session_id, message));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kUnthrottled), FROM_HERE,
+      CrossThreadBind(&WebSharedWorkerImpl::PostMessageToPageInspector,
+                      CrossThreadUnretained(worker_), session_id, message));
 }
 
 void SharedWorkerReportingProxy::DidCloseWorkerGlobalScope() {
   DCHECK(!IsMainThread());
-  parent_frame_task_runners_->Get(TaskType::kUnspecedTimer)
-      ->PostTask(FROM_HERE, CrossThreadBind(
-                                &WebSharedWorkerImpl::DidCloseWorkerGlobalScope,
-                                CrossThreadUnretained(worker_)));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kUnspecedTimer), FROM_HERE,
+      CrossThreadBind(&WebSharedWorkerImpl::DidCloseWorkerGlobalScope,
+                      CrossThreadUnretained(worker_)));
 }
 
 void SharedWorkerReportingProxy::DidTerminateWorkerThread() {
   DCHECK(!IsMainThread());
-  parent_frame_task_runners_->Get(TaskType::kUnspecedTimer)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(&WebSharedWorkerImpl::DidTerminateWorkerThread,
-                                 CrossThreadUnretained(worker_)));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kUnspecedTimer), FROM_HERE,
+      CrossThreadBind(&WebSharedWorkerImpl::DidTerminateWorkerThread,
+                      CrossThreadUnretained(worker_)));
 }
 
 void SharedWorkerReportingProxy::Trace(blink::Visitor* visitor) {
diff --git a/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.cpp b/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.cpp
index 52aaaa9..4d48d120 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedObjectProxyBase.cpp
@@ -17,32 +17,28 @@
 namespace blink {
 
 void ThreadedObjectProxyBase::CountFeature(WebFeature feature) {
-  GetParentFrameTaskRunners()
-      ->Get(TaskType::kUnspecedTimer)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(&ThreadedMessagingProxyBase::CountFeature,
-                                 MessagingProxyWeakPtr(), feature));
+  PostCrossThreadTask(
+      *GetParentFrameTaskRunners()->Get(TaskType::kUnspecedTimer), FROM_HERE,
+      CrossThreadBind(&ThreadedMessagingProxyBase::CountFeature,
+                      MessagingProxyWeakPtr(), feature));
 }
 
 void ThreadedObjectProxyBase::CountDeprecation(WebFeature feature) {
-  GetParentFrameTaskRunners()
-      ->Get(TaskType::kUnspecedTimer)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(&ThreadedMessagingProxyBase::CountDeprecation,
-                                 MessagingProxyWeakPtr(), feature));
+  PostCrossThreadTask(
+      *GetParentFrameTaskRunners()->Get(TaskType::kUnspecedTimer), FROM_HERE,
+      CrossThreadBind(&ThreadedMessagingProxyBase::CountDeprecation,
+                      MessagingProxyWeakPtr(), feature));
 }
 
 void ThreadedObjectProxyBase::ReportConsoleMessage(MessageSource source,
                                                    MessageLevel level,
                                                    const String& message,
                                                    SourceLocation* location) {
-  GetParentFrameTaskRunners()
-      ->Get(TaskType::kUnspecedTimer)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&ThreadedMessagingProxyBase::ReportConsoleMessage,
-                          MessagingProxyWeakPtr(), source, level, message,
-                          WTF::Passed(location->Clone())));
+  PostCrossThreadTask(
+      *GetParentFrameTaskRunners()->Get(TaskType::kUnspecedTimer), FROM_HERE,
+      CrossThreadBind(&ThreadedMessagingProxyBase::ReportConsoleMessage,
+                      MessagingProxyWeakPtr(), source, level, message,
+                      WTF::Passed(location->Clone())));
 }
 
 void ThreadedObjectProxyBase::PostMessageToPageInspector(
@@ -50,31 +46,25 @@
     const String& message) {
   // The TaskType of Inspector tasks need to be Unthrottled because they need to
   // run even on a suspended page.
-  GetParentFrameTaskRunners()
-      ->Get(TaskType::kUnthrottled)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(
-                     &ThreadedMessagingProxyBase::PostMessageToPageInspector,
-                     MessagingProxyWeakPtr(), session_id, message));
+  PostCrossThreadTask(
+      *GetParentFrameTaskRunners()->Get(TaskType::kUnthrottled), FROM_HERE,
+      CrossThreadBind(&ThreadedMessagingProxyBase::PostMessageToPageInspector,
+                      MessagingProxyWeakPtr(), session_id, message));
 }
 
 void ThreadedObjectProxyBase::DidCloseWorkerGlobalScope() {
-  GetParentFrameTaskRunners()
-      ->Get(TaskType::kUnspecedTimer)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&ThreadedMessagingProxyBase::TerminateGlobalScope,
-                          MessagingProxyWeakPtr()));
+  PostCrossThreadTask(
+      *GetParentFrameTaskRunners()->Get(TaskType::kUnspecedTimer), FROM_HERE,
+      CrossThreadBind(&ThreadedMessagingProxyBase::TerminateGlobalScope,
+                      MessagingProxyWeakPtr()));
 }
 
 void ThreadedObjectProxyBase::DidTerminateWorkerThread() {
   // This will terminate the MessagingProxy.
-  GetParentFrameTaskRunners()
-      ->Get(TaskType::kUnspecedTimer)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&ThreadedMessagingProxyBase::WorkerThreadTerminated,
-                          MessagingProxyWeakPtr()));
+  PostCrossThreadTask(
+      *GetParentFrameTaskRunners()->Get(TaskType::kUnspecedTimer), FROM_HERE,
+      CrossThreadBind(&ThreadedMessagingProxyBase::WorkerThreadTerminated,
+                      MessagingProxyWeakPtr()));
 }
 
 ParentFrameTaskRunners* ThreadedObjectProxyBase::GetParentFrameTaskRunners() {
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
index 402c124..219a57e 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
@@ -63,17 +63,15 @@
     scoped_refptr<WebTaskRunner> outside_settings_task_runner,
     WorkletPendingTasks* pending_tasks) {
   DCHECK(IsMainThread());
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kUnspecedLoading)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(
-                     &ThreadedWorkletObjectProxy::FetchAndInvokeScript,
-                     CrossThreadUnretained(worklet_object_proxy_.get()),
-                     module_url_record,
-                     WrapCrossThreadPersistent(module_responses_map),
-                     credentials_mode, std::move(outside_settings_task_runner),
-                     WrapCrossThreadPersistent(pending_tasks),
-                     CrossThreadUnretained(GetWorkerThread())));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kUnspecedLoading), FROM_HERE,
+      CrossThreadBind(&ThreadedWorkletObjectProxy::FetchAndInvokeScript,
+                      CrossThreadUnretained(worklet_object_proxy_.get()),
+                      module_url_record,
+                      WrapCrossThreadPersistent(module_responses_map),
+                      credentials_mode, std::move(outside_settings_task_runner),
+                      WrapCrossThreadPersistent(pending_tasks),
+                      CrossThreadUnretained(GetWorkerThread())));
 }
 
 void ThreadedWorkletMessagingProxy::WorkletObjectDestroyed() {
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
index bd63d12a..8ecda7f9 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
@@ -83,9 +83,9 @@
     // the owner Document's SecurityOrigin shouldn't.
     EXPECT_TRUE(global_scope->GetSecurityOrigin()->IsUnique());
     EXPECT_FALSE(global_scope->DocumentSecurityOrigin()->IsUnique());
-    GetParentFrameTaskRunners()
-        ->Get(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
+    PostCrossThreadTask(
+        *GetParentFrameTaskRunners()->Get(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(&testing::ExitRunLoop));
   }
 
   void TestContentSecurityPolicy() {
@@ -107,18 +107,18 @@
         KURL("https://disallowed.example.com"), String(),
         IntegrityMetadataSet(), kParserInserted));
 
-    GetParentFrameTaskRunners()
-        ->Get(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
+    PostCrossThreadTask(
+        *GetParentFrameTaskRunners()->Get(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(&testing::ExitRunLoop));
   }
 
   // Emulates API use on ThreadedWorkletGlobalScope.
   void CountFeature(WebFeature feature) {
     EXPECT_TRUE(IsCurrentThread());
     GlobalScope()->CountFeature(feature);
-    GetParentFrameTaskRunners()
-        ->Get(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
+    PostCrossThreadTask(
+        *GetParentFrameTaskRunners()->Get(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(&testing::ExitRunLoop));
   }
 
   // Emulates deprecated API use on ThreadedWorkletGlobalScope.
@@ -131,9 +131,9 @@
     String console_message = GetConsoleMessageStorage()->at(0)->Message();
     EXPECT_TRUE(console_message.Contains("deprecated"));
 
-    GetParentFrameTaskRunners()
-        ->Get(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
+    PostCrossThreadTask(
+        *GetParentFrameTaskRunners()->Get(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(&testing::ExitRunLoop));
   }
 
   void TestTaskRunner() {
@@ -141,9 +141,9 @@
     scoped_refptr<WebTaskRunner> task_runner =
         GlobalScope()->GetTaskRunner(TaskType::kInternalTest);
     EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
-    GetParentFrameTaskRunners()
-        ->Get(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
+    PostCrossThreadTask(
+        *GetParentFrameTaskRunners()->Get(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(&testing::ExitRunLoop));
   }
 
  private:
@@ -231,12 +231,10 @@
 TEST_F(ThreadedWorkletTest, SecurityOrigin) {
   MessagingProxy()->Start();
 
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&ThreadedWorkletThreadForTest::TestSecurityOrigin,
-                          CrossThreadUnretained(GetWorkerThread())));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&ThreadedWorkletThreadForTest::TestSecurityOrigin,
+                      CrossThreadUnretained(GetWorkerThread())));
   testing::EnterRunLoop();
 }
 
@@ -251,12 +249,10 @@
 
   MessagingProxy()->Start();
 
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(
-                     &ThreadedWorkletThreadForTest::TestContentSecurityPolicy,
-                     CrossThreadUnretained(GetWorkerThread())));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&ThreadedWorkletThreadForTest::TestContentSecurityPolicy,
+                      CrossThreadUnretained(GetWorkerThread())));
   testing::EnterRunLoop();
 }
 
@@ -269,23 +265,19 @@
   // API use on the ThreadedWorkletGlobalScope should be recorded in UseCounter
   // on the Document.
   EXPECT_FALSE(UseCounter::IsCounted(GetDocument(), kFeature1));
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&ThreadedWorkletThreadForTest::CountFeature,
-                          CrossThreadUnretained(GetWorkerThread()), kFeature1));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&ThreadedWorkletThreadForTest::CountFeature,
+                      CrossThreadUnretained(GetWorkerThread()), kFeature1));
   testing::EnterRunLoop();
   EXPECT_TRUE(UseCounter::IsCounted(GetDocument(), kFeature1));
 
   // API use should be reported to the Document only one time. See comments in
   // ThreadedWorkletGlobalScopeForTest::CountFeature.
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&ThreadedWorkletThreadForTest::CountFeature,
-                          CrossThreadUnretained(GetWorkerThread()), kFeature1));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&ThreadedWorkletThreadForTest::CountFeature,
+                      CrossThreadUnretained(GetWorkerThread()), kFeature1));
   testing::EnterRunLoop();
 
   // This feature is randomly selected from Deprecation::deprecationMessage().
@@ -294,34 +286,29 @@
   // Deprecated API use on the ThreadedWorkletGlobalScope should be recorded in
   // UseCounter on the Document.
   EXPECT_FALSE(UseCounter::IsCounted(GetDocument(), kFeature2));
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&ThreadedWorkletThreadForTest::CountDeprecation,
-                          CrossThreadUnretained(GetWorkerThread()), kFeature2));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&ThreadedWorkletThreadForTest::CountDeprecation,
+                      CrossThreadUnretained(GetWorkerThread()), kFeature2));
   testing::EnterRunLoop();
   EXPECT_TRUE(UseCounter::IsCounted(GetDocument(), kFeature2));
 
   // API use should be reported to the Document only one time. See comments in
   // ThreadedWorkletGlobalScopeForTest::CountDeprecation.
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&ThreadedWorkletThreadForTest::CountDeprecation,
-                          CrossThreadUnretained(GetWorkerThread()), kFeature2));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&ThreadedWorkletThreadForTest::CountDeprecation,
+                      CrossThreadUnretained(GetWorkerThread()), kFeature2));
   testing::EnterRunLoop();
 }
 
 TEST_F(ThreadedWorkletTest, TaskRunner) {
   MessagingProxy()->Start();
 
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kInternalTest)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(&ThreadedWorkletThreadForTest::TestTaskRunner,
-                                 CrossThreadUnretained(GetWorkerThread())));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+      CrossThreadBind(&ThreadedWorkletThreadForTest::TestTaskRunner,
+                      CrossThreadUnretained(GetWorkerThread())));
   testing::EnterRunLoop();
 }
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
index 92c84bb5..152c31b1 100644
--- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -378,10 +378,9 @@
 }
 
 void WorkerGlobalScope::RemoveURLFromMemoryCache(const KURL& url) {
-  thread_->GetParentFrameTaskRunners()
-      ->Get(TaskType::kNetworking)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(&RemoveURLFromMemoryCacheInternal, url));
+  PostCrossThreadTask(
+      *thread_->GetParentFrameTaskRunners()->Get(TaskType::kNetworking),
+      FROM_HERE, CrossThreadBind(&RemoveURLFromMemoryCacheInternal, url));
 }
 
 void WorkerGlobalScope::SetWorkerSettings(
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
index a95fb4e..57b4bdd 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -128,23 +128,22 @@
     std::unique_ptr<Vector<char>> cached_meta_data,
     const v8_inspector::V8StackTraceId& stack_id) {
   DCHECK(IsMainThread());
-  GetTaskRunner(TaskType::kUnthrottled)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&WorkerThread::EvaluateClassicScriptOnWorkerThread,
-                          CrossThreadUnretained(this), script_url, source_code,
-                          WTF::Passed(std::move(cached_meta_data)), stack_id));
+  PostCrossThreadTask(
+      *GetTaskRunner(TaskType::kUnthrottled), FROM_HERE,
+      CrossThreadBind(&WorkerThread::EvaluateClassicScriptOnWorkerThread,
+                      CrossThreadUnretained(this), script_url, source_code,
+                      WTF::Passed(std::move(cached_meta_data)), stack_id));
 }
 
 void WorkerThread::ImportModuleScript(
     const KURL& script_url,
     network::mojom::FetchCredentialsMode credentials_mode) {
   DCHECK(IsMainThread());
-  GetTaskRunner(TaskType::kUnthrottled)
-      ->PostTask(FROM_HERE, CrossThreadBind(
-                                &WorkerThread::ImportModuleScriptOnWorkerThread,
-                                CrossThreadUnretained(this), script_url,
-                                credentials_mode));
+  PostCrossThreadTask(
+      *GetTaskRunner(TaskType::kUnthrottled), FROM_HERE,
+      CrossThreadBind(&WorkerThread::ImportModuleScriptOnWorkerThread,
+                      CrossThreadUnretained(this), script_url,
+                      credentials_mode));
 }
 
 void WorkerThread::Terminate() {
@@ -247,11 +246,10 @@
     if (GetIsolate() && thread_state_ != ThreadState::kReadyToShutdown)
       inspector_task_runner_->InterruptAndRunAllTasksDontWait(GetIsolate());
   }
-  GetTaskRunner(TaskType::kUnthrottled)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(
-                     &WorkerThread::PerformDebuggerTaskDontWaitOnWorkerThread,
-                     CrossThreadUnretained(this)));
+  PostCrossThreadTask(
+      *GetTaskRunner(TaskType::kUnthrottled), FROM_HERE,
+      CrossThreadBind(&WorkerThread::PerformDebuggerTaskDontWaitOnWorkerThread,
+                      CrossThreadUnretained(this)));
 }
 
 void WorkerThread::StartRunningDebuggerTasksOnPauseOnWorkerThread() {
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
index eb3869d..59108cd 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
@@ -57,9 +57,9 @@
   EXPECT_TRUE(worker_thread->IsCurrentThread());
 
   // Notify the main thread that the debugger task is waiting for the signal.
-  worker_thread->GetParentFrameTaskRunners()
-      ->Get(TaskType::kInternalTest)
-      ->PostTask(FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
+  PostCrossThreadTask(
+      *worker_thread->GetParentFrameTaskRunners()->Get(TaskType::kInternalTest),
+      FROM_HERE, CrossThreadBind(&testing::ExitRunLoop));
   waitable_event->Wait();
 }
 
diff --git a/third_party/WebKit/Source/core/workers/WorkletModuleResponsesMapProxy.cpp b/third_party/WebKit/Source/core/workers/WorkletModuleResponsesMapProxy.cpp
index a30bdcba..c13fb18 100644
--- a/third_party/WebKit/Source/core/workers/WorkletModuleResponsesMapProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkletModuleResponsesMapProxy.cpp
@@ -34,15 +34,16 @@
 
   void OnRead(const ModuleScriptCreationParams& params) override {
     DCHECK(IsMainThread());
-    inside_settings_task_runner_->PostTask(
-        FROM_HERE, CrossThreadBind(&WorkletModuleResponsesMap::Client::OnRead,
-                                   client_, params));
+    PostCrossThreadTask(
+        *inside_settings_task_runner_, FROM_HERE,
+        CrossThreadBind(&WorkletModuleResponsesMap::Client::OnRead, client_,
+                        params));
   }
 
   void OnFailed() override {
     DCHECK(IsMainThread());
-    inside_settings_task_runner_->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *inside_settings_task_runner_, FROM_HERE,
         CrossThreadBind(&WorkletModuleResponsesMap::Client::OnFailed, client_));
   }
 
@@ -73,8 +74,8 @@
     const FetchParameters& fetch_params,
     Client* client) {
   DCHECK(inside_settings_task_runner_->RunsTasksInCurrentSequence());
-  outside_settings_task_runner_->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *outside_settings_task_runner_, FROM_HERE,
       CrossThreadBind(&WorkletModuleResponsesMapProxy::ReadEntryOnMainThread,
                       WrapCrossThreadPersistent(this), fetch_params,
                       WrapCrossThreadPersistent(client)));
diff --git a/third_party/WebKit/Source/core/workers/WorkletModuleTreeClient.cpp b/third_party/WebKit/Source/core/workers/WorkletModuleTreeClient.cpp
index 6adb287d..75363d145 100644
--- a/third_party/WebKit/Source/core/workers/WorkletModuleTreeClient.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkletModuleTreeClient.cpp
@@ -29,8 +29,8 @@
     // Step 3: "If script is null, then queue a task on outsideSettings's
     // responsible event loop to run these steps:"
     // The steps are implemented in WorkletPendingTasks::Abort().
-    outside_settings_task_runner_->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *outside_settings_task_runner_, FROM_HERE,
         CrossThreadBind(&WorkletPendingTasks::Abort,
                         WrapCrossThreadPersistent(pending_tasks_.Get())));
     return;
@@ -47,8 +47,8 @@
   //
   // Check whether a syntax error happens.
   if (module_script->HasErrorToRethrow()) {
-    outside_settings_task_runner_->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *outside_settings_task_runner_, FROM_HERE,
         CrossThreadBind(&WorkletPendingTasks::Abort,
                         WrapCrossThreadPersistent(pending_tasks_.Get())));
     return;
@@ -68,8 +68,8 @@
   // Step 5: "Queue a task on outsideSettings's responsible event loop to run
   // these steps:"
   // The steps are implemented in WorkletPendingTasks::DecrementCounter().
-  outside_settings_task_runner_->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *outside_settings_task_runner_, FROM_HERE,
       CrossThreadBind(&WorkletPendingTasks::DecrementCounter,
                       WrapCrossThreadPersistent(pending_tasks_.Get())));
 };
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index 476cbdf..433c923 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -1211,17 +1211,21 @@
   ]
 }
 
-group("devtools_eslint") {
-  data = [
-    # Needed for isolate script to execute.
-    ".eslintignore",
-    ".eslintrc.js",
-    "front_end/",
-    "scripts/buildbot/run_eslint.py",
-    "scripts/local_node/",
-    "//testing/scripts/common.py",
-    "//testing/scripts/run_devtools_check.py",
-    "//testing/xvfb.py",
-    "//third_party/devtools-node-modules/",
-  ]
+if (is_linux && !is_chromeos) {
+  group("devtools_eslint") {
+    data = [
+      # Needed for isolate script to execute.
+      ".eslintignore",
+      ".eslintrc.js",
+      "front_end/",
+      "scripts/lint_javascript.py",
+      "scripts/local_node.py",
+      "//testing/scripts/common.py",
+      "//testing/scripts/run_devtools_check.py",
+      "//testing/xvfb.py",
+      "//third_party/devtools-node-modules/",
+      "//third_party/node/node.py",
+      "//third_party/node/linux/node-linux-x64/",
+    ]
+  }
 }
diff --git a/third_party/WebKit/Source/devtools/PRESUBMIT.py b/third_party/WebKit/Source/devtools/PRESUBMIT.py
index 2aff163..9b4ddfc7 100644
--- a/third_party/WebKit/Source/devtools/PRESUBMIT.py
+++ b/third_party/WebKit/Source/devtools/PRESUBMIT.py
@@ -34,16 +34,6 @@
 import sys
 
 
-def _CheckNodeAndNPMModules(input_api, output_api):
-    node_script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "install_node_deps.py")
-    process = input_api.subprocess.Popen(
-        [input_api.python_executable, node_script_path], stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT)
-    out, _ = process.communicate()
-    if process.returncode != 0:
-        return [output_api.PresubmitError(out)]
-    return [output_api.PresubmitNotifyResult(out)]
-
-
 def _CheckBuildGN(input_api, output_api):
     script_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "check_gn.js")
     return _checkWithNodeScript(input_api, output_api, script_path)
@@ -65,12 +55,10 @@
     original_sys_path = sys.path
     try:
         sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts")]
-        import install_node_deps
+        import local_node
     finally:
         sys.path = original_sys_path
 
-    node_path, _ = install_node_deps.resolve_node_paths()
-
     check_formatting_process = popen(['git', 'cl', 'format', '--js', '--dry-run', input_api.PresubmitLocalPath()])
     check_formatting_process.communicate()
     if check_formatting_process.returncode == 0:
@@ -82,10 +70,11 @@
     if format_process.returncode != 0:
         return [output_api.PresubmitError(format_out)]
 
-    # Use eslint to autofix the braces
-    eslint_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "node_modules", ".bin", "eslint")
+    # Use eslint to autofix the braces.
+    # Also fix semicolon to avoid confusing clang-format.
     eslint_process = popen([
-        node_path, eslint_path, '--no-eslintrc', '--fix', '--env=es6', '--rule={"curly": [2, "multi-or-nest", "consistent"]}'
+        local_node.node_path(), local_node.eslint_path(),
+        '--no-eslintrc', '--fix', '--env=es6', '--rule={"curly": [2, "multi-or-nest", "consistent"], "semi": 2}'
     ] + affected_files)
     eslint_process.communicate()
 
@@ -194,7 +183,6 @@
 
 def CheckChangeOnUpload(input_api, output_api):
     results = []
-    results.extend(_CheckNodeAndNPMModules(input_api, output_api))
     results.extend(_CheckBuildGN(input_api, output_api))
     results.extend(_CheckApplicationDescriptors(input_api, output_api))
     results.extend(_CheckFormat(input_api, output_api))
@@ -236,11 +224,11 @@
     original_sys_path = sys.path
     try:
         sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts")]
-        import install_node_deps
+        import local_node
     finally:
         sys.path = original_sys_path
 
-    node_path, _ = install_node_deps.resolve_node_paths()
+    node_path = local_node.node_path()
 
     process = input_api.subprocess.Popen(
         [node_path, script_path], stdout=input_api.subprocess.PIPE, stderr=input_api.subprocess.STDOUT)
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
index d1c6044..ee3be8c55 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -489,7 +489,7 @@
     var aPriority = aRequest.initialPriority();
     var aScore = aPriority ? priorityMap.get(aPriority) : 0;
     aScore = aScore || 0;
-    var bPriority = aRequest.initialPriority();
+    var bPriority = bRequest.initialPriority();
     var bScore = bPriority ? priorityMap.get(bPriority) : 0;
     bScore = bScore || 0;
 
diff --git a/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js b/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js
index 372e9d4..ad8e4872 100644
--- a/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js
+++ b/third_party/WebKit/Source/devtools/front_end/network_log/NetworkLog.js
@@ -243,6 +243,12 @@
 
     var checkRequest = request;
     do {
+      if (checkRequest[NetworkLog.NetworkLog._initiatorDataSymbol].chain) {
+        initiatorChainCache.addAll(checkRequest[NetworkLog.NetworkLog._initiatorDataSymbol].chain);
+        break;
+      }
+      if (initiatorChainCache.has(checkRequest))
+        break;
       initiatorChainCache.add(checkRequest);
       checkRequest = this._initiatorRequest(checkRequest);
     } while (checkRequest);
diff --git a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
index c4be7f5..96c372b 100644
--- a/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
+++ b/third_party/WebKit/Source/devtools/front_end/test_runner/TestRunner.js
@@ -493,7 +493,7 @@
  * @param {function(*):void} callback
  */
 TestRunner.evaluateFunctionInOverlay = function(func, callback) {
-  var expression = 'testRunner.evaluateInWebInspectorOverlay("(" + ' + func + ' + ")()")';
+  var expression = 'internals.evaluateInInspectorOverlay("(" + ' + func + ' + ")()")';
   var mainContext = TestRunner.runtimeModel.executionContexts()[0];
   mainContext
       .evaluate(
diff --git a/third_party/WebKit/Source/devtools/scripts/README.md b/third_party/WebKit/Source/devtools/scripts/README.md
index 17c3b3ad..0a89e466 100644
--- a/third_party/WebKit/Source/devtools/scripts/README.md
+++ b/third_party/WebKit/Source/devtools/scripts/README.md
@@ -22,7 +22,6 @@
 - convert_svg_images_to_png.py - manually run when adding svg images
 - compile_frontend.py - runs closure compiler to do static type analysis
     - Note: the compiled outputs are not actually used to run DevTools
-- install_node_deps.py - installs node.js & npm modules
 - lint_javascript.py - run eslint
 - optimize_png_images.py - manually run when adding png images
 
diff --git a/third_party/WebKit/Source/devtools/scripts/buildbot/run_eslint.py b/third_party/WebKit/Source/devtools/scripts/buildbot/run_eslint.py
deleted file mode 100644
index 687b626..0000000
--- a/third_party/WebKit/Source/devtools/scripts/buildbot/run_eslint.py
+++ /dev/null
@@ -1,25 +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.
-
-from os import path
-import subprocess
-import sys
-
-scripts_path = path.dirname(path.dirname(path.abspath(__file__)))
-devtools_path = path.dirname(scripts_path)
-eslint_path = path.join(devtools_path, path.pardir, path.pardir, path.pardir,
-                        "devtools-node-modules", "third_party", "node_modules",
-                        ".bin", "eslint")
-node_path = path.join(scripts_path, "local_node", "runtimes", "4.5.0", "bin", "node")
-
-eslint_proc = subprocess.Popen(
-    args=[node_path, eslint_path, "front_end"], cwd=devtools_path, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-(eslint_proc_out, _) = eslint_proc.communicate()
-print(eslint_proc_out)
-
-if eslint_proc.returncode != 0:
-    print("ERRORS DETECTED")
-    sys.exit(1)
-print("No linting errors found")
-sys.exit(0)
diff --git a/third_party/WebKit/Source/devtools/scripts/install_node_deps.py b/third_party/WebKit/Source/devtools/scripts/install_node_deps.py
deleted file mode 100755
index 52d6cbe3..0000000
--- a/third_party/WebKit/Source/devtools/scripts/install_node_deps.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-"""
-Ensure node.js and npm modules are installed
-"""
-
-import os
-from os import path
-import shutil
-import subprocess
-import sys
-
-import utils
-
-MIN_NODE_VERSION = 4
-LOCAL_NODE_VERSION = '4.5.0'
-
-scripts_path = path.dirname(path.abspath(__file__))
-install_local_node_path = path.join(scripts_path, 'local_node', 'node.py')
-local_node_runtimes_path = path.join(scripts_path, 'local_node', 'runtimes')
-local_node_binary_path = path.join(local_node_runtimes_path, LOCAL_NODE_VERSION, 'bin', 'node')
-local_npm_binary_path = path.join(local_node_runtimes_path, LOCAL_NODE_VERSION, 'bin', 'npm')
-
-
-def main():
-    (node_path, npm_path) = resolve_node_paths()
-    npm_install(npm_path)
-
-
-def resolve_node_paths():
-    if has_valid_global_node():
-        if sys.platform == "win32":
-            return (utils.which('node'), utils.which('npm.cmd'))
-        return (utils.which('node'), utils.which('npm'))
-    has_installed_local_node = path.isfile(local_node_binary_path)
-    if has_installed_local_node:
-        return (local_node_binary_path, local_npm_binary_path)
-    if path.isdir(local_node_runtimes_path):
-        shutil.rmtree(local_node_runtimes_path)
-    if sys.platform == 'linux2' or sys.platform == 'darwin':
-        install_node()
-        return (local_node_binary_path, local_npm_binary_path)
-    print('ERROR: Please install the latest node.js LTS version using the Windows installer:')
-    print('https://nodejs.org/en/download/')
-    raise
-
-
-def has_valid_global_node():
-    node_path = utils.which('node')
-    if not node_path:
-        return False
-    node_process = popen([node_path, '--version'])
-    (node_process_out, _) = node_process.communicate()
-    if node_process.returncode != 0:
-        return False
-    major_version = node_process_out[1]
-    return int(major_version) >= MIN_NODE_VERSION
-
-
-def install_node():
-    print('Installing node.js locally at {}'.format(local_node_runtimes_path))
-    print('NOTE: this does not add to PATH or affect global node installation')
-    node_env = {'NODE_VERSION': LOCAL_NODE_VERSION}
-    install_node_process = popen([install_local_node_path, '--version'], env=node_env)
-    (node_process_out, error) = install_node_process.communicate()
-    if install_node_process.returncode != 0:
-        print('Could not install node locally')
-        print(error)
-        raise
-    print(node_process_out)
-
-
-def npm_install(npm_path):
-    print('Runing npm install using {}'.format(npm_path))
-    npm_process = popen([npm_path, 'install'])
-    (npm_process_out, _) = npm_process.communicate()
-    if npm_process.returncode != 0:
-        print('WARNING: npm install had an issue')
-    print(npm_process_out)
-
-
-def popen(arguments, env=None):
-    return subprocess.Popen(arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
-
-
-if __name__ == '__main__':
-    sys.exit(main())
diff --git a/third_party/WebKit/Source/devtools/scripts/lint_javascript.py b/third_party/WebKit/Source/devtools/scripts/lint_javascript.py
index 771fd7d..3d43a5c 100755
--- a/third_party/WebKit/Source/devtools/scripts/lint_javascript.py
+++ b/third_party/WebKit/Source/devtools/scripts/lint_javascript.py
@@ -9,7 +9,7 @@
 import subprocess
 import sys
 
-import install_node_deps
+import local_node
 
 files_to_lint = None
 
@@ -49,17 +49,12 @@
 scripts_path = path.dirname(path.abspath(__file__))
 devtools_path = path.dirname(scripts_path)
 devtools_frontend_path = path.join(devtools_path, "front_end")
-eslint_path = path.join(devtools_path, "node_modules", "eslint", "bin", "eslint.js")
 
 print("Linting JavaScript with eslint...\n")
 
 
 def js_lint(files_list=None):
     eslint_errors_found = False
-    if not path.isfile(eslint_path):
-        print("Failed to run eslint, run ./scripts/install_node_deps.py to install eslint")
-        eslint_errors_found = True
-        return eslint_errors_found
 
     if files_list is None:
         files_list = [devtools_frontend_path]
@@ -67,10 +62,9 @@
 
     eslintconfig_path = path.join(devtools_path, ".eslintrc.js")
     eslintignore_path = path.join(devtools_path, ".eslintignore")
-    (node_path, _) = install_node_deps.resolve_node_paths()
     exec_command = [
-        node_path,
-        eslint_path,
+        local_node.node_path(),
+        local_node.eslint_path(),
         "--config",
         to_platform_path_exact(eslintconfig_path),
         "--ignore-path",
diff --git a/third_party/WebKit/Source/devtools/scripts/local_node.py b/third_party/WebKit/Source/devtools/scripts/local_node.py
new file mode 100644
index 0000000..3054114
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/scripts/local_node.py
@@ -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.
+"""
+Thin wrapper around the local node.js installed as part of chromium DEPS
+"""
+
+from os import path
+import sys
+
+SCRIPTS_PATH = path.dirname(path.abspath(__file__))
+THIRD_PARTY_PATH = path.join(SCRIPTS_PATH, '..', '..', '..', '..')
+NODE_PATH = path.join(THIRD_PARTY_PATH, 'node')
+ESLINT_PATH = path.join(THIRD_PARTY_PATH, 'devtools-node-modules', 'third_party',
+                        'node_modules', '.bin', 'eslint')
+
+try:
+    old_sys_path = sys.path[:]
+    sys.path.append(NODE_PATH)
+    import node
+finally:
+    sys.path = old_sys_path
+
+
+def node_path():
+    return node.GetBinaryPath()
+
+
+def eslint_path():
+    return ESLINT_PATH
diff --git a/third_party/WebKit/Source/devtools/scripts/local_node/__init__.py b/third_party/WebKit/Source/devtools/scripts/local_node/__init__.py
deleted file mode 100644
index 05cc409..0000000
--- a/third_party/WebKit/Source/devtools/scripts/local_node/__init__.py
+++ /dev/null
@@ -1,3 +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.
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/scripts/local_node/node.py b/third_party/WebKit/Source/devtools/scripts/local_node/node.py
deleted file mode 100755
index 7223d3b..0000000
--- a/third_party/WebKit/Source/devtools/scripts/local_node/node.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 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.
-
-import argparse
-import os
-import shutil
-import sys
-import subprocess
-import tarfile
-import tempfile
-import urllib2
-
-THIS_DIR = os.path.dirname(os.path.abspath(__file__))
-
-DEFAULT_VERSION = '4.5.0'
-BUCKET = 'chromium-nodejs'
-
-
-def install_latest_node_js(version, tmp_dir):
-    target_dir = os.path.join(THIS_DIR, 'runtimes', version)
-    version_file = os.path.join(target_dir, 'VERSION')
-
-    if sys.platform == 'win32':
-        bin_location = os.path.join(target_dir, 'node.exe')
-    else:
-        bin_location = os.path.join(target_dir, 'bin', 'node')
-
-    # We assume that, if the VERSION file exists, then the installation is good.
-    if os.path.exists(version_file):
-        with open(version_file, 'r') as f:
-            if f.read() == version:
-                return bin_location
-
-    # TODO(hinoka): This probably doesn't work that well on Windows...
-    shutil.rmtree(target_dir, ignore_errors=True)
-
-    # Get the target name correct.
-    if sys.platform == 'win32':
-        target = 'node.exe'
-    elif sys.platform == 'darwin':
-        target = 'node-v%s-darwin-x64.tar.gz' % version
-    elif sys.platform == 'linux2':
-        target = 'node-v%s-linux-x86.tar.gz' % version
-    else:
-        raise Exception('Unrecognized platform %s' % sys.platform)
-
-    dest = os.path.join(tmp_dir, 'node_download')
-    url = 'https://storage.googleapis.com/%s/%s/%s' % (BUCKET, version, target)
-    print('Fetching %s' % url)
-    u = urllib2.urlopen(url)
-    with open(dest, 'wb') as f:
-        while True:
-            chunk = u.read(2**20)
-            if not chunk:
-                break
-            f.write(chunk)
-
-    # When multiple node.py instances run at the same time for the first time,
-    # the check to see whether or not the installation occured already.  But then
-    # they all race to see who's the first to run shutil.move(), which obviously
-    # fails for everyone other than the first instance.  This CL makes
-    # os.rename() not fail, since its assumed that if it fails that means
-    # someone else already created an installation.
-    #
-    # Another approach is to use an flock, but then it starts to get messy when
-    # you have to keep polling filesystem state to see if another instance
-    # finished, or add timeouts to remove an flock if it was left on the system by
-    # a failed attempt, etc, etc.  This just seemed like a less flaky solution,
-    # despite the fact that it means multiple network requests are spawned.
-    write_version = True
-    if sys.platform != 'win32':
-        # The Windows version comes as a self contained executable, the other
-        # versions come as a tar.gz that needs to be extracted.
-        with tarfile.open(dest, 'r:gz') as f:
-            f.extractall(path=tmp_dir)
-        try:
-            os.mkdir(os.path.join(THIS_DIR, 'runtimes'))
-            os.rename(os.path.join(tmp_dir, target[:-len('.tar.gz')]), target_dir)
-        except OSError:
-            write_version = False
-        os.remove(dest)
-    else:
-        try:
-            # Still potentiall racy, from python docs:
-            # "On Windows...there may be no way to implement an atomic rename when dst
-            # names an existing file."
-            os.makedirs(target_dir)
-            os.rename(dest, bin_location)
-        except OSError:
-            write_version = False
-
-    if write_version:
-        with open(version_file, 'w') as f:
-            f.write(version)
-
-    return bin_location
-
-
-def main(mode=None):
-    parser = argparse.ArgumentParser()
-    parser.add_argument('--running-as-hook', action='store_true')
-    args, rest_args = parser.parse_known_args()
-
-    # Exit early if this is being invoked from `gclient runhooks`
-    # and not on a bot (CHROME_HEADLESS is set on all build bots).
-    if (args.running_as_hook and os.environ.get('CHROME_HEADLESS', '0') != '1'):
-        return 0
-
-    version = os.environ.get('NODE_VERSION', DEFAULT_VERSION)
-    try:
-        tmp_dir = tempfile.mkdtemp(dir=THIS_DIR)
-        bin_location = install_latest_node_js(version, tmp_dir)
-    finally:
-        if os.path.exists(tmp_dir):
-            shutil.rmtree(tmp_dir)
-
-    if mode == 'npm':
-        # TODO(hinoka): How about Windows...?
-        bin_location = os.path.join(os.path.dirname(bin_location), 'npm')
-
-    return subprocess.call([bin_location,] + rest_args)
-
-
-if __name__ == '__main__':
-    sys.exit(main())
diff --git a/third_party/WebKit/Source/devtools/scripts/local_node/npm.py b/third_party/WebKit/Source/devtools/scripts/local_node/npm.py
deleted file mode 100755
index 45f7bfd..0000000
--- a/third_party/WebKit/Source/devtools/scripts/local_node/npm.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 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.
-
-import imp
-import os
-import sys
-
-THIS_PATH = os.path.dirname(os.path.abspath(__file__))
-node_py = imp.load_source('node', os.path.join(THIS_PATH, 'node.py'))
-
-if __name__ == '__main__':
-    sys.exit(node_py.main('npm'))
diff --git a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp
index c59865a..44e5b61 100644
--- a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp
+++ b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp
@@ -76,11 +76,11 @@
   void RunTestOnWorkletThread(TestCalback callback) {
     std::unique_ptr<WorkerThread> worklet = CreateAnimationWorkletThread();
     WaitableEvent waitable_event;
-    worklet->GetTaskRunner(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE,
-                   CrossThreadBind(callback, CrossThreadUnretained(this),
-                                   CrossThreadUnretained(worklet.get()),
-                                   CrossThreadUnretained(&waitable_event)));
+    PostCrossThreadTask(
+        *worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(callback, CrossThreadUnretained(this),
+                        CrossThreadUnretained(worklet.get()),
+                        CrossThreadUnretained(&waitable_event)));
     waitable_event.Wait();
 
     worklet->Terminate();
@@ -264,8 +264,9 @@
     ScriptState* script_state =
         global_scope->ScriptController()->GetScriptState();
     EXPECT_TRUE(script_state);
+    const KURL js_url("https://example.com/worklet.js");
     ScriptModule module = ScriptModule::Compile(
-        script_state->GetIsolate(), source_code, "worklet.js",
+        script_state->GetIsolate(), source_code, js_url, js_url,
         ScriptFetchOptions(), kSharableCrossOrigin,
         TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
     EXPECT_FALSE(module.IsNull());
diff --git a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp
index 80344603..0b4020d 100644
--- a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp
@@ -121,9 +121,10 @@
         thread->GlobalScope()->ScriptController()->GetScriptState();
     EXPECT_TRUE(script_state);
     ScriptState::Scope scope(script_state);
+    const KURL js_url("https://example.com/foo.js");
     ScriptModule module = ScriptModule::Compile(
-        script_state->GetIsolate(), "var counter = 0; ++counter;", "worklet.js",
-        ScriptFetchOptions(), kSharableCrossOrigin,
+        script_state->GetIsolate(), "var counter = 0; ++counter;", js_url,
+        js_url, ScriptFetchOptions(), kSharableCrossOrigin,
         TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
     EXPECT_FALSE(module.IsNull());
     ScriptValue exception = module.Instantiate(script_state);
diff --git a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp
index e5d67d0d..eeee9ff37 100644
--- a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp
+++ b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.cpp
@@ -20,10 +20,8 @@
 
 namespace blink {
 
-constexpr size_t NavigatorBeacon::kMaxAllowance;
-
 NavigatorBeacon::NavigatorBeacon(Navigator& navigator)
-    : Supplement<Navigator>(navigator), transmitted_bytes_(0) {}
+    : Supplement<Navigator>(navigator) {}
 
 NavigatorBeacon::~NavigatorBeacon() {}
 
@@ -66,10 +64,6 @@
   return true;
 }
 
-void NavigatorBeacon::AddTransmittedBytes(size_t sent_bytes) {
-  transmitted_bytes_ += sent_bytes;
-}
-
 bool NavigatorBeacon::sendBeacon(
     ScriptState* script_state,
     Navigator& navigator,
@@ -90,15 +84,11 @@
   if (!CanSendBeacon(context, url, exception_state))
     return false;
 
-  size_t allowance =
-      kMaxAllowance - std::min(kMaxAllowance, transmitted_bytes_);
-  size_t beacon_size = 0;
   bool allowed;
 
   if (data.IsArrayBufferView()) {
-    allowed =
-        PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance, url,
-                               data.GetAsArrayBufferView().View(), beacon_size);
+    allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), url,
+                                     data.GetAsArrayBufferView().View());
   } else if (data.IsBlob()) {
     Blob* blob = data.GetAsBlob();
     if (!FetchUtils::IsCORSSafelistedContentType(AtomicString(blob->type()))) {
@@ -113,17 +103,17 @@
         return false;
       }
     }
-    allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance,
-                                     url, blob, beacon_size);
+    allowed =
+        PingLoader::SendBeacon(GetSupplementable()->GetFrame(), url, blob);
   } else if (data.IsString()) {
-    allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance,
-                                     url, data.GetAsString(), beacon_size);
+    allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), url,
+                                     data.GetAsString());
   } else if (data.IsFormData()) {
-    allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance,
-                                     url, data.GetAsFormData(), beacon_size);
+    allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), url,
+                                     data.GetAsFormData());
   } else {
-    allowed = PingLoader::SendBeacon(GetSupplementable()->GetFrame(), allowance,
-                                     url, String(), beacon_size);
+    allowed =
+        PingLoader::SendBeacon(GetSupplementable()->GetFrame(), url, String());
   }
 
   if (!allowed) {
@@ -131,7 +121,6 @@
     return false;
   }
 
-  AddTransmittedBytes(beacon_size);
   return true;
 }
 
diff --git a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.h b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.h
index 32e4199..c18550c9 100644
--- a/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.h
+++ b/third_party/WebKit/Source/modules/beacon/NavigatorBeacon.h
@@ -42,12 +42,6 @@
                       const ArrayBufferViewOrBlobOrStringOrFormData&,
                       ExceptionState&);
   bool CanSendBeacon(ExecutionContext*, const KURL&, ExceptionState&);
-  int MaxAllowance() const;
-  void AddTransmittedBytes(size_t sent_bytes);
-
-  size_t transmitted_bytes_;
-
-  static constexpr size_t kMaxAllowance = 65536;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.cpp b/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.cpp
index 63685a0..f24319db 100644
--- a/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.cpp
+++ b/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.cpp
@@ -224,8 +224,8 @@
   if (!client_)
     return;
   DCHECK(reader_thread_);
-  reader_thread_->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *reader_thread_->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(&Context::NotifyInternal, WrapRefCounted(this)));
 }
 
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
index 07a97a2..fafeff6 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
@@ -75,7 +75,7 @@
   }
 
   WebString message_string = message->ToWireString();
-  handle_->ServiceWorker()->PostMessage(
+  handle_->ServiceWorker()->PostMessageToWorker(
       client->Provider(), message_string,
       WebSecurityOrigin(GetExecutionContext()->GetSecurityOrigin()),
       std::move(channels));
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
index 6405d05..d380a72 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerGlobalScopeProxy.cpp
@@ -532,12 +532,11 @@
   DCHECK(embedded_worker_);
   // The TaskType of Inspector tasks need to be Unthrottled because they need to
   // run even on a suspended page.
-  parent_frame_task_runners_->Get(TaskType::kUnthrottled)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&WebEmbeddedWorkerImpl::PostMessageToPageInspector,
-                          CrossThreadUnretained(embedded_worker_), session_id,
-                          message));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kUnthrottled), FROM_HERE,
+      CrossThreadBind(&WebEmbeddedWorkerImpl::PostMessageToPageInspector,
+                      CrossThreadUnretained(embedded_worker_), session_id,
+                      message));
 }
 
 void ServiceWorkerGlobalScopeProxy::DidCreateWorkerGlobalScope(
@@ -563,14 +562,13 @@
   // page.
   DCHECK(embedded_worker_);
   WaitableEvent waitable_event;
-  parent_frame_task_runners_->Get(TaskType::kUnthrottled)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(
-              &SetContentSecurityPolicyAndReferrerPolicyOnMainThread,
-              CrossThreadUnretained(embedded_worker_),
-              csp_headers_on_worker_thread, referrer_policy_on_worker_thread,
-              CrossThreadUnretained(&waitable_event)));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kUnthrottled), FROM_HERE,
+      CrossThreadBind(&SetContentSecurityPolicyAndReferrerPolicyOnMainThread,
+                      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
diff --git a/third_party/WebKit/Source/modules/time_zone_monitor/TimeZoneMonitorClient.cpp b/third_party/WebKit/Source/modules/time_zone_monitor/TimeZoneMonitorClient.cpp
index a2a9878c..34bf7f9c 100644
--- a/third_party/WebKit/Source/modules/time_zone_monitor/TimeZoneMonitorClient.cpp
+++ b/third_party/WebKit/Source/modules/time_zone_monitor/TimeZoneMonitorClient.cpp
@@ -74,10 +74,10 @@
     // among multiple WorkerThreads.
     if (posted.Contains(&thread->GetWorkerBackingThread()))
       continue;
-    thread->GetTaskRunner(TaskType::kUnspecedTimer)
-        ->PostTask(FROM_HERE,
-                   CrossThreadBind(&NotifyTimezoneChangeOnWorkerThread,
-                                   WTF::CrossThreadUnretained(thread)));
+    PostCrossThreadTask(*thread->GetTaskRunner(TaskType::kUnspecedTimer),
+                        FROM_HERE,
+                        CrossThreadBind(&NotifyTimezoneChangeOnWorkerThread,
+                                        WTF::CrossThreadUnretained(thread)));
     posted.insert(&thread->GetWorkerBackingThread());
   }
 }
diff --git a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp
index ecacb81..4f0ca5d 100644
--- a/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AsyncAudioDecoder.cpp
@@ -78,14 +78,15 @@
   // We also want to avoid notifying the main thread if AudioContext does not
   // exist any more.
   if (context) {
-    Platform::Current()->MainThread()->GetWebTaskRunner()->PostTask(
-        FROM_HERE, CrossThreadBind(&AsyncAudioDecoder::NotifyComplete,
-                                   WrapCrossThreadPersistent(audio_data),
-                                   WrapCrossThreadPersistent(success_callback),
-                                   WrapCrossThreadPersistent(error_callback),
-                                   WTF::RetainedRef(std::move(bus)),
-                                   WrapCrossThreadPersistent(resolver),
-                                   WrapCrossThreadPersistent(context)));
+    PostCrossThreadTask(
+        *Platform::Current()->MainThread()->GetWebTaskRunner(), FROM_HERE,
+        CrossThreadBind(&AsyncAudioDecoder::NotifyComplete,
+                        WrapCrossThreadPersistent(audio_data),
+                        WrapCrossThreadPersistent(success_callback),
+                        WrapCrossThreadPersistent(error_callback),
+                        WTF::RetainedRef(std::move(bus)),
+                        WrapCrossThreadPersistent(resolver),
+                        WrapCrossThreadPersistent(context)));
   }
 }
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp
index adb0c42..3c08481 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioScheduledSourceNode.cpp
@@ -231,9 +231,9 @@
 void AudioScheduledSourceHandler::Finish() {
   FinishWithoutOnEnded();
 
-  task_runner_->PostTask(
-      FROM_HERE, CrossThreadBind(&AudioScheduledSourceHandler::NotifyEnded,
-                                 WrapRefCounted(this)));
+  PostCrossThreadTask(*task_runner_, FROM_HERE,
+                      CrossThreadBind(&AudioScheduledSourceHandler::NotifyEnded,
+                                      WrapRefCounted(this)));
 }
 
 void AudioScheduledSourceHandler::NotifyEnded() {
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
index 5fd2bc9..4e6c432 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
@@ -82,50 +82,46 @@
 
   void RunBasicTest(WorkerThread* thread) {
     WaitableEvent waitable_event;
-    thread->GetTaskRunner(TaskType::kInternalTest)
-        ->PostTask(
-            FROM_HERE,
-            CrossThreadBind(
-                &AudioWorkletGlobalScopeTest::RunBasicTestOnWorkletThread,
-                CrossThreadUnretained(this), CrossThreadUnretained(thread),
-                CrossThreadUnretained(&waitable_event)));
+    PostCrossThreadTask(
+        *thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(
+            &AudioWorkletGlobalScopeTest::RunBasicTestOnWorkletThread,
+            CrossThreadUnretained(this), CrossThreadUnretained(thread),
+            CrossThreadUnretained(&waitable_event)));
     waitable_event.Wait();
   }
 
   void RunSimpleProcessTest(WorkerThread* thread) {
     WaitableEvent waitable_event;
-    thread->GetTaskRunner(TaskType::kInternalTest)
-        ->PostTask(FROM_HERE,
-                   CrossThreadBind(&AudioWorkletGlobalScopeTest::
-                                       RunSimpleProcessTestOnWorkletThread,
-                                   CrossThreadUnretained(this),
-                                   CrossThreadUnretained(thread),
-                                   CrossThreadUnretained(&waitable_event)));
+    PostCrossThreadTask(
+        *thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(
+            &AudioWorkletGlobalScopeTest::RunSimpleProcessTestOnWorkletThread,
+            CrossThreadUnretained(this), CrossThreadUnretained(thread),
+            CrossThreadUnretained(&waitable_event)));
     waitable_event.Wait();
   }
 
   void RunParsingTest(WorkerThread* thread) {
     WaitableEvent waitable_event;
-    thread->GetTaskRunner(TaskType::kInternalTest)
-        ->PostTask(
-            FROM_HERE,
-            CrossThreadBind(
-                &AudioWorkletGlobalScopeTest::RunParsingTestOnWorkletThread,
-                CrossThreadUnretained(this), CrossThreadUnretained(thread),
-                CrossThreadUnretained(&waitable_event)));
+    PostCrossThreadTask(
+        *thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(
+            &AudioWorkletGlobalScopeTest::RunParsingTestOnWorkletThread,
+            CrossThreadUnretained(this), CrossThreadUnretained(thread),
+            CrossThreadUnretained(&waitable_event)));
     waitable_event.Wait();
   }
 
   void RunParsingParameterDescriptorTest(WorkerThread* thread) {
     WaitableEvent waitable_event;
-    thread->GetTaskRunner(TaskType::kInternalTest)
-        ->PostTask(
-            FROM_HERE,
-            CrossThreadBind(
-                &AudioWorkletGlobalScopeTest::
-                    RunParsingParameterDescriptorTestOnWorkletThread,
-                CrossThreadUnretained(this), CrossThreadUnretained(thread),
-                CrossThreadUnretained(&waitable_event)));
+    PostCrossThreadTask(
+        *thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+        CrossThreadBind(&AudioWorkletGlobalScopeTest::
+                            RunParsingParameterDescriptorTestOnWorkletThread,
+                        CrossThreadUnretained(this),
+                        CrossThreadUnretained(thread),
+                        CrossThreadUnretained(&waitable_event)));
     waitable_event.Wait();
   }
 
@@ -136,8 +132,9 @@
     ScriptState* script_state =
         global_scope->ScriptController()->GetScriptState();
     EXPECT_TRUE(script_state);
+    KURL js_url("https://example.com/worklet.js");
     ScriptModule module = ScriptModule::Compile(
-        script_state->GetIsolate(), source_code, "worklet.js",
+        script_state->GetIsolate(), source_code, js_url, js_url,
         ScriptFetchOptions(), kSharableCrossOrigin,
         TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
     EXPECT_FALSE(module.IsNull());
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
index fa1ab31..e844b88 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletMessagingProxy.cpp
@@ -27,17 +27,14 @@
     AudioWorkletHandler* handler,
     MessagePortChannel message_port_channel) {
   DCHECK(IsMainThread());
-  GetWorkerThread()
-      ->GetTaskRunner(TaskType::kMiscPlatformAPI)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(
-              &AudioWorkletMessagingProxy::CreateProcessorOnRenderingThread,
-              WrapCrossThreadPersistent(this),
-              CrossThreadUnretained(GetWorkerThread()),
-              CrossThreadUnretained(handler), handler->Name(),
-              handler->Context()->sampleRate(),
-              std::move(message_port_channel)));
+  PostCrossThreadTask(
+      *GetWorkerThread()->GetTaskRunner(TaskType::kMiscPlatformAPI), FROM_HERE,
+      CrossThreadBind(
+          &AudioWorkletMessagingProxy::CreateProcessorOnRenderingThread,
+          WrapCrossThreadPersistent(this),
+          CrossThreadUnretained(GetWorkerThread()),
+          CrossThreadUnretained(handler), handler->Name(),
+          handler->Context()->sampleRate(), std::move(message_port_channel)));
 }
 
 void AudioWorkletMessagingProxy::CreateProcessorOnRenderingThread(
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp
index e43ae68..cafa707e5 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletNode.cpp
@@ -154,8 +154,8 @@
   AudioWorkletProcessorState new_state;
   new_state = processor_ ? AudioWorkletProcessorState::kRunning
                          : AudioWorkletProcessorState::kError;
-  task_runner_->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *task_runner_, FROM_HERE,
       CrossThreadBind(&AudioWorkletHandler::NotifyProcessorStateChange,
                       WrapRefCounted(this), new_state));
 }
@@ -169,8 +169,8 @@
   new_state = processor_->IsRunnable()
       ? AudioWorkletProcessorState::kStopped
       : AudioWorkletProcessorState::kError;
-  task_runner_->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *task_runner_, FROM_HERE,
       CrossThreadBind(&AudioWorkletHandler::NotifyProcessorStateChange,
                       WrapRefCounted(this), new_state));
 
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletObjectProxy.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletObjectProxy.cpp
index f2564a4..2b067e1 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletObjectProxy.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletObjectProxy.cpp
@@ -38,14 +38,12 @@
   if (processor_info_list->size() == 0)
     return;
 
-  GetParentFrameTaskRunners()
-      ->Get(TaskType::kUnthrottled)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(
-              &AudioWorkletMessagingProxy::SynchronizeWorkletProcessorInfoList,
-              GetAudioWorkletMessagingProxyWeakPtr(),
-              WTF::Passed(std::move(processor_info_list))));
+  PostCrossThreadTask(
+      *GetParentFrameTaskRunners()->Get(TaskType::kUnthrottled), FROM_HERE,
+      CrossThreadBind(
+          &AudioWorkletMessagingProxy::SynchronizeWorkletProcessorInfoList,
+          GetAudioWorkletMessagingProxyWeakPtr(),
+          WTF::Passed(std::move(processor_info_list))));
 }
 
 void AudioWorkletObjectProxy::WillDestroyWorkerGlobalScope() {
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
index 2314a76..b630e92 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
@@ -81,9 +81,10 @@
         thread->GlobalScope()->ScriptController()->GetScriptState();
     EXPECT_TRUE(script_state);
     ScriptState::Scope scope(script_state);
+    KURL js_url("https://example.com/worklet.js");
     ScriptModule module = ScriptModule::Compile(
-        script_state->GetIsolate(), "var counter = 0; ++counter;", "worklet.js",
-        ScriptFetchOptions(), kSharableCrossOrigin,
+        script_state->GetIsolate(), "var counter = 0; ++counter;", js_url,
+        js_url, ScriptFetchOptions(), kSharableCrossOrigin,
         TextPosition::MinimumPosition(), ASSERT_NO_EXCEPTION);
     EXPECT_FALSE(module.IsNull());
     ScriptValue exception = module.Instantiate(script_state);
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
index abd1027..724e64130 100644
--- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
@@ -862,9 +862,10 @@
 void BaseAudioContext::ScheduleMainThreadCleanup() {
   if (has_posted_cleanup_task_)
     return;
-  Platform::Current()->MainThread()->GetWebTaskRunner()->PostTask(
-      FROM_HERE, CrossThreadBind(&BaseAudioContext::PerformCleanupOnMainThread,
-                                 WrapCrossThreadPersistent(this)));
+  PostCrossThreadTask(
+      *Platform::Current()->MainThread()->GetWebTaskRunner(), FROM_HERE,
+      CrossThreadBind(&BaseAudioContext::PerformCleanupOnMainThread,
+                      WrapCrossThreadPersistent(this)));
   has_posted_cleanup_task_ = true;
 }
 
@@ -906,11 +907,30 @@
   if (!user_gesture_required_)
     return true;
 
-  ToDocument(GetExecutionContext())
-      ->AddConsoleMessage(ConsoleMessage::Create(
+  Document* document = ToDocument(GetExecutionContext());
+  DCHECK(document);
+
+  switch (GetAutoplayPolicy()) {
+    case AutoplayPolicy::Type::kNoUserGestureRequired:
+      NOTREACHED();
+      break;
+    case AutoplayPolicy::Type::kUserGestureRequired:
+    case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+      DCHECK(document->GetFrame() &&
+             document->GetFrame()->IsCrossOriginSubframe());
+      document->AddConsoleMessage(ConsoleMessage::Create(
           kJSMessageSource, kWarningMessageLevel,
-          "An AudioContext in a cross origin iframe must be created or resumed "
-          "from a user gesture to enable audio output."));
+          "An AudioContext in a cross origin iframe must be created or "
+          "resumed from a user gesture to enable audio output."));
+      break;
+    case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+      document->AddConsoleMessage(ConsoleMessage::Create(
+          kJSMessageSource, kWarningMessageLevel,
+          "An AudioContext must be created or resumed after the document "
+          "received a user gesture to enable audio playback."));
+      break;
+  }
+
   return false;
 }
 
diff --git a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp
index 7f488b487..9a67fb4 100644
--- a/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/DeferredTaskHandler.cpp
@@ -266,8 +266,8 @@
     return;
   deletable_orphan_handlers_.AppendVector(rendering_orphan_handlers_);
   rendering_orphan_handlers_.clear();
-  Platform::Current()->MainThread()->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *Platform::Current()->MainThread()->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(&DeferredTaskHandler::DeleteHandlersOnMainThread,
                       scoped_refptr<DeferredTaskHandler>(this)));
 }
diff --git a/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp
index 7aa1ea7..d49647a 100644
--- a/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/MediaElementAudioSourceNode.cpp
@@ -203,8 +203,8 @@
         // Print a CORS message, but just once for each change in the current
         // media element source, and only if we have a document to print to.
         maybe_print_cors_message_ = false;
-        task_runner_->PostTask(
-            FROM_HERE,
+        PostCrossThreadTask(
+            *task_runner_, FROM_HERE,
             CrossThreadBind(&MediaElementAudioSourceHandler::PrintCORSMessage,
                             WrapRefCounted(this), current_src_string_));
       }
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
index 2e24fb7..fa5bc38 100644
--- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioDestinationNode.cpp
@@ -114,8 +114,8 @@
   // Rendering was not started. Starting now.
   if (!is_rendering_started_) {
     is_rendering_started_ = true;
-    GetRenderingThread()->GetWebTaskRunner()->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *GetRenderingThread()->GetWebTaskRunner(), FROM_HERE,
         CrossThreadBind(&OfflineAudioDestinationHandler::StartOfflineRendering,
                         WrapRefCounted(this)));
     return;
@@ -123,8 +123,8 @@
 
   // Rendering is already started, which implicitly means we resume the
   // rendering by calling |doOfflineRendering| on the render thread.
-  GetRenderingThread()->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *GetRenderingThread()->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(&OfflineAudioDestinationHandler::DoOfflineRendering,
                       WrapRefCounted(this)));
 }
@@ -249,8 +249,8 @@
   DCHECK(!IsMainThread());
 
   // The actual rendering has been suspended. Notify the context.
-  task_runner_->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *task_runner_, FROM_HERE,
       CrossThreadBind(&OfflineAudioDestinationHandler::NotifySuspend,
                       WrapRefCounted(this), Context()->CurrentSampleFrame()));
 }
@@ -259,8 +259,8 @@
   DCHECK(!IsMainThread());
 
   // The actual rendering has been completed. Notify the context.
-  task_runner_->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *task_runner_, FROM_HERE,
       CrossThreadBind(&OfflineAudioDestinationHandler::NotifyComplete,
                       WrapRefCounted(this)));
 }
diff --git a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp
index 7d1ce21..52b9a61 100644
--- a/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp
+++ b/third_party/WebKit/Source/modules/webaudio/ScriptProcessorNode.cpp
@@ -222,8 +222,8 @@
       if (Context()->HasRealtimeConstraint()) {
         // Fire the event on the main thread with the appropriate buffer
         // index.
-        task_runner_->PostTask(
-            FROM_HERE,
+        PostCrossThreadTask(
+            *task_runner_, FROM_HERE,
             CrossThreadBind(&ScriptProcessorHandler::FireProcessEvent,
                             WrapRefCounted(this), double_buffer_index_));
       } else {
@@ -232,8 +232,8 @@
         std::unique_ptr<WaitableEvent> waitable_event =
             std::make_unique<WaitableEvent>();
 
-        task_runner_->PostTask(
-            FROM_HERE,
+        PostCrossThreadTask(
+            *task_runner_, FROM_HERE,
             CrossThreadBind(
                 &ScriptProcessorHandler::FireProcessEventForOfflineAudioContext,
                 WrapRefCounted(this), double_buffer_index_,
diff --git a/third_party/WebKit/Source/modules/webdatabase/Database.cpp b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
index 35537f0..b6a278c6 100644
--- a/third_party/WebKit/Source/modules/webdatabase/Database.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/Database.cpp
@@ -922,9 +922,9 @@
 void Database::ScheduleTransactionCallback(SQLTransaction* transaction) {
   // The task is constructed in a database thread, and destructed in the
   // context thread.
-  GetDatabaseTaskRunner()->PostTask(
-      FROM_HERE, CrossThreadBind(&SQLTransaction::PerformPendingCallback,
-                                 WrapCrossThreadPersistent(transaction)));
+  PostCrossThreadTask(*GetDatabaseTaskRunner(), FROM_HERE,
+                      CrossThreadBind(&SQLTransaction::PerformPendingCallback,
+                                      WrapCrossThreadPersistent(transaction)));
 }
 
 Vector<String> Database::PerformGetTableNames() {
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp b/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp
index d08f36b5..5eea3b9 100644
--- a/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseTracker.cpp
@@ -199,8 +199,8 @@
   // We have to call closeImmediately() on the context thread.
   for (DatabaseSet::iterator it = database_set->begin();
        it != database_set->end(); ++it) {
-    (*it)->GetDatabaseTaskRunner()->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *(*it)->GetDatabaseTaskRunner(), FROM_HERE,
         CrossThreadBind(&DatabaseTracker::CloseOneDatabaseImmediately,
                         CrossThreadUnretained(this), origin_string, name, *it));
   }
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
index 73f0af1..5246246 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -617,10 +617,10 @@
   creation_info.using_gpu_compositing = using_gpu_compositing;
   scoped_refptr<WebTaskRunner> task_runner =
       Platform::Current()->MainThread()->GetWebTaskRunner();
-  task_runner->PostTask(
-      FROM_HERE, CrossThreadBind(&CreateContextProviderOnMainThread,
-                                 CrossThreadUnretained(&creation_info),
-                                 CrossThreadUnretained(&waitable_event)));
+  PostCrossThreadTask(*task_runner, FROM_HERE,
+                      CrossThreadBind(&CreateContextProviderOnMainThread,
+                                      CrossThreadUnretained(&creation_info),
+                                      CrossThreadUnretained(&waitable_event)));
   waitable_event.Wait();
   return std::move(creation_info.created_context_provider);
 }
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
index 572a1c9..805e970 100644
--- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
+++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
@@ -254,9 +254,9 @@
 void MainChannelClient::DidConnect(const String& subprotocol,
                                    const String& extensions) {
   DCHECK(IsMainThread());
-  worker_networking_task_runner_->PostTask(
-      FROM_HERE, CrossThreadBind(&WorkerGlobalScopeDidConnect, bridge_,
-                                 subprotocol, extensions));
+  PostCrossThreadTask(*worker_networking_task_runner_, FROM_HERE,
+                      CrossThreadBind(&WorkerGlobalScopeDidConnect, bridge_,
+                                      subprotocol, extensions));
 }
 
 static void WorkerGlobalScopeDidReceiveTextMessage(Bridge* bridge,
@@ -267,9 +267,9 @@
 
 void MainChannelClient::DidReceiveTextMessage(const String& payload) {
   DCHECK(IsMainThread());
-  worker_networking_task_runner_->PostTask(
-      FROM_HERE, CrossThreadBind(&WorkerGlobalScopeDidReceiveTextMessage,
-                                 bridge_, payload));
+  PostCrossThreadTask(*worker_networking_task_runner_, FROM_HERE,
+                      CrossThreadBind(&WorkerGlobalScopeDidReceiveTextMessage,
+                                      bridge_, payload));
 }
 
 static void WorkerGlobalScopeDidReceiveBinaryMessage(
@@ -282,9 +282,10 @@
 void MainChannelClient::DidReceiveBinaryMessage(
     std::unique_ptr<Vector<char>> payload) {
   DCHECK(IsMainThread());
-  worker_networking_task_runner_->PostTask(
-      FROM_HERE, CrossThreadBind(&WorkerGlobalScopeDidReceiveBinaryMessage,
-                                 bridge_, WTF::Passed(std::move(payload))));
+  PostCrossThreadTask(
+      *worker_networking_task_runner_, FROM_HERE,
+      CrossThreadBind(&WorkerGlobalScopeDidReceiveBinaryMessage, bridge_,
+                      WTF::Passed(std::move(payload))));
 }
 
 static void WorkerGlobalScopeDidConsumeBufferedAmount(Bridge* bridge,
@@ -295,9 +296,10 @@
 
 void MainChannelClient::DidConsumeBufferedAmount(uint64_t consumed) {
   DCHECK(IsMainThread());
-  worker_networking_task_runner_->PostTask(
-      FROM_HERE, CrossThreadBind(&WorkerGlobalScopeDidConsumeBufferedAmount,
-                                 bridge_, consumed));
+  PostCrossThreadTask(
+      *worker_networking_task_runner_, FROM_HERE,
+      CrossThreadBind(&WorkerGlobalScopeDidConsumeBufferedAmount, bridge_,
+                      consumed));
 }
 
 static void WorkerGlobalScopeDidStartClosingHandshake(Bridge* bridge) {
@@ -307,8 +309,8 @@
 
 void MainChannelClient::DidStartClosingHandshake() {
   DCHECK(IsMainThread());
-  worker_networking_task_runner_->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *worker_networking_task_runner_, FROM_HERE,
       CrossThreadBind(&WorkerGlobalScopeDidStartClosingHandshake, bridge_));
 }
 
@@ -330,9 +332,10 @@
 
   ReleaseMainChannel();
 
-  worker_networking_task_runner_->PostTask(
-      FROM_HERE, CrossThreadBind(&WorkerGlobalScopeDidClose, bridge_,
-                                 closing_handshake_completion, code, reason));
+  PostCrossThreadTask(
+      *worker_networking_task_runner_, FROM_HERE,
+      CrossThreadBind(&WorkerGlobalScopeDidClose, bridge_,
+                      closing_handshake_completion, code, reason));
 }
 
 static void WorkerGlobalScopeDidError(Bridge* bridge) {
@@ -342,8 +345,8 @@
 
 void MainChannelClient::DidError() {
   DCHECK(IsMainThread());
-  worker_networking_task_runner_->PostTask(
-      FROM_HERE, CrossThreadBind(&WorkerGlobalScopeDidError, bridge_));
+  PostCrossThreadTask(*worker_networking_task_runner_, FROM_HERE,
+                      CrossThreadBind(&WorkerGlobalScopeDidError, bridge_));
 }
 
 void MainChannelClient::ContextDestroyed(WorkerThreadLifecycleContext*) {
@@ -414,18 +417,17 @@
         mojo::MakeRequest(&socket_ptr_info));
   }
 
-  parent_frame_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(
-              &Bridge::ConnectOnMainThread, WrapCrossThreadPersistent(this),
-              WTF::Passed(location->Clone()),
-              WrapCrossThreadPersistent(worker_thread->GetLoadingContext()),
-              std::move(worker_networking_task_runner),
-              WrapCrossThreadPersistent(
-                  worker_thread->GetWorkerThreadLifecycleContext()),
-              url, protocol, WTF::Passed(std::move(socket_ptr_info)),
-              CrossThreadUnretained(&sync_helper)));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kNetworking), FROM_HERE,
+      CrossThreadBind(
+          &Bridge::ConnectOnMainThread, WrapCrossThreadPersistent(this),
+          WTF::Passed(location->Clone()),
+          WrapCrossThreadPersistent(worker_thread->GetLoadingContext()),
+          std::move(worker_networking_task_runner),
+          WrapCrossThreadPersistent(
+              worker_thread->GetWorkerThreadLifecycleContext()),
+          url, protocol, WTF::Passed(std::move(socket_ptr_info)),
+          CrossThreadUnretained(&sync_helper)));
   sync_helper.Wait();
   return sync_helper.ConnectRequestResult();
 }
@@ -438,11 +440,10 @@
     memcpy(data->data(), static_cast<const char*>(message.data()),
            message.length());
 
-  parent_frame_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&MainChannelClient::SendTextAsCharVector,
-                          main_channel_client_, WTF::Passed(std::move(data))));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kNetworking), FROM_HERE,
+      CrossThreadBind(&MainChannelClient::SendTextAsCharVector,
+                      main_channel_client_, WTF::Passed(std::move(data))));
 }
 
 void Bridge::Send(const DOMArrayBuffer& binary_data,
@@ -458,46 +459,45 @@
            static_cast<const char*>(binary_data.Data()) + byte_offset,
            byte_length);
 
-  parent_frame_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(
-          FROM_HERE,
-          CrossThreadBind(&MainChannelClient::SendBinaryAsCharVector,
-                          main_channel_client_, WTF::Passed(std::move(data))));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kNetworking), FROM_HERE,
+      CrossThreadBind(&MainChannelClient::SendBinaryAsCharVector,
+                      main_channel_client_, WTF::Passed(std::move(data))));
 }
 
 void Bridge::Send(scoped_refptr<BlobDataHandle> data) {
   DCHECK(main_channel_client_);
-  parent_frame_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(&MainChannelClient::SendBlob,
-                                 main_channel_client_, std::move(data)));
+  PostCrossThreadTask(*parent_frame_task_runners_->Get(TaskType::kNetworking),
+                      FROM_HERE,
+                      CrossThreadBind(&MainChannelClient::SendBlob,
+                                      main_channel_client_, std::move(data)));
 }
 
 void Bridge::Close(int code, const String& reason) {
   DCHECK(main_channel_client_);
-  parent_frame_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(&MainChannelClient::Close,
-                                 main_channel_client_, code, reason));
+  PostCrossThreadTask(*parent_frame_task_runners_->Get(TaskType::kNetworking),
+                      FROM_HERE,
+                      CrossThreadBind(&MainChannelClient::Close,
+                                      main_channel_client_, code, reason));
 }
 
 void Bridge::Fail(const String& reason,
                   MessageLevel level,
                   std::unique_ptr<SourceLocation> location) {
   DCHECK(main_channel_client_);
-  parent_frame_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(FROM_HERE, CrossThreadBind(&MainChannelClient::Fail,
-                                            main_channel_client_, reason, level,
-                                            WTF::Passed(location->Clone())));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kNetworking), FROM_HERE,
+      CrossThreadBind(&MainChannelClient::Fail, main_channel_client_, reason,
+                      level, WTF::Passed(location->Clone())));
 }
 
 void Bridge::Disconnect() {
   if (!main_channel_client_)
     return;
 
-  parent_frame_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(FROM_HERE, CrossThreadBind(&MainChannelClient::Disconnect,
-                                            main_channel_client_));
+  PostCrossThreadTask(
+      *parent_frame_task_runners_->Get(TaskType::kNetworking), FROM_HERE,
+      CrossThreadBind(&MainChannelClient::Disconnect, main_channel_client_));
 
   client_ = nullptr;
   main_channel_client_ = nullptr;
diff --git a/third_party/WebKit/Source/platform/LongTaskDetectorTest.cpp b/third_party/WebKit/Source/platform/LongTaskDetectorTest.cpp
index 90a9c2fc..e2d6e79c 100644
--- a/third_party/WebKit/Source/platform/LongTaskDetectorTest.cpp
+++ b/third_party/WebKit/Source/platform/LongTaskDetectorTest.cpp
@@ -53,8 +53,8 @@
   double DummyTaskEndTime() { return dummy_task_end_time_; }
 
   void SimulateTask(double duration_seconds) {
-    platform_->CurrentThread()->GetWebTaskRunner()->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *platform_->CurrentThread()->GetWebTaskRunner(), FROM_HERE,
         CrossThreadBind(&LongTaskDetectorTest::DummyTaskWithDuration,
                         CrossThreadUnretained(this), duration_seconds));
     platform_->RunUntilIdle();
diff --git a/third_party/WebKit/Source/platform/MemoryCoordinator.cpp b/third_party/WebKit/Source/platform/MemoryCoordinator.cpp
index fec2a1c..f9653e7 100644
--- a/third_party/WebKit/Source/platform/MemoryCoordinator.cpp
+++ b/third_party/WebKit/Source/platform/MemoryCoordinator.cpp
@@ -114,8 +114,8 @@
     if (!thread->GetWebTaskRunner())
       continue;
 
-    thread->GetWebTaskRunner()->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *thread->GetWebTaskRunner(), FROM_HERE,
         CrossThreadBind(MemoryCoordinator::ClearThreadSpecificMemory));
   }
 }
diff --git a/third_party/WebKit/Source/platform/WebThreadSupportingGC.h b/third_party/WebKit/Source/platform/WebThreadSupportingGC.h
index 402c97d2..fb516850 100644
--- a/third_party/WebKit/Source/platform/WebThreadSupportingGC.h
+++ b/third_party/WebKit/Source/platform/WebThreadSupportingGC.h
@@ -46,7 +46,8 @@
   }
 
   void PostTask(const base::Location& location, CrossThreadClosure task) {
-    thread_->GetWebTaskRunner()->PostTask(location, std::move(task));
+    PostCrossThreadTask(*thread_->GetWebTaskRunner(), location,
+                        std::move(task));
   }
 
   void PostDelayedTask(const base::Location& location,
diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
index 4bc8be6..8476c133 100644
--- a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
+++ b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
@@ -127,8 +127,8 @@
   // Use the dual-thread rendering model if the thread from AudioWorkletThread
   // is available.
   if (worklet_backing_thread_) {
-    worklet_backing_thread_->GetWebTaskRunner()->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *worklet_backing_thread_->GetWebTaskRunner(), FROM_HERE,
         CrossThreadBind(&AudioDestination::RequestRender, WrapRefCounted(this),
                         number_of_frames, frames_to_render, delay,
                         delay_timestamp, prior_frames_skipped));
diff --git a/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp b/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp
index bacc42a..f1e0fdc1 100644
--- a/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp
+++ b/third_party/WebKit/Source/platform/audio/HRTFDatabaseLoader.cpp
@@ -97,9 +97,9 @@
   // Start the asynchronous database loading process.
   thread_ = Platform::Current()->CreateThread("HRTF database loader");
   // TODO(alexclarke): Should this be posted as a loading task?
-  thread_->GetWebTaskRunner()->PostTask(
-      FROM_HERE, CrossThreadBind(&HRTFDatabaseLoader::LoadTask,
-                                 CrossThreadUnretained(this)));
+  PostCrossThreadTask(*thread_->GetWebTaskRunner(), FROM_HERE,
+                      CrossThreadBind(&HRTFDatabaseLoader::LoadTask,
+                                      CrossThreadUnretained(this)));
 }
 
 HRTFDatabase* HRTFDatabaseLoader::Database() {
@@ -127,10 +127,10 @@
 
   WaitableEvent sync;
   // TODO(alexclarke): Should this be posted as a loading task?
-  thread_->GetWebTaskRunner()->PostTask(
-      FROM_HERE, CrossThreadBind(&HRTFDatabaseLoader::CleanupTask,
-                                 CrossThreadUnretained(this),
-                                 CrossThreadUnretained(&sync)));
+  PostCrossThreadTask(*thread_->GetWebTaskRunner(), FROM_HERE,
+                      CrossThreadBind(&HRTFDatabaseLoader::CleanupTask,
+                                      CrossThreadUnretained(this),
+                                      CrossThreadUnretained(&sync)));
   sync.Wait();
   thread_.reset();
 }
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
index b4dff74..85c5568c 100644
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFOMultithreadTest.cpp
@@ -36,9 +36,9 @@
   WaitableEvent* Start(double duration_ms, double interval_ms) {
     duration_ms_ = duration_ms;
     interval_ms_ = interval_ms;
-    client_thread_->GetWebTaskRunner()->PostTask(
-        FROM_HERE, CrossThreadBind(&FIFOClient::RunTaskOnOwnThread,
-                                   CrossThreadUnretained(this)));
+    PostCrossThreadTask(*client_thread_->GetWebTaskRunner(), FROM_HERE,
+                        CrossThreadBind(&FIFOClient::RunTaskOnOwnThread,
+                                        CrossThreadUnretained(this)));
     return done_event_.get();
   }
 
diff --git a/third_party/WebKit/Source/platform/audio/ReverbConvolver.cpp b/third_party/WebKit/Source/platform/audio/ReverbConvolver.cpp
index 52b8ace0..a3c0108 100644
--- a/third_party/WebKit/Source/platform/audio/ReverbConvolver.cpp
+++ b/third_party/WebKit/Source/platform/audio/ReverbConvolver.cpp
@@ -200,9 +200,9 @@
   // Now that we've buffered more input, post another task to the background
   // thread.
   if (background_thread_) {
-    background_thread_->GetWebTaskRunner()->PostTask(
-        FROM_HERE, CrossThreadBind(&ReverbConvolver::ProcessInBackground,
-                                   CrossThreadUnretained(this)));
+    PostCrossThreadTask(*background_thread_->GetWebTaskRunner(), FROM_HERE,
+                        CrossThreadBind(&ReverbConvolver::ProcessInBackground,
+                                        CrossThreadUnretained(this)));
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/blob/BlobBytesProvider.cpp b/third_party/WebKit/Source/platform/blob/BlobBytesProvider.cpp
index 1f68f24..71ab705 100644
--- a/third_party/WebKit/Source/platform/blob/BlobBytesProvider.cpp
+++ b/third_party/WebKit/Source/platform/blob/BlobBytesProvider.cpp
@@ -84,8 +84,9 @@
 // This keeps the process alive while blobs are being transferred.
 void IncreaseChildProcessRefCount() {
   if (!Platform::Current()->MainThread()->IsCurrentThread()) {
-    Platform::Current()->MainThread()->GetWebTaskRunner()->PostTask(
-        FROM_HERE, CrossThreadBind(&IncreaseChildProcessRefCount));
+    PostCrossThreadTask(*Platform::Current()->MainThread()->GetWebTaskRunner(),
+                        FROM_HERE,
+                        CrossThreadBind(&IncreaseChildProcessRefCount));
     return;
   }
   Platform::Current()->SuddenTerminationChanged(false);
@@ -94,8 +95,9 @@
 
 void DecreaseChildProcessRefCount() {
   if (!Platform::Current()->MainThread()->IsCurrentThread()) {
-    Platform::Current()->MainThread()->GetWebTaskRunner()->PostTask(
-        FROM_HERE, CrossThreadBind(&DecreaseChildProcessRefCount));
+    PostCrossThreadTask(*Platform::Current()->MainThread()->GetWebTaskRunner(),
+                        FROM_HERE,
+                        CrossThreadBind(&DecreaseChildProcessRefCount));
     return;
   }
   Platform::Current()->SuddenTerminationChanged(true);
diff --git a/third_party/WebKit/Source/platform/blob/BlobData.cpp b/third_party/WebKit/Source/platform/blob/BlobData.cpp
index 1dc3d22f9..575ba18c 100644
--- a/third_party/WebKit/Source/platform/blob/BlobData.cpp
+++ b/third_party/WebKit/Source/platform/blob/BlobData.cpp
@@ -354,8 +354,8 @@
             if (file_runner) {
               // TODO(mek): Considering binding BytesProvider on the IO thread
               // instead, only using the File thread for actual file operations.
-              file_runner->PostTask(
-                  FROM_HERE,
+              PostCrossThreadTask(
+                  *file_runner, FROM_HERE,
                   CrossThreadBind(
                       &BindBytesProvider, WTF::Passed(std::move(provider)),
                       WTF::Passed(MakeRequest(&bytes_provider_info))));
diff --git a/third_party/WebKit/Source/platform/exported/Platform.cpp b/third_party/WebKit/Source/platform/exported/Platform.cpp
index 69e4d36..972583e 100644
--- a/third_party/WebKit/Source/platform/exported/Platform.cpp
+++ b/third_party/WebKit/Source/platform/exported/Platform.cpp
@@ -104,8 +104,9 @@
 
 static void CallOnMainThreadFunction(WTF::MainThreadFunction function,
                                      void* context) {
-  Platform::Current()->MainThread()->GetWebTaskRunner()->PostTask(
-      FROM_HERE, CrossThreadBind(function, CrossThreadUnretained(context)));
+  PostCrossThreadTask(
+      *Platform::Current()->MainThread()->GetWebTaskRunner(), FROM_HERE,
+      CrossThreadBind(function, CrossThreadUnretained(context)));
 }
 
 Platform::Platform() : main_thread_(nullptr) {
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
index 5861585f..9e8cf27 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
@@ -412,10 +412,6 @@
   return resource_request_->CORSPreflightPolicy();
 }
 
-WebURLRequest::LoadingIPCType WebURLRequest::GetLoadingIPCType() const {
-  return resource_request_->GetLoadingIPCType();
-}
-
 void WebURLRequest::SetNavigationStartTime(double navigation_start_seconds) {
   resource_request_->SetNavigationStartTime(navigation_start_seconds);
 }
diff --git a/third_party/WebKit/Source/platform/geometry/FloatRect.cpp b/third_party/WebKit/Source/platform/geometry/FloatRect.cpp
index 0617c83c..e3b6002 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatRect.cpp
+++ b/third_party/WebKit/Source/platform/geometry/FloatRect.cpp
@@ -210,13 +210,24 @@
   return result;
 }
 
-IntRect EnclosedIntRect(const FloatRect& rect) {
-  IntPoint location = CeiledIntPoint(rect.MinXMinYCorner());
-  IntPoint max_point = FlooredIntPoint(rect.MaxXMaxYCorner());
-  IntSize size = max_point - location;
-  size.ClampNegativeToZero();
+IntRect EnclosingIntRect(const FloatRect& rect) {
+  // Compute the enclosing rect using float types directly rather than
+  // FlooredIntPoint(...) et.c to avoid triggering integer overflows.
+  FloatPoint location(floorf(rect.X()), floorf(rect.Y()));
+  FloatPoint max_point(ceilf(rect.MaxX()), ceilf(rect.MaxY()));
+  FloatRect enclosing_rect(location, max_point - location);
+  return IntRect(enclosing_rect);
+}
 
-  return IntRect(location, size);
+IntRect EnclosedIntRect(const FloatRect& rect) {
+  // Compute the enclosed rect using float types directly rather than
+  // FlooredIntPoint(...) et.c to avoid triggering integer overflows.
+  FloatPoint location(ceilf(rect.X()), ceilf(rect.Y()));
+  FloatPoint max_point(floorf(rect.MaxX()), floorf(rect.MaxY()));
+  FloatSize size = max_point - location;
+  size.ClampNegativeToZero();
+  FloatRect enclosed_rect(location, size);
+  return IntRect(enclosed_rect);
 }
 
 IntRect RoundedIntRect(const FloatRect& rect) {
diff --git a/third_party/WebKit/Source/platform/geometry/FloatRect.h b/third_party/WebKit/Source/platform/geometry/FloatRect.h
index 0be6fa1..1bf5932 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatRect.h
+++ b/third_party/WebKit/Source/platform/geometry/FloatRect.h
@@ -236,12 +236,8 @@
   return a.Location() != b.Location() || a.Size() != b.Size();
 }
 
-inline IntRect EnclosingIntRect(const FloatRect& rect) {
-  IntPoint location = FlooredIntPoint(rect.MinXMinYCorner());
-  IntPoint max_point = CeiledIntPoint(rect.MaxXMaxYCorner());
-
-  return IntRect(location, max_point - location);
-}
+// Returns a IntRect containing the given FloatRect.
+PLATFORM_EXPORT IntRect EnclosingIntRect(const FloatRect&);
 
 // Returns a valid IntRect contained within the given FloatRect.
 PLATFORM_EXPORT IntRect EnclosedIntRect(const FloatRect&);
diff --git a/third_party/WebKit/Source/platform/geometry/FloatRectTest.cpp b/third_party/WebKit/Source/platform/geometry/FloatRectTest.cpp
index e9a45aa9..64c5bee18 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatRectTest.cpp
+++ b/third_party/WebKit/Source/platform/geometry/FloatRectTest.cpp
@@ -161,4 +161,100 @@
   EXPECT_EQ("0,0 nanxnan", nan_rect.ToString());
 }
 
+TEST(FloatRectTest, EnclosingIntRect) {
+  FloatRect small_dimensions_rect(42.5f, 84.5f,
+                                  std::numeric_limits<float>::epsilon(),
+                                  std::numeric_limits<float>::epsilon());
+  EXPECT_EQ(IntRect(42, 84, 1, 1), EnclosingIntRect(small_dimensions_rect));
+
+  FloatRect integral_rect(100, 150, 200, 350);
+  EXPECT_EQ(IntRect(100, 150, 200, 350), EnclosingIntRect(integral_rect));
+
+  FloatRect fractional_pos_rect(100.6f, 150.8f, 200, 350);
+  EXPECT_EQ(IntRect(100, 150, 201, 351), EnclosingIntRect(fractional_pos_rect));
+
+  FloatRect fractional_dimensions_rect(100, 150, 200.6f, 350.4f);
+  EXPECT_EQ(IntRect(100, 150, 201, 351),
+            EnclosingIntRect(fractional_dimensions_rect));
+
+  FloatRect fractional_both_rect1(100.6f, 150.8f, 200.4f, 350.2f);
+  EXPECT_EQ(IntRect(100, 150, 201, 351),
+            EnclosingIntRect(fractional_both_rect1));
+
+  FloatRect fractional_both_rect2(100.6f, 150.8f, 200.3f, 350.3f);
+  EXPECT_EQ(IntRect(100, 150, 201, 352),
+            EnclosingIntRect(fractional_both_rect2));
+
+  FloatRect fractional_both_rect3(100.6f, 150.8f, 200.5f, 350.3f);
+  EXPECT_EQ(IntRect(100, 150, 202, 352),
+            EnclosingIntRect(fractional_both_rect3));
+
+  FloatRect fractional_negpos_rect1(-100.4f, -150.8f, 200, 350);
+  EXPECT_EQ(IntRect(-101, -151, 201, 351),
+            EnclosingIntRect(fractional_negpos_rect1));
+
+  FloatRect fractional_negpos_rect2(-100.4f, -150.8f, 199.4f, 350.3f);
+  EXPECT_EQ(IntRect(-101, -151, 200, 351),
+            EnclosingIntRect(fractional_negpos_rect2));
+
+  FloatRect fractional_negpos_rect3(-100.6f, -150.8f, 199.6f, 350.3f);
+  EXPECT_EQ(IntRect(-101, -151, 201, 351),
+            EnclosingIntRect(fractional_negpos_rect3));
+
+  FloatRect max_rect(-std::numeric_limits<float>::max() / 2,
+                     -std::numeric_limits<float>::max() / 2,
+                     std::numeric_limits<float>::max(),
+                     std::numeric_limits<float>::max());
+  EXPECT_EQ(IntRect(INT_MIN, INT_MIN, INT_MAX, INT_MAX),
+            EnclosingIntRect(max_rect));
+}
+
+TEST(FloatRectTest, EnclosedIntRect) {
+  FloatRect small_dimensions_rect(42.5f, 84.5f,
+                                  std::numeric_limits<float>::epsilon(),
+                                  std::numeric_limits<float>::epsilon());
+  EXPECT_EQ(IntRect(43, 85, 0, 0), EnclosedIntRect(small_dimensions_rect));
+
+  FloatRect integral_rect(100, 150, 200, 350);
+  EXPECT_EQ(IntRect(100, 150, 200, 350), EnclosedIntRect(integral_rect));
+
+  FloatRect fractional_pos_rect(100.6f, 150.8f, 200, 350);
+  EXPECT_EQ(IntRect(101, 151, 199, 349), EnclosedIntRect(fractional_pos_rect));
+
+  FloatRect fractional_dimensions_rect(100, 150, 200.6f, 350.4f);
+  EXPECT_EQ(IntRect(100, 150, 200, 350),
+            EnclosedIntRect(fractional_dimensions_rect));
+
+  FloatRect fractional_both_rect1(100.6f, 150.8f, 200.4f, 350.2f);
+  EXPECT_EQ(IntRect(101, 151, 200, 350),
+            EnclosedIntRect(fractional_both_rect1));
+
+  FloatRect fractional_both_rect2(100.6f, 150.8f, 200.3f, 350.3f);
+  EXPECT_EQ(IntRect(101, 151, 199, 350),
+            EnclosedIntRect(fractional_both_rect2));
+
+  FloatRect fractional_both_rect3(100.6f, 150.8f, 200.5f, 350.3f);
+  EXPECT_EQ(IntRect(101, 151, 200, 350),
+            EnclosedIntRect(fractional_both_rect3));
+
+  FloatRect fractional_negpos_rect1(-100.4f, -150.8f, 200, 350);
+  EXPECT_EQ(IntRect(-100, -150, 199, 349),
+            EnclosedIntRect(fractional_negpos_rect1));
+
+  FloatRect fractional_negpos_rect2(-100.4f, -150.8f, 199.5f, 350.3f);
+  EXPECT_EQ(IntRect(-100, -150, 199, 349),
+            EnclosedIntRect(fractional_negpos_rect2));
+
+  FloatRect fractional_negpos_rect3(-100.6f, -150.8f, 199.6f, 350.3f);
+  EXPECT_EQ(IntRect(-100, -150, 199, 349),
+            EnclosedIntRect(fractional_negpos_rect3));
+
+  FloatRect max_rect(-std::numeric_limits<float>::max() / 2,
+                     -std::numeric_limits<float>::max() / 2,
+                     std::numeric_limits<float>::max(),
+                     std::numeric_limits<float>::max());
+  EXPECT_EQ(IntRect(INT_MIN, INT_MIN, INT_MAX, INT_MAX),
+            EnclosedIntRect(max_rect));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/geometry/FloatSize.h b/third_party/WebKit/Source/platform/geometry/FloatSize.h
index 3e4466c13..5b1880b5 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatSize.h
+++ b/third_party/WebKit/Source/platform/geometry/FloatSize.h
@@ -102,6 +102,8 @@
                      height_ < other.height_ ? height_ : other.height_);
   }
 
+  void ClampNegativeToZero() { *this = ExpandedTo(FloatSize()); }
+
   float DiagonalLength() const;
   float DiagonalLengthSquared() const {
     return width_ * width_ + height_ * height_;
diff --git a/third_party/WebKit/Source/platform/graphics/AcceleratedStaticBitmapImage.cpp b/third_party/WebKit/Source/platform/graphics/AcceleratedStaticBitmapImage.cpp
index 2fbe206..6407ebe 100644
--- a/third_party/WebKit/Source/platform/graphics/AcceleratedStaticBitmapImage.cpp
+++ b/third_party/WebKit/Source/platform/graphics/AcceleratedStaticBitmapImage.cpp
@@ -101,8 +101,8 @@
         base::WrapUnique(new gpu::SyncToken(texture_holder_->GetSyncToken()));
     if (original_skia_image_thread_id_ !=
         Platform::Current()->CurrentThread()->ThreadId()) {
-      original_skia_image_task_runner_->PostTask(
-          FROM_HERE,
+      PostCrossThreadTask(
+          *original_skia_image_task_runner_, FROM_HERE,
           CrossThreadBind(
               &DestroySkImageOnOriginalThread, std::move(original_skia_image_),
               std::move(original_skia_image_context_provider_wrapper_),
diff --git a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
index e709d21c..68fa72c 100644
--- a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
@@ -227,9 +227,10 @@
   // Create a thread to rasterize PaintRecord.
   std::unique_ptr<WebThread> thread =
       Platform::Current()->CreateThread("RasterThread");
-  thread->GetWebTaskRunner()->PostTask(
-      FROM_HERE, CrossThreadBind(&RasterizeMain,
-                                 CrossThreadUnretained(canvas_.get()), record));
+  PostCrossThreadTask(
+      *thread->GetWebTaskRunner(), FROM_HERE,
+      CrossThreadBind(&RasterizeMain, CrossThreadUnretained(canvas_.get()),
+                      record));
   thread.reset();
   EXPECT_EQ(0, decode_request_count_);
   EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), bitmap_.getColor(0, 0));
diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
index 3ea746e..d1e1aed 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
@@ -258,8 +258,8 @@
   AddNewData();
   std::unique_ptr<WebThread> thread =
       Platform::Current()->CreateThread("DecodeThread");
-  thread->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *thread->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(&DecodeThreadMain, WTF::RetainedRef(generator_),
                       WTF::RetainedRef(segment_reader_)));
   thread.reset();
diff --git a/third_party/WebKit/Source/platform/graphics/MailboxTextureHolder.cpp b/third_party/WebKit/Source/platform/graphics/MailboxTextureHolder.cpp
index a72b753..4f83b700 100644
--- a/third_party/WebKit/Source/platform/graphics/MailboxTextureHolder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/MailboxTextureHolder.cpp
@@ -139,8 +139,8 @@
   if (!IsAbandoned()) {
     if (texture_thread_task_runner_ &&
         thread_id_ != Platform::Current()->CurrentThread()->ThreadId()) {
-      texture_thread_task_runner_->PostTask(
-          FROM_HERE,
+      PostCrossThreadTask(
+          *texture_thread_task_runner_, FROM_HERE,
           CrossThreadBind(&ReleaseTexture, is_converted_from_skia_texture_,
                           texture_id_, WTF::Passed(std::move(passed_mailbox)),
                           WTF::Passed(ContextProviderWrapper()),
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
index e9d00fb..b542af4 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
@@ -121,15 +121,12 @@
   scoped_refptr<WebTaskRunner> dispatcher_task_runner =
       Platform::Current()->CurrentThread()->GetWebTaskRunner();
 
-  Platform::Current()
-      ->MainThread()
-      ->Scheduler()
-      ->CompositorTaskRunner()
-      ->PostTask(FROM_HERE,
-                 CrossThreadBind(UpdatePlaceholderImage, this->GetWeakPtr(),
-                                 WTF::Passed(std::move(dispatcher_task_runner)),
-                                 placeholder_canvas_id_, std::move(image),
-                                 resource_id));
+  PostCrossThreadTask(
+      *Platform::Current()->MainThread()->Scheduler()->CompositorTaskRunner(),
+      FROM_HERE,
+      CrossThreadBind(UpdatePlaceholderImage, this->GetWeakPtr(),
+                      WTF::Passed(std::move(dispatcher_task_runner)),
+                      placeholder_canvas_id_, std::move(image), resource_id));
 }
 
 void OffscreenCanvasFrameDispatcherImpl::DispatchFrame(
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasPlaceholder.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasPlaceholder.cpp
index a2a6de7..3a9dfef4 100644
--- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasPlaceholder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasPlaceholder.cpp
@@ -97,8 +97,8 @@
   DCHECK(IsPlaceholderRegistered());
   if (placeholder_frame_) {
     placeholder_frame_->Transfer();
-    frame_dispatcher_task_runner_->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *frame_dispatcher_task_runner_, FROM_HERE,
         CrossThreadBind(releaseFrameToDispatcher, std::move(frame_dispatcher_),
                         std::move(placeholder_frame_),
                         placeholder_frame_resource_id_));
@@ -145,8 +145,8 @@
     bool suspend) {
   if (!frame_dispatcher_task_runner_)
     return false;
-  frame_dispatcher_task_runner_->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *frame_dispatcher_task_runner_, FROM_HERE,
       CrossThreadBind(SetSuspendAnimation, frame_dispatcher_, suspend));
   return true;
 }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp
index 12ba637..56a9fd3 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContext.cpp
@@ -122,8 +122,8 @@
     WaitableEvent waitable_event;
     scoped_refptr<WebTaskRunner> task_runner =
         Platform::Current()->MainThread()->GetWebTaskRunner();
-    task_runner->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *task_runner, FROM_HERE,
         CrossThreadBind(&CreateContextProviderOnMainThread,
                         only_if_gpu_compositing,
                         CrossThreadUnretained(&is_gpu_compositing_disabled_),
diff --git a/third_party/WebKit/Source/platform/heap/HeapTest.cpp b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
index 0e4875f..7da1b93 100644
--- a/third_party/WebKit/Source/platform/heap/HeapTest.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
@@ -457,8 +457,8 @@
     for (int i = 0; i < kNumberOfThreads; i++) {
       threads.push_back(
           Platform::Current()->CreateThread("blink gc testing thread"));
-      threads.back()->GetWebTaskRunner()->PostTask(
-          FROM_HERE,
+      PostCrossThreadTask(
+          *threads.back()->GetWebTaskRunner(), FROM_HERE,
           CrossThreadBind(ThreadFunc, CrossThreadUnretained(tester)));
     }
     while (tester->threads_to_finish_) {
@@ -5443,8 +5443,8 @@
     MutexLocker locker(MainThreadMutex());
     std::unique_ptr<WebThread> worker_thread =
         Platform::Current()->CreateThread("Test Worker Thread");
-    worker_thread->GetWebTaskRunner()->PostTask(
-        FROM_HERE, CrossThreadBind(WorkerThreadMain));
+    PostCrossThreadTask(*worker_thread->GetWebTaskRunner(), FROM_HERE,
+                        CrossThreadBind(WorkerThreadMain));
 
     // Wait for the worker thread initialization. The worker
     // allocates a weak collection where both collection and
@@ -5542,8 +5542,8 @@
     MutexLocker locker(MainThreadMutex());
     std::unique_ptr<WebThread> worker_thread =
         Platform::Current()->CreateThread("Test Worker Thread");
-    worker_thread->GetWebTaskRunner()->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *worker_thread->GetWebTaskRunner(), FROM_HERE,
         CrossThreadBind(&MemberSameThreadCheckTester::WorkerThreadMain,
                         CrossThreadUnretained(this)));
 
@@ -5585,8 +5585,8 @@
     MutexLocker locker(MainThreadMutex());
     std::unique_ptr<WebThread> worker_thread =
         Platform::Current()->CreateThread("Test Worker Thread");
-    worker_thread->GetWebTaskRunner()->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *worker_thread->GetWebTaskRunner(), FROM_HERE,
         CrossThreadBind(&PersistentSameThreadCheckTester::WorkerThreadMain,
                         CrossThreadUnretained(this)));
 
@@ -5629,8 +5629,8 @@
     std::unique_ptr<WebThread> worker_thread =
         Platform::Current()->CreateThread("Test Worker Thread");
     Persistent<MainThreadObject> main_thread_object = new MainThreadObject();
-    worker_thread->GetWebTaskRunner()->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *worker_thread->GetWebTaskRunner(), FROM_HERE,
         CrossThreadBind(&MarkingSameThreadCheckTester::WorkerThreadMain,
                         CrossThreadUnretained(this),
                         WrapCrossThreadPersistent(main_thread_object.Get())));
@@ -6414,8 +6414,8 @@
   std::unique_ptr<WebThread> worker_thread =
       Platform::Current()->CreateThread("Test Worker Thread");
   DestructorLockingObject* object = nullptr;
-  worker_thread->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *worker_thread->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(WorkerThreadMainForCrossThreadWeakPersistentTest,
                       CrossThreadUnretained(&object)));
   ParkMainThread();
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
index a6976e9..d1ca12b 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
@@ -77,7 +77,6 @@
       is_external_request_(false),
       cors_preflight_policy_(
           network::mojom::CORSPreflightPolicy::kConsiderPreflight),
-      loading_ipc_type_(WebURLRequest::LoadingIPCType::kMojo),
       is_same_document_navigation_(false),
       input_perf_metric_report_policy_(
           InputToLoadPerfMetricReportPolicy::kNoReport),
@@ -119,7 +118,6 @@
   ui_start_time_ = data->ui_start_time_;
   is_external_request_ = data->is_external_request_;
   cors_preflight_policy_ = data->cors_preflight_policy_;
-  loading_ipc_type_ = data->loading_ipc_type_;
   input_perf_metric_report_policy_ = data->input_perf_metric_report_policy_;
   redirect_status_ = data->redirect_status_;
 }
@@ -206,7 +204,6 @@
   data->ui_start_time_ = ui_start_time_;
   data->is_external_request_ = is_external_request_;
   data->cors_preflight_policy_ = cors_preflight_policy_;
-  data->loading_ipc_type_ = loading_ipc_type_;
   data->input_perf_metric_report_policy_ = input_perf_metric_report_policy_;
   data->redirect_status_ = redirect_status_;
   return data;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
index 54c4bac7..d63cab1 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
@@ -334,13 +334,6 @@
     cors_preflight_policy_ = policy;
   }
 
-  void OverrideLoadingIPCType(WebURLRequest::LoadingIPCType loading_ipc_type) {
-    loading_ipc_type_ = loading_ipc_type;
-  }
-  WebURLRequest::LoadingIPCType GetLoadingIPCType() const {
-    return loading_ipc_type_;
-  }
-
   InputToLoadPerfMetricReportPolicy InputPerfMetricReportPolicy() const {
     return input_perf_metric_report_policy_;
   }
@@ -402,7 +395,6 @@
   double ui_start_time_;
   bool is_external_request_;
   network::mojom::CORSPreflightPolicy cors_preflight_policy_;
-  WebURLRequest::LoadingIPCType loading_ipc_type_;
   bool is_same_document_navigation_;
   InputToLoadPerfMetricReportPolicy input_perf_metric_report_policy_;
   RedirectStatus redirect_status_;
@@ -464,7 +456,6 @@
   double ui_start_time_;
   bool is_external_request_;
   network::mojom::CORSPreflightPolicy cors_preflight_policy_;
-  WebURLRequest::LoadingIPCType loading_ipc_type_;
   InputToLoadPerfMetricReportPolicy input_perf_metric_report_policy_;
   ResourceRequest::RedirectStatus redirect_status_;
 };
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponseTest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponseTest.cpp
index ac5a59e..caf0f866 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceResponseTest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceResponseTest.cpp
@@ -78,8 +78,8 @@
   RunHeaderRelatedTest(response);
   std::unique_ptr<WebThread> thread =
       Platform::Current()->CreateThread("WorkerThread");
-  thread->GetWebTaskRunner()->PostTask(FROM_HERE,
-                                       CrossThreadBind(&RunInThread));
+  PostCrossThreadTask(*thread->GetWebTaskRunner(), FROM_HERE,
+                      CrossThreadBind(&RunInThread));
   thread.reset();
 }
 
diff --git a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
index 1f4d4a3..898e172 100644
--- a/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
+++ b/third_party/WebKit/Source/platform/network/NetworkStateNotifier.cpp
@@ -229,8 +229,8 @@
   MutexLocker locker(mutex_);
   for (const auto& entry : map) {
     scoped_refptr<WebTaskRunner> task_runner = entry.key;
-    task_runner->PostTask(
-        FROM_HERE,
+    PostCrossThreadTask(
+        *task_runner, FROM_HERE,
         CrossThreadBind(&NetworkStateNotifier::NotifyObserversOnTaskRunner,
                         CrossThreadUnretained(this),
                         CrossThreadUnretained(&map), type, task_runner, state));
diff --git a/third_party/WebKit/Source/platform/network/mime/MIMETypeRegistry.cpp b/third_party/WebKit/Source/platform/network/mime/MIMETypeRegistry.cpp
index 46e2b97..14a2f7b0 100644
--- a/third_party/WebKit/Source/platform/network/mime/MIMETypeRegistry.cpp
+++ b/third_party/WebKit/Source/platform/network/mime/MIMETypeRegistry.cpp
@@ -64,13 +64,11 @@
   // The sandbox restricts our access to the registry, so we need to proxy
   // these calls over to the browser process.
   DEFINE_STATIC_LOCAL(MimeRegistryPtrHolder, registry_holder, ());
-
-  // TODO(https://crbug.com/791168): Remove this temporary CHECK.
-  CHECK(!ext.IsNull());
-
   String mime_type;
-  if (!registry_holder.mime_registry->GetMimeTypeFromExtension(ext, &mime_type))
+  if (!registry_holder.mime_registry->GetMimeTypeFromExtension(
+          ext.IsNull() ? "" : ext, &mime_type)) {
     return String();
+  }
   return mime_type;
 }
 
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
index c93d044..4b08059 100644
--- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5
+++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -40,7 +40,7 @@
     // feature to be enabled at runtime on a per-page basis through a signed
     // token for the corresponding feature name. Declaring the
     // origin_trial_feature_name will cause a static method to be generated in
-    // OriginTrials.h/cpp. This static method allows the feature implementation
+    // origin_trials.h/cpp. This static method allows the feature implementation
     // to check if it is enabled for the current context.
     origin_trial_feature_name: {
     },
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
index 0c0f5dc4..7c9ea2d 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
@@ -113,8 +113,8 @@
     completion.Signal();
   }));
 
-  thread_->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *thread_->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(&MockTask::Run, WTF::CrossThreadUnretained(&task)));
   completion.Wait();
 }
@@ -131,8 +131,8 @@
     completion.Signal();
   }));
 
-  thread_->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *thread_->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(&MockTask::Run, WTF::CrossThreadUnretained(&task)));
   thread_.reset();
 }
@@ -163,8 +163,8 @@
 
   RunOnWorkerThread(FROM_HERE,
                     base::Bind(&AddTaskObserver, thread_.get(), &observer));
-  thread_->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *thread_->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(&RunTestTask, WTF::CrossThreadUnretained(&calls)));
   RunOnWorkerThread(FROM_HERE,
                     base::Bind(&RemoveTaskObserver, thread_.get(), &observer));
@@ -186,8 +186,8 @@
   EXPECT_CALL(delayed_task, Run()).Times(0);
 
   RunOnWorkerThread(FROM_HERE, base::Bind(&ShutdownOnThread, thread_.get()));
-  thread_->GetWebTaskRunner()->PostTask(
-      FROM_HERE,
+  PostCrossThreadTask(
+      *thread_->GetWebTaskRunner(), FROM_HERE,
       CrossThreadBind(&MockTask::Run, WTF::CrossThreadUnretained(&task)));
   thread_->GetWebTaskRunner()->PostDelayedTask(
       FROM_HERE,
diff --git a/third_party/WebKit/public/platform/WebTextInputMode.h b/third_party/WebKit/public/platform/WebTextInputMode.h
index b35e670..ac7e11b 100644
--- a/third_party/WebKit/public/platform/WebTextInputMode.h
+++ b/third_party/WebKit/public/platform/WebTextInputMode.h
@@ -13,19 +13,15 @@
 // GENERATED_JAVA_PREFIX_TO_STRIP: WebTextInputMode
 enum WebTextInputMode {
   kWebTextInputModeDefault,
-  kWebTextInputModeVerbatim,
-  kWebTextInputModeLatin,
-  kWebTextInputModeLatinName,
-  kWebTextInputModeLatinProse,
-  kWebTextInputModeFullWidthLatin,
-  kWebTextInputModeKana,
-  kWebTextInputModeKanaName,
-  kWebTextInputModeKataKana,
-  kWebTextInputModeNumeric,
+  kWebTextInputModeNone,
+  kWebTextInputModeText,
   kWebTextInputModeTel,
-  kWebTextInputModeEmail,
   kWebTextInputModeUrl,
-  kWebTextInputModeMax = kWebTextInputModeUrl,
+  kWebTextInputModeEmail,
+  kWebTextInputModeNumeric,
+  kWebTextInputModeDecimal,
+  kWebTextInputModeSearch,
+  kWebTextInputModeMax = kWebTextInputModeSearch,
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/WebURLRequest.h b/third_party/WebKit/public/platform/WebURLRequest.h
index 2b4515f..9575dda 100644
--- a/third_party/WebKit/public/platform/WebURLRequest.h
+++ b/third_party/WebKit/public/platform/WebURLRequest.h
@@ -155,11 +155,6 @@
     kNone
   };
 
-  enum class LoadingIPCType : uint8_t {
-    kChromeIPC,
-    kMojo,
-  };
-
   class ExtraData {
    public:
     virtual ~ExtraData() = default;
@@ -343,8 +338,6 @@
   BLINK_PLATFORM_EXPORT network::mojom::CORSPreflightPolicy
   GetCORSPreflightPolicy() const;
 
-  BLINK_PLATFORM_EXPORT LoadingIPCType GetLoadingIPCType() const;
-
   BLINK_PLATFORM_EXPORT void SetNavigationStartTime(double);
 
   // PlzNavigate: specify that the request was intended to be loaded as a same
diff --git a/third_party/WebKit/public/platform/WebVector.h b/third_party/WebKit/public/platform/WebVector.h
index afaf554..6cc2882c 100644
--- a/third_party/WebKit/public/platform/WebVector.h
+++ b/third_party/WebKit/public/platform/WebVector.h
@@ -78,11 +78,11 @@
   template <typename C>
   WebVector(const C& other) : data_(other.begin(), other.end()) {}
 
-  WebVector(WebVector<T>&& other) { Swap(other); }
+  WebVector(WebVector<T>&& other) noexcept { Swap(other); }
 
-  WebVector(std::vector<T>&& other) : data_(std::move(other)) {}
+  WebVector(std::vector<T>&& other) noexcept : data_(std::move(other)) {}
 
-  std::vector<T> ReleaseVector() { return std::move(data_); }
+  std::vector<T> ReleaseVector() noexcept { return std::move(data_); }
 
   WebVector& operator=(const WebVector& other) {
     if (this != &other)
@@ -90,7 +90,7 @@
     return *this;
   }
 
-  WebVector& operator=(WebVector&& other) {
+  WebVector& operator=(WebVector&& other) noexcept {
     if (this != &other)
       Swap(other);
     return *this;
@@ -103,7 +103,7 @@
     return *this;
   }
 
-  WebVector<T>& operator=(std::vector<T>&& other) {
+  WebVector<T>& operator=(std::vector<T>&& other) noexcept {
     data_ = std::move(other);
     return *this;
   }
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h
index cbf263a6..8601750f 100644
--- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h
+++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h
@@ -72,10 +72,10 @@
 
   // Callee receives ownership of the passed vector.
   // FIXME: Blob refs should be passed to maintain ref counts. crbug.com/351753
-  virtual void PostMessage(WebServiceWorkerProvider*,
-                           const WebString&,
-                           const WebSecurityOrigin&,
-                           WebVector<MessagePortChannel>) = 0;
+  virtual void PostMessageToWorker(WebServiceWorkerProvider*,
+                                   const WebString&,
+                                   const WebSecurityOrigin&,
+                                   WebVector<MessagePortChannel>) = 0;
 
   virtual void Terminate() {}
 };
diff --git a/third_party/WebKit/public/platform/web_feature.mojom b/third_party/WebKit/public/platform/web_feature.mojom
index 4a63a089..f109f87e 100644
--- a/third_party/WebKit/public/platform/web_feature.mojom
+++ b/third_party/WebKit/public/platform/web_feature.mojom
@@ -1826,6 +1826,7 @@
   kCSSSelectorWebkitSliderThumb = 2317,
   kCSSSelectorWebkitTextfieldDecorationContainer = 2318,
   kCSSSelectorWebkitUnknownPseudo = 2319,
+  kFilterAsContainingBlockMayChangeOutput = 2320,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/public/web/WebDevToolsAgent.h b/third_party/WebKit/public/web/WebDevToolsAgent.h
index 1b730f2..a81c3ca 100644
--- a/third_party/WebKit/public/web/WebDevToolsAgent.h
+++ b/third_party/WebKit/public/web/WebDevToolsAgent.h
@@ -54,9 +54,6 @@
   virtual void InspectElementAt(int session_id, const WebPoint&) = 0;
   virtual void FailedToRequestDevTools(int session_id) = 0;
 
-  // Exposed for TestRunner.
-  virtual WebString EvaluateInWebInspectorOverlay(const WebString& script) = 0;
-
   class MessageDescriptor {
    public:
     virtual ~MessageDescriptor() {}
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js
index 5d8a092b..607cc06 100644
--- a/third_party/closure_compiler/externs/automation.js
+++ b/third_party/closure_compiler/externs/automation.js
@@ -1058,15 +1058,27 @@
 
 /**
  * @type {(!chrome.automation.AutomationNode|undefined)}
+ * @see https://developer.chrome.com/extensions/automation#type-previousOnLine
+ */
+chrome.automation.AutomationNode.prototype.previousOnLine;
+
+/**
+ * @type {(!chrome.automation.AutomationNode|undefined)}
  * @see https://developer.chrome.com/extensions/automation#type-nextOnLine
  */
 chrome.automation.AutomationNode.prototype.nextOnLine;
 
 /**
  * @type {(!chrome.automation.AutomationNode|undefined)}
- * @see https://developer.chrome.com/extensions/automation#type-previousOnLine
+ * @see https://developer.chrome.com/extensions/automation#type-previousFocus
  */
-chrome.automation.AutomationNode.prototype.previousOnLine;
+chrome.automation.AutomationNode.prototype.previousFocus;
+
+/**
+ * @type {(!chrome.automation.AutomationNode|undefined)}
+ * @see https://developer.chrome.com/extensions/automation#type-nextFocus
+ */
+chrome.automation.AutomationNode.prototype.nextFocus;
 
 /**
  * The index of this node in its parent node's list of children. If this is the root node, this will be undefined.
diff --git a/third_party/closure_compiler/externs/networking_private.js b/third_party/closure_compiler/externs/networking_private.js
index 2c6609a4..8fda402 100644
--- a/third_party/closure_compiler/externs/networking_private.js
+++ b/third_party/closure_compiler/externs/networking_private.js
@@ -581,6 +581,7 @@
  *   StaticChallenge: (string|undefined),
  *   TLSAuthContents: (string|undefined),
  *   TLSRemote: (string|undefined),
+ *   TLSVersionMin: (string|undefined),
  *   UserAuthenticationType: (string|undefined),
  *   Username: (string|undefined),
  *   Verb: (string|undefined),
@@ -625,6 +626,7 @@
  *   StaticChallenge: (!chrome.networkingPrivate.ManagedDOMString|undefined),
  *   TLSAuthContents: (!chrome.networkingPrivate.ManagedDOMString|undefined),
  *   TLSRemote: (!chrome.networkingPrivate.ManagedDOMString|undefined),
+ *   TLSVersionMin: (!chrome.networkingPrivate.ManagedDOMString|undefined),
  *   UserAuthenticationType: (!chrome.networkingPrivate.ManagedDOMString|undefined),
  *   Username: (!chrome.networkingPrivate.ManagedDOMString|undefined),
  *   Verb: (!chrome.networkingPrivate.ManagedDOMString|undefined),
diff --git a/third_party/fontconfig/BUILD.gn b/third_party/fontconfig/BUILD.gn
index be7cb657..8ff1984 100644
--- a/third_party/fontconfig/BUILD.gn
+++ b/third_party/fontconfig/BUILD.gn
@@ -55,6 +55,13 @@
       "FONTCONFIG_PATH=\"/etc/fonts\"",
     ]
 
+    # This is a hack to remove visibility("default") annotations.  Fontconfig
+    # symbols should not be exported from chrome, nacl_helper, or anything
+    # else.
+    if (!is_component_build) {
+      defines += [ "visibility(x)=" ]
+    }
+
     deps = [
       "//build/config/freetype",
       "//third_party/libxml",
diff --git a/third_party/fontconfig/fontconfig.gni b/third_party/fontconfig/fontconfig.gni
index 8bc15ee..3ea4dd2a 100644
--- a/third_party/fontconfig/fontconfig.gni
+++ b/third_party/fontconfig/fontconfig.gni
@@ -7,5 +7,5 @@
 assert(is_linux)
 
 declare_args() {
-  use_bundled_fontconfig = is_chromecast
+  use_bundled_fontconfig = is_chromecast || is_desktop_linux
 }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-spinner/BUILD.gn b/third_party/polymer/v1_0/components-chromium/paper-spinner/BUILD.gn
index 4f251b8..e3975fc 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-spinner/BUILD.gn
+++ b/third_party/polymer/v1_0/components-chromium/paper-spinner/BUILD.gn
@@ -9,12 +9,6 @@
 js_library("paper-spinner-behavior-extracted") {
 }
 
-js_library("paper-spinner-extracted") {
-  deps = [
-    ":paper-spinner-behavior-extracted",
-  ]
-}
-
 js_library("paper-spinner-lite-extracted") {
   deps = [
     ":paper-spinner-behavior-extracted",
diff --git a/third_party/polymer/v1_0/components-chromium/paper-spinner/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-spinner/compiled_resources2.gyp
index 195630bf..521f47e 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-spinner/compiled_resources2.gyp
+++ b/third_party/polymer/v1_0/components-chromium/paper-spinner/compiled_resources2.gyp
@@ -10,13 +10,6 @@
       'includes': ['../../../../closure_compiler/compile_js2.gypi'],
     },
     {
-      'target_name': 'paper-spinner-extracted',
-      'dependencies': [
-        'paper-spinner-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
       'target_name': 'paper-spinner-lite-extracted',
       'dependencies': [
         'paper-spinner-behavior-extracted',
diff --git a/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-extracted.js
deleted file mode 100644
index 6b05563..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-extracted.js
+++ /dev/null
@@ -1,7 +0,0 @@
-Polymer({
-      is: 'paper-spinner',
-
-      behaviors: [
-        Polymer.PaperSpinnerBehavior
-      ]
-    });
\ No newline at end of file
diff --git a/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner.html b/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner.html
deleted file mode 100644
index 9ab85bb6..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!--
-@license
-Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
-This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
-The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
-The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
-Code distributed by Google as part of the polymer project is also
-subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
---><html><head><link rel="import" href="../polymer/polymer.html">
-<link rel="import" href="../iron-flex-layout/iron-flex-layout.html">
-<link rel="import" href="../paper-styles/color.html">
-<link rel="import" href="paper-spinner-behavior.html">
-<link rel="import" href="paper-spinner-styles.html">
-
-<!--
-Material design: [Progress & activity](https://www.google.com/design/spec/components/progress-activity.html)
-
-Element providing a multiple color material design circular spinner.
-
-    <paper-spinner active></paper-spinner>
-
-The default spinner cycles between four layers of colors; by default they are
-blue, red, yellow and green. It can be customized to cycle between four different
-colors. Use <paper-spinner-lite> for single color spinners.
-
-### Accessibility
-
-Alt attribute should be set to provide adequate context for accessibility. If not provided,
-it defaults to 'loading'.
-Empty alt can be provided to mark the element as decorative if alternative content is provided
-in another form (e.g. a text block following the spinner).
-
-    <paper-spinner alt="Loading contacts list" active></paper-spinner>
-
-### Styling
-
-The following custom properties and mixins are available for styling:
-
-Custom property | Description | Default
-----------------|-------------|----------
-`--paper-spinner-layer-1-color` | Color of the first spinner rotation | `--google-blue-500`
-`--paper-spinner-layer-2-color` | Color of the second spinner rotation | `--google-red-500`
-`--paper-spinner-layer-3-color` | Color of the third spinner rotation | `--google-yellow-500`
-`--paper-spinner-layer-4-color` | Color of the fourth spinner rotation | `--google-green-500`
-`--paper-spinner-stroke-width` | The width of the spinner stroke | 3px
-
-@group Paper Elements
-@element paper-spinner
-@hero hero.svg
-@demo demo/index.html
--->
-
-</head><body><dom-module id="paper-spinner">
-  <template strip-whitespace="">
-    <style include="paper-spinner-styles"></style>
-
-    <div id="spinnerContainer" class-name="[[__computeContainerClasses(active, __coolingDown)]]">
-      <div class="spinner-layer layer-1">
-        <div class="circle-clipper left"></div>
-        <div class="circle-clipper right"></div>
-      </div>
-
-      <div class="spinner-layer layer-2">
-        <div class="circle-clipper left"></div>
-        <div class="circle-clipper right"></div>
-      </div>
-
-      <div class="spinner-layer layer-3">
-        <div class="circle-clipper left"></div>
-        <div class="circle-clipper right"></div>
-      </div>
-
-      <div class="spinner-layer layer-4">
-        <div class="circle-clipper left"></div>
-        <div class="circle-clipper right"></div>
-      </div>
-    </div>
-  </template>
-
-  </dom-module>
-<script src="paper-spinner-extracted.js"></script></body></html>
\ No newline at end of file
diff --git a/third_party/polymer/v1_0/rsync_exclude.txt b/third_party/polymer/v1_0/rsync_exclude.txt
index bd42190..d40603d3 100644
--- a/third_party/polymer/v1_0/rsync_exclude.txt
+++ b/third_party/polymer/v1_0/rsync_exclude.txt
@@ -24,6 +24,8 @@
 # iron-flex-layout
 iron-flex-layout/classes/
 
-#paper-material
+# paper-material
 paper-material/paper-material.html
-paper-material/paper-material.js
+
+# paper-spinner
+paper-spinner/paper-spinner.html
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py
index d46cdf1..7627d42 100755
--- a/tools/binary_size/diagnose_bloat.py
+++ b/tools/binary_size/diagnose_bloat.py
@@ -664,25 +664,33 @@
 
 
 def _DownloadAndArchive(gsutil_path, archive, dl_dir, build, supersize_path):
-  proc = subprocess.Popen([gsutil_path, 'version'], stdout=subprocess.PIPE,
-                          stderr=subprocess.STDOUT)
-  output, _ = proc.communicate()
-  if proc.returncode:
-    _Die('gsutil error. Please file a bug in Tools>BinarySize. Output:\n%s',
-         output)
+  # Wraps gsutil calls and returns stdout + stderr.
+  def gsutil_cmd(args, fail_msg=None):
+    fail_msg = fail_msg or ''
+    proc = subprocess.Popen([gsutil_path] + args, stdout=subprocess.PIPE,
+                            stderr=subprocess.STDOUT)
+    output = proc.communicate()[0].rstrip()
+    if proc.returncode or not output:
+      _Die(fail_msg + ' Process output:\n%s' % output)
+    return output
 
+  # Fails if gsutil isn't configured.
+  gsutil_cmd(['version'],
+             'gsutil error. Please file a bug in Tools>BinarySize.')
   dl_dst = os.path.join(dl_dir, archive.rev)
   logging.info('Downloading build artifacts for %s', archive.rev)
-  # gsutil writes stdout and stderr to stderr, so pipe stdout and stderr to
-  # sys.stdout.
-  retcode = subprocess.call(
-      [gsutil_path, 'cp', build.DownloadUrl(archive.rev), dl_dst],
-      stdout=sys.stdout, stderr=subprocess.STDOUT)
-  if retcode:
-      _Die('unexpected error while downloading %s. It may no longer exist on '
-           'the server or it may not have been uploaded yet (check %s). '
-           'Otherwise, you may not have the correct access permissions.',
-           build.DownloadUrl(archive.rev), build.builder_url)
+
+  # Fails if archive isn't found.
+  output = gsutil_cmd(['stat', build.DownloadUrl(archive.rev)],
+      'Unexpected error while downloading %s. It may no longer exist on the '
+      'server or it may not have been uploaded yet (check %s). Otherwise, you '
+      'may not have the correct access permissions.' % (
+      build.DownloadUrl(archive.rev), build.builder_url))
+  size = re.search(r'Content-Length:\s+([0-9]+)', output).group(1)
+  logging.info('File size: %s', _ReadableBytes(int(size)))
+
+  # Download archive. Any failures here are unexpected.
+  gsutil_cmd(['cp', build.DownloadUrl(archive.rev), dl_dst])
 
   # Files needed for supersize and resource_sizes. Paths relative to out dir.
   to_extract = [build.main_lib_path, build.map_file_path, 'args.gn']
@@ -698,6 +706,17 @@
     build.output_directory = output_directory
 
 
+def _ReadableBytes(b):
+  val = b
+  units = ['Bytes','KB', 'MB', 'GB']
+  for unit in units:
+    if val < 1024:
+      return '%.2f %s' % (val, unit)
+    val /= 1024.0
+  else:
+    return '%d %s' % (b, 'Bytes')
+
+
 def _ExtractFiles(to_extract, dst, z):
   """Extract a list of files. Returns the common prefix of the extracted files.
 
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
index 5a5a664f6..1df0b4e 100644
--- a/tools/binary_size/libsupersize/archive.py
+++ b/tools/binary_size/libsupersize/archive.py
@@ -779,7 +779,7 @@
 def _ParseApkElfSectionSize(section_sizes, metadata, apk_elf_result):
   if metadata:
     logging.debug('Extracting section sizes from .so within .apk')
-    apk_build_id, apk_section_sizes = apk_elf_result.get()
+    apk_build_id, apk_section_sizes, elf_overhead_size = apk_elf_result.get()
     assert apk_build_id == metadata[models.METADATA_ELF_BUILD_ID], (
         'BuildID from apk_elf_result did not match')
 
@@ -798,13 +798,16 @@
       else:
         apk_section_sizes['%s (unpacked)' % packed_section_name] = (
             section_sizes.get(packed_section_name))
-  return apk_section_sizes
+    return apk_section_sizes, elf_overhead_size
+  return section_sizes
 
 
 def _ParseApkOtherSymbols(section_sizes, apk_path):
   apk_symbols = []
+  zip_info_total = 0
   with zipfile.ZipFile(apk_path) as z:
     for zip_info in z.infolist():
+      zip_info_total += zip_info.compress_size
       # Skip shared library and pak files as they are already accounted for.
       if (zip_info.filename.endswith('.so')
           or zip_info.filename.endswith('.pak')):
@@ -812,6 +815,10 @@
       apk_symbols.append(models.Symbol(
             models.SECTION_OTHER, zip_info.compress_size,
             full_name=zip_info.filename))
+  overhead_size = os.path.getsize(apk_path) - zip_info_total
+  apk_symbols.append(models.Symbol(
+        models.SECTION_OTHER, overhead_size,
+        full_name='APK zip overhead'))
   prev = section_sizes.setdefault(models.SECTION_OTHER, 0)
   section_sizes[models.SECTION_OTHER] = prev + sum(s.size for s in apk_symbols)
   return apk_symbols
@@ -847,6 +854,18 @@
   return symbols_by_id
 
 
+def _CalculateElfOverhead(section_sizes, elf_path):
+  if elf_path:
+    section_sizes_total_without_bss = sum(
+        s for k, s in section_sizes.iteritems() if k != models.SECTION_BSS)
+    elf_overhead_size = (
+        os.path.getsize(elf_path) - section_sizes_total_without_bss)
+    assert elf_overhead_size >= 0, (
+        'Negative ELF overhead {}'.format(elf_overhead_size))
+    return elf_overhead_size
+  return 0
+
+
 def CreateSectionSizesAndSymbols(
       map_path=None, tool_prefix=None, output_directory=None, elf_path=None,
       apk_path=None, track_string_literals=True, metadata=None,
@@ -879,17 +898,26 @@
   section_sizes, raw_symbols = _ParseElfInfo(
       map_path, elf_path, tool_prefix, output_directory, track_string_literals,
       elf_object_paths)
+  elf_overhead_size = _CalculateElfOverhead(section_sizes, elf_path)
 
   pak_symbols_by_id = None
   if apk_path:
     pak_symbols_by_id = _FindPakSymbolsFromApk(apk_path, output_directory)
-    section_sizes = _ParseApkElfSectionSize(
+    section_sizes, elf_overhead_size = _ParseApkElfSectionSize(
         section_sizes, metadata, apk_elf_result)
     raw_symbols.extend(_ParseApkOtherSymbols(section_sizes, apk_path))
   elif pak_files and pak_info_file:
     pak_symbols_by_id = _FindPakSymbolsFromFiles(
         pak_files, pak_info_file, output_directory)
 
+  if elf_path:
+    elf_overhead_symbol = models.Symbol(
+        models.SECTION_OTHER, elf_overhead_size,
+        full_name='ELF file overhead')
+    prev = section_sizes.setdefault(models.SECTION_OTHER, 0)
+    section_sizes[models.SECTION_OTHER] = prev + elf_overhead_size
+    raw_symbols.append(elf_overhead_symbol)
+
   if pak_symbols_by_id:
     object_paths = (p for p in source_mapper.IterAllPaths() if p.endswith('.o'))
     pak_raw_symbols = _ParsePakSymbols(
@@ -994,7 +1022,8 @@
     f.flush()
     build_id = BuildIdFromElf(f.name, tool_prefix)
     section_sizes = _SectionSizesFromElf(f.name, tool_prefix)
-    return build_id, section_sizes
+    elf_overhead_size = _CalculateElfOverhead(section_sizes, f.name)
+    return build_id, section_sizes, elf_overhead_size
 
 
 def AddArguments(parser):
diff --git a/tools/binary_size/libsupersize/integration_test.py b/tools/binary_size/libsupersize/integration_test.py
index edac84a..224265d7 100755
--- a/tools/binary_size/libsupersize/integration_test.py
+++ b/tools/binary_size/libsupersize/integration_test.py
@@ -12,6 +12,7 @@
 import os
 import unittest
 import re
+import shutil
 import subprocess
 import sys
 import tempfile
@@ -29,9 +30,10 @@
 _TEST_TOOL_PREFIX = os.path.join(
     os.path.abspath(_TEST_DATA_DIR), 'mock_toolchain', '')
 _TEST_MAP_PATH = os.path.join(_TEST_DATA_DIR, 'test.map')
-_TEST_ELF_PATH = os.path.join(_TEST_OUTPUT_DIR, 'elf')
 _TEST_PAK_PATH = os.path.join(_TEST_OUTPUT_DIR, 'en-US.pak')
 _TEST_PAK_INFO_PATH = os.path.join(_TEST_OUTPUT_DIR, 'en-US.pak.info')
+_TEST_ELF_PATH = os.path.join(_TEST_OUTPUT_DIR, 'elf')  # Dynamically created
+_TEST_ELF_FILE_BEGIN = os.path.join(_TEST_OUTPUT_DIR, 'elf.begin')
 
 update_goldens = False
 
@@ -100,6 +102,20 @@
   maxDiff = None  # Don't trucate diffs in errors.
   cached_size_info = {}
 
+  @classmethod
+  def setUpClass(cls):
+    shutil.copy(_TEST_ELF_FILE_BEGIN, _TEST_ELF_PATH)
+    with open(_TEST_ELF_PATH, 'a') as elf_file:
+      data = '0'
+      # Exactly 128MB of data (2^27), extra bytes will be accounted in overhead.
+      for _ in range(27):
+        data = data + data
+      elf_file.write(data)
+
+  @classmethod
+  def tearDownClass(cls):
+    os.remove(_TEST_ELF_PATH)
+
   def _CloneSizeInfo(self, use_output_directory=True, use_elf=True,
                      use_pak=False):
     assert not use_elf or use_output_directory
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Elf.golden b/tools/binary_size/libsupersize/testdata/Archive_Elf.golden
index d770f07..e735455 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_Elf.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_Elf.golden
@@ -31,6 +31,10 @@
 * Padding accounts for 196 bytes (0.0%)
 * Contains 0 aliases
 * 0 symbols have shared ownership
+Section .other: has 100.0% of 33984171 bytes accounted for from 1 symbols. 0 bytes are unaccounted for.
+* Padding accounts for 0 bytes (0.0%)
+* Contains 0 aliases
+* 0 symbols have shared ownership
 .data@2de7000(size_without_padding=4,padding=0,full_name=google::protobuf::internal::pLinuxKernelCmpxchg,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=1)
 .data@2de7004(size_without_padding=4,padding=0,full_name=google::protobuf::internal::pLinuxKernelMemoryBarrier,object_path=third_party/WebKit.a/ContiguousContainer.o,source_path=third_party/container.c,flags={},num_aliases=1)
 .data@2de7008(size_without_padding=152,padding=0,full_name=base::android::kBaseRegisteredMethods,object_path=third_party/WebKit.a/ContiguousContainer.o,source_path=third_party/container.c,flags={rel},num_aliases=1)
@@ -46,6 +50,7 @@
 .data.rel.ro.local@2c17740(size_without_padding=789904,padding=0,full_name=chrome::mojom::FieldTrialRecorderProxy [vtable],object_path=third_party/WebKit.a/ContiguousContainer.o,source_path=third_party/container.c,flags={},num_aliases=1)
 .data.rel.ro.local@2cd84e0(size_without_padding=16,padding=16,full_name=.Lswitch.table.45,object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o,source_path=,flags={},num_aliases=1)
 .data.rel.ro.local@2cd84f0(size_without_padding=8,padding=0,full_name=kSystemClassPrefixes,object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o,source_path=,flags={anon},num_aliases=1)
+.other@0(size_without_padding=33984171,padding=0,full_name=ELF file overhead,object_path=,source_path=,flags={},num_aliases=1)
 .rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2)
 .rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2)
 .rodata@266e605(size_without_padding=16,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Pak.golden b/tools/binary_size/libsupersize/testdata/Archive_Pak.golden
index bd3e0308..daa279c 100644
--- a/tools/binary_size/libsupersize/testdata/Archive_Pak.golden
+++ b/tools/binary_size/libsupersize/testdata/Archive_Pak.golden
@@ -35,6 +35,10 @@
 * Padding accounts for 0 bytes (0.0%)
 * Contains 0 aliases
 * 0 symbols have shared ownership
+Section .other: has 100.0% of 33984171 bytes accounted for from 1 symbols. 0 bytes are unaccounted for.
+* Padding accounts for 0 bytes (0.0%)
+* Contains 0 aliases
+* 0 symbols have shared ownership
 .data@2de7000(size_without_padding=4,padding=0,full_name=google::protobuf::internal::pLinuxKernelCmpxchg,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=1)
 .data@2de7004(size_without_padding=4,padding=0,full_name=google::protobuf::internal::pLinuxKernelMemoryBarrier,object_path=third_party/WebKit.a/ContiguousContainer.o,source_path=third_party/container.c,flags={},num_aliases=1)
 .data@2de7008(size_without_padding=152,padding=0,full_name=base::android::kBaseRegisteredMethods,object_path=third_party/WebKit.a/ContiguousContainer.o,source_path=third_party/container.c,flags={rel},num_aliases=1)
@@ -50,6 +54,7 @@
 .data.rel.ro.local@2c17740(size_without_padding=789904,padding=0,full_name=chrome::mojom::FieldTrialRecorderProxy [vtable],object_path=third_party/WebKit.a/ContiguousContainer.o,source_path=third_party/container.c,flags={},num_aliases=1)
 .data.rel.ro.local@2cd84e0(size_without_padding=16,padding=16,full_name=.Lswitch.table.45,object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o,source_path=,flags={},num_aliases=1)
 .data.rel.ro.local@2cd84f0(size_without_padding=8,padding=0,full_name=kSystemClassPrefixes,object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o,source_path=,flags={anon},num_aliases=1)
+.other@0(size_without_padding=33984171,padding=0,full_name=ELF file overhead,object_path=,source_path=,flags={},num_aliases=1)
 .rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2)
 .rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2)
 .rodata@266e605(size_without_padding=16,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1)
diff --git a/tools/binary_size/libsupersize/testdata/Console.golden b/tools/binary_size/libsupersize/testdata/Console.golden
index 7b24e7ae..6d00d099 100644
--- a/tools/binary_size/libsupersize/testdata/Console.golden
+++ b/tools/binary_size/libsupersize/testdata/Console.golden
@@ -68,26 +68,27 @@
     map_file_name=../test.map
     tool_prefix=tools/binary_size/libsupersize/testdata/mock_toolchain/
 
-Section Sizes (Total=95.6mb (100233874 bytes)):
-    .ARM.exidx: 1.47mb (1536456 bytes) (1.5%)
+Section Sizes (Total=128.0mb (134218045 bytes)):
+    .ARM.exidx: 1.47mb (1536456 bytes) (1.1%)
     .bss: 1.24mb (1300456 bytes) (not included in totals)
     .data: 99.4kb (101768 bytes) (0.1%)
-    .data.rel.ro: 1.02mb (1065224 bytes) (1.1%)
-    .rel.dyn: 2.53mb (2655384 bytes) (2.6%)
-    .rodata: 5.65mb (5927652 bytes) (5.9%)
-    .strtab: 33.2mb (34841854 bytes) (34.8%)
-    .symtab: 16.4mb (17166112 bytes) (17.1%)
-    .text: 34.2mb (35900712 bytes) (35.8%)
+    .data.rel.ro: 1.02mb (1065224 bytes) (0.8%)
+    .other: 32.4mb (33984171 bytes) (25.3%)
+    .rel.dyn: 2.53mb (2655384 bytes) (2.0%)
+    .rodata: 5.65mb (5927652 bytes) (4.4%)
+    .strtab: 33.2mb (34841854 bytes) (26.0%)
+    .symtab: 16.4mb (17166112 bytes) (12.8%)
+    .text: 34.2mb (35900712 bytes) (26.7%)
 
-Showing 49 symbols (44 unique) with total pss: 43785380 bytes
+Showing 50 symbols (45 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
      [2,4): 6    [16,32): 10        [128,256): 2    [131072,262144): 2     [1048576,2097152): 2
      [4,8): 6    [32,64): 9         [256,512): 1    [262144,524288): 1     [2097152,4194304): 1
-    [8,16): 3   [64,128): 1    [65536,131072): 2   [524288,1048576): 2   [33554432,67108864): 1
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
+    [8,16): 3   [64,128): 1    [65536,131072): 2   [524288,1048576): 2   [33554432,67108864): 2
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
 Number of unique paths: 9
 
-Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
+Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
 Index | Running Total | Section@Address | PSS | Path
 ------------------------------------------------------------
 0)          4 (0.0%)  d@0x2de7000  4              base/page_allocator.cc
@@ -100,90 +101,92 @@
              base::android::g_renderer_histogram_code
 4)        168 (0.0%)  d@0x2de70a4  4              third_party/container.c
              base::android::g_library_version_number
-5)     101768 (0.2%)  d@0x2dffd88  101600         {no path}
+5)     101768 (0.1%)  d@0x2dffd88  101600         {no path}
              ** symbol gap 0 (end of section)
-6)     101824 (0.2%)  R@0x2cd8500  56             third_party/paint.cc
+6)     101824 (0.1%)  R@0x2cd8500  56             third_party/paint.cc
              ChromeMainDelegateAndroid [vtable]
-7)     101848 (0.2%)  R@0x2cd8538  24             base/page_allocator.cc
+7)     101848 (0.1%)  R@0x2cd8538  24             base/page_allocator.cc
              mojo::MessageReceiver [vtable]
-8)     101860 (0.2%)  R@0x2cd8550  12             base/page_allocator.cc
+8)     101860 (0.1%)  R@0x2cd8550  12             base/page_allocator.cc
              kMethodsAnimationFrameTimeHistogram
-9)    1166992 (2.7%)  R@0x2ddc608  1065132        {no path}
+9)    1166992 (1.5%)  R@0x2ddc608  1065132        {no path}
              ** symbol gap 0 (end of section)
-10)   1167048 (2.7%)  R@0x2c176f0  56             third_party/icu/ucnv_ext.c
+10)   1167048 (1.5%)  R@0x2c176f0  56             third_party/icu/ucnv_ext.c
              ChromeMainDelegate [vtable]
-11)   1167072 (2.7%)  R@0x2c17728  24             third_party/icu/ucnv_ext.c
+11)   1167072 (1.5%)  R@0x2c17728  24             third_party/icu/ucnv_ext.c
              chrome::mojom::FieldTrialRecorder [vtable]
-12)   1956976 (4.5%)  R@0x2c17740  789904         third_party/container.c
+12)   1956976 (2.5%)  R@0x2c17740  789904         third_party/container.c
              chrome::mojom::FieldTrialRecorderProxy [vtable]
-13)   1957008 (4.5%)  R@0x2cd84e0  32             third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o
+13)   1957008 (2.5%)  R@0x2cd84e0  32             third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o
              .Lswitch.table.45
-14)   1957016 (4.5%)  R@0x2cd84f0  8              third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o
+14)   1957016 (2.5%)  R@0x2cd84f0  8              third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o
              kSystemClassPrefixes
-15)   1957018 (4.5%)  r@0x266e600  2.5 (size=5)   base/page_allocator.cc
+15)  35941187 (46.2%) o@0x0        33984171       {no path}
+             ELF file overhead
+16)  35941189 (46.2%) r@0x266e600  2.5 (size=5)   base/page_allocator.cc
              string literal (num_aliases=2)
-16)   1957021 (4.5%)  r@0x266e600  2.5 (size=5)   third_party/icu/ucnv_ext.c
+17)  35941192 (46.2%) r@0x266e600  2.5 (size=5)   third_party/icu/ucnv_ext.c
              string literal (num_aliases=2)
-17)   1957037 (4.5%)  r@0x266e605  16             third_party/icu/ucnv_ext.c
+18)  35941208 (46.2%) r@0x266e605  16             third_party/icu/ucnv_ext.c
              string literal
-18)   1957080 (4.5%)  r@0x266e630  43             {no path}
+19)  35941251 (46.2%) r@0x266e630  43             {no path}
              ** merge strings
-19)   3922425 (9.0%)  r@0x284d600  1965345        {no path}
+20)  37906596 (48.7%) r@0x284d600  1965345        {no path}
              ** merge constants
-20)   7208540 (16.5%) r@Group      3286115        {no path}
+21)  41192711 (53.0%) r@Group      3286115        {no path}
              ** symbol gaps (count=2)
-21)   7208548 (16.5%) r@0x284e364  8              base/page_allocator.cc
-22)   7208592 (16.5%) r@0x284e370  44             base/page_allocator.cc
+22)  41192719 (53.0%) r@0x284e364  8              base/page_allocator.cc
+23)  41192763 (53.0%) r@0x284e370  44             base/page_allocator.cc
              Name
-23)   7208624 (16.5%) r@0x284e398  32             third_party/container.c
+24)  41192795 (53.0%) r@0x284e398  32             third_party/container.c
              chrome::mojom::FilePatcher::Name_
-24)   7884664 (18.0%) r@0x28f3450  676040         third_party/paint.cc
+25)  41868835 (53.8%) r@0x28f3450  676040         third_party/paint.cc
              kAnimationFrameTimeHistogramClassPath
-25)   7884668 (18.0%) r@0x28f3480  4              third_party/paint.cc
+26)  41868839 (53.8%) r@0x28f3480  4              third_party/paint.cc
              blink::CSSValueKeywordsHash::findValueImpl::value_word_list
-26)   7884684 (18.0%) t@0x28d900   16             base/page_allocator.cc
+27)  41868855 (53.8%) t@0x28d900   16             base/page_allocator.cc
              _GLOBAL__sub_I_page_allocator.cc
-27)   7884740 (18.0%) t@0x28d910   56             base/page_allocator.cc
+28)  41868911 (53.8%) t@0x28d910   56             base/page_allocator.cc
              _GLOBAL__sub_I_bbr_sender.cc
-28)   7884768 (18.0%) t@0x28d948   28             base/page_allocator.cc
+29)  41868939 (53.8%) t@0x28d948   28             base/page_allocator.cc
              _GLOBAL__sub_I_pacing_sender.cc
-29)   7884806 (18.0%) t@0x28d964   38             base/page_allocator.cc
+30)  41868977 (53.8%) t@0x28d964   38             base/page_allocator.cc
              extFromUUseMapping
-30)   7884838 (18.0%) t@0x28d98a   32             base/page_allocator.cc
+31)  41869009 (53.8%) t@0x28d98a   32             base/page_allocator.cc
              extFromUUseMapping
-31)  43715598 (99.8%) t@Group      35830760       {no path}
+32)  77699769 (99.9%) t@Group      35830760       {no path}
              ** symbol gaps (count=3)
-32)  43716046 (99.8%) t@0x28f000   448            third_party/icu/ucnv_ext.c
+33)  77700217 (99.9%) t@0x28f000   448            third_party/icu/ucnv_ext.c
              ucnv_extMatchFromU
-33)  43716074 (99.8%) t@0x28f1c8   28             third_party/icu/ucnv_ext.c
+34)  77700245 (99.9%) t@0x28f1c8   28             third_party/icu/ucnv_ext.c
              _GLOBAL__sub_I_SkDeviceProfile.cpp
-34)  43785198 (100.0%) t@0x28f1e0   69124          third_party/icu/ucnv_ext.c
+35)  77769369 (100.0%) t@0x28f1e0   69124          third_party/icu/ucnv_ext.c
              foo_bar
-35)  43785222 (100.0%) t@0x2a0000   24 (size=48)   {no path}
+36)  77769393 (100.0%) t@0x2a0000   24 (size=48)   {no path}
              blink::ContiguousContainerBase::shrinkToFit (num_aliases=2)
-36)  43785246 (100.0%) t@0x2a0000   24 (size=48)   third_party/icu/ucnv_ext.c
+37)  77769417 (100.0%) t@0x2a0000   24 (size=48)   third_party/icu/ucnv_ext.c
              BazAlias (num_aliases=2)
-37)  43785249 (100.0%) t@0x2a0010   3 (size=12)    third_party/paint.cc
+38)  77769420 (100.0%) t@0x2a0010   3 (size=12)    third_party/paint.cc
              blink::ContiguousContainerBase::shrinkToFit (num_aliases=4)
-38)  43785252 (100.0%) t@0x2a0010   3 (size=12)    third_party/icu/ucnv_ext.c
+39)  77769423 (100.0%) t@0x2a0010   3 (size=12)    third_party/icu/ucnv_ext.c
              blink::ContiguousContainerBase::shrinkToFit (num_aliases=4)
-39)  43785255 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
+40)  77769426 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
              FooAlias (num_aliases=4)
-40)  43785258 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
+41)  77769429 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
              BarAlias (num_aliases=4)
-41)  43785286 (100.0%) t@0x2a0020   28             third_party/container.c
+42)  77769457 (100.0%) t@0x2a0020   28             third_party/container.c
              blink::ContiguousContainerBase::ContiguousContainerBase
-42)  43785380 (100.0%) t@0x2a1000   94             third_party/container.c
+43)  77769551 (100.0%) t@0x2a1000   94             third_party/container.c
              blink::PaintChunker::releasePaintChunks
-43)  43785380 (100.0%) b@0x0        262144         third_party/fft_float.cc
+44)  77769551 (100.0%) b@0x0        262144         third_party/fft_float.cc
              ff_cos_131072
-44)  43785380 (100.0%) b@0x0        131072         third_party/fft_fixed.cc
+45)  77769551 (100.0%) b@0x0        131072         third_party/fft_fixed.cc
              ff_cos_131072_fixed
-45)  43785380 (100.0%) b@0x0        131072         third_party/fft_float.cc
+46)  77769551 (100.0%) b@0x0        131072         third_party/fft_float.cc
              ff_cos_65536
-46)  43785380 (100.0%) b@0x2dffda0  28             third_party/icu/ucnv_ext.c
+47)  77769551 (100.0%) b@0x2dffda0  28             third_party/icu/ucnv_ext.c
              g_chrome_content_browser_client
-47)  43785380 (100.0%) b@0x2dffe80  200            third_party/icu/ucnv_ext.c
+48)  77769551 (100.0%) b@0x2dffe80  200            third_party/icu/ucnv_ext.c
              SaveHistogram::atomic_histogram_pointer
-48)  43785380 (100.0%) b@0x2dffe84  4              third_party/icu/ucnv_ext.c
+49)  77769551 (100.0%) b@0x2dffe84  4              third_party/icu/ucnv_ext.c
              g_AnimationFrameTimeHistogram_clazz
diff --git a/tools/binary_size/libsupersize/testdata/Csv.golden b/tools/binary_size/libsupersize/testdata/Csv.golden
index 99bbabc..d2f1ded 100644
--- a/tools/binary_size/libsupersize/testdata/Csv.golden
+++ b/tools/binary_size/libsupersize/testdata/Csv.golden
@@ -3,6 +3,7 @@
 .bss,1300456
 .data,101768
 .data.rel.ro,1065224
+.other,33984171
 .rel.dyn,2655384
 .rodata,5927652
 .strtab,34841854
@@ -25,6 +26,7 @@
 ,0x2c17740,789904,0,1,789904.0,R,chrome::mojom::FieldTrialRecorderProxy [vtable]
 ,0x2cd84e0,16,16,1,32.0,R,.Lswitch.table.45
 ,0x2cd84f0,8,0,1,8.0,R,kSystemClassPrefixes
+,0x0,33984171,0,1,33984171.0,o,ELF file overhead
 ,0x266e600,5,0,2,2.5,r,string literal
 ,0x266e600,5,0,2,2.5,r,string literal
 ,0x266e605,16,0,1,16.0,r,string literal
diff --git a/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden b/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
index 8aca96b9..d689d22 100644
--- a/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
+++ b/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
@@ -14,19 +14,20 @@
     .bss: 0 bytes (0 bytes) (not included in totals)
     .data: 0 bytes (0 bytes) (0.0%)
     .data.rel.ro: 0 bytes (0 bytes) (0.0%)
+    .other: 0 bytes (0 bytes) (0.0%)
     .rel.dyn: 0 bytes (0 bytes) (0.0%)
     .rodata: 0 bytes (0 bytes) (0.0%)
     .text: 0 bytes (0 bytes) (0.0%)
 
-0 symbols added (+), 0 changed (~), 0 removed (-), 49 unchanged (not shown)
+0 symbols added (+), 0 changed (~), 0 removed (-), 50 unchanged (not shown)
 Of changed symbols, 0 grew, 0 shrank
-Number of unique symbols 47 -> 47 (+0)
+Number of unique symbols 48 -> 48 (+0)
 0 paths added, 0 removed, 0 changed
 
 Showing 0 symbols (aliases not grouped for diffs) with total pss: 0 bytes
-.text=0 bytes    .rodata=0 bytes    .data.rel.ro=0 bytes    .data=0 bytes    .bss=0 bytes    total=0 bytes
+.text=0 bytes    .rodata=0 bytes    .data.rel.ro=0 bytes    .data=0 bytes    .bss=0 bytes    .other=0 bytes    total=0 bytes
 Number of unique paths: 0
 
-Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
+Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
 Index | Running Total | Section@Address | Δ PSS (Δ size_without_padding) | Path
 ------------------------------------------------------------
diff --git a/tools/binary_size/libsupersize/testdata/FullDescription.golden b/tools/binary_size/libsupersize/testdata/FullDescription.golden
index 2a4aa5ec..83ccda7 100644
--- a/tools/binary_size/libsupersize/testdata/FullDescription.golden
+++ b/tools/binary_size/libsupersize/testdata/FullDescription.golden
@@ -8,16 +8,17 @@
     map_file_name=../test.map
     tool_prefix=tools/binary_size/libsupersize/testdata/mock_toolchain/
 
-Section Sizes (Total=95.6mb (100233874 bytes)):
-    .ARM.exidx: 1.47mb (1536456 bytes) (1.5%)
+Section Sizes (Total=128.0mb (134218045 bytes)):
+    .ARM.exidx: 1.47mb (1536456 bytes) (1.1%)
     .bss: 1.24mb (1300456 bytes) (not included in totals)
     .data: 99.4kb (101768 bytes) (0.1%)
-    .data.rel.ro: 1.02mb (1065224 bytes) (1.1%)
-    .rel.dyn: 2.53mb (2655384 bytes) (2.6%)
-    .rodata: 5.65mb (5927652 bytes) (5.9%)
-    .strtab: 33.2mb (34841854 bytes) (34.8%)
-    .symtab: 16.4mb (17166112 bytes) (17.1%)
-    .text: 34.2mb (35900712 bytes) (35.8%)
+    .data.rel.ro: 1.02mb (1065224 bytes) (0.8%)
+    .other: 32.4mb (33984171 bytes) (25.3%)
+    .rel.dyn: 2.53mb (2655384 bytes) (2.0%)
+    .rodata: 5.65mb (5927652 bytes) (4.4%)
+    .strtab: 33.2mb (34841854 bytes) (26.0%)
+    .symtab: 16.4mb (17166112 bytes) (12.8%)
+    .text: 34.2mb (35900712 bytes) (26.7%)
 
 Other section sizes:
     .ARM.attributes: 60 bytes (60 bytes)
@@ -65,16 +66,20 @@
 * Padding accounts for 196 bytes (0.0%)
 * Contains 0 aliases
 * 0 symbols have shared ownership
+Section .other: has 100.0% of 33984171 bytes accounted for from 1 symbols. 0 bytes are unaccounted for.
+* Padding accounts for 0 bytes (0.0%)
+* Contains 0 aliases
+* 0 symbols have shared ownership
 
-Showing 52 symbols (47 unique) with total pss: 43785380 bytes
+Showing 53 symbols (48 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
      [2,4): 7    [16,32): 10     [128,256): 2       [4096,8192): 1     [262144,524288): 1     [2097152,4194304): 1
-     [4,8): 6    [32,64): 9      [256,512): 1    [65536,131072): 2    [524288,1048576): 2   [33554432,67108864): 1
+     [4,8): 6    [32,64): 9      [256,512): 1    [65536,131072): 2    [524288,1048576): 2   [33554432,67108864): 2
     [8,16): 3   [64,128): 1    [2048,4096): 1   [131072,262144): 2   [1048576,2097152): 2
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
 Number of unique paths: 9
 
-Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
+Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
 Index | Running Total | Section@Address | ...
 ------------------------------------------------------------
 0)          4 (0.0%)  d@0x2de7000  pss=4  padding=0  num_aliases=1
@@ -92,168 +97,171 @@
 4)        168 (0.0%)  d@0x2de70a4  pss=4  padding=0  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={anon,rel.loc}  name=base::android::g_library_version_number
-5)     101768 (0.2%)  d@0x2dffd88  pss=101600  padding=101600  num_aliases=1
+5)     101768 (0.1%)  d@0x2dffd88  pss=101600  padding=101600  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 0 (end of section)
-6)     101824 (0.2%)  R@0x2cd8500  pss=56  padding=0  num_aliases=1
+6)     101824 (0.1%)  R@0x2cd8500  pss=56  padding=0  num_aliases=1
              source_path=third_party/paint.cc 	object_path=third_party/WebKit.a/PaintChunker.o
              flags={}  name=ChromeMainDelegateAndroid [vtable]
-7)     101848 (0.2%)  R@0x2cd8538  pss=24  padding=0  num_aliases=1
+7)     101848 (0.1%)  R@0x2cd8538  pss=24  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=mojo::MessageReceiver [vtable]
-8)     101860 (0.2%)  R@0x2cd8550  pss=12  padding=0  num_aliases=1
+8)     101860 (0.1%)  R@0x2cd8550  pss=12  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=kMethodsAnimationFrameTimeHistogram
-9)    1166992 (2.7%)  R@0x2ddc608  pss=1065132  padding=1065132  num_aliases=1
+9)    1166992 (1.5%)  R@0x2ddc608  pss=1065132  padding=1065132  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 0 (end of section)
-10)   1167048 (2.7%)  R@0x2c176f0  pss=56  padding=0  num_aliases=1
+10)   1167048 (1.5%)  R@0x2c176f0  pss=56  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=ChromeMainDelegate [vtable]
-11)   1167072 (2.7%)  R@0x2c17728  pss=24  padding=0  num_aliases=1
+11)   1167072 (1.5%)  R@0x2c17728  pss=24  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=chrome::mojom::FieldTrialRecorder [vtable]
-12)   1956976 (4.5%)  R@0x2c17740  pss=789904  padding=0  num_aliases=1
+12)   1956976 (2.5%)  R@0x2c17740  pss=789904  padding=0  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={}  name=chrome::mojom::FieldTrialRecorderProxy [vtable]
-13)   1957008 (4.5%)  R@0x2cd84e0  pss=32  padding=16  num_aliases=1
+13)   1957008 (2.5%)  R@0x2cd84e0  pss=32  padding=16  num_aliases=1
              source_path= 	object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o
              flags={}  name=.Lswitch.table.45
-14)   1957016 (4.5%)  R@0x2cd84f0  pss=8  padding=0  num_aliases=1
+14)   1957016 (2.5%)  R@0x2cd84f0  pss=8  padding=0  num_aliases=1
              source_path= 	object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o
              flags={anon}  name=kSystemClassPrefixes
-15)   1957018 (4.5%)  r@0x266e600  pss=2.5 (size=5)  padding=0  num_aliases=2
+15)  35941187 (46.2%) o@0x0        pss=33984171  padding=0  num_aliases=1
+             source_path= 	object_path=
+             flags={}  name=ELF file overhead
+16)  35941189 (46.2%) r@0x266e600  pss=2.5 (size=5)  padding=0  num_aliases=2
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=string literal
-16)   1957021 (4.5%)  r@0x266e600  pss=2.5 (size=5)  padding=0  num_aliases=2
+17)  35941192 (46.2%) r@0x266e600  pss=2.5 (size=5)  padding=0  num_aliases=2
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=string literal
-17)   1957037 (4.5%)  r@0x266e605  pss=16  padding=0  num_aliases=1
+18)  35941208 (46.2%) r@0x266e605  pss=16  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=string literal
-18)   1957080 (4.5%)  r@0x266e630  pss=43  padding=27  num_aliases=1
+19)  35941251 (46.2%) r@0x266e630  pss=43  padding=27  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** merge strings
-19)   3922425 (9.0%)  r@0x284d600  pss=1965345  padding=1961920  num_aliases=1
+20)  37906596 (48.7%) r@0x284d600  pss=1965345  padding=1961920  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** merge constants
-20)   3922428 (9.0%)  r@0x284e364  pss=3  padding=3  num_aliases=1
+21)  37906599 (48.7%) r@0x284e364  pss=3  padding=3  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 0
-21)   3922436 (9.0%)  r@0x284e364  pss=8  padding=0  num_aliases=1
+22)  37906607 (48.7%) r@0x284e364  pss=8  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
-22)   3922480 (9.0%)  r@0x284e370  pss=44  padding=4  num_aliases=1
+23)  37906651 (48.7%) r@0x284e370  pss=44  padding=4  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=Name
-23)   3922512 (9.0%)  r@0x284e398  pss=32  padding=0  num_aliases=1
+24)  37906683 (48.7%) r@0x284e398  pss=32  padding=0  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={}  name=chrome::mojom::FilePatcher::Name_
-24)   4598552 (10.5%) r@0x28f3450  pss=676040  padding=675992  num_aliases=1
+25)  38582723 (49.6%) r@0x28f3450  pss=676040  padding=675992  num_aliases=1
              source_path=third_party/paint.cc 	object_path=third_party/WebKit.a/PaintChunker.o
              flags={anon}  name=kAnimationFrameTimeHistogramClassPath
-25)   4598556 (10.5%) r@0x28f3480  pss=4  padding=0  num_aliases=1
+26)  38582727 (49.6%) r@0x28f3480  pss=4  padding=0  num_aliases=1
              source_path=third_party/paint.cc 	object_path=third_party/WebKit.a/PaintChunker.o
              flags={anon}  name=blink::CSSValueKeywordsHash::findValueImpl::value_word_list
                   full_name=blink::CSSValueKeywordsHash::findValueImpl(char const*, unsigned int)::value_word_list
-26)   7884668 (18.0%) r@0x2c158e4  pss=3286112  padding=3286112  num_aliases=1
+27)  41868839 (53.8%) r@0x2c158e4  pss=3286112  padding=3286112  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 1 (end of section)
-27)   7884684 (18.0%) t@0x28d900   pss=16  padding=0  num_aliases=1
+28)  41868855 (53.8%) t@0x28d900   pss=16  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={startup}  name=_GLOBAL__sub_I_page_allocator.cc
-28)   7884740 (18.0%) t@0x28d910   pss=56  padding=0  num_aliases=1
+29)  41868911 (53.8%) t@0x28d910   pss=56  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={startup}  name=_GLOBAL__sub_I_bbr_sender.cc
-29)   7884768 (18.0%) t@0x28d948   pss=28  padding=0  num_aliases=1
+30)  41868939 (53.8%) t@0x28d948   pss=28  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={startup}  name=_GLOBAL__sub_I_pacing_sender.cc
-30)   7884806 (18.0%) t@0x28d964   pss=38  padding=0  num_aliases=1
+31)  41868977 (53.8%) t@0x28d964   pss=38  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=extFromUUseMapping
                   full_name=extFromUUseMapping(signed char, unsigned int, int)
-31)   7884838 (18.0%) t@0x28d98a   pss=32  padding=0  num_aliases=1
+32)  41869009 (53.8%) t@0x28d98a   pss=32  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=extFromUUseMapping
                   full_name=extFromUUseMapping(aj, int)
-32)   7890556 (18.0%) t@0x28f000   pss=5718  padding=5718  num_aliases=1
+33)  41874727 (53.8%) t@0x28f000   pss=5718  padding=5718  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 0
-33)   7891004 (18.0%) t@0x28f000   pss=448  padding=0  num_aliases=1
+34)  41875175 (53.8%) t@0x28f000   pss=448  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=ucnv_extMatchFromU
                   full_name=ucnv_extMatchFromU(int const*, int, unsigned short const*, int, unsigned short const*, int, unsigned int*, signed char, signed char)
-34)   7891032 (18.0%) t@0x28f1c8   pss=28  padding=8  num_aliases=1
+35)  41875203 (53.8%) t@0x28f1c8   pss=28  padding=8  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={startup,gen}  name=_GLOBAL__sub_I_SkDeviceProfile.cpp
-35)   7960156 (18.2%) t@0x28f1e0   pss=69124  padding=4  num_aliases=1
+36)  41944327 (53.9%) t@0x28f1e0   pss=69124  padding=4  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={unlikely,gen}  name=foo_bar
-36)   7960180 (18.2%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
+37)  41944351 (53.9%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
              source_path= 	object_path=
              flags={}  name=blink::ContiguousContainerBase::shrinkToFit
                   full_name=blink::ContiguousContainerBase::shrinkToFit()
-37)   7960204 (18.2%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
+38)  41944375 (53.9%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=BazAlias
                   full_name=BazAlias(bool)
-38)   7960207 (18.2%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+39)  41944378 (53.9%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/paint.cc 	object_path=third_party/WebKit.a/PaintChunker.o
              flags={clone}  name=blink::ContiguousContainerBase::shrinkToFit
                   full_name=blink::ContiguousContainerBase::shrinkToFit()
-39)   7960210 (18.2%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+40)  41944381 (53.9%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen,clone}  name=blink::ContiguousContainerBase::shrinkToFit
                   full_name=blink::ContiguousContainerBase::shrinkToFit()
-40)   7960213 (18.2%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+41)  41944384 (53.9%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=FooAlias
                   full_name=FooAlias()
-41)   7960216 (18.2%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+42)  41944387 (53.9%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=BarAlias
                   full_name=BarAlias()
-42)   7960244 (18.2%) t@0x2a0020   pss=28  padding=4  num_aliases=1
+43)  41944415 (53.9%) t@0x2a0020   pss=28  padding=4  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={}  name=blink::ContiguousContainerBase::ContiguousContainerBase
                   full_name=blink::ContiguousContainerBase::ContiguousContainerBase(blink::ContiguousContainerBase&&)
-43)   7964284 (18.2%) t@0x2a1000   pss=4040  padding=4040  num_aliases=1
+44)  41948455 (53.9%) t@0x2a1000   pss=4040  padding=4040  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 1
-44)   7964378 (18.2%) t@0x2a1000   pss=94  padding=0  num_aliases=1
+45)  41948549 (53.9%) t@0x2a1000   pss=94  padding=0  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={anon,clone}  name=blink::PaintChunker::releasePaintChunks
                   full_name=blink::PaintChunker::releasePaintChunks()
-45)  43785380 (100.0%) t@0x24ca628  pss=35821002  padding=35821002  num_aliases=1
+46)  77769551 (100.0%) t@0x24ca628  pss=35821002  padding=35821002  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 2 (end of section)
-46)  43785380 (100.0%) b@0x0        pss=262144  padding=0  num_aliases=1
+47)  77769551 (100.0%) b@0x0        pss=262144  padding=0  num_aliases=1
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=ff_cos_131072
-47)  43785380 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
+48)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
              source_path=third_party/fft_fixed.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_fixed.o
              flags={}  name=ff_cos_131072_fixed
-48)  43785380 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
+49)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=ff_cos_65536
-49)  43785380 (100.0%) b@0x2dffda0  pss=28  padding=0  num_aliases=1
+50)  77769551 (100.0%) b@0x2dffda0  pss=28  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=g_chrome_content_browser_client
-50)  43785380 (100.0%) b@0x2dffe80  pss=200  padding=196  num_aliases=1
+51)  77769551 (100.0%) b@0x2dffe80  pss=200  padding=196  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=SaveHistogram::atomic_histogram_pointer
                   full_name=SaveHistogram(_JNIEnv*, base::android::JavaParamRef<_jobject*> const&, base::android::JavaParamRef<_jstring*> const&, base::android::JavaParamRef<_jlongArray*> const&, int)::atomic_histogram_pointer
-51)  43785380 (100.0%) b@0x2dffe84  pss=4  padding=0  num_aliases=1
+52)  77769551 (100.0%) b@0x2dffe84  pss=4  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={anon,gen}  name=g_AnimationFrameTimeHistogram_clazz
-Showing 49 symbols (44 unique) with total pss: 43785380 bytes
+Showing 50 symbols (45 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
      [2,4): 6    [16,32): 10        [128,256): 2    [131072,262144): 2     [1048576,2097152): 2
      [4,8): 6    [32,64): 9         [256,512): 1    [262144,524288): 1     [2097152,4194304): 1
-    [8,16): 3   [64,128): 1    [65536,131072): 2   [524288,1048576): 2   [33554432,67108864): 1
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
+    [8,16): 3   [64,128): 1    [65536,131072): 2   [524288,1048576): 2   [33554432,67108864): 2
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
 Number of unique paths: 9
 
-Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
+Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
 Index | Running Total | Section@Address | ...
 ------------------------------------------------------------
 0)          4 (0.0%)  d@0x2de7000  pss=4  padding=0  num_aliases=1
@@ -271,52 +279,55 @@
 4)        168 (0.0%)  d@0x2de70a4  pss=4  padding=0  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={anon,rel.loc}  name=base::android::g_library_version_number
-5)     101768 (0.2%)  d@0x2dffd88  pss=101600  padding=101600  num_aliases=1
+5)     101768 (0.1%)  d@0x2dffd88  pss=101600  padding=101600  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 0 (end of section)
-6)     101824 (0.2%)  R@0x2cd8500  pss=56  padding=0  num_aliases=1
+6)     101824 (0.1%)  R@0x2cd8500  pss=56  padding=0  num_aliases=1
              source_path=third_party/paint.cc 	object_path=third_party/WebKit.a/PaintChunker.o
              flags={}  name=ChromeMainDelegateAndroid [vtable]
-7)     101848 (0.2%)  R@0x2cd8538  pss=24  padding=0  num_aliases=1
+7)     101848 (0.1%)  R@0x2cd8538  pss=24  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=mojo::MessageReceiver [vtable]
-8)     101860 (0.2%)  R@0x2cd8550  pss=12  padding=0  num_aliases=1
+8)     101860 (0.1%)  R@0x2cd8550  pss=12  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=kMethodsAnimationFrameTimeHistogram
-9)    1166992 (2.7%)  R@0x2ddc608  pss=1065132  padding=1065132  num_aliases=1
+9)    1166992 (1.5%)  R@0x2ddc608  pss=1065132  padding=1065132  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** symbol gap 0 (end of section)
-10)   1167048 (2.7%)  R@0x2c176f0  pss=56  padding=0  num_aliases=1
+10)   1167048 (1.5%)  R@0x2c176f0  pss=56  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=ChromeMainDelegate [vtable]
-11)   1167072 (2.7%)  R@0x2c17728  pss=24  padding=0  num_aliases=1
+11)   1167072 (1.5%)  R@0x2c17728  pss=24  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=chrome::mojom::FieldTrialRecorder [vtable]
-12)   1956976 (4.5%)  R@0x2c17740  pss=789904  padding=0  num_aliases=1
+12)   1956976 (2.5%)  R@0x2c17740  pss=789904  padding=0  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={}  name=chrome::mojom::FieldTrialRecorderProxy [vtable]
-13)   1957008 (4.5%)  R@0x2cd84e0  pss=32  padding=16  num_aliases=1
+13)   1957008 (2.5%)  R@0x2cd84e0  pss=32  padding=16  num_aliases=1
              source_path= 	object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o
              flags={}  name=.Lswitch.table.45
-14)   1957016 (4.5%)  R@0x2cd84f0  pss=8  padding=0  num_aliases=1
+14)   1957016 (2.5%)  R@0x2cd84f0  pss=8  padding=0  num_aliases=1
              source_path= 	object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o
              flags={anon}  name=kSystemClassPrefixes
-15)   1957018 (4.5%)  r@0x266e600  pss=2.5 (size=5)  padding=0  num_aliases=2
+15)  35941187 (46.2%) o@0x0        pss=33984171  padding=0  num_aliases=1
+             source_path= 	object_path=
+             flags={}  name=ELF file overhead
+16)  35941189 (46.2%) r@0x266e600  pss=2.5 (size=5)  padding=0  num_aliases=2
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=string literal
-16)   1957021 (4.5%)  r@0x266e600  pss=2.5 (size=5)  padding=0  num_aliases=2
+17)  35941192 (46.2%) r@0x266e600  pss=2.5 (size=5)  padding=0  num_aliases=2
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=string literal
-17)   1957037 (4.5%)  r@0x266e605  pss=16  padding=0  num_aliases=1
+18)  35941208 (46.2%) r@0x266e605  pss=16  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=string literal
-18)   1957080 (4.5%)  r@0x266e630  pss=43  padding=27  num_aliases=1
+19)  35941251 (46.2%) r@0x266e630  pss=43  padding=27  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** merge strings
-19)   3922425 (9.0%)  r@0x284d600  pss=1965345  padding=1961920  num_aliases=1
+20)  37906596 (48.7%) r@0x284d600  pss=1965345  padding=1961920  num_aliases=1
              source_path= 	object_path=
              flags={}  name=** merge constants
-20)   7208540 (16.5%) r@Group      pss=3286115  padding=3286115  count=2
+21)  41192711 (53.0%) r@Group      pss=3286115  padding=3286115  count=2
              source_path= 	object_path=
              flags={}  name=** symbol gaps
 > 0)          3 (0.0%)  r@0x284e364  pss=3  padding=3  num_aliases=1
@@ -325,39 +336,39 @@
 > 1)    3286115 (100.0%) r@0x2c158e4  pss=3286112  padding=3286112  num_aliases=1
                source_path= 	object_path=
                flags={}  name=** symbol gap 1 (end of section)
-21)   7208548 (16.5%) r@0x284e364  pss=8  padding=0  num_aliases=1
+22)  41192719 (53.0%) r@0x284e364  pss=8  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
-22)   7208592 (16.5%) r@0x284e370  pss=44  padding=4  num_aliases=1
+23)  41192763 (53.0%) r@0x284e370  pss=44  padding=4  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=Name
-23)   7208624 (16.5%) r@0x284e398  pss=32  padding=0  num_aliases=1
+24)  41192795 (53.0%) r@0x284e398  pss=32  padding=0  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={}  name=chrome::mojom::FilePatcher::Name_
-24)   7884664 (18.0%) r@0x28f3450  pss=676040  padding=675992  num_aliases=1
+25)  41868835 (53.8%) r@0x28f3450  pss=676040  padding=675992  num_aliases=1
              source_path=third_party/paint.cc 	object_path=third_party/WebKit.a/PaintChunker.o
              flags={anon}  name=kAnimationFrameTimeHistogramClassPath
-25)   7884668 (18.0%) r@0x28f3480  pss=4  padding=0  num_aliases=1
+26)  41868839 (53.8%) r@0x28f3480  pss=4  padding=0  num_aliases=1
              source_path=third_party/paint.cc 	object_path=third_party/WebKit.a/PaintChunker.o
              flags={anon}  name=blink::CSSValueKeywordsHash::findValueImpl::value_word_list
                   full_name=blink::CSSValueKeywordsHash::findValueImpl(char const*, unsigned int)::value_word_list
-26)   7884684 (18.0%) t@0x28d900   pss=16  padding=0  num_aliases=1
+27)  41868855 (53.8%) t@0x28d900   pss=16  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={startup}  name=_GLOBAL__sub_I_page_allocator.cc
-27)   7884740 (18.0%) t@0x28d910   pss=56  padding=0  num_aliases=1
+28)  41868911 (53.8%) t@0x28d910   pss=56  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={startup}  name=_GLOBAL__sub_I_bbr_sender.cc
-28)   7884768 (18.0%) t@0x28d948   pss=28  padding=0  num_aliases=1
+29)  41868939 (53.8%) t@0x28d948   pss=28  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={startup}  name=_GLOBAL__sub_I_pacing_sender.cc
-29)   7884806 (18.0%) t@0x28d964   pss=38  padding=0  num_aliases=1
+30)  41868977 (53.8%) t@0x28d964   pss=38  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=extFromUUseMapping
                   full_name=extFromUUseMapping(signed char, unsigned int, int)
-30)   7884838 (18.0%) t@0x28d98a   pss=32  padding=0  num_aliases=1
+31)  41869009 (53.8%) t@0x28d98a   pss=32  padding=0  num_aliases=1
              source_path=base/page_allocator.cc 	object_path=base/base/page_allocator.o
              flags={}  name=extFromUUseMapping
                   full_name=extFromUUseMapping(aj, int)
-31)  43715598 (99.8%) t@Group      pss=35830760  padding=35830760  count=3
+32)  77699769 (99.9%) t@Group      pss=35830760  padding=35830760  count=3
              source_path= 	object_path=
              flags={}  name=** symbol gaps
 > 0)       5718 (0.0%)  t@0x28f000   pss=5718  padding=5718  num_aliases=1
@@ -369,64 +380,64 @@
 > 2)   35830760 (100.0%) t@0x24ca628  pss=35821002  padding=35821002  num_aliases=1
                source_path= 	object_path=
                flags={}  name=** symbol gap 2 (end of section)
-32)  43716046 (99.8%) t@0x28f000   pss=448  padding=0  num_aliases=1
+33)  77700217 (99.9%) t@0x28f000   pss=448  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=ucnv_extMatchFromU
                   full_name=ucnv_extMatchFromU(int const*, int, unsigned short const*, int, unsigned short const*, int, unsigned int*, signed char, signed char)
-33)  43716074 (99.8%) t@0x28f1c8   pss=28  padding=8  num_aliases=1
+34)  77700245 (99.9%) t@0x28f1c8   pss=28  padding=8  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={startup,gen}  name=_GLOBAL__sub_I_SkDeviceProfile.cpp
-34)  43785198 (100.0%) t@0x28f1e0   pss=69124  padding=4  num_aliases=1
+35)  77769369 (100.0%) t@0x28f1e0   pss=69124  padding=4  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={unlikely,gen}  name=foo_bar
-35)  43785222 (100.0%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
+36)  77769393 (100.0%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
              source_path= 	object_path=
              flags={}  name=blink::ContiguousContainerBase::shrinkToFit
                   full_name=blink::ContiguousContainerBase::shrinkToFit()
-36)  43785246 (100.0%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
+37)  77769417 (100.0%) t@0x2a0000   pss=24 (size=48)  padding=32  num_aliases=2
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=BazAlias
                   full_name=BazAlias(bool)
-37)  43785249 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+38)  77769420 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/paint.cc 	object_path=third_party/WebKit.a/PaintChunker.o
              flags={clone}  name=blink::ContiguousContainerBase::shrinkToFit
                   full_name=blink::ContiguousContainerBase::shrinkToFit()
-38)  43785252 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+39)  77769423 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen,clone}  name=blink::ContiguousContainerBase::shrinkToFit
                   full_name=blink::ContiguousContainerBase::shrinkToFit()
-39)  43785255 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+40)  77769426 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=FooAlias
                   full_name=FooAlias()
-40)  43785258 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
+41)  77769429 (100.0%) t@0x2a0010   pss=3 (size=12)  padding=0  num_aliases=4
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=BarAlias
                   full_name=BarAlias()
-41)  43785286 (100.0%) t@0x2a0020   pss=28  padding=4  num_aliases=1
+42)  77769457 (100.0%) t@0x2a0020   pss=28  padding=4  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={}  name=blink::ContiguousContainerBase::ContiguousContainerBase
                   full_name=blink::ContiguousContainerBase::ContiguousContainerBase(blink::ContiguousContainerBase&&)
-42)  43785380 (100.0%) t@0x2a1000   pss=94  padding=0  num_aliases=1
+43)  77769551 (100.0%) t@0x2a1000   pss=94  padding=0  num_aliases=1
              source_path=third_party/container.c 	object_path=third_party/WebKit.a/ContiguousContainer.o
              flags={anon,clone}  name=blink::PaintChunker::releasePaintChunks
                   full_name=blink::PaintChunker::releasePaintChunks()
-43)  43785380 (100.0%) b@0x0        pss=262144  padding=0  num_aliases=1
+44)  77769551 (100.0%) b@0x0        pss=262144  padding=0  num_aliases=1
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=ff_cos_131072
-44)  43785380 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
+45)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
              source_path=third_party/fft_fixed.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_fixed.o
              flags={}  name=ff_cos_131072_fixed
-45)  43785380 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
+46)  77769551 (100.0%) b@0x0        pss=131072  padding=0  num_aliases=1
              source_path=third_party/fft_float.cc 	object_path=third_party/ffmpeg/libffmpeg_internal.a/fft_float.o
              flags={}  name=ff_cos_65536
-46)  43785380 (100.0%) b@0x2dffda0  pss=28  padding=0  num_aliases=1
+47)  77769551 (100.0%) b@0x2dffda0  pss=28  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=g_chrome_content_browser_client
-47)  43785380 (100.0%) b@0x2dffe80  pss=200  padding=196  num_aliases=1
+48)  77769551 (100.0%) b@0x2dffe80  pss=200  padding=196  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={gen}  name=SaveHistogram::atomic_histogram_pointer
                   full_name=SaveHistogram(_JNIEnv*, base::android::JavaParamRef<_jobject*> const&, base::android::JavaParamRef<_jstring*> const&, base::android::JavaParamRef<_jlongArray*> const&, int)::atomic_histogram_pointer
-48)  43785380 (100.0%) b@0x2dffe84  pss=4  padding=0  num_aliases=1
+49)  77769551 (100.0%) b@0x2dffe84  pss=4  padding=0  num_aliases=1
              source_path=third_party/icu/ucnv_ext.c 	object_path=third_party/icu/icuuc/ucnv_ext.o
              flags={anon,gen}  name=g_AnimationFrameTimeHistogram_clazz
diff --git a/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden b/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
index b46f92b..c9abbf0 100644
--- a/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
+++ b/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
@@ -1,13 +1,13 @@
 GroupedByName()
-Showing 42 symbols (42 unique) with total pss: 43785380 bytes
+Showing 43 symbols (43 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
-      {0}: 6    [8,16): 3    [64,128): 2      [65536,131072): 1   [33554432,67108864): 1
+      {0}: 6    [8,16): 3    [64,128): 2      [65536,131072): 1   [33554432,67108864): 2
     [2,4): 2   [16,32): 9   [128,256): 1    [524288,1048576): 2
     [4,8): 5   [32,64): 7   [256,512): 1   [1048576,2097152): 2
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
 Number of unique paths: 9
 
-Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
+Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
 Index | Running Total | Section@Address | PSS | Path
 ------------------------------------------------------------
 0)          4 (0.0%)  *@Group      4               google::protobuf::internal::pLinuxKernelCmpxchg (count=1)
@@ -15,213 +15,218 @@
 2)        160 (0.0%)  *@Group      152             base::android::kBaseRegisteredMethods (count=1)
 3)        164 (0.0%)  *@Group      4               base::android::g_renderer_histogram_code (count=1)
 4)        168 (0.0%)  *@Group      4               base::android::g_library_version_number (count=1)
-5)    1166900 (2.7%)  *@Group      1166732         ** symbol gap 0 (end of section) (count=2)
-6)    1166956 (2.7%)  *@Group      56              ChromeMainDelegateAndroid [vtable] (count=1)
-7)    1166980 (2.7%)  *@Group      24              mojo::MessageReceiver [vtable] (count=1)
-8)    1166992 (2.7%)  *@Group      12              kMethodsAnimationFrameTimeHistogram (count=1)
-9)    1167048 (2.7%)  *@Group      56              ChromeMainDelegate [vtable] (count=1)
-10)   1167072 (2.7%)  *@Group      24              chrome::mojom::FieldTrialRecorder [vtable] (count=1)
-11)   1956976 (4.5%)  *@Group      789904          chrome::mojom::FieldTrialRecorderProxy [vtable] (count=1)
-12)   1957008 (4.5%)  *@Group      32              .Lswitch.table.45 (count=1)
-13)   1957016 (4.5%)  *@Group      8               kSystemClassPrefixes (count=1)
-14)   1957037 (4.5%)  *@Group      21              string literal (count=3)
-15)   1957080 (4.5%)  *@Group      43              ** merge strings (count=1)
-16)   3922425 (9.0%)  *@Group      1965345         ** merge constants (count=1)
-17)  43039300 (98.3%) *@Group      39116875        ** symbol gaps (count=2)
-18)  43039308 (98.3%) *@Group      8                (count=1)
-19)  43039352 (98.3%) *@Group      44              Name (count=1)
-20)  43039384 (98.3%) *@Group      32              chrome::mojom::FilePatcher::Name_ (count=1)
-21)  43715424 (99.8%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
-22)  43715428 (99.8%) *@Group      4               blink::CSSValueKeywordsHash::findValueImpl::value_word_list (count=1)
-23)  43715444 (99.8%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
-24)  43715500 (99.8%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
-25)  43715528 (99.8%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
-26)  43715598 (99.8%) *@Group      70              extFromUUseMapping (count=2)
-27)  43716046 (99.8%) *@Group      448             ucnv_extMatchFromU (count=1)
-28)  43716074 (99.8%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
-29)  43785198 (100.0%) *@Group      69124           foo_bar (count=1)
-30)  43785228 (100.0%) *@Group      30              blink::ContiguousContainerBase::shrinkToFit (count=3)
-31)  43785252 (100.0%) *@Group      24              BazAlias (count=1)
-32)  43785255 (100.0%) *@Group      3               FooAlias (count=1)
-33)  43785258 (100.0%) *@Group      3               BarAlias (count=1)
-34)  43785286 (100.0%) *@Group      28              blink::ContiguousContainerBase::ContiguousContainerBase (count=1)
-35)  43785380 (100.0%) *@Group      94              blink::PaintChunker::releasePaintChunks (count=1)
-36)  43785380 (100.0%) *@Group      0               ff_cos_131072 (count=1)
-37)  43785380 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
-38)  43785380 (100.0%) *@Group      0               ff_cos_65536 (count=1)
-39)  43785380 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
-40)  43785380 (100.0%) *@Group      0               SaveHistogram::atomic_histogram_pointer (count=1)
-41)  43785380 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
+5)    1166900 (1.5%)  *@Group      1166732         ** symbol gap 0 (end of section) (count=2)
+6)    1166956 (1.5%)  *@Group      56              ChromeMainDelegateAndroid [vtable] (count=1)
+7)    1166980 (1.5%)  *@Group      24              mojo::MessageReceiver [vtable] (count=1)
+8)    1166992 (1.5%)  *@Group      12              kMethodsAnimationFrameTimeHistogram (count=1)
+9)    1167048 (1.5%)  *@Group      56              ChromeMainDelegate [vtable] (count=1)
+10)   1167072 (1.5%)  *@Group      24              chrome::mojom::FieldTrialRecorder [vtable] (count=1)
+11)   1956976 (2.5%)  *@Group      789904          chrome::mojom::FieldTrialRecorderProxy [vtable] (count=1)
+12)   1957008 (2.5%)  *@Group      32              .Lswitch.table.45 (count=1)
+13)   1957016 (2.5%)  *@Group      8               kSystemClassPrefixes (count=1)
+14)  35941187 (46.2%) *@Group      33984171        ELF file overhead (count=1)
+15)  35941208 (46.2%) *@Group      21              string literal (count=3)
+16)  35941251 (46.2%) *@Group      43              ** merge strings (count=1)
+17)  37906596 (48.7%) *@Group      1965345         ** merge constants (count=1)
+18)  77023471 (99.0%) *@Group      39116875        ** symbol gaps (count=2)
+19)  77023479 (99.0%) *@Group      8                (count=1)
+20)  77023523 (99.0%) *@Group      44              Name (count=1)
+21)  77023555 (99.0%) *@Group      32              chrome::mojom::FilePatcher::Name_ (count=1)
+22)  77699595 (99.9%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
+23)  77699599 (99.9%) *@Group      4               blink::CSSValueKeywordsHash::findValueImpl::value_word_list (count=1)
+24)  77699615 (99.9%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
+25)  77699671 (99.9%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
+26)  77699699 (99.9%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
+27)  77699769 (99.9%) *@Group      70              extFromUUseMapping (count=2)
+28)  77700217 (99.9%) *@Group      448             ucnv_extMatchFromU (count=1)
+29)  77700245 (99.9%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
+30)  77769369 (100.0%) *@Group      69124           foo_bar (count=1)
+31)  77769399 (100.0%) *@Group      30              blink::ContiguousContainerBase::shrinkToFit (count=3)
+32)  77769423 (100.0%) *@Group      24              BazAlias (count=1)
+33)  77769426 (100.0%) *@Group      3               FooAlias (count=1)
+34)  77769429 (100.0%) *@Group      3               BarAlias (count=1)
+35)  77769457 (100.0%) *@Group      28              blink::ContiguousContainerBase::ContiguousContainerBase (count=1)
+36)  77769551 (100.0%) *@Group      94              blink::PaintChunker::releasePaintChunks (count=1)
+37)  77769551 (100.0%) *@Group      0               ff_cos_131072 (count=1)
+38)  77769551 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
+39)  77769551 (100.0%) *@Group      0               ff_cos_65536 (count=1)
+40)  77769551 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
+41)  77769551 (100.0%) *@Group      0               SaveHistogram::atomic_histogram_pointer (count=1)
+42)  77769551 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
 GroupedByName(depth=1)
-Showing 34 symbols (34 unique) with total pss: 43785380 bytes
+Showing 35 symbols (35 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
       {0}: 6    [8,16): 4    [32,64): 6   [128,256): 2     [65536,131072): 1     [1048576,2097152): 2
-    [2,4): 2   [16,32): 6   [64,128): 1   [256,512): 1   [524288,1048576): 2   [33554432,67108864): 1
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
+    [2,4): 2   [16,32): 6   [64,128): 1   [256,512): 1   [524288,1048576): 2   [33554432,67108864): 2
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
 Number of unique paths: 9
 
-Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
+Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
 Index | Running Total | Section@Address | PSS | Path
 ------------------------------------------------------------
 0)          8 (0.0%)  *@Group      8               google (count=2)
 1)        168 (0.0%)  *@Group      160             base (count=3)
-2)    1166900 (2.7%)  *@Group      1166732         ** symbol gap 0 (end of section) (count=2)
-3)    1166956 (2.7%)  *@Group      56              ChromeMainDelegateAndroid [vtable] (count=1)
-4)    1166980 (2.7%)  *@Group      24              mojo (count=1)
-5)    1166992 (2.7%)  *@Group      12              kMethodsAnimationFrameTimeHistogram (count=1)
-6)    1167048 (2.7%)  *@Group      56              ChromeMainDelegate [vtable] (count=1)
-7)    1957008 (4.5%)  *@Group      789960          chrome (count=3)
-8)    1957040 (4.5%)  *@Group      32              .Lswitch.table.45 (count=1)
-9)    1957048 (4.5%)  *@Group      8               kSystemClassPrefixes (count=1)
-10)   1957069 (4.5%)  *@Group      21              string literal (count=3)
-11)   1957112 (4.5%)  *@Group      43              ** merge strings (count=1)
-12)   3922457 (9.0%)  *@Group      1965345         ** merge constants (count=1)
-13)  43039332 (98.3%) *@Group      39116875        ** symbol gaps (count=2)
-14)  43039340 (98.3%) *@Group      8                (count=1)
-15)  43039384 (98.3%) *@Group      44              Name (count=1)
-16)  43715424 (99.8%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
-17)  43715580 (99.8%) *@Group      156             blink (count=6)
-18)  43715596 (99.8%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
-19)  43715652 (99.8%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
-20)  43715680 (99.8%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
-21)  43715750 (99.8%) *@Group      70              extFromUUseMapping (count=2)
-22)  43716198 (99.8%) *@Group      448             ucnv_extMatchFromU (count=1)
-23)  43716226 (99.8%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
-24)  43785350 (100.0%) *@Group      69124           foo_bar (count=1)
-25)  43785374 (100.0%) *@Group      24              BazAlias (count=1)
-26)  43785377 (100.0%) *@Group      3               FooAlias (count=1)
-27)  43785380 (100.0%) *@Group      3               BarAlias (count=1)
-28)  43785380 (100.0%) *@Group      0               ff_cos_131072 (count=1)
-29)  43785380 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
-30)  43785380 (100.0%) *@Group      0               ff_cos_65536 (count=1)
-31)  43785380 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
-32)  43785380 (100.0%) *@Group      0               SaveHistogram (count=1)
-33)  43785380 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
+2)    1166900 (1.5%)  *@Group      1166732         ** symbol gap 0 (end of section) (count=2)
+3)    1166956 (1.5%)  *@Group      56              ChromeMainDelegateAndroid [vtable] (count=1)
+4)    1166980 (1.5%)  *@Group      24              mojo (count=1)
+5)    1166992 (1.5%)  *@Group      12              kMethodsAnimationFrameTimeHistogram (count=1)
+6)    1167048 (1.5%)  *@Group      56              ChromeMainDelegate [vtable] (count=1)
+7)    1957008 (2.5%)  *@Group      789960          chrome (count=3)
+8)    1957040 (2.5%)  *@Group      32              .Lswitch.table.45 (count=1)
+9)    1957048 (2.5%)  *@Group      8               kSystemClassPrefixes (count=1)
+10)  35941219 (46.2%) *@Group      33984171        ELF file overhead (count=1)
+11)  35941240 (46.2%) *@Group      21              string literal (count=3)
+12)  35941283 (46.2%) *@Group      43              ** merge strings (count=1)
+13)  37906628 (48.7%) *@Group      1965345         ** merge constants (count=1)
+14)  77023503 (99.0%) *@Group      39116875        ** symbol gaps (count=2)
+15)  77023511 (99.0%) *@Group      8                (count=1)
+16)  77023555 (99.0%) *@Group      44              Name (count=1)
+17)  77699595 (99.9%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
+18)  77699751 (99.9%) *@Group      156             blink (count=6)
+19)  77699767 (99.9%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
+20)  77699823 (99.9%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
+21)  77699851 (99.9%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
+22)  77699921 (99.9%) *@Group      70              extFromUUseMapping (count=2)
+23)  77700369 (99.9%) *@Group      448             ucnv_extMatchFromU (count=1)
+24)  77700397 (99.9%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
+25)  77769521 (100.0%) *@Group      69124           foo_bar (count=1)
+26)  77769545 (100.0%) *@Group      24              BazAlias (count=1)
+27)  77769548 (100.0%) *@Group      3               FooAlias (count=1)
+28)  77769551 (100.0%) *@Group      3               BarAlias (count=1)
+29)  77769551 (100.0%) *@Group      0               ff_cos_131072 (count=1)
+30)  77769551 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
+31)  77769551 (100.0%) *@Group      0               ff_cos_65536 (count=1)
+32)  77769551 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
+33)  77769551 (100.0%) *@Group      0               SaveHistogram (count=1)
+34)  77769551 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
 GroupedByName(depth=-1)
-Showing 37 symbols (37 unique) with total pss: 43785380 bytes
+Showing 38 symbols (38 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
-      {0}: 6    [8,16): 4    [64,128): 2      [65536,131072): 1   [33554432,67108864): 1
+      {0}: 6    [8,16): 4    [64,128): 2      [65536,131072): 1   [33554432,67108864): 2
     [2,4): 2   [16,32): 6   [128,256): 1    [524288,1048576): 2
     [4,8): 1   [32,64): 8   [256,512): 1   [1048576,2097152): 2
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
 Number of unique paths: 9
 
-Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
+Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
 Index | Running Total | Section@Address | PSS | Path
 ------------------------------------------------------------
 0)          8 (0.0%)  *@Group      8               google::protobuf::internal (count=2)
 1)        168 (0.0%)  *@Group      160             base::android (count=3)
-2)    1166900 (2.7%)  *@Group      1166732         ** symbol gap 0 (end of section) (count=2)
-3)    1166956 (2.7%)  *@Group      56              ChromeMainDelegateAndroid [vtable] (count=1)
-4)    1166980 (2.7%)  *@Group      24              mojo (count=1)
-5)    1166992 (2.7%)  *@Group      12              kMethodsAnimationFrameTimeHistogram (count=1)
-6)    1167048 (2.7%)  *@Group      56              ChromeMainDelegate [vtable] (count=1)
-7)    1956976 (4.5%)  *@Group      789928          chrome::mojom (count=2)
-8)    1957008 (4.5%)  *@Group      32              .Lswitch.table.45 (count=1)
-9)    1957016 (4.5%)  *@Group      8               kSystemClassPrefixes (count=1)
-10)   1957037 (4.5%)  *@Group      21              string literal (count=3)
-11)   1957080 (4.5%)  *@Group      43              ** merge strings (count=1)
-12)   3922425 (9.0%)  *@Group      1965345         ** merge constants (count=1)
-13)  43039300 (98.3%) *@Group      39116875        ** symbol gaps (count=2)
-14)  43039308 (98.3%) *@Group      8                (count=1)
-15)  43039352 (98.3%) *@Group      44              Name (count=1)
-16)  43039384 (98.3%) *@Group      32              chrome::mojom::FilePatcher (count=1)
-17)  43715424 (99.8%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
-18)  43715428 (99.8%) *@Group      4               blink::CSSValueKeywordsHash::findValueImpl (count=1)
-19)  43715444 (99.8%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
-20)  43715500 (99.8%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
-21)  43715528 (99.8%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
-22)  43715598 (99.8%) *@Group      70              extFromUUseMapping (count=2)
-23)  43716046 (99.8%) *@Group      448             ucnv_extMatchFromU (count=1)
-24)  43716074 (99.8%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
-25)  43785198 (100.0%) *@Group      69124           foo_bar (count=1)
-26)  43785256 (100.0%) *@Group      58              blink::ContiguousContainerBase (count=4)
-27)  43785280 (100.0%) *@Group      24              BazAlias (count=1)
-28)  43785283 (100.0%) *@Group      3               FooAlias (count=1)
-29)  43785286 (100.0%) *@Group      3               BarAlias (count=1)
-30)  43785380 (100.0%) *@Group      94              blink::PaintChunker (count=1)
-31)  43785380 (100.0%) *@Group      0               ff_cos_131072 (count=1)
-32)  43785380 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
-33)  43785380 (100.0%) *@Group      0               ff_cos_65536 (count=1)
-34)  43785380 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
-35)  43785380 (100.0%) *@Group      0               SaveHistogram (count=1)
-36)  43785380 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
+2)    1166900 (1.5%)  *@Group      1166732         ** symbol gap 0 (end of section) (count=2)
+3)    1166956 (1.5%)  *@Group      56              ChromeMainDelegateAndroid [vtable] (count=1)
+4)    1166980 (1.5%)  *@Group      24              mojo (count=1)
+5)    1166992 (1.5%)  *@Group      12              kMethodsAnimationFrameTimeHistogram (count=1)
+6)    1167048 (1.5%)  *@Group      56              ChromeMainDelegate [vtable] (count=1)
+7)    1956976 (2.5%)  *@Group      789928          chrome::mojom (count=2)
+8)    1957008 (2.5%)  *@Group      32              .Lswitch.table.45 (count=1)
+9)    1957016 (2.5%)  *@Group      8               kSystemClassPrefixes (count=1)
+10)  35941187 (46.2%) *@Group      33984171        ELF file overhead (count=1)
+11)  35941208 (46.2%) *@Group      21              string literal (count=3)
+12)  35941251 (46.2%) *@Group      43              ** merge strings (count=1)
+13)  37906596 (48.7%) *@Group      1965345         ** merge constants (count=1)
+14)  77023471 (99.0%) *@Group      39116875        ** symbol gaps (count=2)
+15)  77023479 (99.0%) *@Group      8                (count=1)
+16)  77023523 (99.0%) *@Group      44              Name (count=1)
+17)  77023555 (99.0%) *@Group      32              chrome::mojom::FilePatcher (count=1)
+18)  77699595 (99.9%) *@Group      676040          kAnimationFrameTimeHistogramClassPath (count=1)
+19)  77699599 (99.9%) *@Group      4               blink::CSSValueKeywordsHash::findValueImpl (count=1)
+20)  77699615 (99.9%) *@Group      16              _GLOBAL__sub_I_page_allocator.cc (count=1)
+21)  77699671 (99.9%) *@Group      56              _GLOBAL__sub_I_bbr_sender.cc (count=1)
+22)  77699699 (99.9%) *@Group      28              _GLOBAL__sub_I_pacing_sender.cc (count=1)
+23)  77699769 (99.9%) *@Group      70              extFromUUseMapping (count=2)
+24)  77700217 (99.9%) *@Group      448             ucnv_extMatchFromU (count=1)
+25)  77700245 (99.9%) *@Group      28              _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1)
+26)  77769369 (100.0%) *@Group      69124           foo_bar (count=1)
+27)  77769427 (100.0%) *@Group      58              blink::ContiguousContainerBase (count=4)
+28)  77769451 (100.0%) *@Group      24              BazAlias (count=1)
+29)  77769454 (100.0%) *@Group      3               FooAlias (count=1)
+30)  77769457 (100.0%) *@Group      3               BarAlias (count=1)
+31)  77769551 (100.0%) *@Group      94              blink::PaintChunker (count=1)
+32)  77769551 (100.0%) *@Group      0               ff_cos_131072 (count=1)
+33)  77769551 (100.0%) *@Group      0               ff_cos_131072_fixed (count=1)
+34)  77769551 (100.0%) *@Group      0               ff_cos_65536 (count=1)
+35)  77769551 (100.0%) *@Group      0               g_chrome_content_browser_client (count=1)
+36)  77769551 (100.0%) *@Group      0               SaveHistogram (count=1)
+37)  77769551 (100.0%) *@Group      0               g_AnimationFrameTimeHistogram_clazz (count=1)
 GroupedByName(depth=1, min_count=2)
-Showing 34 symbols (33 unique) with total pss: 43785380 bytes
+Showing 35 symbols (34 unique) with total pss: 77769551 bytes
 Histogram of symbols based on PSS:
      [2,4): 2    [16,32): 7        [128,256): 3    [131072,262144): 2     [1048576,2097152): 2
-     [4,8): 1    [32,64): 6        [256,512): 1    [262144,524288): 1   [33554432,67108864): 1
+     [4,8): 1    [32,64): 6        [256,512): 1    [262144,524288): 1   [33554432,67108864): 2
     [8,16): 4   [64,128): 1   [65536,131072): 1   [524288,1048576): 2
-.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      total=41.8mb
+.text=34.2mb     .rodata=5.65mb     .data.rel.ro=1.02mb     .data=99.4kb     .bss=512kb      .other=32.4mb     total=74.2mb
 Number of unique paths: 9
 
-Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss
+Section Legend: t=.text, r=.rodata, R=.data.rel.ro, d=.data, b=.bss, o=.other
 Index | Running Total | Section@Address | PSS | Path
 ------------------------------------------------------------
 0)          8 (0.0%)  *@Group      8              {no path}
              google (count=2)
 1)        168 (0.0%)  *@Group      160            third_party/container.c
              base (count=3)
-2)    1166900 (2.7%)  *@Group      1166732        {no path}
+2)    1166900 (1.5%)  *@Group      1166732        {no path}
              ** symbol gap 0 (end of section) (count=2)
-3)    1166956 (2.7%)  R@0x2cd8500  56             third_party/paint.cc
+3)    1166956 (1.5%)  R@0x2cd8500  56             third_party/paint.cc
              ChromeMainDelegateAndroid [vtable]
-4)    1166980 (2.7%)  R@0x2cd8538  24             base/page_allocator.cc
+4)    1166980 (1.5%)  R@0x2cd8538  24             base/page_allocator.cc
              mojo::MessageReceiver [vtable]
-5)    1166992 (2.7%)  R@0x2cd8550  12             base/page_allocator.cc
+5)    1166992 (1.5%)  R@0x2cd8550  12             base/page_allocator.cc
              kMethodsAnimationFrameTimeHistogram
-6)    1167048 (2.7%)  R@0x2c176f0  56             third_party/icu/ucnv_ext.c
+6)    1167048 (1.5%)  R@0x2c176f0  56             third_party/icu/ucnv_ext.c
              ChromeMainDelegate [vtable]
-7)    1957008 (4.5%)  *@Group      789960         {no path}
+7)    1957008 (2.5%)  *@Group      789960         {no path}
              chrome (count=3)
-8)    1957040 (4.5%)  R@0x2cd84e0  32             third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o
+8)    1957040 (2.5%)  R@0x2cd84e0  32             third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o
              .Lswitch.table.45
-9)    1957048 (4.5%)  R@0x2cd84f0  8              third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o
+9)    1957048 (2.5%)  R@0x2cd84f0  8              third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o
              kSystemClassPrefixes
-10)   1957069 (4.5%)  *@Group      21             {no path}
+10)  35941219 (46.2%) o@0x0        33984171       {no path}
+             ELF file overhead
+11)  35941240 (46.2%) *@Group      21             {no path}
              string literal (count=3)
-11)   1957112 (4.5%)  r@0x266e630  43             {no path}
+12)  35941283 (46.2%) r@0x266e630  43             {no path}
              ** merge strings
-12)   3922457 (9.0%)  r@0x284d600  1965345        {no path}
+13)  37906628 (48.7%) r@0x284d600  1965345        {no path}
              ** merge constants
-13)  43039332 (98.3%) *@Group      39116875       {no path}
+14)  77023503 (99.0%) *@Group      39116875       {no path}
              ** symbol gaps (count=2)
-14)  43039340 (98.3%) r@0x284e364  8              base/page_allocator.cc
-15)  43039384 (98.3%) r@0x284e370  44             base/page_allocator.cc
+15)  77023511 (99.0%) r@0x284e364  8              base/page_allocator.cc
+16)  77023555 (99.0%) r@0x284e370  44             base/page_allocator.cc
              Name
-16)  43715424 (99.8%) r@0x28f3450  676040         third_party/paint.cc
+17)  77699595 (99.9%) r@0x28f3450  676040         third_party/paint.cc
              kAnimationFrameTimeHistogramClassPath
-17)  43715580 (99.8%) *@Group      156            {no path}
+18)  77699751 (99.9%) *@Group      156            {no path}
              blink (count=6)
-18)  43715596 (99.8%) t@0x28d900   16             base/page_allocator.cc
+19)  77699767 (99.9%) t@0x28d900   16             base/page_allocator.cc
              _GLOBAL__sub_I_page_allocator.cc
-19)  43715652 (99.8%) t@0x28d910   56             base/page_allocator.cc
+20)  77699823 (99.9%) t@0x28d910   56             base/page_allocator.cc
              _GLOBAL__sub_I_bbr_sender.cc
-20)  43715680 (99.8%) t@0x28d948   28             base/page_allocator.cc
+21)  77699851 (99.9%) t@0x28d948   28             base/page_allocator.cc
              _GLOBAL__sub_I_pacing_sender.cc
-21)  43715750 (99.8%) *@Group      70             base/page_allocator.cc
+22)  77699921 (99.9%) *@Group      70             base/page_allocator.cc
              extFromUUseMapping (count=2)
-22)  43716198 (99.8%) t@0x28f000   448            third_party/icu/ucnv_ext.c
+23)  77700369 (99.9%) t@0x28f000   448            third_party/icu/ucnv_ext.c
              ucnv_extMatchFromU
-23)  43716226 (99.8%) t@0x28f1c8   28             third_party/icu/ucnv_ext.c
+24)  77700397 (99.9%) t@0x28f1c8   28             third_party/icu/ucnv_ext.c
              _GLOBAL__sub_I_SkDeviceProfile.cpp
-24)  43785350 (100.0%) t@0x28f1e0   69124          third_party/icu/ucnv_ext.c
+25)  77769521 (100.0%) t@0x28f1e0   69124          third_party/icu/ucnv_ext.c
              foo_bar
-25)  43785374 (100.0%) t@0x2a0000   24 (size=48)   third_party/icu/ucnv_ext.c
+26)  77769545 (100.0%) t@0x2a0000   24 (size=48)   third_party/icu/ucnv_ext.c
              BazAlias (num_aliases=2)
-26)  43785377 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
+27)  77769548 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
              FooAlias (num_aliases=4)
-27)  43785380 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
+28)  77769551 (100.0%) t@0x2a0010   3 (size=12)    third_party/fft_float.cc
              BarAlias (num_aliases=4)
-28)  43785380 (100.0%) b@0x0        262144         third_party/fft_float.cc
+29)  77769551 (100.0%) b@0x0        262144         third_party/fft_float.cc
              ff_cos_131072
-29)  43785380 (100.0%) b@0x0        131072         third_party/fft_fixed.cc
+30)  77769551 (100.0%) b@0x0        131072         third_party/fft_fixed.cc
              ff_cos_131072_fixed
-30)  43785380 (100.0%) b@0x0        131072         third_party/fft_float.cc
+31)  77769551 (100.0%) b@0x0        131072         third_party/fft_float.cc
              ff_cos_65536
-31)  43785380 (100.0%) b@0x2dffda0  28             third_party/icu/ucnv_ext.c
+32)  77769551 (100.0%) b@0x2dffda0  28             third_party/icu/ucnv_ext.c
              g_chrome_content_browser_client
-32)  43785380 (100.0%) b@0x2dffe80  200            third_party/icu/ucnv_ext.c
+33)  77769551 (100.0%) b@0x2dffe80  200            third_party/icu/ucnv_ext.c
              SaveHistogram::atomic_histogram_pointer
-33)  43785380 (100.0%) b@0x2dffe84  4              third_party/icu/ucnv_ext.c
+34)  77769551 (100.0%) b@0x2dffe84  4              third_party/icu/ucnv_ext.c
              g_AnimationFrameTimeHistogram_clazz
diff --git a/tools/binary_size/libsupersize/testdata/mock_output_directory/elf b/tools/binary_size/libsupersize/testdata/mock_output_directory/elf.begin
similarity index 100%
rename from tools/binary_size/libsupersize/testdata/mock_output_directory/elf
rename to tools/binary_size/libsupersize/testdata/mock_output_directory/elf.begin
Binary files differ
diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py
index 5030a549..a0f32ad 100755
--- a/tools/gn/bootstrap/bootstrap.py
+++ b/tools/gn/bootstrap/bootstrap.py
@@ -724,6 +724,7 @@
         'base/strings/sys_string_conversions_mac.mm',
         'base/synchronization/waitable_event_mac.cc',
         'base/sys_info_mac.mm',
+        'base/time/time_exploded_posix.cc',
         'base/time/time_mac.cc',
         'base/threading/platform_thread_mac.mm',
     ])
diff --git a/tools/licenses.py b/tools/licenses.py
index 8dc8be89..bd1e1a5 100755
--- a/tools/licenses.py
+++ b/tools/licenses.py
@@ -102,7 +102,6 @@
                'layout_tests'))            # lots of subdirs
 
 ADDITIONAL_PATHS = (
-    os.path.join('breakpad'),
     os.path.join('chrome', 'common', 'extensions', 'docs', 'examples'),
     os.path.join('chrome', 'test', 'chromeos', 'autotest'),
     os.path.join('chrome', 'test', 'data'),
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index 1bfe40d4..04a731d 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -913,13 +913,23 @@
                                 output_path=None)
 
     if is_android and test_type != "script":
+      extra_files = [
+          '../../testing/test_env.py'
+      ]
       cmdline = [
+          '../../testing/test_env.py',
           '../../build/android/test_wrapper/logdog_wrapper.py',
           '--target', target,
           '--logdog-bin-cmd', '../../bin/logdog_butler',
           '--store-tombstones']
     elif is_fuchsia and test_type != 'script':
-      cmdline = [os.path.join('bin', 'run_%s' % target)]
+      extra_files = [
+          '../../testing/test_env.py'
+      ]
+      cmdline = [
+          '../../testing/test_env.py',
+          os.path.join('bin', 'run_%s' % target),
+      ]
     elif use_xvfb and test_type == 'windowed_test_launcher':
       extra_files = [
           '../../testing/test_env.py',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 96560952..7344cb21 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -4207,6 +4207,12 @@
   <int value="5" label="App provided items"/>
 </enum>
 
+<enum name="BubbleDismissalReason">
+  <int value="0" label="The timer dismissed the bubble."/>
+  <int value="1" label="A tap inside the bubble caused dismissal."/>
+  <int value="2" label="A tap outside the bubble caused dismissal."/>
+</enum>
+
 <enum name="BubbleType">
   <int value="0" label="Unknown Bubble"/>
   <int value="1" label="Mock Bubble"/>
@@ -16948,7 +16954,7 @@
   <int value="1958" label="MediaStreamConstraintsGoogDAEchoCancellation"/>
   <int value="1959" label="MediaStreamConstraintsGoogNoiseReduction"/>
   <int value="1960" label="MediaStreamConstraintsGoogPowerLineFrequency"/>
-  <int value="1961" label="ViewportFixedPositionUnderFilter (obsolete)"/>
+  <int value="1961" label="ViewportFixedPositionUnderFilter"/>
   <int value="1962"
       label="RequestMIDIAccessWithSysExOption_ObscuredByFootprinting"/>
   <int value="1963"
@@ -17324,6 +17330,7 @@
   <int value="2317" label="CSSSelectorWebkitSliderThumb"/>
   <int value="2318" label="CSSSelectorWebkitTextfieldDecorationContainer"/>
   <int value="2319" label="CSSSelectorWebkitUnknownPseudo"/>
+  <int value="2320" label="FilterAsContainingBlockMayChangeOutput"/>
 </enum>
 
 <enum name="FeedbackSource">
@@ -24912,6 +24919,7 @@
   <int value="-1575984706" label="gl-composited-overlay-candidate-quad-border"/>
   <int value="-1575554415" label="AndroidPaymentAppsFilter:enabled"/>
   <int value="-1575430234" label="DontPrefetchLibraries:disabled"/>
+  <int value="-1575375861" label="enable-captive-portal-random-url"/>
   <int value="-1572010356" label="enable-privet-v3"/>
   <int value="-1571841513" label="enable-devtools-experiments"/>
   <int value="-1559789642" label="RunAllFlashInAllowMode:enabled"/>
@@ -25174,7 +25182,6 @@
   <int value="-881054479" label="WebAssemblyStreaming:disabled"/>
   <int value="-879055117" label="ClipboardContentSetting:enabled"/>
   <int value="-879031960" label="FetchKeepaliveTimeoutSetting:disabled"/>
-  <int value="-876773752" label="enable-tablet-splitview"/>
   <int value="-876148583" label="ArcBootCompletedBroadcast:disabled"/>
   <int value="-867087281" label="enable-virtual-keyboard"/>
   <int value="-866993841" label="OfflinePagesCTV2:disabled"/>
@@ -25879,6 +25886,7 @@
   <int value="1070449228" label="ContextualSuggestionsCarousel:enabled"/>
   <int value="1072010558" label="NTPModernLayout:disabled"/>
   <int value="1074359194" label="UseSuggestionsEvenIfFew:enabled"/>
+  <int value="1075637651" label="disable-tablet-splitview"/>
   <int value="1079032226" label="ParallelDownloading:enabled"/>
   <int value="1081546525" label="ash-enable-docked-windows"/>
   <int value="1087235172" label="file-manager-enable-new-audio-player"/>
@@ -28300,6 +28308,15 @@
   <int value="2" label="SUCCESS">All operations succeeded.</int>
 </enum>
 
+<enum name="MultiDisplayModes">
+  <summary>
+    Defines the modes in which displays connected to the device are in.
+  </summary>
+  <int value="0" label="Extended mode"/>
+  <int value="1" label="Mirroring mode"/>
+  <int value="2" label="Unified mode"/>
+</enum>
+
 <enum name="MultiProfileSessionMode">
   <int value="0" label="Single user mode"/>
   <int value="1" label="Side by side mode"/>
@@ -42295,6 +42312,18 @@
   <int value="7" label="kNoStore"/>
 </enum>
 
+<enum name="UnifiedDesktopDisplayCountRanges">
+  <summary>
+    Defines the ranges in which the number of displays connected in Unified Mode
+    may reside
+  </summary>
+  <int value="0" label="2 displays"/>
+  <int value="1" label="(2 to 4] displays"/>
+  <int value="2" label="(4 to 6] displays"/>
+  <int value="3" label="(6 to 8] displays"/>
+  <int value="4" label="More than 8 displays"/>
+</enum>
+
 <enum name="UniformityTrialGroupNotActive">
   <int value="0" label="Invalid"/>
   <int value="1" label="Group not reported"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index abee1719..72e3d22 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -7400,6 +7400,12 @@
   </summary>
 </histogram>
 
+<histogram name="BlinkGC.TimeForCoalesce" units="ms">
+  <owner>haraken@chromium.org</owner>
+  <owner>hpayer@chromium.org</owner>
+  <summary>Duration of memory coalesce operation in the Blink GC.</summary>
+</histogram>
+
 <histogram name="BlinkGC.TimeForGlobalWeakProcessing" units="ms">
   <owner>haraken@chromium.org</owner>
   <summary>
@@ -7444,6 +7450,12 @@
   <summary>Duration of time taken to run thread-local weak processing.</summary>
 </histogram>
 
+<histogram name="BlinkGC.TimeForTotalCollectGarbage" units="ms">
+  <owner>haraken@chromium.org</owner>
+  <owner>hpayer@chromium.org</owner>
+  <summary>Duration of total Blink garbage collection time.</summary>
+</histogram>
+
 <histogram name="BlinkGC.TotalAllocatedSpace" units="KB">
   <owner>haraken@chromium.org</owner>
   <summary>
@@ -15279,6 +15291,25 @@
   </summary>
 </histogram>
 
+<histogram name="DisplayManager.MultiDisplayMode" enum="MultiDisplayModes">
+  <owner>afakhry@chromium.org</owner>
+  <summary>
+    The mode in which the connected displays to the device is in. This is
+    emitted once when displays are added or removed, or when the user changes
+    the mode by e.g. enabling mirror or unified modes.
+  </summary>
+</histogram>
+
+<histogram name="DisplayManager.UnifiedDesktopDisplayCountRange"
+    enum="UnifiedDesktopDisplayCountRanges">
+  <owner>afakhry@chromium.org</owner>
+  <summary>
+    The the number of displays connected to the device when Unified Desktop mode
+    is on. This is emitted when Unified Desktop mode is turned on, or the
+    displays are added or removed while in Unified Mode.
+  </summary>
+</histogram>
+
 <histogram name="DNS.AttemptCancelled">
   <owner>mgersh@chromium.org</owner>
   <summary>
@@ -30978,6 +31009,13 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.IPHBubbleDismissalReason" enum="BubbleDismissalReason">
+  <owner>gchatz@chromium.org</owner>
+  <summary>
+    Tracks the reason for why the In Product Help bubble was dismissed.
+  </summary>
+</histogram>
+
 <histogram name="IOS.MailtoURLRewritten" enum="Boolean">
   <owner>pkl@chromium.org</owner>
   <summary>
@@ -59066,6 +59104,18 @@
 </histogram>
 
 <histogram name="PartnerBookmark.TimeSinceLastEmptyRead" units="ms">
+  <obsolete>
+    Deprecated 2017-12. Use PartnerBookmark.TimeSinceLastEmptyRead2.
+  </obsolete>
+  <owner>wychen@chromium.org</owner>
+  <summary>
+    When trying to load the partner bookmarks, if no partner bookmark is read
+    last time, record the time elapsed since then. It is recorded no matter
+    whether loading would be skipped.
+  </summary>
+</histogram>
+
+<histogram name="PartnerBookmark.TimeSinceLastEmptyRead2" units="seconds">
   <owner>wychen@chromium.org</owner>
   <summary>
     When trying to load the partner bookmarks, if no partner bookmark is read
@@ -69339,6 +69389,17 @@
   </summary>
 </histogram>
 
+<histogram name="Renderer.WKWebViewCallbackAfterDestroy" enum="BooleanHit">
+  <owner>michaeldo@chromium.org</owner>
+  <summary>
+    [iOS] Counts the number of times a WKNavigationDelegate callback was called
+    after the CRWWebController was closed. This is unexpected and could be the
+    cause of many crashes. If this histogram is ever logged, it means that
+    Chrome needs to gracefully handle the case when WKNavigationDelegate
+    callbacks are called for a destroyed web controller. Only logged on iOS.
+  </summary>
+</histogram>
+
 <histogram name="Renderer2.FinishDocToFinish">
   <obsolete>
     Deprecated 04/2016 as doesn't have data nor owner.
diff --git a/ui/DEPS b/ui/DEPS
index 7a20cbd6..154e1b6 100644
--- a/ui/DEPS
+++ b/ui/DEPS
@@ -2,3 +2,9 @@
   # Components within ui must state their dependencies explicitly.
   "-ui",
 ]
+
+specific_include_rules = {
+  ".*unittest\.mm": [
+    "+ui/base/test",
+  ],
+}
diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl
index 0bd3f8f..221c2ce 100644
--- a/ui/accessibility/ax_enums.idl
+++ b/ui/accessibility/ax_enums.idl
@@ -459,7 +459,11 @@
     text_direction,
 
     // Bold, italic, underline, etc.
-    text_style
+    text_style,
+
+    // Focus traversal in views and Android.
+    previous_focus_id,
+    next_focus_id
   };
 
   [cpp_enum_prefix_override="ax_attr"] enum AXFloatAttribute {
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index ce28139..ec4ef8b 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -98,6 +98,8 @@
     case AX_ATTR_TABLE_HEADER_ID:
     case AX_ATTR_TABLE_COLUMN_HEADER_ID:
     case AX_ATTR_TABLE_ROW_HEADER_ID:
+    case AX_ATTR_NEXT_FOCUS_ID:
+    case AX_ATTR_PREVIOUS_FOCUS_ID:
       return true;
 
     // Note: all of the attributes are included here explicitly,
@@ -794,6 +796,12 @@
             break;
         }
         break;
+      case AX_ATTR_NEXT_FOCUS_ID:
+        result += " next_focus_id=" + value;
+        break;
+      case AX_ATTR_PREVIOUS_FOCUS_ID:
+        result += " previous_focus_id=" + value;
+        break;
       case AX_INT_ATTRIBUTE_NONE:
         break;
     }
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
index 6e6a2e2..06bbf69 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -770,6 +770,8 @@
     atk_hyperlink_ = nullptr;
   }
   if (atk_object_) {
+    if (atk_object_ == current_focused_)
+      current_focused_ = nullptr;
     ax_platform_node_auralinux_detach(AX_PLATFORM_NODE_AURALINUX(atk_object_));
     g_object_unref(atk_object_);
     atk_object_ = nullptr;
@@ -1071,7 +1073,34 @@
   return atk_object_;
 }
 
+AtkObject* AXPlatformNodeAuraLinux::current_focused_ = nullptr;
+
+void AXPlatformNodeAuraLinux::OnFocused() {
+  DCHECK(atk_object_);
+
+  if (atk_object_ == current_focused_)
+    return;
+
+  if (current_focused_) {
+    g_signal_emit_by_name(current_focused_, "focus-event", false);
+    atk_object_notify_state_change(ATK_OBJECT(current_focused_),
+                                   ATK_STATE_FOCUSED, false);
+  }
+
+  current_focused_ = atk_object_;
+  g_signal_emit_by_name(atk_object_, "focus-event", true);
+  atk_object_notify_state_change(ATK_OBJECT(atk_object_), ATK_STATE_FOCUSED,
+                                 true);
+}
+
 void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(ui::AXEvent event_type) {
+  switch (event_type) {
+    case AX_EVENT_FOCUS:
+      OnFocused();
+      break;
+    default:
+      break;
+  }
 }
 
 int AXPlatformNodeAuraLinux::GetIndexInParent() {
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h
index 4b28b90..6eaa14ab 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.h
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -72,6 +72,9 @@
   // Misc helpers
   void GetFloatAttributeInGValue(AXFloatAttribute attr, GValue* value);
 
+  // Event helpers
+  void OnFocused();
+
   // AXPlatformNode overrides.
   gfx::NativeViewAccessible GetNativeViewAccessible() override;
   void NotifyAccessibilityEvent(ui::AXEvent event_type) override;
@@ -112,6 +115,10 @@
   // top-level windows.
   static AXPlatformNode* application_;
 
+  // The last AtkObject with keyboard focus. Tracking this is required
+  // to emit the ATK_STATE_FOCUSED change to false.
+  static AtkObject* current_focused_;
+
   DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeAuraLinux);
 };
 
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn
index f72e9916..43756d3 100644
--- a/ui/app_list/BUILD.gn
+++ b/ui/app_list/BUILD.gn
@@ -101,8 +101,6 @@
     "views/speech_view.h",
     "views/suggestions_container_view.cc",
     "views/suggestions_container_view.h",
-    "views/tile_item_view.cc",
-    "views/tile_item_view.h",
     "views/top_icon_animation_view.cc",
     "views/top_icon_animation_view.h",
   ]
diff --git a/ui/app_list/app_list_features.cc b/ui/app_list/app_list_features.cc
index 3868ae2..9c6e80b 100644
--- a/ui/app_list/app_list_features.cc
+++ b/ui/app_list/app_list_features.cc
@@ -37,11 +37,6 @@
   return base::FeatureList::IsEnabled(kEnablePlayStoreAppSearch);
 }
 
-bool IsAppListFocusEnabled() {
-  // TODO(766807): Remove this method.
-  return true;
-}
-
 std::string AnswerServerUrl() {
   const std::string experiment_url =
       base::GetFieldTrialParamValueByFeature(kEnableAnswerCard, "ServerUrl");
diff --git a/ui/app_list/app_list_features.h b/ui/app_list/app_list_features.h
index b13abacd4..5ab2da9 100644
--- a/ui/app_list/app_list_features.h
+++ b/ui/app_list/app_list_features.h
@@ -33,7 +33,6 @@
 bool APP_LIST_EXPORT IsBackgroundBlurEnabled();
 bool APP_LIST_EXPORT IsFullscreenAppListEnabled();
 bool APP_LIST_EXPORT IsPlayStoreAppSearchEnabled();
-bool APP_LIST_EXPORT IsAppListFocusEnabled();
 std::string APP_LIST_EXPORT AnswerServerUrl();
 std::string APP_LIST_EXPORT AnswerServerQuerySuffix();
 
diff --git a/ui/app_list/views/app_list_folder_view.cc b/ui/app_list/views/app_list_folder_view.cc
index f764e2a..e177d99 100644
--- a/ui/app_list/views/app_list_folder_view.cc
+++ b/ui/app_list/views/app_list_folder_view.cc
@@ -10,7 +10,6 @@
 #include "ash/app_list/model/app_list_model.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/app_list/app_list_constants.h"
-#include "ui/app_list/app_list_features.h"
 #include "ui/app_list/views/app_list_item_view.h"
 #include "ui/app_list/views/app_list_main_view.h"
 #include "ui/app_list/views/apps_container_view.h"
@@ -55,8 +54,7 @@
       view_model_(new views::ViewModel),
       model_(model),
       folder_item_(NULL),
-      hide_for_reparent_(false),
-      is_app_list_focus_enabled_(features::IsAppListFocusEnabled()) {
+      hide_for_reparent_(false) {
   AddChildView(folder_header_view_);
   view_model_->Add(folder_header_view_, kIndexFolderHeader);
 
@@ -130,32 +128,6 @@
   views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_);
 }
 
-bool AppListFolderView::OnKeyPressed(const ui::KeyEvent& event) {
-  if (is_app_list_focus_enabled_) {
-    // TODO(weidongg/766807) Remove this function when the flag is enabled by
-    // default.
-    return false;
-  }
-  // Process TAB if focus should go to header; otherwise, AppsGridView will do
-  // the right thing.
-  if (event.key_code() == ui::VKEY_TAB) {
-    if (items_grid_view_->has_selected_view() == event.IsShiftDown() &&
-        !folder_header_view_->HasTextFocus()) {
-      folder_header_view_->SetTextFocus();
-      items_grid_view_->ClearAnySelectedView();
-      return true;
-    } else {
-      GiveBackFocusToSearchBox();
-    }
-  }
-
-  // This will select an app in the list, so we need to relinquish focus.
-  if (event.key_code() == ui::VKEY_DOWN)
-    GiveBackFocusToSearchBox();
-
-  return items_grid_view_->OnKeyPressed(event);
-}
-
 void AppListFolderView::OnAppListItemWillBeDeleted(AppListItem* item) {
   if (item == folder_item_) {
     items_grid_view_->OnFolderItemRemoved();
diff --git a/ui/app_list/views/app_list_folder_view.h b/ui/app_list/views/app_list_folder_view.h
index ea20c069..6641797 100644
--- a/ui/app_list/views/app_list_folder_view.h
+++ b/ui/app_list/views/app_list_folder_view.h
@@ -62,7 +62,6 @@
   // views::View
   gfx::Size CalculatePreferredSize() const override;
   void Layout() override;
-  bool OnKeyPressed(const ui::KeyEvent& event) override;
 
   // AppListModelObserver
   void OnAppListItemWillBeDeleted(AppListItem* item) override;
@@ -122,9 +121,6 @@
 
   base::string16 accessible_name_;
 
-  // Whether the app list focus is enabled.
-  const bool is_app_list_focus_enabled_;
-
   DISALLOW_COPY_AND_ASSIGN(AppListFolderView);
 };
 
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc
index 3b59e67..1cead10 100644
--- a/ui/app_list/views/app_list_view_unittest.cc
+++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -44,7 +44,6 @@
 #include "ui/app_list/views/search_result_view.h"
 #include "ui/app_list/views/suggestions_container_view.h"
 #include "ui/app_list/views/test/apps_grid_view_test_api.h"
-#include "ui/app_list/views/tile_item_view.h"
 #include "ui/compositor/layer_animator.h"
 #include "ui/events/event_utils.h"
 #include "ui/views/controls/textfield/textfield.h"
@@ -1031,7 +1030,7 @@
   EXPECT_EQ(results_container->child_at(0), focused_view());
   EXPECT_EQ(tile_views[0], first_result_view);
   EXPECT_FALSE(
-      static_cast<SearchResultTileItemView*>(first_result_view)->selected());
+      static_cast<SearchResultTileItemView*>(first_result_view)->HasFocus());
   EXPECT_TRUE(static_cast<SearchResultView*>(focused_view())->selected());
 }
 
diff --git a/ui/app_list/views/apps_container_view.cc b/ui/app_list/views/apps_container_view.cc
index df566b56c..cdb919e 100644
--- a/ui/app_list/views/apps_container_view.cc
+++ b/ui/app_list/views/apps_container_view.cc
@@ -37,8 +37,7 @@
 
 AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view,
                                      AppListModel* model)
-    : is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()),
-      is_app_list_focus_enabled_(features::IsAppListFocusEnabled()) {
+    : is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()) {
   apps_grid_view_ =
       new AppsGridView(app_list_main_view->contents_view(), nullptr);
   if (is_fullscreen_app_list_enabled_) {
@@ -75,10 +74,7 @@
 
   CreateViewsForFolderTopItemsAnimation(folder_item, true);
 
-  if (is_app_list_focus_enabled_)
-    contents_view()->GetSearchBoxView()->search_box()->RequestFocus();
-  else
-    apps_grid_view_->ClearAnySelectedView();
+  contents_view()->GetSearchBoxView()->search_box()->RequestFocus();
 }
 
 void AppsContainerView::ShowApps(AppListFolderItem* folder_item) {
diff --git a/ui/app_list/views/apps_container_view.h b/ui/app_list/views/apps_container_view.h
index fc66ffbdc..28909aa 100644
--- a/ui/app_list/views/apps_container_view.h
+++ b/ui/app_list/views/apps_container_view.h
@@ -133,9 +133,6 @@
 
   const bool is_fullscreen_app_list_enabled_;
 
-  // Whether the app list focus is enabled.
-  const bool is_app_list_focus_enabled_;
-
   DISALLOW_COPY_AND_ASSIGN(AppsContainerView);
 };
 
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc
index 519d842..e82ca79f 100644
--- a/ui/app_list/views/apps_grid_view.cc
+++ b/ui/app_list/views/apps_grid_view.cc
@@ -37,7 +37,6 @@
 #include "ui/app_list/views/search_box_view.h"
 #include "ui/app_list/views/search_result_tile_item_view.h"
 #include "ui/app_list/views/suggestions_container_view.h"
-#include "ui/app_list/views/tile_item_view.h"
 #include "ui/app_list/views/top_icon_animation_view.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -356,7 +355,6 @@
       contents_view_(contents_view),
       bounds_animator_(this),
       is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()),
-      is_app_list_focus_enabled_(features::IsAppListFocusEnabled()),
       page_flip_delay_in_ms_(is_fullscreen_app_list_enabled_
                                  ? kPageFlipDelayInMsFullscreen
                                  : kPageFlipDelayInMs),
@@ -997,114 +995,18 @@
 }
 
 bool AppsGridView::OnKeyPressed(const ui::KeyEvent& event) {
-  if (is_app_list_focus_enabled_) {
-    // Let the FocusManager handle Left/Right keys.
-    if (!CanProcessUpDownKeyTraversal(event))
-      return false;
-
-    AppListViewState state = contents_view_->app_list_view()->app_list_state();
-    bool arrow_up = event.key_code() == ui::VKEY_UP;
-    if (state == AppListViewState::PEEKING)
-      return HandleFocusMovementInPeekingState(arrow_up);
-
-    DCHECK(state == AppListViewState::FULLSCREEN_ALL_APPS);
-    return HandleFocusMovementInFullscreenAllAppsState(arrow_up);
-  }
-  // TODO(weidongg/766807) Remove everything below when the flag is enabled by
-  // default.
-  bool handled = false;
-  if (suggestions_container_ &&
-      suggestions_container_->selected_index() != -1) {
-    int selected_suggested_index = suggestions_container_->selected_index();
-    handled = suggestions_container_->GetTileItemView(selected_suggested_index)
-                  ->OnKeyPressed(event);
-  }
-
-  if (expand_arrow_view_ && expand_arrow_view_->selected())
-    handled = expand_arrow_view_->OnKeyPressed(event);
-
-  if (selected_view_)
-    handled = static_cast<views::View*>(selected_view_)->OnKeyPressed(event);
-
-  if (!handled) {
-    const int forward_dir = base::i18n::IsRTL() ? -1 : 1;
-    switch (event.key_code()) {
-      case ui::VKEY_LEFT:
-        if (!base::i18n::IsRTL() && is_fullscreen_app_list_enabled_ &&
-            suggestions_container_ &&
-            suggestions_container_->selected_index() == 0) {
-          // Left arrow key moves focus back to search box when
-          // |suggestions_container|'s first app is selected in LTR.
-          ClearAnySelectedView();
-          return false;
-        }
-        MoveSelected(0, -forward_dir, 0);
-        return true;
-      case ui::VKEY_RIGHT:
-        if (base::i18n::IsRTL() && is_fullscreen_app_list_enabled_ &&
-            suggestions_container_ &&
-            suggestions_container_->selected_index() == 0) {
-          // Right arrow key moves focus back to search box when
-          // |suggestions_container|'s first app is selected in RTL.
-          ClearAnySelectedView();
-          return false;
-        }
-
-        MoveSelected(0, forward_dir, 0);
-        return true;
-      case ui::VKEY_UP:
-        if (is_fullscreen_app_list_enabled_ && suggestions_container_ &&
-            suggestions_container_->selected_index() != -1) {
-          // Up arrow key moves focus back to search box when
-          // |suggestions_container| is selected.
-          ClearAnySelectedView();
-          return false;
-        }
-        if (is_fullscreen_app_list_enabled_ || selected_view_) {
-          // Don't initiate selection with UP in non-fullscreen app list. In
-          // fullscreen app list, UP is already handled by SearchBoxView.
-          MoveSelected(0, 0, -1);
-        }
-        return true;
-      case ui::VKEY_DOWN:
-        MoveSelected(0, 0, 1);
-        return true;
-      case ui::VKEY_PRIOR: {
-        MoveSelected(-1, 0, 0);
-        return true;
-      }
-      case ui::VKEY_NEXT: {
-        MoveSelected(1, 0, 0);
-        return true;
-      }
-      case ui::VKEY_TAB: {
-        if (event.IsShiftDown()) {
-          ClearAnySelectedView();  // ContentsView will move focus back.
-        } else {
-          MoveSelected(0, 0, 0);  // Ensure but don't change selection.
-          handled = true;         // TABing internally doesn't move focus.
-        }
-        break;
-      }
-      default:
-        break;
-    }
-  }
-
-  return handled;
-}
-
-bool AppsGridView::OnKeyReleased(const ui::KeyEvent& event) {
-  if (is_app_list_focus_enabled_) {
-    // TODO(weidongg/766807) Remove this function when the flag is enabled by
-    // default.
+  // Let the FocusManager handle Left/Right keys.
+  if (!CanProcessUpDownKeyTraversal(event))
     return false;
-  }
-  bool handled = false;
-  if (selected_view_)
-    handled = selected_view_->OnKeyReleased(event);
 
-  return handled;
+  const AppListViewState state =
+      contents_view_->app_list_view()->app_list_state();
+  const bool arrow_up = event.key_code() == ui::VKEY_UP;
+  if (state == AppListViewState::PEEKING)
+    return HandleFocusMovementInPeekingState(arrow_up);
+
+  DCHECK(state == AppListViewState::FULLSCREEN_ALL_APPS);
+  return HandleFocusMovementInFullscreenAllAppsState(arrow_up);
 }
 
 void AppsGridView::ViewHierarchyChanged(
diff --git a/ui/app_list/views/apps_grid_view.h b/ui/app_list/views/apps_grid_view.h
index 06b94446..a017c2a 100644
--- a/ui/app_list/views/apps_grid_view.h
+++ b/ui/app_list/views/apps_grid_view.h
@@ -142,7 +142,6 @@
   gfx::Size CalculatePreferredSize() const override;
   void Layout() override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
-  bool OnKeyReleased(const ui::KeyEvent& event) override;
   void ViewHierarchyChanged(
       const ViewHierarchyChangedDetails& details) override;
   bool GetDropFormats(
@@ -644,9 +643,6 @@
   // True if the fullscreen app list feature is enabled.
   const bool is_fullscreen_app_list_enabled_;
 
-  // Whether the app list focus is enabled.
-  const bool is_app_list_focus_enabled_;
-
   // Delay in milliseconds of when |page_flip_timer_| should fire after user
   // drags an item near the edges.
   int page_flip_delay_in_ms_;
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc
index a52c81a..b5a2b9bf 100644
--- a/ui/app_list/views/contents_view.cc
+++ b/ui/app_list/views/contents_view.cc
@@ -223,10 +223,6 @@
     app_list_main_view_->search_box_view()->Layout();
     app_list_main_view_->search_box_view()->SetBackButtonLabel(folder_active);
   }
-
-  // Whenever the page changes, the custom launcher page is considered to have
-  // been reset.
-  app_list_main_view_->search_box_view()->ResetTabFocus(false);
 }
 
 void ContentsView::ShowSearchResults(bool show) {
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc
index 3d15260..6c4ce22 100644
--- a/ui/app_list/views/search_box_view.cc
+++ b/ui/app_list/views/search_box_view.cc
@@ -15,7 +15,6 @@
 #include "components/wallpaper/wallpaper_color_profile.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/app_list/app_list_constants.h"
-#include "ui/app_list/app_list_features.h"
 #include "ui/app_list/app_list_switches.h"
 #include "ui/app_list/app_list_util.h"
 #include "ui/app_list/app_list_view_delegate.h"
@@ -170,8 +169,7 @@
 class SearchBoxTextfield : public views::Textfield {
  public:
   explicit SearchBoxTextfield(SearchBoxView* search_box_view)
-      : search_box_view_(search_box_view),
-        is_app_list_focus_enabled_(features::IsAppListFocusEnabled()) {}
+      : search_box_view_(search_box_view) {}
   ~SearchBoxTextfield() override = default;
 
   // Overridden from views::View:
@@ -203,9 +201,6 @@
  private:
   SearchBoxView* const search_box_view_;
 
-  // Whether the app list focus is enabled.
-  const bool is_app_list_focus_enabled_;
-
   DISALLOW_COPY_AND_ASSIGN(SearchBoxTextfield);
 };
 
@@ -217,7 +212,6 @@
       content_container_(new views::View),
       search_box_(new SearchBoxTextfield(this)),
       app_list_view_(app_list_view),
-      is_app_list_focus_enabled_(features::IsAppListFocusEnabled()),
       focused_view_(FOCUS_NONE) {
   SetPaintToLayer();
   layer()->SetFillsBoundsOpaquely(false);
@@ -442,23 +436,6 @@
   return (focused_view_ < FOCUS_CONTENTS_VIEW);
 }
 
-void SearchBoxView::ResetTabFocus(bool on_contents) {
-  if (is_app_list_focus_enabled_) {
-    // TODO(weidongg/766807) Remove this function when the flag is enabled by
-    // default.
-    return;
-  }
-
-  if (back_button_)
-    back_button_->SetSelected(false);
-  if (speech_button_)
-    speech_button_->SetSelected(false);
-  if (close_button_)
-    close_button_->SetSelected(false);
-  SetSelected(false);
-  focused_view_ = on_contents ? FOCUS_CONTENTS_VIEW : FOCUS_NONE;
-}
-
 void SearchBoxView::SetBackButtonLabel(bool folder) {
   if (!back_button_)
     return;
@@ -499,8 +476,6 @@
   UpdateSearchBoxBorder();
   UpdateKeyboardVisibility();
 
-  if (focused_view_ != FOCUS_CONTENTS_VIEW)
-    ResetTabFocus(false);
   content_container_->Layout();
   SchedulePaint();
 }
@@ -748,96 +723,33 @@
   const bool is_trimmed_query_empty = IsSearchBoxTrimmedQueryEmpty();
   // If the query is only whitespace, don't transition the AppListView state.
   app_list_view_->SetStateFromSearchBoxView(is_trimmed_query_empty);
-  // Opened search box is shown when |is_trimmed_query_empty| is false and vice
-  // versa. Set the focus to the search results page when opened search box is
-  // shown. Otherwise, set the focus to search box.
-  ResetTabFocus(!is_trimmed_query_empty);
 }
 
 bool SearchBoxView::HandleKeyEvent(views::Textfield* sender,
                                    const ui::KeyEvent& key_event) {
-  if (is_app_list_focus_enabled_) {
-    if (key_event.type() == ui::ET_KEY_PRESSED &&
-        key_event.key_code() == ui::VKEY_RETURN) {
-      if (!IsSearchBoxTrimmedQueryEmpty()) {
-        // Hitting Enter when focus is on search box opens the first result.
-        ui::KeyEvent event(key_event);
-        views::View* first_result_view =
-            static_cast<ContentsView*>(contents_view_)
-                ->search_results_page_view()
-                ->first_result_view();
-        if (first_result_view)
-          first_result_view->OnKeyEvent(&event);
-        return true;
-      }
-
-      if (!is_search_box_active()) {
-        SetSearchBoxActive(true);
-        return true;
-      }
-      return false;
+  if (key_event.type() == ui::ET_KEY_PRESSED &&
+      key_event.key_code() == ui::VKEY_RETURN) {
+    if (!IsSearchBoxTrimmedQueryEmpty()) {
+      // Hitting Enter when focus is on search box opens the first result.
+      ui::KeyEvent event(key_event);
+      views::View* first_result_view =
+          static_cast<ContentsView*>(contents_view_)
+              ->search_results_page_view()
+              ->first_result_view();
+      if (first_result_view)
+        first_result_view->OnKeyEvent(&event);
+      return true;
     }
 
-    if (CanProcessLeftRightKeyTraversal(key_event))
-      return ProcessLeftRightKeyTraversalForTextfield(search_box_, key_event);
+    if (!is_search_box_active()) {
+      SetSearchBoxActive(true);
+      return true;
+    }
     return false;
   }
-  // TODO(weidongg/766807) Remove everything below when the flag is enabled by
-  // default.
-  if (key_event.type() == ui::ET_KEY_PRESSED) {
-    if (key_event.key_code() == ui::VKEY_TAB &&
-        focused_view_ != FOCUS_CONTENTS_VIEW &&
-        MoveTabFocus(key_event.IsShiftDown()))
-      return true;
 
-    if ((key_event.key_code() == ui::VKEY_LEFT ||
-         key_event.key_code() == ui::VKEY_RIGHT) &&
-        focused_view_ == FOCUS_SEARCH_BOX && !search_box_->text().empty()) {
-      // When focus is on |search_box_| and query is not empty, then left and
-      // arrow key should move cursor in |search_box_|. In this situation only
-      // tab key could move the focus outside |search_box_|.
-      return false;
-    }
-
-    if (IsArrowKey(key_event) && focused_view_ != FOCUS_CONTENTS_VIEW &&
-        MoveArrowFocus(key_event))
-      return true;
-
-    if (focused_view_ == FOCUS_BACK_BUTTON && back_button_ &&
-        back_button_->OnKeyPressed(key_event))
-      return true;
-
-    if (focused_view_ == FOCUS_MIC_BUTTON && speech_button_ &&
-        speech_button_->OnKeyPressed(key_event))
-      return true;
-
-    if (focused_view_ == FOCUS_CLOSE_BUTTON && close_button_ &&
-        close_button_->OnKeyPressed(key_event))
-      return true;
-
-    const bool handled = contents_view_ && contents_view_->visible() &&
-                         contents_view_->OnKeyPressed(key_event);
-
-    return handled;
-  }
-
-  if (key_event.type() == ui::ET_KEY_RELEASED) {
-    if (focused_view_ == FOCUS_BACK_BUTTON && back_button_ &&
-        back_button_->OnKeyReleased(key_event))
-      return true;
-
-    if (focused_view_ == FOCUS_MIC_BUTTON && speech_button_ &&
-        speech_button_->OnKeyReleased(key_event))
-      return true;
-
-    if (focused_view_ == FOCUS_CLOSE_BUTTON && close_button_ &&
-        close_button_->OnKeyReleased(key_event))
-      return true;
-
-    return contents_view_ && contents_view_->visible() &&
-           contents_view_->OnKeyReleased(key_event);
-  }
-
+  if (CanProcessLeftRightKeyTraversal(key_event))
+    return ProcessLeftRightKeyTraversalForTextfield(search_box_, key_event);
   return false;
 }
 
diff --git a/ui/app_list/views/search_box_view.h b/ui/app_list/views/search_box_view.h
index 71c1b7db..31be1bf2 100644
--- a/ui/app_list/views/search_box_view.h
+++ b/ui/app_list/views/search_box_view.h
@@ -86,9 +86,6 @@
   // Moves focus forward/backwards in response to TAB.
   bool MoveTabFocus(bool move_backwards);
 
-  // Moves focus to contents or SearchBox and unselects buttons.
-  void ResetTabFocus(bool on_contents);
-
   // Sets voice label for Back button depending on whether a folder is open.
   void SetBackButtonLabel(bool folder);
 
@@ -244,9 +241,6 @@
   // Owned by |content_container_|. It is deleted when the view is deleted.
   views::BoxLayout* box_layout_ = nullptr;
 
-  // Whether the app list focus is enabled.
-  const bool is_app_list_focus_enabled_;
-
   SearchBoxFocus focused_view_;  // Which element has TAB'd focus.
 
   // Whether the search box is active.
diff --git a/ui/app_list/views/search_result_tile_item_list_view.cc b/ui/app_list/views/search_result_tile_item_list_view.cc
index 5b87124..fdd2813 100644
--- a/ui/app_list/views/search_result_tile_item_list_view.cc
+++ b/ui/app_list/views/search_result_tile_item_list_view.cc
@@ -65,8 +65,7 @@
     }
 
     SearchResultTileItemView* tile_item = new SearchResultTileItemView(
-        this, view_delegate, nullptr, false /* Not a suggested app */,
-        is_play_store_app_search_enabled_);
+        this, view_delegate, nullptr /* pagination model */);
     tile_item->SetParentBackgroundColor(kCardBackgroundColor);
     tile_views_.push_back(tile_item);
     AddChildView(tile_item);
@@ -107,12 +106,9 @@
   return num_results() <= 0 ? nullptr : tile_views_[0];
 }
 
-void SearchResultTileItemListView::SetFirstResultSelected(bool selected) {
-  DCHECK(!tile_views_.empty());
-  if (num_results() <= 0)
-    return;
-  tile_views_[0]->SetSelected(selected);
-}
+// TODO(warx): This implementation is deprecated and should be removed as part
+// of removing "pseudo-focus" logic work (https://crbug.com/766807).
+void SearchResultTileItemListView::SetFirstResultSelected(bool selected) {}
 
 int SearchResultTileItemListView::DoUpdate() {
   std::vector<SearchResult*> display_results =
@@ -154,16 +150,10 @@
   return display_results.size();
 }
 
+// TODO(warx): This implementation is deprecated and should be removed as part
+// of removing "pseudo-focus" logic work (https://crbug.com/766807).
 void SearchResultTileItemListView::UpdateSelectedIndex(int old_selected,
-                                                       int new_selected) {
-  if (old_selected >= 0)
-    tile_views_[old_selected]->SetSelected(false);
-
-  if (new_selected >= 0) {
-    tile_views_[new_selected]->SetSelected(true);
-    ScrollRectToVisible(GetLocalBounds());
-  }
-}
+                                                       int new_selected) {}
 
 bool SearchResultTileItemListView::OnKeyPressed(const ui::KeyEvent& event) {
   // Let the FocusManager handle Left/Right keys.
diff --git a/ui/app_list/views/search_result_tile_item_view.cc b/ui/app_list/views/search_result_tile_item_view.cc
index 64646ee..2c0cb56 100644
--- a/ui/app_list/views/search_result_tile_item_view.cc
+++ b/ui/app_list/views/search_result_tile_item_view.cc
@@ -11,11 +11,15 @@
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/app_list/app_list_constants.h"
+#include "ui/app_list/app_list_features.h"
 #include "ui/app_list/app_list_view_delegate.h"
 #include "ui/app_list/pagination_model.h"
 #include "ui/app_list/vector_icons/vector_icons.h"
 #include "ui/app_list/views/search_result_container_view.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/image/canvas_image_source.h"
+#include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
@@ -37,6 +41,11 @@
 constexpr int kSearchRatingStarHorizontalSpacing = 1;
 constexpr int kSearchRatingStarVerticalSpacing = 2;
 
+constexpr int kIconSelectedSize = 56;
+constexpr int kIconSelectedCornerRadius = 4;
+// Icon selected color, #000 8%.
+constexpr int kIconSelectedColor = SkColorSetARGBMacro(0x14, 0x00, 0x00, 0x00);
+
 constexpr SkColor kSearchTitleColor =
     SkColorSetARGBMacro(0xDF, 0x00, 0x00, 0x00);
 constexpr SkColor kSearchAppRatingColor =
@@ -46,23 +55,71 @@
 constexpr SkColor kSearchRatingStarColor =
     SkColorSetARGBMacro(0x8F, 0x00, 0x00, 0x00);
 
+// The background image source for badge.
+class BadgeBackgroundImageSource : public gfx::CanvasImageSource {
+ public:
+  explicit BadgeBackgroundImageSource(int size)
+      : CanvasImageSource(gfx::Size(size, size), false),
+        radius_(static_cast<float>(size / 2)) {}
+  ~BadgeBackgroundImageSource() override = default;
+
+ private:
+  // gfx::CanvasImageSource overrides:
+  void Draw(gfx::Canvas* canvas) override {
+    cc::PaintFlags flags;
+    flags.setColor(SK_ColorWHITE);
+    flags.setAntiAlias(true);
+    flags.setStyle(cc::PaintFlags::kFill_Style);
+    canvas->DrawCircle(gfx::PointF(radius_, radius_), radius_, flags);
+  }
+
+  const float radius_;
+
+  DISALLOW_COPY_AND_ASSIGN(BadgeBackgroundImageSource);
+};
+
 }  // namespace
 
 SearchResultTileItemView::SearchResultTileItemView(
     SearchResultContainerView* result_container,
     AppListViewDelegate* view_delegate,
-    PaginationModel* pagination_model,
-    bool is_suggested_app,
-    bool is_play_store_search_enabled)
-    : is_suggested_app_(is_suggested_app),
+    PaginationModel* pagination_model)
+    : views::Button(this),
       result_container_(result_container),
       view_delegate_(view_delegate),
-      pagination_model_(pagination_model) {
+      pagination_model_(pagination_model),
+      is_play_store_app_search_enabled_(
+          features::IsPlayStoreAppSearchEnabled()) {
+  SetFocusBehavior(FocusBehavior::ALWAYS);
+
   // When |item_| is null, the tile is invisible. Calling SetSearchResult with a
   // non-null item makes the tile visible.
   SetVisible(false);
 
-  if (is_play_store_search_enabled) {
+  // Prevent the icon view from interfering with our mouse events.
+  icon_ = new views::ImageView;
+  icon_->set_can_process_events_within_subtree(false);
+  icon_->SetVerticalAlignment(views::ImageView::LEADING);
+  AddChildView(icon_);
+
+  if (is_play_store_app_search_enabled_) {
+    badge_ = new views::ImageView;
+    badge_->set_can_process_events_within_subtree(false);
+    badge_->SetVerticalAlignment(views::ImageView::LEADING);
+    badge_->SetVisible(false);
+    AddChildView(badge_);
+  }
+
+  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+  title_ = new views::Label;
+  title_->SetAutoColorReadabilityEnabled(false);
+  title_->SetEnabledColor(kGridTitleColor);
+  title_->SetFontList(rb.GetFontList(kItemTextFontStyle));
+  title_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+  title_->SetHandlesTooltips(false);
+  AddChildView(title_);
+
+  if (is_play_store_app_search_enabled_) {
     const gfx::FontList& font = AppListAppTitleFont();
     rating_ = new views::Label;
     rating_->SetEnabledColor(kSearchAppRatingColor);
@@ -120,13 +177,12 @@
   SetPrice(item_->formatted_price());
 
   const gfx::FontList& font = AppListAppTitleFont();
-  if (item_->display_type() == SearchResult::DISPLAY_RECOMMENDATION) {
-    set_is_recommendation(true);
-
-    title()->SetFontList(font);
-    title()->SetLineHeight(font.GetHeight());
-    title()->SetEnabledColor(kGridTitleColor);
-  } else if (item_->display_type() == SearchResult::DISPLAY_TILE) {
+  if (IsSuggestedAppTile()) {
+    title_->SetFontList(font);
+    title_->SetLineHeight(font.GetHeight());
+    title_->SetEnabledColor(kGridTitleColor);
+  } else {
+    DCHECK_EQ(SearchResult::DISPLAY_TILE, item_->display_type());
     // Set solid color background to avoid broken text. See crbug.com/746563.
     if (rating_) {
       rating_->SetBackground(
@@ -135,16 +191,16 @@
     if (price_) {
       price_->SetBackground(views::CreateSolidBackground(kCardBackgroundColor));
     }
-    title()->SetBackground(views::CreateSolidBackground(kCardBackgroundColor));
-    title()->SetFontList(font);
-    title()->SetLineHeight(font.GetHeight());
-    title()->SetEnabledColor(kSearchTitleColor);
+    title_->SetBackground(views::CreateSolidBackground(kCardBackgroundColor));
+    title_->SetFontList(font);
+    title_->SetLineHeight(font.GetHeight());
+    title_->SetEnabledColor(kSearchTitleColor);
   }
 
-  title()->SetMaxLines(2);
-  title()->SetMultiLine(item_->display_type() == SearchResult::DISPLAY_TILE &&
-                        item_->result_type() ==
-                            SearchResult::RESULT_INSTALLED_APP);
+  title_->SetMaxLines(2);
+  title_->SetMultiLine(item_->display_type() == SearchResult::DISPLAY_TILE &&
+                       item_->result_type() ==
+                           SearchResult::RESULT_INSTALLED_APP);
 
   // Only refresh the icon if it's different from the old one. This prevents
   // flickering.
@@ -159,7 +215,7 @@
     OnBadgeIconChanged();
   }
 
-  base::string16 accessible_name = title()->text();
+  base::string16 accessible_name = title_->text();
   if (rating_ && rating_->visible()) {
     accessible_name +=
         base::UTF8ToUTF16(", ") +
@@ -171,54 +227,40 @@
   SetAccessibleName(accessible_name);
 }
 
-void SearchResultTileItemView::SetRating(float rating) {
-  if (!rating_)
-    return;
-
-  if (rating < 0) {
-    rating_->SetVisible(false);
-    rating_star_->SetVisible(false);
-    return;
-  }
-
-  rating_->SetText(base::FormatDouble(rating, 1));
-  rating_->SetVisible(true);
-  rating_star_->SetVisible(true);
-}
-
-void SearchResultTileItemView::SetPrice(const base::string16& price) {
-  if (!price_)
-    return;
-
-  if (price.empty()) {
-    price_->SetVisible(false);
-    return;
-  }
-
-  price_->SetText(price);
-  price_->SetVisible(true);
-}
-
-void SearchResultTileItemView::LogAppLaunch() const {
-  // Only log the app launch if the class is being used as a suggested app.
-  if (!is_suggested_app_)
-    return;
-
-  UMA_HISTOGRAM_BOOLEAN(kAppListAppLaunchedFullscreen, is_suggested_app_);
-  base::RecordAction(base::UserMetricsAction("AppList_OpenSuggestedApp"));
+void SearchResultTileItemView::SetParentBackgroundColor(SkColor color) {
+  parent_background_color_ = color;
+  UpdateBackgroundColor();
 }
 
 void SearchResultTileItemView::ButtonPressed(views::Button* sender,
                                              const ui::Event& event) {
-  if (is_suggested_app_)
+  if (IsSuggestedAppTile())
     LogAppLaunch();
 
   view_delegate_->OpenSearchResult(item_, false, event.flags());
 }
 
+void SearchResultTileItemView::GetAccessibleNodeData(
+    ui::AXNodeData* node_data) {
+  views::Button::GetAccessibleNodeData(node_data);
+  // Specify |ui::AX_ATTR_DESCRIPTION| with an empty string, so that long
+  // truncated names are not read twice.
+  // Details of this issue:
+  // - The Play Store app's name is shown in a label |title_|.
+  // - If the name is too long, it'll get truncated and the full name will
+  //   go to the label's tooltip.
+  // - SearchResultTileItemView uses that label's tooltip as its tooltip.
+  // - If a view doesn't have |ui::AX_ATTR_DESCRIPTION| defined in the
+  //   |AXNodeData|, |AXViewObjWrapper::Serialize| will use the tooltip text
+  //   as its description.
+  // - We're customizing this view's accessible name, so it get focused
+  //   ChromeVox will read its accessible name and then its description.
+  node_data->AddStringAttribute(ui::AX_ATTR_DESCRIPTION, "");
+}
+
 bool SearchResultTileItemView::OnKeyPressed(const ui::KeyEvent& event) {
   if (event.key_code() == ui::VKEY_RETURN) {
-    if (is_suggested_app_)
+    if (IsSuggestedAppTile())
       LogAppLaunch();
 
     view_delegate_->OpenSearchResult(item_, false, event.flags());
@@ -229,14 +271,45 @@
 }
 
 void SearchResultTileItemView::OnFocus() {
-  if (pagination_model_ && is_recommendation() &&
+  if (pagination_model_ && IsSuggestedAppTile() &&
       view_delegate_->GetModel()->state() == AppListModel::STATE_APPS) {
     // Go back to first page when app in suggestions container is focused.
     pagination_model_->SelectPage(0, false);
-  } else if (!is_recommendation()) {
+  } else if (!IsSuggestedAppTile()) {
     ScrollRectToVisible(GetLocalBounds());
   }
-  TileItemView::OnFocus();
+  UpdateBackgroundColor();
+}
+
+void SearchResultTileItemView::OnBlur() {
+  UpdateBackgroundColor();
+}
+
+void SearchResultTileItemView::StateChanged(ButtonState old_state) {
+  UpdateBackgroundColor();
+}
+
+void SearchResultTileItemView::PaintButtonContents(gfx::Canvas* canvas) {
+  if (!item_ || !HasFocus())
+    return;
+
+  gfx::Rect rect(GetContentsBounds());
+  cc::PaintFlags flags;
+  flags.setAntiAlias(true);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  if (IsSuggestedAppTile()) {
+    rect.Inset((rect.width() - kGridSelectedSize) / 2,
+               (rect.height() - kGridSelectedSize) / 2);
+    flags.setColor(kGridSelectedColor);
+    canvas->DrawRoundRect(gfx::RectF(rect), kGridSelectedCornerRadius, flags);
+  } else {
+    DCHECK(item_->display_type() == SearchResult::DISPLAY_TILE);
+    const int kLeftRightPadding = (rect.width() - kIconSelectedSize) / 2;
+    rect.Inset(kLeftRightPadding, 0);
+    rect.set_height(kIconSelectedSize);
+    flags.setColor(kIconSelectedColor);
+    canvas->DrawRoundRect(gfx::RectF(rect), kIconSelectedCornerRadius, flags);
+  }
 }
 
 void SearchResultTileItemView::OnIconChanged() {
@@ -279,7 +352,8 @@
   if (!menu_model)
     return;
 
-  if (!selected())
+  // TODO(warx): This is broken (https://crbug.com/795994).
+  if (!HasFocus())
     result_container_->ClearSelectedIndex();
 
   context_menu_runner_.reset(
@@ -289,45 +363,124 @@
                                   views::MENU_ANCHOR_TOPLEFT, source_type);
 }
 
-void SearchResultTileItemView::Layout() {
-  gfx::Rect rect(GetContentsBounds());
-  if (rect.IsEmpty())
+void SearchResultTileItemView::SetIcon(const gfx::ImageSkia& icon) {
+  icon_->SetImage(icon);
+}
+
+void SearchResultTileItemView::SetBadgeIcon(const gfx::ImageSkia& badge_icon) {
+  if (!badge_)
     return;
 
-  if (!item_) {
-    TileItemView::Layout();
+  if (badge_icon.isNull()) {
+    badge_->SetVisible(false);
     return;
   }
 
-  if (item_->display_type() == SearchResult::DISPLAY_RECOMMENDATION) {
+  const int size = kBadgeBackgroundRadius * 2;
+  gfx::ImageSkia background(std::make_unique<BadgeBackgroundImageSource>(size),
+                            gfx::Size(size, size));
+  gfx::ImageSkia icon_with_background =
+      gfx::ImageSkiaOperations::CreateSuperimposedImage(background, badge_icon);
+
+  gfx::ShadowValues shadow_values;
+  shadow_values.push_back(
+      gfx::ShadowValue(gfx::Vector2d(0, 1), 0, SkColorSetARGB(0x33, 0, 0, 0)));
+  shadow_values.push_back(
+      gfx::ShadowValue(gfx::Vector2d(0, 1), 2, SkColorSetARGB(0x33, 0, 0, 0)));
+  badge_->SetImage(gfx::ImageSkiaOperations::CreateImageWithDropShadow(
+      icon_with_background, shadow_values));
+  badge_->SetVisible(true);
+}
+
+void SearchResultTileItemView::SetTitle(const base::string16& title) {
+  title_->SetText(title);
+}
+
+void SearchResultTileItemView::SetRating(float rating) {
+  if (!rating_)
+    return;
+
+  if (rating < 0) {
+    rating_->SetVisible(false);
+    rating_star_->SetVisible(false);
+    return;
+  }
+
+  rating_->SetText(base::FormatDouble(rating, 1));
+  rating_->SetVisible(true);
+  rating_star_->SetVisible(true);
+}
+
+void SearchResultTileItemView::SetPrice(const base::string16& price) {
+  if (!price_)
+    return;
+
+  if (price.empty()) {
+    price_->SetVisible(false);
+    return;
+  }
+
+  price_->SetText(price);
+  price_->SetVisible(true);
+}
+
+bool SearchResultTileItemView::IsSuggestedAppTile() const {
+  return item_ && item_->display_type() == SearchResult::DISPLAY_RECOMMENDATION;
+}
+
+void SearchResultTileItemView::LogAppLaunch() const {
+  // Only log the app launch if the class is being used as a suggested app.
+  if (!IsSuggestedAppTile())
+    return;
+
+  UMA_HISTOGRAM_BOOLEAN(kAppListAppLaunchedFullscreen,
+                        true /* suggested app */);
+  base::RecordAction(base::UserMetricsAction("AppList_OpenSuggestedApp"));
+}
+
+void SearchResultTileItemView::UpdateBackgroundColor() {
+  // Tell the label what color it will be drawn onto. It will use whether the
+  // background color is opaque or transparent to decide whether to use subpixel
+  // rendering. Does not actually set the label's background color.
+  title_->SetBackgroundColor(parent_background_color_);
+  SchedulePaint();
+}
+
+void SearchResultTileItemView::Layout() {
+  gfx::Rect rect(GetContentsBounds());
+  if (rect.IsEmpty() || !item_)
+    return;
+
+  if (IsSuggestedAppTile()) {
     rect.Inset(0, kGridIconTopPadding, 0, 0);
-    icon()->SetBoundsRect(rect);
+    icon_->SetBoundsRect(rect);
 
     rect.Inset(kGridTitleHorizontalPadding,
                kGridIconDimension + kGridTitleSpacing,
                kGridTitleHorizontalPadding, 0);
-    rect.set_height(title()->GetPreferredSize().height());
-    title()->SetBoundsRect(rect);
-  } else if (item_->display_type() == SearchResult::DISPLAY_TILE) {
+    rect.set_height(title_->GetPreferredSize().height());
+    title_->SetBoundsRect(rect);
+  } else {
+    DCHECK(item_->display_type() == SearchResult::DISPLAY_TILE);
     rect.Inset(0, kSearchTileTopPadding, 0, 0);
-    icon()->SetBoundsRect(rect);
+    icon_->SetBoundsRect(rect);
 
-    if (badge()) {
+    if (badge_) {
       gfx::Rect badge_rect(rect);
-      gfx::Size icon_size = icon()->GetImage().size();
+      gfx::Size icon_size = icon_->GetImage().size();
       badge_rect.Offset(
           (icon_size.width() - kAppBadgeIconSize) / 2,
           icon_size.height() - kBadgeBackgroundRadius - kAppBadgeIconSize / 2);
-      badge()->SetBoundsRect(badge_rect);
+      badge_->SetBoundsRect(badge_rect);
     }
 
     rect.Inset(0, kGridIconDimension + kSearchTitleSpacing, 0, 0);
-    rect.set_height(title()->GetPreferredSize().height());
-    title()->SetBoundsRect(rect);
+    rect.set_height(title_->GetPreferredSize().height());
+    title_->SetBoundsRect(rect);
 
     if (rating_) {
       gfx::Rect rating_rect(rect);
-      rating_rect.Inset(0, title()->GetPreferredSize().height(), 0, 0);
+      rating_rect.Inset(0, title_->GetPreferredSize().height(), 0, 0);
       rating_rect.set_size(rating_->GetPreferredSize());
       rating_rect.set_width(kSearchRatingSize);
       rating_->SetBoundsRect(rating_rect);
@@ -337,7 +490,7 @@
       gfx::Rect rating_star_rect(rect);
       rating_star_rect.Inset(
           kSearchRatingSize + kSearchRatingStarHorizontalSpacing,
-          title()->GetPreferredSize().height() +
+          title_->GetPreferredSize().height() +
               kSearchRatingStarVerticalSpacing,
           0, 0);
       rating_star_rect.set_size(rating_star_->GetPreferredSize());
@@ -347,42 +500,38 @@
     if (price_) {
       gfx::Rect price_rect(rect);
       price_rect.Inset(rect.width() - kSearchPriceSize,
-                       title()->GetPreferredSize().height(), 0, 0);
+                       title_->GetPreferredSize().height(), 0, 0);
       price_rect.set_size(price_->GetPreferredSize());
       price_->SetBoundsRect(price_rect);
     }
-  } else {
-    TileItemView::Layout();
   }
 }
 
+const char* SearchResultTileItemView::GetClassName() const {
+  return "SearchResultTileItemView";
+}
+
 gfx::Size SearchResultTileItemView::CalculatePreferredSize() const {
-  if (item_) {
-    if (item_->display_type() == SearchResult::DISPLAY_RECOMMENDATION)
-      return gfx::Size(kGridTileWidth, kGridTileHeight);
-    if (item_->display_type() == SearchResult::DISPLAY_TILE)
-      return gfx::Size(kSearchTileWidth, kSearchTileHeight);
-  }
+  if (!item_)
+    return gfx::Size();
 
-  return TileItemView::CalculatePreferredSize();
+  if (IsSuggestedAppTile())
+    return gfx::Size(kGridTileWidth, kGridTileHeight);
+
+  DCHECK(item_->display_type() == SearchResult::DISPLAY_TILE);
+  return gfx::Size(kSearchTileWidth, kSearchTileHeight);
 }
 
-void SearchResultTileItemView::GetAccessibleNodeData(
-    ui::AXNodeData* node_data) {
-  TileItemView::GetAccessibleNodeData(node_data);
-  // Specify |ui::AX_ATTR_DESCRIPTION| with an empty string, so that long
-  // truncated names are not read twice.
-  // Details of this issue:
-  // - The Play Store app's name is shown in a label |TileItemView::title_|.
-  // - If the name is too long, it'll get truncated and the full name will
-  //   go to the label's tooltip.
-  // - |app_list::TileItemView| uses that label's tooltip as its tooltip.
-  // - If a view doesn't have |ui::AX_ATTR_DESCRIPTION| defined in the
-  //   |AXNodeData|, |AXViewObjWrapper::Serialize| will use the tooltip text
-  //   as its description.
-  // - We're customizing this view's accessible name, so it get focused
-  //   ChromeVox will read its accessible name and then its description.
-  node_data->AddStringAttribute(ui::AX_ATTR_DESCRIPTION, "");
+bool SearchResultTileItemView::GetTooltipText(const gfx::Point& p,
+                                              base::string16* tooltip) const {
+  // Use the label to generate a tooltip, so that it will consider its text
+  // truncation in making the tooltip. We do not want the label itself to have a
+  // tooltip, so we only temporarily enable it to get the tooltip text from the
+  // label, then disable it again.
+  title_->SetHandlesTooltips(true);
+  bool handled = title_->GetTooltipText(p, tooltip);
+  title_->SetHandlesTooltips(false);
+  return handled;
 }
 
 }  // namespace app_list
diff --git a/ui/app_list/views/search_result_tile_item_view.h b/ui/app_list/views/search_result_tile_item_view.h
index 24d4ff5..d41fe4b 100644
--- a/ui/app_list/views/search_result_tile_item_view.h
+++ b/ui/app_list/views/search_result_tile_item_view.h
@@ -9,10 +9,12 @@
 
 #include "ash/app_list/model/search/search_result_observer.h"
 #include "base/macros.h"
-#include "ui/app_list/views/tile_item_view.h"
+#include "ui/app_list/app_list_export.h"
 #include "ui/views/context_menu_controller.h"
+#include "ui/views/controls/button/button.h"
 
 namespace views {
+class ImageView;
 class MenuRunner;
 class Label;
 }  // namespace views
@@ -24,27 +26,37 @@
 class SearchResultContainerView;
 class PaginationModel;
 
-// A TileItemView that displays a search result.
+// A tile view that displays a search result. It hosts view for search result
+// that has SearchResult::DisplayType DISPLAY_TILE or DISPLAY_RECOMMENDATION.
 class APP_LIST_EXPORT SearchResultTileItemView
-    : public TileItemView,
+    : public views::Button,
+      public views::ButtonListener,
       public views::ContextMenuController,
       public SearchResultObserver {
  public:
   SearchResultTileItemView(SearchResultContainerView* result_container,
                            AppListViewDelegate* view_delegate,
-                           PaginationModel* pagination_model,
-                           bool is_suggested_app,
-                           bool is_play_store_search_enabled);
+                           PaginationModel* pagination_model);
   ~SearchResultTileItemView() override;
 
   SearchResult* result() { return item_; }
   void SetSearchResult(SearchResult* item);
 
-  // Overridden from TileItemView:
+  // Informs the SearchResultTileItemView of its parent's background color. The
+  // controls within the SearchResultTileItemView will adapt to suit the given
+  // color.
+  void SetParentBackgroundColor(SkColor color);
+
+  // Overridden from views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+
+  // Overridden from views::Button:
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
   void OnFocus() override;
+  void OnBlur() override;
+  void StateChanged(ButtonState old_state) override;
+  void PaintButtonContents(gfx::Canvas* canvas) override;
 
   // Overridden from SearchResultObserver:
   void OnIconChanged() override;
@@ -59,38 +71,47 @@
                               ui::MenuSourceType source_type) override;
 
  private:
-  // Shows rating in proper format if |rating| is not negative. Otherwise, hides
-  // the rating label.
+  void SetIcon(const gfx::ImageSkia& icon);
+  void SetBadgeIcon(const gfx::ImageSkia& badge_icon);
+  void SetTitle(const base::string16& title);
   void SetRating(float rating);
-
-  // Shows price if |price| is not empty. Otherwise, hides the price label.
   void SetPrice(const base::string16& price);
 
+  // Whether the tile view is a suggested app.
+  bool IsSuggestedAppTile() const;
+
   // Records an app being launched.
   void LogAppLaunch() const;
 
+  void UpdateBackgroundColor();
+
   // Overridden from views::View:
   void Layout() override;
+  const char* GetClassName() const override;
   gfx::Size CalculatePreferredSize() const override;
+  bool GetTooltipText(const gfx::Point& p,
+                      base::string16* tooltip) const override;
 
-  // Whether the tile item view is a suggested app.
-  const bool is_suggested_app_;
-
-  SearchResultContainerView* result_container_;  // Parent view
+  SearchResultContainerView* const result_container_;  // Parent view
+  AppListViewDelegate* const view_delegate_;           // Owned by AppListView.
+  PaginationModel* const pagination_model_;            // Owned by AppsGridView.
 
   // Owned by the model provided by the AppListViewDelegate.
   SearchResult* item_ = nullptr;
 
+  views::ImageView* icon_ = nullptr;         // Owned by views hierarchy.
+  views::ImageView* badge_ = nullptr;        // Owned by views hierarchy.
+  views::Label* title_ = nullptr;            // Owned by views hierarchy.
   views::Label* rating_ = nullptr;           // Owned by views hierarchy.
   views::Label* price_ = nullptr;            // Owned by views hierarchy.
   views::ImageView* rating_star_ = nullptr;  // Owned by views hierarchy.
 
-  AppListViewDelegate* view_delegate_;
-
-  PaginationModel* const pagination_model_;  // Owned by AppsGridView.
+  SkColor parent_background_color_ = SK_ColorTRANSPARENT;
 
   std::unique_ptr<views::MenuRunner> context_menu_runner_;
 
+  const bool is_play_store_app_search_enabled_;
+
   DISALLOW_COPY_AND_ASSIGN(SearchResultTileItemView);
 };
 
diff --git a/ui/app_list/views/search_result_view.cc b/ui/app_list/views/search_result_view.cc
index 2aa2eafc..6cbbf784 100644
--- a/ui/app_list/views/search_result_view.cc
+++ b/ui/app_list/views/search_result_view.cc
@@ -10,7 +10,6 @@
 #include "ash/app_list/model/search/search_result.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/app_list/app_list_constants.h"
-#include "ui/app_list/app_list_features.h"
 #include "ui/app_list/app_list_switches.h"
 #include "ui/app_list/views/search_result_actions_view.h"
 #include "ui/app_list/views/search_result_list_view.h"
@@ -61,8 +60,7 @@
       icon_(new views::ImageView),
       badge_icon_(new views::ImageView),
       actions_view_(new SearchResultActionsView(this)),
-      progress_bar_(new views::ProgressBar),
-      is_app_list_focus_enabled_(features::IsAppListFocusEnabled()) {
+      progress_bar_(new views::ProgressBar) {
   SetFocusBehavior(FocusBehavior::ALWAYS);
   icon_->set_can_process_events_within_subtree(false);
   badge_icon_->set_can_process_events_within_subtree(false);
@@ -250,16 +248,6 @@
     return false;
 
   switch (event.key_code()) {
-    case ui::VKEY_TAB: {
-      if (is_app_list_focus_enabled_) {
-        // Let FocusManager handle default focus move.
-        return false;
-      }
-      int new_selected =
-          actions_view_->selected_action() + (event.IsShiftDown() ? -1 : 1);
-      actions_view_->SetSelectedAction(new_selected);
-      return actions_view_->IsValidActionIndex(new_selected);
-    }
     case ui::VKEY_RETURN: {
       int selected = actions_view_->selected_action();
       if (actions_view_->IsValidActionIndex(selected)) {
@@ -307,10 +295,8 @@
 
   // Possibly call FillRect a second time (these colours are partially
   // transparent, so the previous FillRect is not redundant).
-  if (is_app_list_focus_enabled_ ? selected()
-                                 : list_view_->IsResultViewSelected(this)) {
+  if (selected())
     canvas->FillRect(content_rect, kRowSelectedColor);
-  }
 
   gfx::Rect border_bottom = gfx::SubtractRects(rect, content_rect);
   canvas->FillRect(border_bottom, kResultBorderColor);
diff --git a/ui/app_list/views/search_result_view.h b/ui/app_list/views/search_result_view.h
index 1637982..a09708d1 100644
--- a/ui/app_list/views/search_result_view.h
+++ b/ui/app_list/views/search_result_view.h
@@ -134,9 +134,6 @@
   // Whether this view is selected.
   bool selected_ = false;
 
-  // Whether the app list focus is enabled.
-  const bool is_app_list_focus_enabled_;
-
   DISALLOW_COPY_AND_ASSIGN(SearchResultView);
 };
 
diff --git a/ui/app_list/views/suggestions_container_view.cc b/ui/app_list/views/suggestions_container_view.cc
index 07890ae..6a991a2 100644
--- a/ui/app_list/views/suggestions_container_view.cc
+++ b/ui/app_list/views/suggestions_container_view.cc
@@ -30,12 +30,6 @@
 
 SuggestionsContainerView::~SuggestionsContainerView() = default;
 
-TileItemView* SuggestionsContainerView::GetTileItemView(int index) {
-  DCHECK_GT(num_results(), index);
-
-  return search_result_tile_views_[index];
-}
-
 int SuggestionsContainerView::DoUpdate() {
   // Ignore updates and disable buttons when suggestions container view is not
   // shown.
@@ -76,13 +70,7 @@
 }
 
 void SuggestionsContainerView::UpdateSelectedIndex(int old_selected,
-                                                   int new_selected) {
-  if (old_selected >= 0 && old_selected < num_results())
-    GetTileItemView(old_selected)->SetSelected(false);
-
-  if (new_selected >= 0 && new_selected < num_results())
-    GetTileItemView(new_selected)->SetSelected(true);
-}
+                                                   int new_selected) {}
 
 void SuggestionsContainerView::OnContainerSelected(
     bool /*from_bottom*/,
@@ -127,19 +115,14 @@
   // Add SearchResultTileItemViews to the container.
   int i = 0;
   search_result_tile_views_.reserve(apps_num);
-  const bool is_play_store_app_search_enabled =
-      features::IsPlayStoreAppSearchEnabled();
   tiles_layout_manager->StartRow(0, 0);
   DCHECK_LE(apps_num, kNumStartPageTiles);
   for (; i < apps_num; ++i) {
-    SearchResultTileItemView* tile_item = new SearchResultTileItemView(
-        this, view_delegate_, pagination_model_, true,
-
-        is_play_store_app_search_enabled);
+    SearchResultTileItemView* tile_item =
+        new SearchResultTileItemView(this, view_delegate_, pagination_model_);
     tiles_layout_manager->AddView(tile_item);
     AddChildView(tile_item);
     tile_item->SetParentBackgroundColor(kLabelBackgroundColor);
-    tile_item->SetHoverStyle(TileItemView::HOVER_STYLE_ANIMATE_SHADOW);
     search_result_tile_views_.emplace_back(tile_item);
   }
 }
diff --git a/ui/app_list/views/suggestions_container_view.h b/ui/app_list/views/suggestions_container_view.h
index 00afaf61..a095aab 100644
--- a/ui/app_list/views/suggestions_container_view.h
+++ b/ui/app_list/views/suggestions_container_view.h
@@ -16,7 +16,6 @@
 class ContentsView;
 class PaginationModel;
 class SearchResultTileItemView;
-class TileItemView;
 
 // A container that holds the suggested app tiles. If fullscreen app list is not
 // enabled, it also holds the all apps button.
@@ -26,8 +25,6 @@
                            PaginationModel* pagination_model);
   ~SuggestionsContainerView() override;
 
-  TileItemView* GetTileItemView(int index);
-
   const std::vector<SearchResultTileItemView*>& tile_views() const {
     return search_result_tile_views_;
   }
diff --git a/ui/app_list/views/tile_item_view.cc b/ui/app_list/views/tile_item_view.cc
deleted file mode 100644
index 843140b..0000000
--- a/ui/app_list/views/tile_item_view.cc
+++ /dev/null
@@ -1,241 +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 "ui/app_list/views/tile_item_view.h"
-
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "ui/app_list/app_list_constants.h"
-#include "ui/app_list/app_list_features.h"
-#include "ui/app_list/views/app_list_main_view.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/image/canvas_image_source.h"
-#include "ui/gfx/image/image_skia_operations.h"
-#include "ui/views/background.h"
-#include "ui/views/controls/image_view.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/layout/box_layout.h"
-
-namespace {
-
-constexpr int kTopPadding = 5;
-constexpr int kTileSize = 90;
-constexpr int kIconTitleSpacing = 6;
-
-constexpr int kIconSelectedSize = 56;
-constexpr int kIconSelectedCornerRadius = 4;
-// Icon selected color, #000 8%.
-constexpr int kIconSelectedColor = SkColorSetARGBMacro(0x14, 0x00, 0x00, 0x00);
-
-// The background image source for badge.
-class BadgeBackgroundImageSource : public gfx::CanvasImageSource {
- public:
-  explicit BadgeBackgroundImageSource(int size)
-      : CanvasImageSource(gfx::Size(size, size), false),
-        radius_(static_cast<float>(size / 2)) {}
-  ~BadgeBackgroundImageSource() override = default;
-
- private:
-  // gfx::CanvasImageSource overrides:
-  void Draw(gfx::Canvas* canvas) override {
-    cc::PaintFlags flags;
-    flags.setColor(SK_ColorWHITE);
-    flags.setAntiAlias(true);
-    flags.setStyle(cc::PaintFlags::kFill_Style);
-    canvas->DrawCircle(gfx::PointF(radius_, radius_), radius_, flags);
-  }
-
-  const float radius_;
-
-  DISALLOW_COPY_AND_ASSIGN(BadgeBackgroundImageSource);
-};
-
-}  // namespace
-
-namespace app_list {
-
-TileItemView::TileItemView()
-    : views::Button(this),
-      parent_background_color_(SK_ColorTRANSPARENT),
-      icon_(new views::ImageView),
-      badge_(nullptr),
-      title_(new views::Label) {
-  SetFocusBehavior(FocusBehavior::ALWAYS);
-  // Prevent the icon view from interfering with our mouse events.
-  icon_->set_can_process_events_within_subtree(false);
-  icon_->SetVerticalAlignment(views::ImageView::LEADING);
-
-  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-  title_->SetAutoColorReadabilityEnabled(false);
-  title_->SetEnabledColor(kGridTitleColor);
-  title_->SetFontList(rb.GetFontList(kItemTextFontStyle));
-  title_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
-  title_->SetHandlesTooltips(false);
-
-  AddChildView(icon_);
-  if (features::IsPlayStoreAppSearchEnabled()) {
-    badge_ = new views::ImageView();
-    badge_->set_can_process_events_within_subtree(false);
-    badge_->SetVerticalAlignment(views::ImageView::LEADING);
-    AddChildView(badge_);
-  }
-  AddChildView(title_);
-}
-
-TileItemView::~TileItemView() = default;
-
-void TileItemView::SetSelected(bool selected) {
-  if (selected == selected_)
-    return;
-
-  selected_ = selected;
-  UpdateBackgroundColor();
-
-  if (selected)
-    NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true);
-}
-
-void TileItemView::SetParentBackgroundColor(SkColor color) {
-  parent_background_color_ = color;
-  UpdateBackgroundColor();
-}
-
-void TileItemView::SetHoverStyle(HoverStyle hover_style) {
-  if (hover_style == HOVER_STYLE_DARKEN_BACKGROUND) {
-    image_shadow_animator_.reset();
-    return;
-  }
-
-  image_shadow_animator_.reset(new ImageShadowAnimator(this));
-  image_shadow_animator_->animation()->SetTweenType(
-      gfx::Tween::FAST_OUT_SLOW_IN);
-  image_shadow_animator_->SetStartAndEndShadows(IconStartShadows(),
-                                                IconEndShadows());
-}
-
-void TileItemView::SetIcon(const gfx::ImageSkia& icon) {
-  if (image_shadow_animator_) {
-    // Will call icon_->SetImage synchronously.
-    image_shadow_animator_->SetOriginalImage(icon);
-    return;
-  }
-
-  icon_->SetImage(icon);
-}
-
-void TileItemView::SetBadgeIcon(const gfx::ImageSkia& badge_icon) {
-  if (!badge_)
-    return;
-
-  if (badge_icon.isNull()) {
-    badge_->SetVisible(false);
-    return;
-  }
-
-  const int size = kBadgeBackgroundRadius * 2;
-  gfx::ImageSkia background(std::make_unique<BadgeBackgroundImageSource>(size),
-                            gfx::Size(size, size));
-  gfx::ImageSkia icon_with_background =
-      gfx::ImageSkiaOperations::CreateSuperimposedImage(background, badge_icon);
-
-  gfx::ShadowValues shadow_values;
-  shadow_values.push_back(
-      gfx::ShadowValue(gfx::Vector2d(0, 1), 0, SkColorSetARGB(0x33, 0, 0, 0)));
-  shadow_values.push_back(
-      gfx::ShadowValue(gfx::Vector2d(0, 1), 2, SkColorSetARGB(0x33, 0, 0, 0)));
-  badge_->SetImage(gfx::ImageSkiaOperations::CreateImageWithDropShadow(
-      icon_with_background, shadow_values));
-  badge_->SetVisible(true);
-}
-
-void TileItemView::SetTitle(const base::string16& title) {
-  title_->SetText(title);
-  SetAccessibleName(title);
-}
-
-void TileItemView::StateChanged(ButtonState old_state) {
-  UpdateBackgroundColor();
-}
-
-void TileItemView::PaintButtonContents(gfx::Canvas* canvas) {
-  if (!selected_)
-    return;
-
-  gfx::Rect rect(GetContentsBounds());
-  cc::PaintFlags flags;
-  flags.setAntiAlias(true);
-  flags.setStyle(cc::PaintFlags::kFill_Style);
-  if (is_recommendation_) {
-    rect.Inset((rect.width() - kGridSelectedSize) / 2,
-               (rect.height() - kGridSelectedSize) / 2);
-    flags.setColor(kGridSelectedColor);
-    canvas->DrawRoundRect(gfx::RectF(rect), kGridSelectedCornerRadius, flags);
-  } else {
-    const int kLeftRightPadding = (rect.width() - kIconSelectedSize) / 2;
-    rect.Inset(kLeftRightPadding, 0);
-    rect.set_height(kIconSelectedSize);
-    flags.setColor(kIconSelectedColor);
-    canvas->DrawRoundRect(gfx::RectF(rect), kIconSelectedCornerRadius, flags);
-  }
-}
-
-void TileItemView::Layout() {
-  gfx::Rect rect(GetContentsBounds());
-
-  rect.Inset(0, kTopPadding, 0, 0);
-  icon_->SetBoundsRect(rect);
-
-  rect.Inset(0, kGridIconDimension + kIconTitleSpacing, 0, 0);
-  rect.set_height(title_->GetPreferredSize().height());
-  title_->SetBoundsRect(rect);
-}
-
-const char* TileItemView::GetClassName() const {
-  return "TileItemView";
-}
-
-void TileItemView::OnFocus() {
-  SetSelected(true);
-}
-
-void TileItemView::OnBlur() {
-  SetSelected(false);
-}
-
-void TileItemView::ImageShadowAnimationProgressed(
-    ImageShadowAnimator* animator) {
-  icon_->SetImage(animator->shadow_image());
-}
-
-gfx::Size TileItemView::CalculatePreferredSize() const {
-  return gfx::Size(kTileSize, kTileSize);
-}
-
-bool TileItemView::GetTooltipText(const gfx::Point& p,
-                                  base::string16* tooltip) const {
-  // Use the label to generate a tooltip, so that it will consider its text
-  // truncation in making the tooltip. We do not want the label itself to have a
-  // tooltip, so we only temporarily enable it to get the tooltip text from the
-  // label, then disable it again.
-  title_->SetHandlesTooltips(true);
-  bool handled = title_->GetTooltipText(p, tooltip);
-  title_->SetHandlesTooltips(false);
-  return handled;
-}
-
-void TileItemView::UpdateBackgroundColor() {
-  SkColor background_color = parent_background_color_;
-
-  // Tell the label what color it will be drawn onto. It will use whether the
-  // background color is opaque or transparent to decide whether to use subpixel
-  // rendering. Does not actually set the label's background color.
-  title_->SetBackgroundColor(background_color);
-
-  SetBackground(nullptr);
-  SchedulePaint();
-  return;
-}
-
-}  // namespace app_list
diff --git a/ui/app_list/views/tile_item_view.h b/ui/app_list/views/tile_item_view.h
deleted file mode 100644
index c1114877..0000000
--- a/ui/app_list/views/tile_item_view.h
+++ /dev/null
@@ -1,110 +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 UI_APP_LIST_VIEWS_TILE_ITEM_VIEW_H_
-#define UI_APP_LIST_VIEWS_TILE_ITEM_VIEW_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/app_list/app_list_export.h"
-#include "ui/app_list/views/image_shadow_animator.h"
-#include "ui/views/controls/button/button.h"
-
-namespace gfx {
-class ImageSkia;
-}
-
-namespace views {
-class ImageView;
-class Label;
-}
-
-namespace app_list {
-
-// The view for a tile in the app list on the start/search page.
-// TODO(warx): Merge this class to its subclass SearchResultTileItemView once
-// bubble launcher deprecates.
-class APP_LIST_EXPORT TileItemView : public views::Button,
-                                     public views::ButtonListener,
-                                     public ImageShadowAnimator::Delegate {
- public:
-  enum HoverStyle {
-    HOVER_STYLE_ANIMATE_SHADOW,
-    HOVER_STYLE_DARKEN_BACKGROUND,
-  };
-
-  TileItemView();
-  ~TileItemView() override;
-
-  bool selected() { return selected_; }
-  void SetSelected(bool selected);
-
-  // Informs the TileItemView of its parent's background color. The controls
-  // within the TileItemView will adapt to suit the given color.
-  void SetParentBackgroundColor(SkColor color);
-  SkColor parent_background_color() { return parent_background_color_; }
-
-  // Sets the behavior of the tile item on mouse hover.
-  void SetHoverStyle(HoverStyle hover_style);
-
-  // Overridden from views::Button:
-  void StateChanged(ButtonState old_state) override;
-  void PaintButtonContents(gfx::Canvas* canvas) override;
-
-  // Overridden from views::View:
-  void Layout() override;
-  const char* GetClassName() const override;
-  void OnFocus() override;
-  void OnBlur() override;
-
-  // Overridden from ImageShadowAnimator::Delegate:
-  void ImageShadowAnimationProgressed(ImageShadowAnimator* animator) override;
-
- protected:
-  // Overridden from views::View:
-  gfx::Size CalculatePreferredSize() const override;
-  bool GetTooltipText(const gfx::Point& p,
-                      base::string16* tooltip) const override;
-
-  views::ImageView* icon() const { return icon_; }
-  void SetIcon(const gfx::ImageSkia& icon);
-
-  views::ImageView* badge() const { return badge_; }
-  void SetBadgeIcon(const gfx::ImageSkia& badge_icon);
-
-  views::Label* title() const { return title_; }
-  void SetTitle(const base::string16& title);
-
-  void set_is_recommendation(bool is_recommendation) {
-    is_recommendation_ = is_recommendation;
-  }
-  bool is_recommendation() const { return is_recommendation_; }
-
- private:
-  void UpdateBackgroundColor();
-
-  SkColor parent_background_color_;
-  std::unique_ptr<ImageShadowAnimator> image_shadow_animator_;
-
-  views::ImageView* icon_;   // Owned by views hierarchy.
-  views::ImageView* badge_;  // Owned by views hierarchy.
-  views::Label* title_;      // Owned by views hierarchy.
-
-  bool selected_ = false;
-
-  // Indicates whether this view is the base class for recommendation display
-  // type SearchResultTileItemView.
-  // TODO(warx): It is not needed once TileItemView class is merged to
-  // SearchResultTileItemVIew.
-  bool is_recommendation_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(TileItemView);
-};
-
-}  // namespace app_list
-
-#endif  // UI_APP_LIST_VIEWS_TILE_ITEM_VIEW_H_
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 19bf909..277cf83 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -663,6 +663,8 @@
 
   if (!is_ios) {
     sources += [
+      "test/cocoa_helper.h",
+      "test/cocoa_helper.mm",
       "test/menu_test_observer.h",
       "test/menu_test_observer.mm",
       "test/nswindow_fullscreen_notification_waiter.h",
@@ -699,6 +701,7 @@
   deps = [
     "//base",
     "//base/test:test_config",
+    "//base/test:test_support",
     "//skia",
     "//testing/gtest",
     "//ui/base:ui_data_pack",
diff --git a/ui/base/cocoa/base_view_unittest.mm b/ui/base/cocoa/base_view_unittest.mm
index ceb1c65..5528a5e 100644
--- a/ui/base/cocoa/base_view_unittest.mm
+++ b/ui/base/cocoa/base_view_unittest.mm
@@ -8,7 +8,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 #include "ui/base/cocoa/base_view.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace {
 
diff --git a/ui/base/cocoa/bubble_closer_unittest.mm b/ui/base/cocoa/bubble_closer_unittest.mm
index f2857a7..1e725c5 100644
--- a/ui/base/cocoa/bubble_closer_unittest.mm
+++ b/ui/base/cocoa/bubble_closer_unittest.mm
@@ -5,9 +5,9 @@
 #include "ui/base/cocoa/bubble_closer.h"
 
 #include "base/bind.h"
+#import "ui/base/test/cocoa_helper.h"
 #import "ui/base/test/menu_test_observer.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 namespace ui {
 
diff --git a/ui/base/cocoa/cocoa_base_utils_unittest.mm b/ui/base/cocoa/cocoa_base_utils_unittest.mm
index a2b64a55..fa5ac35 100644
--- a/ui/base/cocoa/cocoa_base_utils_unittest.mm
+++ b/ui/base/cocoa/cocoa_base_utils_unittest.mm
@@ -9,9 +9,9 @@
 #import "base/mac/scoped_objc_class_swizzler.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/events/event_constants.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 // We provide a donor class with a specially modified |modifierFlags|
 // implementation that we swap with NSEvent's. This is because we can't create a
diff --git a/ui/base/cocoa/constrained_window/constrained_window_animation_unittest.mm b/ui/base/cocoa/constrained_window/constrained_window_animation_unittest.mm
index faa863d..d646282 100644
--- a/ui/base/cocoa/constrained_window/constrained_window_animation_unittest.mm
+++ b/ui/base/cocoa/constrained_window/constrained_window_animation_unittest.mm
@@ -7,7 +7,7 @@
 #include <memory>
 
 #include "base/mac/scoped_nsobject.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 // This class runs an animation for exactly two frames then end it.
 @interface ConstrainedWindowAnimationTestDelegate
diff --git a/ui/base/cocoa/controls/blue_label_button_unittest.mm b/ui/base/cocoa/controls/blue_label_button_unittest.mm
index 0427d9b0..33200cb 100644
--- a/ui/base/cocoa/controls/blue_label_button_unittest.mm
+++ b/ui/base/cocoa/controls/blue_label_button_unittest.mm
@@ -7,7 +7,7 @@
 #include "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
 #import "testing/gtest_mac.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace ui {
 namespace test {
diff --git a/ui/base/cocoa/controls/hover_image_menu_button_unittest.mm b/ui/base/cocoa/controls/hover_image_menu_button_unittest.mm
index e137d551..ea6bd91 100644
--- a/ui/base/cocoa/controls/hover_image_menu_button_unittest.mm
+++ b/ui/base/cocoa/controls/hover_image_menu_button_unittest.mm
@@ -8,8 +8,8 @@
 #include "base/macros.h"
 #import "testing/gtest_mac.h"
 #import "ui/base/cocoa/controls/hover_image_menu_button_cell.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 namespace ui {
 
diff --git a/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm b/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm
index b45f7b7..2caf8a6 100644
--- a/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm
+++ b/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm
@@ -11,8 +11,8 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 namespace ui {
 
diff --git a/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm b/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm
index efbf6865..d4fbd07 100644
--- a/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm
+++ b/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#import "ui/base/cocoa/controls/hyperlink_text_view.h"
+
 #include "base/mac/scoped_nsobject.h"
 #include "testing/gtest_mac.h"
-#import "ui/base/cocoa/controls/hyperlink_text_view.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace {
 
diff --git a/ui/base/cocoa/focus_tracker_unittest.mm b/ui/base/cocoa/focus_tracker_unittest.mm
index 6e98f90..87df54b1 100644
--- a/ui/base/cocoa/focus_tracker_unittest.mm
+++ b/ui/base/cocoa/focus_tracker_unittest.mm
@@ -8,7 +8,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 #import "ui/base/cocoa/focus_tracker.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace {
 
diff --git a/ui/base/cocoa/fullscreen_window_manager_unittest.mm b/ui/base/cocoa/fullscreen_window_manager_unittest.mm
index c720a26f..25f3dc3 100644
--- a/ui/base/cocoa/fullscreen_window_manager_unittest.mm
+++ b/ui/base/cocoa/fullscreen_window_manager_unittest.mm
@@ -6,7 +6,7 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 typedef ui::CocoaTest FullscreenWindowManagerTest;
 
diff --git a/ui/base/cocoa/hover_button_unittest.mm b/ui/base/cocoa/hover_button_unittest.mm
index 54f15c2..68c2399 100644
--- a/ui/base/cocoa/hover_button_unittest.mm
+++ b/ui/base/cocoa/hover_button_unittest.mm
@@ -6,8 +6,8 @@
 
 #import <Cocoa/Cocoa.h>
 
+#import "ui/base/test/cocoa_helper.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 @interface TestHoverButton : HoverButton
 @property(readwrite, nonatomic) NSRect hitbox;
diff --git a/ui/base/cocoa/hover_image_button_unittest.mm b/ui/base/cocoa/hover_image_button_unittest.mm
index c061d8f2..8f6c19a0 100644
--- a/ui/base/cocoa/hover_image_button_unittest.mm
+++ b/ui/base/cocoa/hover_image_button_unittest.mm
@@ -5,8 +5,8 @@
 #import "ui/base/cocoa/hover_image_button.h"
 
 #import "base/mac/scoped_nsobject.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 namespace {
 
diff --git a/ui/base/cocoa/menu_controller_unittest.mm b/ui/base/cocoa/menu_controller_unittest.mm
index 1ae82a8..9803ebb 100644
--- a/ui/base/cocoa/menu_controller_unittest.mm
+++ b/ui/base/cocoa/menu_controller_unittest.mm
@@ -15,9 +15,9 @@
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/resource/resource_bundle.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/events/test/cocoa_test_event_utils.h"
 #include "ui/gfx/image/image.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 #include "ui/resources/grit/ui_resources.h"
 #include "ui/strings/grit/ui_strings.h"
 
diff --git a/ui/base/cocoa/nsgraphics_context_additions_unittest.mm b/ui/base/cocoa/nsgraphics_context_additions_unittest.mm
index d63f8f3..632add7 100644
--- a/ui/base/cocoa/nsgraphics_context_additions_unittest.mm
+++ b/ui/base/cocoa/nsgraphics_context_additions_unittest.mm
@@ -5,7 +5,7 @@
 #import "ui/base/cocoa/nsgraphics_context_additions.h"
 
 #include "base/mac/scoped_nsobject.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 typedef ui::CocoaTest NSGraphicsContextCrAdditionsTest;
 
diff --git a/ui/base/cocoa/nsview_additions_unittest.mm b/ui/base/cocoa/nsview_additions_unittest.mm
index 80ad751..9d1f66f 100644
--- a/ui/base/cocoa/nsview_additions_unittest.mm
+++ b/ui/base/cocoa/nsview_additions_unittest.mm
@@ -7,7 +7,7 @@
 #include "base/mac/scoped_nsobject.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 typedef ui::CocoaTest NSViewChromeAdditionsTest;
 
diff --git a/ui/base/cocoa/three_part_image_unittest.mm b/ui/base/cocoa/three_part_image_unittest.mm
index 2c9d0d07..223d5e6f 100644
--- a/ui/base/cocoa/three_part_image_unittest.mm
+++ b/ui/base/cocoa/three_part_image_unittest.mm
@@ -11,9 +11,9 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkRect.h"
 #include "ui/base/resource/resource_bundle.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_unittest_util.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 namespace ui {
 namespace test {
diff --git a/ui/base/cocoa/touch_bar_util_unittest.mm b/ui/base/cocoa/touch_bar_util_unittest.mm
index d0235c3..1abbc35 100644
--- a/ui/base/cocoa/touch_bar_util_unittest.mm
+++ b/ui/base/cocoa/touch_bar_util_unittest.mm
@@ -7,7 +7,7 @@
 #include "base/mac/foundation_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 namespace {
 
diff --git a/ui/base/cocoa/tracking_area_unittest.mm b/ui/base/cocoa/tracking_area_unittest.mm
index cb2c829..5e23dd05 100644
--- a/ui/base/cocoa/tracking_area_unittest.mm
+++ b/ui/base/cocoa/tracking_area_unittest.mm
@@ -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 "base/mac/scoped_nsobject.h"
 #import "ui/base/cocoa/tracking_area.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#include "base/mac/scoped_nsobject.h"
+#import "ui/base/test/cocoa_helper.h"
 
 // A test object that counts the number of times a message is sent to it.
 @interface TestTrackingAreaOwner : NSObject {
diff --git a/ui/base/ime/input_method_chromeos_unittest.cc b/ui/base/ime/input_method_chromeos_unittest.cc
index 8d5cc641..0e64f21 100644
--- a/ui/base/ime/input_method_chromeos_unittest.cc
+++ b/ui/base/ime/input_method_chromeos_unittest.cc
@@ -449,7 +449,7 @@
             mock_ime_engine_handler_->last_text_input_context().mode);
 
   input_type_ = TEXT_INPUT_TYPE_TEXT;
-  input_mode_ = TEXT_INPUT_MODE_LATIN;
+  input_mode_ = TEXT_INPUT_MODE_TEXT;
   ime_->OnTextInputTypeChanged(this);
   // Confirm that only FocusIn is called, the TextInputType is TEXT and the
   // TextInputMode is LATIN..
@@ -457,17 +457,17 @@
   EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
   EXPECT_EQ(TEXT_INPUT_TYPE_TEXT,
             mock_ime_engine_handler_->last_text_input_context().type);
-  EXPECT_EQ(TEXT_INPUT_MODE_LATIN,
+  EXPECT_EQ(TEXT_INPUT_MODE_TEXT,
             mock_ime_engine_handler_->last_text_input_context().mode);
 
-  input_mode_ = TEXT_INPUT_MODE_KANA;
+  input_mode_ = TEXT_INPUT_MODE_SEARCH;
   ime_->OnTextInputTypeChanged(this);
   // Confirm that both FocusIn and FocusOut are called for mode change.
   EXPECT_EQ(2, mock_ime_engine_handler_->focus_in_call_count());
   EXPECT_EQ(1, mock_ime_engine_handler_->focus_out_call_count());
   EXPECT_EQ(TEXT_INPUT_TYPE_TEXT,
             mock_ime_engine_handler_->last_text_input_context().type);
-  EXPECT_EQ(TEXT_INPUT_MODE_KANA,
+  EXPECT_EQ(TEXT_INPUT_MODE_SEARCH,
             mock_ime_engine_handler_->last_text_input_context().mode);
 
   input_type_ = TEXT_INPUT_TYPE_URL;
@@ -478,7 +478,7 @@
   EXPECT_EQ(2, mock_ime_engine_handler_->focus_out_call_count());
   EXPECT_EQ(TEXT_INPUT_TYPE_URL,
             mock_ime_engine_handler_->last_text_input_context().type);
-  EXPECT_EQ(TEXT_INPUT_MODE_KANA,
+  EXPECT_EQ(TEXT_INPUT_MODE_SEARCH,
             mock_ime_engine_handler_->last_text_input_context().mode);
 
   // Confirm that FocusOut is called when set focus to NULL client.
diff --git a/ui/base/ime/text_input_mode.h b/ui/base/ime/text_input_mode.h
index bf624d3..742c5713 100644
--- a/ui/base/ime/text_input_mode.h
+++ b/ui/base/ime/text_input_mode.h
@@ -11,20 +11,16 @@
 // http://www.whatwg.org/specs/web-apps/current-work/#attr-fe-inputmode
 enum TextInputMode {
   TEXT_INPUT_MODE_DEFAULT,
-  TEXT_INPUT_MODE_VERBATIM,
-  TEXT_INPUT_MODE_LATIN,
-  TEXT_INPUT_MODE_LATIN_NAME,
-  TEXT_INPUT_MODE_LATIN_PROSE,
-  TEXT_INPUT_MODE_FULL_WIDTH_LATIN,
-  TEXT_INPUT_MODE_KANA,
-  TEXT_INPUT_MODE_KANA_NAME,
-  TEXT_INPUT_MODE_KATAKANA,
-  TEXT_INPUT_MODE_NUMERIC,
+  TEXT_INPUT_MODE_NONE,
+  TEXT_INPUT_MODE_TEXT,
   TEXT_INPUT_MODE_TEL,
-  TEXT_INPUT_MODE_EMAIL,
   TEXT_INPUT_MODE_URL,
+  TEXT_INPUT_MODE_EMAIL,
+  TEXT_INPUT_MODE_NUMERIC,
+  TEXT_INPUT_MODE_DECIMAL,
+  TEXT_INPUT_MODE_SEARCH,
 
-  TEXT_INPUT_MODE_MAX = TEXT_INPUT_MODE_URL,
+  TEXT_INPUT_MODE_MAX = TEXT_INPUT_MODE_SEARCH,
 };
 
 }  // namespace ui
diff --git a/ui/base/ime/win/imm32_manager.cc b/ui/base/ime/win/imm32_manager.cc
index 83a7be9..ed9b186 100644
--- a/ui/base/ime/win/imm32_manager.cc
+++ b/ui/base/ime/win/imm32_manager.cc
@@ -583,28 +583,8 @@
                                               DWORD initial_conversion_mode,
                                               BOOL* open,
                                               DWORD* new_conversion_mode) {
-  *open = TRUE;
+  *open = FALSE;
   *new_conversion_mode = initial_conversion_mode;
-  switch (input_mode) {
-    case ui::TEXT_INPUT_MODE_FULL_WIDTH_LATIN:
-      *new_conversion_mode |= IME_CMODE_FULLSHAPE;
-      *new_conversion_mode &= ~(IME_CMODE_NATIVE
-                              | IME_CMODE_KATAKANA);
-      break;
-    case ui::TEXT_INPUT_MODE_KANA:
-      *new_conversion_mode |= (IME_CMODE_NATIVE
-                             | IME_CMODE_FULLSHAPE);
-      *new_conversion_mode &= ~IME_CMODE_KATAKANA;
-      break;
-    case ui::TEXT_INPUT_MODE_KATAKANA:
-      *new_conversion_mode |= (IME_CMODE_NATIVE
-                             | IME_CMODE_KATAKANA
-                             | IME_CMODE_FULLSHAPE);
-      break;
-    default:
-      *open = FALSE;
-      break;
-  }
 }
 
 }  // namespace ui
diff --git a/ui/base/ime/win/imm32_manager_unittest.cc b/ui/base/ime/win/imm32_manager_unittest.cc
index 0c73b03..07353be 100644
--- a/ui/base/ime/win/imm32_manager_unittest.cc
+++ b/ui/base/ime/win/imm32_manager_unittest.cc
@@ -26,47 +26,24 @@
     : public ::testing::TestWithParam<InputModeTestCase> {
 };
 
-const InputModeTestCase
-    kInputModeTestCases[] = {
-  {TEXT_INPUT_MODE_DEFAULT, 0, FALSE, 0},
-  {TEXT_INPUT_MODE_DEFAULT, IME_CMODE_NATIVE, FALSE, IME_CMODE_NATIVE},
-  {TEXT_INPUT_MODE_VERBATIM, 0, FALSE, 0},
-  {TEXT_INPUT_MODE_VERBATIM, IME_CMODE_KATAKANA, FALSE, IME_CMODE_KATAKANA},
-  {TEXT_INPUT_MODE_LATIN, 0, FALSE, 0},
-  {TEXT_INPUT_MODE_LATIN, IME_CMODE_NATIVE, FALSE, IME_CMODE_NATIVE},
-  {TEXT_INPUT_MODE_LATIN_NAME, 0, FALSE, 0},
-  {TEXT_INPUT_MODE_LATIN_NAME, IME_CMODE_NATIVE, FALSE, IME_CMODE_NATIVE},
-  {TEXT_INPUT_MODE_LATIN_PROSE, 0, FALSE, 0},
-  {TEXT_INPUT_MODE_LATIN_PROSE, IME_CMODE_NATIVE, FALSE, IME_CMODE_NATIVE},
-  {TEXT_INPUT_MODE_FULL_WIDTH_LATIN,
-       IME_CMODE_NATIVE | IME_CMODE_KATAKANA | IME_CMODE_FULLSHAPE,
-       TRUE,
-       IME_CMODE_FULLSHAPE},
-  {TEXT_INPUT_MODE_KANA,
-       0,
-       TRUE,
-       IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE},
-  {TEXT_INPUT_MODE_KANA,
-       IME_CMODE_ROMAN,
-       TRUE,
-       IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE | IME_CMODE_ROMAN},
-  {TEXT_INPUT_MODE_KATAKANA,
-       IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE,
-       TRUE,
-       IME_CMODE_NATIVE | IME_CMODE_KATAKANA | IME_CMODE_FULLSHAPE},
-  {TEXT_INPUT_MODE_KATAKANA,
-       IME_CMODE_NATIVE | IME_CMODE_FULLSHAPE | IME_CMODE_ROMAN,
-       TRUE,
-       IME_CMODE_NATIVE | IME_CMODE_KATAKANA | IME_CMODE_FULLSHAPE
-           | IME_CMODE_ROMAN},
-  {TEXT_INPUT_MODE_NUMERIC, 0, FALSE, 0},
-  {TEXT_INPUT_MODE_NUMERIC, IME_CMODE_FULLSHAPE, FALSE, IME_CMODE_FULLSHAPE},
-  {TEXT_INPUT_MODE_TEL, 0, FALSE, 0},
-  {TEXT_INPUT_MODE_TEL, IME_CMODE_ROMAN, FALSE, IME_CMODE_ROMAN},
-  {TEXT_INPUT_MODE_EMAIL, 0, FALSE, 0},
-  {TEXT_INPUT_MODE_EMAIL, IME_CMODE_CHARCODE, FALSE, IME_CMODE_CHARCODE},
-  {TEXT_INPUT_MODE_URL, 0, FALSE, 0},
-  {TEXT_INPUT_MODE_URL, IME_CMODE_HANJACONVERT, FALSE, IME_CMODE_HANJACONVERT},
+const InputModeTestCase kInputModeTestCases[] = {
+    {TEXT_INPUT_MODE_DEFAULT, 0, FALSE, 0},
+    {TEXT_INPUT_MODE_DEFAULT, IME_CMODE_NATIVE, FALSE, IME_CMODE_NATIVE},
+    {TEXT_INPUT_MODE_TEXT, 0, FALSE, 0},
+    {TEXT_INPUT_MODE_TEXT, IME_CMODE_NATIVE, FALSE, IME_CMODE_NATIVE},
+    {TEXT_INPUT_MODE_NUMERIC, 0, FALSE, 0},
+    {TEXT_INPUT_MODE_NUMERIC, IME_CMODE_FULLSHAPE, FALSE, IME_CMODE_FULLSHAPE},
+    {TEXT_INPUT_MODE_DECIMAL, 0, FALSE, 0},
+    {TEXT_INPUT_MODE_DECIMAL, IME_CMODE_FULLSHAPE, FALSE, IME_CMODE_FULLSHAPE},
+    {TEXT_INPUT_MODE_TEL, 0, FALSE, 0},
+    {TEXT_INPUT_MODE_TEL, IME_CMODE_ROMAN, FALSE, IME_CMODE_ROMAN},
+    {TEXT_INPUT_MODE_EMAIL, 0, FALSE, 0},
+    {TEXT_INPUT_MODE_EMAIL, IME_CMODE_CHARCODE, FALSE, IME_CMODE_CHARCODE},
+    {TEXT_INPUT_MODE_URL, 0, FALSE, 0},
+    {TEXT_INPUT_MODE_URL, IME_CMODE_HANJACONVERT, FALSE,
+     IME_CMODE_HANJACONVERT},
+    {TEXT_INPUT_MODE_SEARCH, 0, FALSE, 0},
+    {TEXT_INPUT_MODE_SEARCH, IME_CMODE_CHARCODE, FALSE, IME_CMODE_CHARCODE},
 };
 
 TEST_P(IMM32ManagerTest, ConvertInputModeToImmFlags) {
diff --git a/ui/base/ime/win/tsf_input_scope.cc b/ui/base/ime/win/tsf_input_scope.cc
index d8025ef..d11c2073 100644
--- a/ui/base/ime/win/tsf_input_scope.cc
+++ b/ui/base/ime/win/tsf_input_scope.cc
@@ -138,13 +138,9 @@
 
 InputScope ConvertTextInputModeToInputScope(TextInputMode text_input_mode) {
   switch (text_input_mode) {
-    case TEXT_INPUT_MODE_FULL_WIDTH_LATIN:
-      return IS_ALPHANUMERIC_FULLWIDTH;
-    case TEXT_INPUT_MODE_KANA:
-      return IS_HIRAGANA;
-    case TEXT_INPUT_MODE_KATAKANA:
-      return IS_KATAKANA_FULLWIDTH;
     case TEXT_INPUT_MODE_NUMERIC:
+      return IS_DIGITS;
+    case TEXT_INPUT_MODE_DECIMAL:
       return IS_NUMBER;
     case TEXT_INPUT_MODE_TEL:
       return IS_TELEPHONE_FULLTELEPHONENUMBER;
@@ -152,6 +148,8 @@
       return IS_EMAIL_SMTPEMAILADDRESS;
     case TEXT_INPUT_MODE_URL:
       return IS_URL;
+    case TEXT_INPUT_MODE_SEARCH:
+      return IS_SEARCH;
     default:
       return IS_DEFAULT;
   }
diff --git a/ui/base/ime/win/tsf_input_scope_unittest.cc b/ui/base/ime/win/tsf_input_scope_unittest.cc
index ed36a18..237e4e49a 100644
--- a/ui/base/ime/win/tsf_input_scope_unittest.cc
+++ b/ui/base/ime/win/tsf_input_scope_unittest.cc
@@ -30,77 +30,62 @@
 };
 
 const GetInputScopesTestCase kGetInputScopesTestCases[] = {
-  // Test cases of TextInputType.
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_TEXT, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_PASSWORD, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_PASSWORD}},
-  {TEXT_INPUT_TYPE_SEARCH, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_SEARCH}},
-  {TEXT_INPUT_TYPE_EMAIL, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_EMAIL_SMTPEMAILADDRESS}},
-  {TEXT_INPUT_TYPE_NUMBER, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_NUMBER}},
-  {TEXT_INPUT_TYPE_TELEPHONE, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_TELEPHONE_FULLTELEPHONENUMBER}},
-  {TEXT_INPUT_TYPE_URL, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_URL}},
-  {TEXT_INPUT_TYPE_DATE, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_DATE_TIME, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_DATE_TIME_LOCAL, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_MONTH, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_TIME, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_WEEK, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_TEXT_AREA, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_CONTENT_EDITABLE, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_DATE_TIME_FIELD, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  // Test cases of TextInputMode.
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_DEFAULT,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_VERBATIM,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_LATIN,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_LATIN_NAME,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_LATIN_PROSE,
-   1, {IS_DEFAULT}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_FULL_WIDTH_LATIN,
-   1, {IS_ALPHANUMERIC_FULLWIDTH}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_KANA,
-   1, {IS_HIRAGANA}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_KATAKANA,
-   1, {IS_KATAKANA_FULLWIDTH}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_NUMERIC,
-   1, {IS_NUMBER}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_TEL,
-   1, {IS_TELEPHONE_FULLTELEPHONENUMBER}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_EMAIL,
-   1, {IS_EMAIL_SMTPEMAILADDRESS}},
-  {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_URL,
-   1, {IS_URL}},
-   // Mixed test cases.
-  {TEXT_INPUT_TYPE_SEARCH, TEXT_INPUT_MODE_KANA,
-   2, {IS_SEARCH, IS_HIRAGANA}},
-  {TEXT_INPUT_TYPE_EMAIL, TEXT_INPUT_MODE_EMAIL,
-   1, {IS_EMAIL_SMTPEMAILADDRESS}},
-  {TEXT_INPUT_TYPE_NUMBER, TEXT_INPUT_MODE_NUMERIC,
-   1, {IS_NUMBER}},
-  {TEXT_INPUT_TYPE_TELEPHONE, TEXT_INPUT_MODE_TEL,
-   1, {IS_TELEPHONE_FULLTELEPHONENUMBER}},
-  {TEXT_INPUT_TYPE_URL, TEXT_INPUT_MODE_URL,
-   1, {IS_URL}},
+    // Test cases of TextInputType.
+    {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_TEXT, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_PASSWORD, TEXT_INPUT_MODE_DEFAULT, 1, {IS_PASSWORD}},
+    {TEXT_INPUT_TYPE_SEARCH, TEXT_INPUT_MODE_DEFAULT, 1, {IS_SEARCH}},
+    {TEXT_INPUT_TYPE_EMAIL,
+     TEXT_INPUT_MODE_DEFAULT,
+     1,
+     {IS_EMAIL_SMTPEMAILADDRESS}},
+    {TEXT_INPUT_TYPE_NUMBER, TEXT_INPUT_MODE_DEFAULT, 1, {IS_NUMBER}},
+    {TEXT_INPUT_TYPE_TELEPHONE,
+     TEXT_INPUT_MODE_DEFAULT,
+     1,
+     {IS_TELEPHONE_FULLTELEPHONENUMBER}},
+    {TEXT_INPUT_TYPE_URL, TEXT_INPUT_MODE_DEFAULT, 1, {IS_URL}},
+    {TEXT_INPUT_TYPE_DATE, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_DATE_TIME, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_DATE_TIME_LOCAL, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_MONTH, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_TIME, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_WEEK, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_TEXT_AREA, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_CONTENT_EDITABLE,
+     TEXT_INPUT_MODE_DEFAULT,
+     1,
+     {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_DATE_TIME_FIELD, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    // Test cases of TextInputMode.
+    {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_DEFAULT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_TEXT, 1, {IS_DEFAULT}},
+    {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_NUMERIC, 1, {IS_DIGITS}},
+    {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_DECIMAL, 1, {IS_NUMBER}},
+    {TEXT_INPUT_TYPE_NONE,
+     TEXT_INPUT_MODE_TEL,
+     1,
+     {IS_TELEPHONE_FULLTELEPHONENUMBER}},
+    {TEXT_INPUT_TYPE_NONE,
+     TEXT_INPUT_MODE_EMAIL,
+     1,
+     {IS_EMAIL_SMTPEMAILADDRESS}},
+    {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_URL, 1, {IS_URL}},
+    {TEXT_INPUT_TYPE_NONE, TEXT_INPUT_MODE_SEARCH, 1, {IS_SEARCH}},
+    // Mixed test cases.
+    {TEXT_INPUT_TYPE_EMAIL,
+     TEXT_INPUT_MODE_EMAIL,
+     1,
+     {IS_EMAIL_SMTPEMAILADDRESS}},
+    {TEXT_INPUT_TYPE_NUMBER,
+     TEXT_INPUT_MODE_NUMERIC,
+     2,
+     {IS_NUMBER, IS_DIGITS}},
+    {TEXT_INPUT_TYPE_TELEPHONE,
+     TEXT_INPUT_MODE_TEL,
+     1,
+     {IS_TELEPHONE_FULLTELEPHONENUMBER}},
+    {TEXT_INPUT_TYPE_URL, TEXT_INPUT_MODE_URL, 1, {IS_URL}},
 };
 
 TEST_P(TSFInputScopeTest, GetInputScopes) {
diff --git a/ui/gfx/test/ui_cocoa_test_helper.h b/ui/base/test/cocoa_helper.h
similarity index 85%
rename from ui/gfx/test/ui_cocoa_test_helper.h
rename to ui/base/test/cocoa_helper.h
index df10f0c..ebea0fb2 100644
--- a/ui/gfx/test/ui_cocoa_test_helper.h
+++ b/ui/base/test/cocoa_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 UI_GFX_TEST_UI_COCOA_TEST_HELPER_H_
-#define UI_GFX_TEST_UI_COCOA_TEST_HELPER_H_
+#ifndef UI_BASE_TEST_COCOA_HELPER_H_
+#define UI_BASE_TEST_COCOA_HELPER_H_
 
 #include <set>
 
@@ -12,6 +12,7 @@
 #include "base/compiler_specific.h"
 #import "base/mac/scoped_nsautorelease_pool.h"
 #import "base/mac/scoped_nsobject.h"
+#import "base/strings/sys_string_conversions.h"
 #include "testing/platform_test.h"
 
 // CocoaTestHelperWindow behaves differently from a regular NSWindow in the
@@ -145,24 +146,23 @@
 
 // A macro which which determines if two CGFloats are equal taking a
 // proper epsilon into consideration.
-#define CGFLOAT_EQ(expected, actual) \
-    (actual >= (expected - CGFLOAT_EPSILON) && \
-     actual <= (expected + CGFLOAT_EPSILON))
+#define CGFLOAT_EQ(expected, actual)         \
+  (actual >= (expected - CGFLOAT_EPSILON) && \
+   actual <= (expected + CGFLOAT_EPSILON))
 
 // A test support macro which ascertains if two CGFloats are equal.
 #define EXPECT_CGFLOAT_EQ(expected, actual) \
-    EXPECT_TRUE(CGFLOAT_EQ(expected, actual)) << \
-                expected << " != " << actual
+  EXPECT_TRUE(CGFLOAT_EQ(expected, actual)) << expected << " != " << actual
 
 // A test support macro which compares two NSRects for equality taking
 // the float epsilon into consideration.
-#define EXPECT_NSRECT_EQ(expected, actual) \
-    EXPECT_TRUE(CGFLOAT_EQ(expected.origin.x, actual.origin.x) && \
-                CGFLOAT_EQ(expected.origin.y, actual.origin.y) && \
-                CGFLOAT_EQ(expected.size.width, actual.size.width) && \
-                CGFLOAT_EQ(expected.size.height, actual.size.height)) << \
-                "Rects do not match: " << \
-                [NSStringFromRect(expected) UTF8String] << \
-                " != " << [NSStringFromRect(actual) UTF8String]
+#define EXPECT_NSRECT_EQ(expected, actual)                          \
+  EXPECT_TRUE(CGFLOAT_EQ(expected.origin.x, actual.origin.x) &&     \
+              CGFLOAT_EQ(expected.origin.y, actual.origin.y) &&     \
+              CGFLOAT_EQ(expected.size.width, actual.size.width) && \
+              CGFLOAT_EQ(expected.size.height, actual.size.height)) \
+      << "Rects do not match: "                                     \
+      << base::SysNSStringToUTF8(NSStringFromRect(expected))        \
+      << " != " << base::SysNSStringToUTF8(NSStringFromRect(actual))
 
-#endif  // UI_GFX_TEST_UI_COCOA_TEST_HELPER_H_
+#endif  // UI_BASE_TEST_COCOA_HELPER_H_
diff --git a/ui/gfx/test/ui_cocoa_test_helper.mm b/ui/base/test/cocoa_helper.mm
similarity index 95%
rename from ui/gfx/test/ui_cocoa_test_helper.mm
rename to ui/base/test/cocoa_helper.mm
index ec3b1f6..2ff39bd 100644
--- a/ui/gfx/test/ui_cocoa_test_helper.mm
+++ b/ui/base/test/cocoa_helper.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 
 #include "base/debug/debugger.h"
 #include "base/logging.h"
@@ -203,7 +203,7 @@
       {
         base::mac::ScopedNSAutoreleasePool pool;
         ++spins;
-        NSEvent *next_event = [NSApp nextEventMatchingMask:NSAnyEventMask
+        NSEvent* next_event = [NSApp nextEventMatchingMask:NSAnyEventMask
                                                  untilDate:nil
                                                     inMode:NSDefaultRunLoopMode
                                                    dequeue:YES];
@@ -224,8 +224,8 @@
       EXPECT_EQ(0U, windows_left.size());
       for (std::set<NSWindow*>::iterator iter = windows_left.begin();
            iter != windows_left.end(); ++iter) {
-        const char* desc = [[*iter description] UTF8String];
-        LOG(WARNING) << "Didn't close window " << desc;
+        LOG(WARNING) << "Didn't close window "
+                     << base::SysNSStringToUTF8([*iter description]);
       }
       break;
     }
@@ -242,8 +242,8 @@
   // Must create a pool here because [NSApp windows] has created an array
   // with retains on all the windows in it.
   base::mac::ScopedNSAutoreleasePool pool;
-  NSArray *appWindows = [NSApp windows];
-  for (NSWindow *window in appWindows) {
+  NSArray* appWindows = [NSApp windows];
+  for (NSWindow* window in appWindows) {
     windows.insert(window);
   }
   return windows;
@@ -252,7 +252,7 @@
 std::set<NSWindow*> CocoaTest::WindowsLeft() {
   const std::set<NSWindow*> windows(ApplicationWindows());
   std::set<NSWindow*> windows_left =
-      base::STLSetDifference<std::set<NSWindow*> >(windows, initial_windows_);
+      base::STLSetDifference<std::set<NSWindow*>>(windows, initial_windows_);
   return windows_left;
 }
 
diff --git a/ui/base/test/view_tree_validator_unittest.mm b/ui/base/test/view_tree_validator_unittest.mm
index 1a79215fb..b7266d69 100644
--- a/ui/base/test/view_tree_validator_unittest.mm
+++ b/ui/base/test/view_tree_validator_unittest.mm
@@ -4,7 +4,7 @@
 
 #include "ui/base/test/view_tree_validator.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/test/ui_cocoa_test_helper.h"
+#include "ui/base/test/cocoa_helper.h"
 
 using ViewTreeValidatorTest = ui::CocoaTest;
 
diff --git a/ui/base/x/BUILD.gn b/ui/base/x/BUILD.gn
index 75b4e1b..eb77c5f 100644
--- a/ui/base/x/BUILD.gn
+++ b/ui/base/x/BUILD.gn
@@ -1,12 +1,14 @@
 # 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.
+
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//ui/ozone/ozone.gni")
 
 assert(use_x11 || ozone_platform_x11)
 
-component("x") {
+jumbo_component("x") {
   output_name = "ui_base_x"
 
   sources = [
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn
index 141aff7..b8f0cac 100644
--- a/ui/compositor/BUILD.gn
+++ b/ui/compositor/BUILD.gn
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 
-component("compositor") {
+jumbo_component("compositor") {
   sources = [
     "callback_layer_animation_observer.cc",
     "callback_layer_animation_observer.h",
@@ -152,7 +153,7 @@
     "//components/viz/test:test_support",
     "//gpu/command_buffer/client:gles2_c_lib",
     "//gpu/command_buffer/client:gles2_implementation",
-    "//gpu/command_buffer/common:gles2_utils",
+    "//gpu/command_buffer/common",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings",
     "//skia",
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index c344067f4..2142bbb2 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -27,7 +27,7 @@
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "ui/compositor/compositor_switches.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/reflector.h"
@@ -203,7 +203,7 @@
       shared_worker_context_provider_ = nullptr;
   }
 
-  gpu::gles2::ContextCreationAttribHelper attribs;
+  gpu::ContextCreationAttribs attribs;
   attribs.alpha_size = 8;
   attribs.blue_size = 8;
   attribs.green_size = 8;
diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc
index 265c48b..db9c279b 100644
--- a/ui/compositor/test/in_process_context_provider.cc
+++ b/ui/compositor/test/in_process_context_provider.cc
@@ -25,7 +25,7 @@
 
 // static
 scoped_refptr<InProcessContextProvider> InProcessContextProvider::Create(
-    const gpu::gles2::ContextCreationAttribHelper& attribs,
+    const gpu::ContextCreationAttribs& attribs,
     InProcessContextProvider* shared_context,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     gpu::ImageFactory* image_factory,
@@ -44,7 +44,7 @@
     gpu::ImageFactory* image_factory,
     InProcessContextProvider* shared_context,
     bool support_locking) {
-  gpu::gles2::ContextCreationAttribHelper attribs;
+  gpu::ContextCreationAttribs attribs;
   attribs.alpha_size = 8;
   attribs.blue_size = 8;
   attribs.green_size = 8;
@@ -61,7 +61,7 @@
 }
 
 InProcessContextProvider::InProcessContextProvider(
-    const gpu::gles2::ContextCreationAttribHelper& attribs,
+    const gpu::ContextCreationAttribs& attribs,
     InProcessContextProvider* shared_context,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     gpu::ImageFactory* image_factory,
diff --git a/ui/compositor/test/in_process_context_provider.h b/ui/compositor/test/in_process_context_provider.h
index 11e1263..431002e7 100644
--- a/ui/compositor/test/in_process_context_provider.h
+++ b/ui/compositor/test/in_process_context_provider.h
@@ -15,7 +15,7 @@
 #include "base/threading/thread_checker.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/gpu/raster_context_provider.h"
-#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/ipc/common/surface_handle.h"
 #include "ui/gfx/native_widget_types.h"
 
@@ -37,7 +37,7 @@
       public viz::RasterContextProvider {
  public:
   static scoped_refptr<InProcessContextProvider> Create(
-      const gpu::gles2::ContextCreationAttribHelper& attribs,
+      const gpu::ContextCreationAttribs& attribs,
       InProcessContextProvider* shared_context,
       gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
       gpu::ImageFactory* image_factory,
@@ -76,7 +76,7 @@
   friend class base::RefCountedThreadSafe<InProcessContextProvider>;
 
   InProcessContextProvider(
-      const gpu::gles2::ContextCreationAttribHelper& attribs,
+      const gpu::ContextCreationAttribs& attribs,
       InProcessContextProvider* shared_context,
       gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
       gpu::ImageFactory* image_factory,
@@ -107,7 +107,7 @@
   bool bind_tried_ = false;
   gpu::ContextResult bind_result_;
 
-  gpu::gles2::ContextCreationAttribHelper attribs_;
+  gpu::ContextCreationAttribs attribs_;
   InProcessContextProvider* shared_context_;
   gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
   gpu::ImageFactory* image_factory_;
diff --git a/ui/display/manager/BUILD.gn b/ui/display/manager/BUILD.gn
index 25ee130..f54a2bbf3 100644
--- a/ui/display/manager/BUILD.gn
+++ b/ui/display/manager/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 
-component("manager") {
+jumbo_component("manager") {
   sources = [
     "chromeos/apply_content_protection_task.cc",
     "chromeos/apply_content_protection_task.h",
diff --git a/ui/display/manager/chromeos/display_change_observer.cc b/ui/display/manager/chromeos/display_change_observer.cc
index 79bfc80..0424688 100644
--- a/ui/display/manager/chromeos/display_change_observer.cc
+++ b/ui/display/manager/chromeos/display_change_observer.cc
@@ -45,9 +45,6 @@
     {0.0f, 1.0f},
 };
 
-// 1 inch in mm.
-const float kInchInMm = 25.4f;
-
 // The minimum pixel width whose monitor can be called as '4K'.
 const int kMinimumWidthFor4K = 3840;
 
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc
index 3940ca5..dce178f 100644
--- a/ui/display/manager/display_manager.cc
+++ b/ui/display/manager/display_manager.cc
@@ -241,6 +241,47 @@
   return true;
 }
 
+// Defines the ranges in which the number of displays can reside as reported by
+// UMA in the case of Unified Desktop mode.
+//
+// WARNING: These values are persisted to logs. Entries should not be
+//          renumbered and numeric values should never be reused.
+enum class DisplayCountRange {
+  // Exactly 2 displays.
+  k2Displays = 0,
+  // Range (2 : 4] displays.
+  kUpTo4Displays = 1,
+  // Range (4 : 6] displays.
+  kUpTo6Displays = 2,
+  // Range (6 : 8] displays.
+  kUpTo8Displays = 3,
+  // Greater than 8 displays.
+  kGreaterThan8Displays = 4,
+
+  // Always keep this the last item.
+  kCount,
+};
+
+// Returns the display count range bucket in which |display_count| resides.
+DisplayCountRange GetUnifiedDisplayCountRange(int display_count) {
+  // Note that Unified Mode cannot be enabled with a single display.
+  DCHECK_GE(display_count, 2);
+
+  if (display_count <= 2)
+    return DisplayCountRange::k2Displays;
+
+  if (display_count <= 4)
+    return DisplayCountRange::kUpTo4Displays;
+
+  if (display_count <= 6)
+    return DisplayCountRange::kUpTo6Displays;
+
+  if (display_count <= 8)
+    return DisplayCountRange::kUpTo8Displays;
+
+  return DisplayCountRange::kGreaterThan8Displays;
+}
+
 }  // namespace
 
 DisplayManager::BeginEndNotifier::BeginEndNotifier(
@@ -853,6 +894,9 @@
   if (multi_display_mode_ != MIRRORING)
     multi_display_mode_ = current_default_multi_display_mode_;
 
+  UMA_HISTOGRAM_ENUMERATION("DisplayManager.MultiDisplayMode",
+                            multi_display_mode_, MULTI_DISPLAY_MODE_LAST + 1);
+
   CreateSoftwareMirroringDisplayInfo(&new_display_info_list);
 
   // Close the mirroring window if any here to avoid creating two compositor on
@@ -1756,6 +1800,11 @@
   display_info_list->clear();
   display_info_list->emplace_back(unified_display_info);
   InsertAndUpdateDisplayInfo(unified_display_info);
+
+  UMA_HISTOGRAM_ENUMERATION(
+      "DisplayManager.UnifiedDesktopDisplayCountRange",
+      GetUnifiedDisplayCountRange(software_mirroring_display_list_.size()),
+      DisplayCountRange::kCount);
 }
 
 Display* DisplayManager::FindDisplayForId(int64_t id) {
diff --git a/ui/display/manager/display_manager.h b/ui/display/manager/display_manager.h
index 386c79c2..895bcf2d6 100644
--- a/ui/display/manager/display_manager.h
+++ b/ui/display/manager/display_manager.h
@@ -92,10 +92,16 @@
   //    spans multiple physical displays via software mirroring. The primary
   //    physical display has a shelf and status tray, and user windows may
   //    render spanning across multiple displays.
+  //
+  // WARNING: These values are persisted to logs. Entries should not be
+  //          renumbered and numeric values should never be reused.
   enum MultiDisplayMode {
     EXTENDED = 0,
-    MIRRORING,
-    UNIFIED,
+    MIRRORING = 1,
+    UNIFIED = 2,
+
+    // Always keep this the last item.
+    MULTI_DISPLAY_MODE_LAST = UNIFIED,
   };
 
   explicit DisplayManager(std::unique_ptr<Screen> screen);
diff --git a/ui/display/manager/fake_display_snapshot.cc b/ui/display/manager/fake_display_snapshot.cc
index 117310b..3db0e2c8 100644
--- a/ui/display/manager/fake_display_snapshot.cc
+++ b/ui/display/manager/fake_display_snapshot.cc
@@ -14,6 +14,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "third_party/re2/src/re2/re2.h"
+#include "ui/display/util/display_util.h"
 
 using base::StringPiece;
 
@@ -21,11 +22,9 @@
 
 namespace {
 
-static const float kInchInMm = 25.4f;
-
 // Get pixel pitch in millimeters from DPI.
-float PixelPitchMmFromDPI(float dpi) {
-  return (1.0f / dpi) * kInchInMm;
+constexpr float PixelPitchMmFromDPI(float dpi) {
+  return kInchInMm / dpi;
 }
 
 // Extracts text after specified delimiter. If the delimiter doesn't appear
diff --git a/ui/display/types/BUILD.gn b/ui/display/types/BUILD.gn
index 7fe106f1..2b4ae22 100644
--- a/ui/display/types/BUILD.gn
+++ b/ui/display/types/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("types") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("types") {
   output_name = "display_types"
   sources = [
     "display_constants.h",
diff --git a/ui/display/util/BUILD.gn b/ui/display/util/BUILD.gn
index c81f0e36..e787088 100644
--- a/ui/display/util/BUILD.gn
+++ b/ui/display/util/BUILD.gn
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 
-component("util") {
+jumbo_component("util") {
   output_name = "display_util"
   sources = [
     "display_util.cc",
diff --git a/ui/display/util/display_util.h b/ui/display/util/display_util.h
index 722803e..6617e52 100644
--- a/ui/display/util/display_util.h
+++ b/ui/display/util/display_util.h
@@ -12,6 +12,9 @@
 
 namespace display {
 
+// 1 inch in mm.
+constexpr float kInchInMm = 25.4f;
+
 // Returns true if a given size is in the list of bogus sizes in mm that should
 // be ignored.
 DISPLAY_UTIL_EXPORT bool IsDisplaySizeBlackListed(
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index e6bf735..d6363a7b 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -410,6 +410,7 @@
       "//testing/gmock",
       "//testing/gtest",
       "//third_party/WebKit/public:blink_headers",
+      "//ui/base:test_support",
       "//ui/display",
       "//ui/events/blink",
       "//ui/events/devices",
@@ -417,7 +418,6 @@
       "//ui/events/gestures/blink",
       "//ui/events/mojo:test_interfaces",
       "//ui/events/platform",
-      "//ui/gfx:test_support",
       "//ui/gfx/ipc/geometry",
     ]
 
diff --git a/ui/events/blink/BUILD.gn b/ui/events/blink/BUILD.gn
index e60d41a..f226976 100644
--- a/ui/events/blink/BUILD.gn
+++ b/ui/events/blink/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 
-source_set("blink") {
+jumbo_source_set("blink") {
   sources = [
     "blink_event_util.cc",
     "blink_event_util.h",
diff --git a/ui/events/cocoa/events_mac_unittest.mm b/ui/events/cocoa/events_mac_unittest.mm
index 4fb6b62cc..41cec46 100644
--- a/ui/events/cocoa/events_mac_unittest.mm
+++ b/ui/events/cocoa/events_mac_unittest.mm
@@ -13,12 +13,12 @@
 #include "base/mac/sdk_forward_declarations.h"
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#import "ui/base/test/cocoa_helper.h"
 #import "ui/events/cocoa/cocoa_event_utils.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/event_utils.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
 #include "ui/gfx/geometry/point.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 namespace ui {
 
diff --git a/ui/events/devices/BUILD.gn b/ui/events/devices/BUILD.gn
index 5913ef1a..2caa514b 100644
--- a/ui/events/devices/BUILD.gn
+++ b/ui/events/devices/BUILD.gn
@@ -2,12 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
+
 if (is_android) {
   import("//build/config/android/config.gni")
   import("//build/config/android/rules.gni")
 }
 
-component("devices") {
+jumbo_component("devices") {
   sources = [
     "device_data_manager.cc",
     "device_data_manager.h",
diff --git a/ui/events/devices/x11/BUILD.gn b/ui/events/devices/x11/BUILD.gn
index a9c963c..b95e1cc 100644
--- a/ui/events/devices/x11/BUILD.gn
+++ b/ui/events/devices/x11/BUILD.gn
@@ -1,12 +1,14 @@
 # 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.
+
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//ui/ozone/ozone.gni")
 
 assert(use_x11 || ozone_platform_x11)
 
-component("x11") {
+jumbo_component("x11") {
   output_name = "events_devices_x11"
 
   sources = [
diff --git a/ui/events/keycodes/BUILD.gn b/ui/events/keycodes/BUILD.gn
index 4552930..e0705f2 100644
--- a/ui/events/keycodes/BUILD.gn
+++ b/ui/events/keycodes/BUILD.gn
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//ui/ozone/ozone.gni")
 
-source_set("xkb") {
+jumbo_source_set("xkb") {
   sources = [
     "keyboard_code_conversion_xkb.cc",
     "keyboard_code_conversion_xkb.h",
@@ -21,7 +22,7 @@
 }
 
 if (use_x11 || ozone_platform_x11) {
-  component("x11") {
+  jumbo_component("x11") {
     output_name = "keycodes_x11"
 
     sources = [
diff --git a/ui/events/platform/BUILD.gn b/ui/events/platform/BUILD.gn
index b9a977f..5055e6c 100644
--- a/ui/events/platform/BUILD.gn
+++ b/ui/events/platform/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 
-component("platform") {
+jumbo_component("platform") {
   sources = [
     # Allow this target to include events_export.h without depending on the
     # events target (which would be circular).
diff --git a/ui/events/platform/x11/BUILD.gn b/ui/events/platform/x11/BUILD.gn
index ede8caf..d4c7462 100644
--- a/ui/events/platform/x11/BUILD.gn
+++ b/ui/events/platform/x11/BUILD.gn
@@ -2,12 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//ui/ozone/ozone.gni")
 
 assert(use_x11 || ozone_platform_x11)
 
-component("x11") {
+jumbo_component("x11") {
   output_name = "x11_events_platform"
 
   sources = [
diff --git a/ui/events/platform/x11/x11_event_source.cc b/ui/events/platform/x11/x11_event_source.cc
index a3f614d..ed3581a9 100644
--- a/ui/events/platform/x11/x11_event_source.cc
+++ b/ui/events/platform/x11/x11_event_source.cc
@@ -143,10 +143,6 @@
   ExtractCookieDataDispatchEvent(event);
 }
 
-void X11EventSource::BlockUntilWindowMapped(XID window) {
-  BlockOnWindowStructureEvent(window, MapNotify);
-}
-
 Time X11EventSource::GetCurrentServerTime() {
   DCHECK(display_);
 
@@ -276,16 +272,6 @@
   }
 }
 
-void X11EventSource::BlockOnWindowStructureEvent(XID window, int type) {
-  XEvent event;
-  do {
-    // Block until there's a StructureNotify event of |type| on |window|. Then
-    // remove it from the queue and stuff it in |event|.
-    XWindowEvent(display_, window, StructureNotifyMask, &event);
-    ExtractCookieDataDispatchEvent(&event);
-  } while (event.type != type);
-}
-
 void X11EventSource::StopCurrentEventStream() {
   continue_stream_ = false;
 }
diff --git a/ui/events/platform/x11/x11_event_source.h b/ui/events/platform/x11/x11_event_source.h
index c274490..a0cd370 100644
--- a/ui/events/platform/x11/x11_event_source.h
+++ b/ui/events/platform/x11/x11_event_source.h
@@ -62,17 +62,6 @@
   // main X11 event loop.
   void DispatchXEventNow(XEvent* event);
 
-  // Blocks on the X11 event queue until we receive notification from the
-  // xserver that |w| has been mapped; StructureNotifyMask events on |w| are
-  // pulled out from the queue and dispatched out of order.
-  //
-  // For those that know X11, this is really a wrapper around XWindowEvent
-  // which still makes sure the preempted event is dispatched instead of
-  // dropped on the floor. This method exists because mapping a window is
-  // asynchronous (and we receive an XEvent when mapped), while there are also
-  // functions which require a mapped window.
-  void BlockUntilWindowMapped(XID window);
-
   XDisplay* display() { return display_; }
 
   // Returns the timestamp of the event currently being dispatched.  Falls back
@@ -96,10 +85,6 @@
   // Handles updates after event has been dispatched.
   void PostDispatchEvent(XEvent* xevent);
 
-  // Block until receiving a structure notify event of |type| on |window|.
-  // Dispatch all encountered events prior to the one we're blocking on.
-  void BlockOnWindowStructureEvent(XID window, int type);
-
   // Explicitly asks the X11 server for the current timestamp, and updates
   // |last_seen_server_time_| with this value.
   Time GetCurrentServerTime();
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index fbdd3add..580b686 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//device/vr/features/features.gni")
 import("//testing/test.gni")
@@ -22,7 +23,7 @@
   ]
 }
 
-component("geometry_skia") {
+jumbo_component("geometry_skia") {
   sources = [
     "skia_util.cc",
     "skia_util.h",
@@ -42,7 +43,7 @@
   defines = [ "GFX_IMPLEMENTATION" ]
 }
 
-component("gfx") {
+jumbo_component("gfx") {
   sources = [
     "android/java_bitmap.cc",
     "android/java_bitmap.h",
@@ -394,7 +395,7 @@
   }
 }
 
-component("color_space") {
+jumbo_component("color_space") {
   sources = [
     "color_space.cc",
     "color_space.h",
@@ -576,7 +577,7 @@
 }
 
 # TODO(ccameron): This can be moved into a separate source_set.
-component("gfx_switches") {
+jumbo_component("gfx_switches") {
   sources = [
     "switches.cc",
     "switches.h",
@@ -608,8 +609,6 @@
     "test/gfx_util.h",
     "test/icc_profiles.cc",
     "test/icc_profiles.h",
-    "test/ui_cocoa_test_helper.h",
-    "test/ui_cocoa_test_helper.mm",
   ]
 
   public_deps = [
@@ -625,13 +624,6 @@
     "//ui/gfx/geometry",
   ]
 
-  if (is_ios) {
-    # The cocoa files don't apply to iOS.
-    sources -= [
-      "test/ui_cocoa_test_helper.h",
-      "test/ui_cocoa_test_helper.mm",
-    ]
-  }
   if (is_linux) {
     deps += [ "//third_party/fontconfig" ]
   }
diff --git a/ui/gfx/animation/BUILD.gn b/ui/gfx/animation/BUILD.gn
index 3352799..2ac0a604 100644
--- a/ui/gfx/animation/BUILD.gn
+++ b/ui/gfx/animation/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 
 if (is_android) {
@@ -9,7 +10,7 @@
   import("//build/config/android/rules.gni")
 }
 
-component("animation") {
+jumbo_component("animation") {
   sources = [
     "animation.cc",
     "animation.h",
diff --git a/ui/gfx/codec/BUILD.gn b/ui/gfx/codec/BUILD.gn
index 7c0201e..2d36488 100644
--- a/ui/gfx/codec/BUILD.gn
+++ b/ui/gfx/codec/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 
-component("codec") {
+jumbo_component("codec") {
   sources = [
     "codec_export.h",
     "jpeg_codec.cc",
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc
index f070b88..1c79c47 100644
--- a/ui/gfx/color_space.cc
+++ b/ui/gfx/color_space.cc
@@ -22,7 +22,7 @@
 namespace {
 
 // See comments in ToSkColorSpace about this cache. This cache may only be
-// accessed while holding g_lock.
+// accessed while holding g_sk_color_space_cache_lock.
 static const size_t kMaxCachedSkColorSpaces = 16;
 using SkColorSpaceCacheBase =
     base::MRUCache<gfx::ColorSpace, sk_sp<SkColorSpace>>;
@@ -32,7 +32,8 @@
 };
 base::LazyInstance<SkColorSpaceCache>::Leaky g_sk_color_space_cache =
     LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::Lock>::Leaky g_sk_color_space_cache_lock =
+    LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
 
@@ -500,7 +501,7 @@
   // Maintain a gfx::ColorSpace to SkColorSpace map, so that pointer-based
   // comparisons of SkColorSpaces will be more likely to be accurate.
   // https://crbug.com/793116
-  base::AutoLock lock(g_lock.Get());
+  base::AutoLock lock(g_sk_color_space_cache_lock.Get());
 
   auto found = g_sk_color_space_cache.Get().Get(*this);
   if (found != g_sk_color_space_cache.Get().end())
diff --git a/ui/gfx/geometry/BUILD.gn b/ui/gfx/geometry/BUILD.gn
index 7c2ee72..74043fa 100644
--- a/ui/gfx/geometry/BUILD.gn
+++ b/ui/gfx/geometry/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("geometry") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("geometry") {
   sources = [
     "../gfx_export.h",
     "angle_conversions.h",
diff --git a/ui/gfx/icc_profile.cc b/ui/gfx/icc_profile.cc
index 5c73ce5..a84543b 100644
--- a/ui/gfx/icc_profile.cc
+++ b/ui/gfx/icc_profile.cc
@@ -65,7 +65,8 @@
 
 // Lock that must be held to access |g_space_to_profile_cache_mac| and
 // |g_next_unused_id|.
-base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::Lock>::Leaky g_icc_profile_lock =
+    LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
 
@@ -184,7 +185,7 @@
   const char* data_as_byte = reinterpret_cast<const char*>(data_as_void);
   std::vector<char> data(data_as_byte, data_as_byte + size);
 
-  base::AutoLock lock(g_lock.Get());
+  base::AutoLock lock(g_icc_profile_lock.Get());
 
   // See if there is already an entry with the same data. If so, return that
   // entry. If not, parse the data.
@@ -278,7 +279,7 @@
 
 // static
 ICCProfile ICCProfile::FromCacheMac(const ColorSpace& color_space) {
-  base::AutoLock lock(g_lock.Get());
+  base::AutoLock lock(g_icc_profile_lock.Get());
   auto found_by_space = g_space_to_profile_cache_mac.Get().Get(color_space);
   if (found_by_space != g_space_to_profile_cache_mac.Get().end())
     return found_by_space->second;
@@ -291,7 +292,7 @@
 
 // static
 sk_sp<SkColorSpace> ICCProfile::GetSkColorSpaceFromId(uint64_t id) {
-  base::AutoLock lock(g_lock.Get());
+  base::AutoLock lock(g_icc_profile_lock.Get());
   auto found = g_id_to_profile_cache.Get().Get(id);
   if (found == g_id_to_profile_cache.Get().end()) {
     DLOG(ERROR) << "Failed to find ICC profile with SkColorSpace from id.";
diff --git a/ui/gfx/ipc/BUILD.gn b/ui/gfx/ipc/BUILD.gn
index 170b9fc..91f59bd 100644
--- a/ui/gfx/ipc/BUILD.gn
+++ b/ui/gfx/ipc/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("ipc") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("ipc") {
   output_name = "gfx_ipc"
 
   sources = [
diff --git a/ui/gfx/ipc/color/BUILD.gn b/ui/gfx/ipc/color/BUILD.gn
index 46d38d98..a2e66760 100644
--- a/ui/gfx/ipc/color/BUILD.gn
+++ b/ui/gfx/ipc/color/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("color") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("color") {
   output_name = "gfx_ipc_color"
 
   sources = [
diff --git a/ui/gfx/ipc/geometry/BUILD.gn b/ui/gfx/ipc/geometry/BUILD.gn
index b8796b22..bd57c70 100644
--- a/ui/gfx/ipc/geometry/BUILD.gn
+++ b/ui/gfx/ipc/geometry/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("geometry") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("geometry") {
   output_name = "gfx_ipc_geometry"
 
   sources = [
diff --git a/ui/gfx/ipc/skia/BUILD.gn b/ui/gfx/ipc/skia/BUILD.gn
index fcb670e..2e4df260 100644
--- a/ui/gfx/ipc/skia/BUILD.gn
+++ b/ui/gfx/ipc/skia/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("skia") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("skia") {
   output_name = "gfx_ipc_skia"
 
   sources = [
diff --git a/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc b/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
index e5d11bb8..b86d8ef 100644
--- a/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
+++ b/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
@@ -76,9 +76,10 @@
         return
 #if defined(ARCH_CPU_X86_FAMILY)
             // Currently only Intel driver (i.e. minigbm and Mesa) supports R_8
-            // and RG_88. crbug.com/356871
+            // RG_88 and NV12. https://crbug.com/356871
             format == gfx::BufferFormat::R_8 ||
             format == gfx::BufferFormat::RG_88 ||
+            format == gfx::BufferFormat::YUV_420_BIPLANAR ||
 #endif
             format == gfx::BufferFormat::BGRA_8888;
 #else
diff --git a/ui/gfx/range/BUILD.gn b/ui/gfx/range/BUILD.gn
index 0a8d8b2..2a2568a2 100644
--- a/ui/gfx/range/BUILD.gn
+++ b/ui/gfx/range/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("range") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("range") {
   sources = [
     "gfx_range_export.h",
     "range.cc",
diff --git a/ui/gfx/x/BUILD.gn b/ui/gfx/x/BUILD.gn
index a46d1d4..b14d8ac 100644
--- a/ui/gfx/x/BUILD.gn
+++ b/ui/gfx/x/BUILD.gn
@@ -2,12 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//ui/ozone/ozone.gni")
 
 assert(use_x11 || ozone_platform_x11)
 
-component("x") {
+jumbo_component("x") {
   output_name = "gfx_x11"
 
   sources = [
diff --git a/ui/gl/init/BUILD.gn b/ui/gl/init/BUILD.gn
index c6fe4e87..3400ef6 100644
--- a/ui/gl/init/BUILD.gn
+++ b/ui/gl/init/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 
-component("init") {
+jumbo_component("init") {
   output_name = "gl_init"
 
   public = [
diff --git a/ui/keyboard/BUILD.gn b/ui/keyboard/BUILD.gn
index 88599b7..3b28161 100644
--- a/ui/keyboard/BUILD.gn
+++ b/ui/keyboard/BUILD.gn
@@ -2,13 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//testing/test.gni")
 import("//third_party/google_input_tools/closure.gni")
 import("//third_party/google_input_tools/inputview.gni")
 import("//tools/grit/grit_rule.gni")
 
-component("keyboard") {
+jumbo_component("keyboard") {
   sources = [
     "container_behavior.h",
     "container_floating_behavior.cc",
@@ -57,7 +58,7 @@
   }
 }
 
-component("keyboard_with_content") {
+jumbo_component("keyboard_with_content") {
   sources = [
     "content/keyboard.cc",
     "content/keyboard.h",
diff --git a/ui/latency/BUILD.gn b/ui/latency/BUILD.gn
index e1ff274d..e5abf3bd 100644
--- a/ui/latency/BUILD.gn
+++ b/ui/latency/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//testing/test.gni")
 
-source_set("latency") {
+jumbo_source_set("latency") {
   sources = [
     "latency_histogram_macros.h",
     "latency_info.cc",
@@ -23,7 +24,7 @@
   ]
 }
 
-source_set("test_support") {
+jumbo_source_set("test_support") {
   testonly = true
   sources = [
     "latency_info_test_support.cc",
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn
index 1d6e0ce..9b8512b 100644
--- a/ui/message_center/BUILD.gn
+++ b/ui/message_center/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/features.gni")
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//components/vector_icons/vector_icons.gni")
 import("//testing/test.gni")
@@ -23,7 +24,7 @@
 }
 
 # TODO(msw|mukai|dewittj): Move ash-specific files: crbug.com/585175
-component("message_center") {
+jumbo_component("message_center") {
   deps = [
     "//base",
     "//ui/base",
diff --git a/ui/message_center/cocoa/notification_controller_unittest.mm b/ui/message_center/cocoa/notification_controller_unittest.mm
index 5b385a5e..99bb804 100644
--- a/ui/message_center/cocoa/notification_controller_unittest.mm
+++ b/ui/message_center/cocoa/notification_controller_unittest.mm
@@ -13,7 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #import "ui/base/cocoa/hover_image_button.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/message_center/fake_message_center.h"
 #include "ui/message_center/notification.h"
 #include "ui/message_center/notification_types.h"
diff --git a/ui/message_center/cocoa/popup_collection_unittest.mm b/ui/message_center/cocoa/popup_collection_unittest.mm
index b1e64524..0bdc3968 100644
--- a/ui/message_center/cocoa/popup_collection_unittest.mm
+++ b/ui/message_center/cocoa/popup_collection_unittest.mm
@@ -12,7 +12,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_task_environment.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 #import "ui/message_center/cocoa/notification_controller.h"
 #import "ui/message_center/cocoa/popup_controller.h"
 #include "ui/message_center/message_center.h"
diff --git a/ui/message_center/cocoa/popup_controller_unittest.mm b/ui/message_center/cocoa/popup_controller_unittest.mm
index 1b8943e..cbe289e 100644
--- a/ui/message_center/cocoa/popup_controller_unittest.mm
+++ b/ui/message_center/cocoa/popup_controller_unittest.mm
@@ -9,7 +9,7 @@
 #include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/message_center/notification.h"
 
 using base::ASCIIToUTF16;
diff --git a/ui/message_center/public/cpp/BUILD.gn b/ui/message_center/public/cpp/BUILD.gn
index 83d39cc..75ce71c 100644
--- a/ui/message_center/public/cpp/BUILD.gn
+++ b/ui/message_center/public/cpp/BUILD.gn
@@ -2,8 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
+
 # C++ headers and sources that can be used outside message_center.
-component("cpp") {
+jumbo_component("cpp") {
   sources = [
     "message_center_constants.h",
     "message_center_public_export.h",
diff --git a/ui/native_theme/BUILD.gn b/ui/native_theme/BUILD.gn
index ab9e852..753d4fd 100644
--- a/ui/native_theme/BUILD.gn
+++ b/ui/native_theme/BUILD.gn
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 
-component("native_theme") {
+jumbo_component("native_theme") {
   sources = [
     "common_theme.cc",
     "common_theme.h",
@@ -57,7 +58,7 @@
 }
 
 if (is_win) {
-  component("native_theme_browser") {
+  jumbo_component("native_theme_browser") {
     defines = [ "NATIVE_THEME_IMPLEMENTATION" ]
 
     # These files cannot work in the renderer on Windows.
@@ -76,7 +77,7 @@
     ]
   }
 } else {
-  source_set("native_theme_browser") {
+  jumbo_source_set("native_theme_browser") {
   }
 }
 
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn
index d38a202..55fb22c 100644
--- a/ui/ozone/BUILD.gn
+++ b/ui/ozone/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//ui/ozone/ozone.gni")
 import("//ui/ozone/ozone_extra.gni")
@@ -52,7 +53,7 @@
 platform_list_txt_file = "$target_gen_dir/platform_list.txt"
 constructor_list_cc_file = "$target_gen_dir/constructor_list.cc"
 
-component("ozone_base") {
+jumbo_component("ozone_base") {
   sources = [
     "ozone_base_export.h",
     "public/cursor_factory_ozone.cc",
@@ -158,7 +159,7 @@
   visibility += [ "//ui/ozone/platform/*" ]
 }
 
-component("ozone") {
+jumbo_component("ozone") {
   visibility = []
   visibility = [ "*" ]
   public_deps = [
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc
index 92dd569..93db1b1 100644
--- a/ui/ozone/platform/drm/common/drm_util.cc
+++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -262,21 +262,24 @@
   DCHECK(resources) << "Failed to get DRM resources";
   std::vector<std::unique_ptr<HardwareDisplayControllerInfo>> displays;
 
-  std::vector<ScopedDrmConnectorPtr> available_connectors;
-  std::vector<ScopedDrmConnectorPtr::element_type*> connectors;
+  std::vector<ScopedDrmConnectorPtr> connectors;
+  std::vector<drmModeConnector*> available_connectors;
   for (int i = 0; i < resources->count_connectors; ++i) {
     ScopedDrmConnectorPtr connector(
         drmModeGetConnector(fd, resources->connectors[i]));
-    connectors.push_back(connector.get());
+    if (!connector)
+      continue;
 
-    if (connector && connector->connection == DRM_MODE_CONNECTED &&
+    if (connector->connection == DRM_MODE_CONNECTED &&
         connector->count_modes != 0) {
-      available_connectors.push_back(std::move(connector));
+      available_connectors.push_back(connector.get());
     }
+
+    connectors.emplace_back(std::move(connector));
   }
 
-  base::flat_map<ScopedDrmConnectorPtr::element_type*, int> connector_crtcs;
-  for (auto& c : available_connectors) {
+  base::flat_map<drmModeConnector*, int> connector_crtcs;
+  for (auto* c : available_connectors) {
     uint32_t possible_crtcs = 0;
     for (int i = 0; i < c->count_encoders; ++i) {
       ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, c->encoders[i]));
@@ -284,32 +287,36 @@
         continue;
       possible_crtcs |= encoder->possible_crtcs;
     }
-    connector_crtcs[c.get()] = possible_crtcs;
+    connector_crtcs[c] = possible_crtcs;
   }
   // Make sure to start assigning a crtc to the connector that supports the
   // fewest crtcs first.
   std::stable_sort(available_connectors.begin(), available_connectors.end(),
-                   [&connector_crtcs](const ScopedDrmConnectorPtr& c1,
-                                      const ScopedDrmConnectorPtr& c2) {
+                   [&connector_crtcs](drmModeConnector* const c1,
+                                      drmModeConnector* const c2) {
                      // When c1 supports a proper subset of the crtcs of c2, we
                      // should process c1 first (return true).
-                     int c1_crtcs = connector_crtcs[c1.get()];
-                     int c2_crtcs = connector_crtcs[c2.get()];
+                     int c1_crtcs = connector_crtcs[c1];
+                     int c2_crtcs = connector_crtcs[c2];
                      return (c1_crtcs & c2_crtcs) == c1_crtcs &&
                             c1_crtcs != c2_crtcs;
                    });
 
-  for (auto& c : available_connectors) {
-    uint32_t crtc_id = GetCrtc(fd, c.get(), resources.get(), displays);
+  for (auto* c : available_connectors) {
+    uint32_t crtc_id = GetCrtc(fd, c, resources.get(), displays);
     if (!crtc_id)
       continue;
 
     ScopedDrmCrtcPtr crtc(drmModeGetCrtc(fd, crtc_id));
-    size_t index = std::find(connectors.begin(), connectors.end(), c.get()) -
-                   connectors.begin();
+    auto iter = std::find_if(connectors.begin(), connectors.end(),
+                             [c](const ScopedDrmConnectorPtr& connector) {
+                               return connector.get() == c;
+                             });
+    DCHECK(iter != connectors.end());
+    const size_t index = iter - connectors.begin();
     DCHECK_LT(index, connectors.size());
     displays.push_back(std::make_unique<HardwareDisplayControllerInfo>(
-        std::move(c), std::move(crtc), index));
+        std::move(*iter), std::move(crtc), index));
   }
 
   return displays;
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index f62ed70..843d7c99 100644
--- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -75,10 +75,6 @@
   }
 
   void InitializeUI(const InitParams& args) override {
-    connection_.reset(new WaylandConnection);
-    if (!connection_->Initialize())
-      LOG(FATAL) << "Failed to initialize Wayland platform";
-
 #if BUILDFLAG(USE_XKBCOMMON)
     KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
         std::make_unique<WaylandXkbKeyboardLayoutEngine>(
@@ -87,6 +83,9 @@
     KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
         std::make_unique<StubKeyboardLayoutEngine>());
 #endif
+    connection_.reset(new WaylandConnection);
+    if (!connection_->Initialize())
+      LOG(FATAL) << "Failed to initialize Wayland platform";
 
     cursor_factory_.reset(new BitmapCursorFactoryOzone);
     overlay_manager_.reset(new StubOverlayManager);
diff --git a/ui/ozone/platform/wayland/wayland_keyboard.cc b/ui/ozone/platform/wayland/wayland_keyboard.cc
index 036eecb6..a9f7399 100644
--- a/ui/ozone/platform/wayland/wayland_keyboard.cc
+++ b/ui/ozone/platform/wayland/wayland_keyboard.cc
@@ -38,6 +38,12 @@
       &WaylandKeyboard::Modifiers, &WaylandKeyboard::RepeatInfo,
   };
 
+#if BUILDFLAG(USE_XKBCOMMON)
+  auto* engine = static_cast<WaylandXkbKeyboardLayoutEngine*>(
+      KeyboardLayoutEngineManager::GetKeyboardLayoutEngine());
+  engine->set_event_modifiers(&event_modifiers_);
+#endif
+
   wl_keyboard_add_listener(obj_.get(), &listener, this);
 
   // TODO(tonikitoo): Default auto-repeat to ON here?
@@ -95,7 +101,7 @@
   if (dom_code == ui::DomCode::NONE)
     return;
 
-  uint8_t flags = keyboard->modifiers_;
+  uint8_t flags = keyboard->event_modifiers_.GetModifierFlags();
   DomKey dom_key;
   KeyboardCode key_code;
   if (!KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()->Lookup(
@@ -106,7 +112,7 @@
   bool down = state == WL_KEYBOARD_KEY_STATE_PRESSED;
   ui::KeyEvent event(
       down ? ET_KEY_PRESSED : ET_KEY_RELEASED, key_code, dom_code,
-      keyboard->modifiers_, dom_key,
+      keyboard->event_modifiers_.GetModifierFlags(), dom_key,
       base::TimeTicks() + base::TimeDelta::FromMilliseconds(time));
   event.set_source_device_id(keyboard->obj_.id());
   keyboard->callback_.Run(&event);
@@ -120,13 +126,9 @@
                                 uint32_t mods_locked,
                                 uint32_t group) {
 #if BUILDFLAG(USE_XKBCOMMON)
-  WaylandKeyboard* keyboard = static_cast<WaylandKeyboard*>(data);
   auto* engine = static_cast<WaylandXkbKeyboardLayoutEngine*>(
       KeyboardLayoutEngineManager::GetKeyboardLayoutEngine());
-
-  keyboard->modifiers_ =
-      engine->UpdateModifiers(mods_depressed, mods_latched, mods_locked, group);
-
+  engine->UpdateModifiers(mods_depressed, mods_latched, mods_locked, group);
 #endif
 }
 
diff --git a/ui/ozone/platform/wayland/wayland_keyboard.h b/ui/ozone/platform/wayland/wayland_keyboard.h
index e0ce521..756318e 100644
--- a/ui/ozone/platform/wayland/wayland_keyboard.h
+++ b/ui/ozone/platform/wayland/wayland_keyboard.h
@@ -5,6 +5,7 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_KEYBOARD_H_
 #define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_KEYBOARD_H_
 
+#include "ui/events/event_modifiers.h"
 #include "ui/events/ozone/evdev/event_dispatch_callback.h"
 #include "ui/ozone/platform/wayland/wayland_object.h"
 
@@ -21,7 +22,7 @@
     connection_ = connection;
   }
 
-  int modifiers() { return modifiers_; }
+  int modifiers() { return event_modifiers_.GetModifierFlags(); }
 
  private:
   // wl_keyboard_listener
@@ -60,7 +61,7 @@
   WaylandConnection* connection_ = nullptr;
   wl::Object<wl_keyboard> obj_;
   EventDispatchCallback callback_;
-  int modifiers_ = 0;
+  EventModifiers event_modifiers_;
 };
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_xkb_keyboard_layout_engine.cc b/ui/ozone/platform/wayland/wayland_xkb_keyboard_layout_engine.cc
index 79532d9a..8e6e4fe 100644
--- a/ui/ozone/platform/wayland/wayland_xkb_keyboard_layout_engine.cc
+++ b/ui/ozone/platform/wayland/wayland_xkb_keyboard_layout_engine.cc
@@ -5,6 +5,7 @@
 #include "ui/ozone/platform/wayland/wayland_xkb_keyboard_layout_engine.h"
 
 #include "ui/events/event_constants.h"
+#include "ui/events/event_modifiers.h"
 
 namespace ui {
 
@@ -21,27 +22,28 @@
   xkb_mod_indexes_.shift = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
 }
 
-int WaylandXkbKeyboardLayoutEngine::UpdateModifiers(uint32_t depressed_mods,
-                                                    uint32_t latched_mods,
-                                                    uint32_t locked_mods,
-                                                    uint32_t group) {
+void WaylandXkbKeyboardLayoutEngine::UpdateModifiers(uint32_t depressed_mods,
+                                                     uint32_t latched_mods,
+                                                     uint32_t locked_mods,
+                                                     uint32_t group) {
   xkb_state_update_mask(xkb_state_.get(), depressed_mods, latched_mods,
                         locked_mods, 0, 0, group);
 
-  int modifiers = 0;
+  event_modifiers_->ResetKeyboardModifiers();
+
   auto component = static_cast<xkb_state_component>(XKB_STATE_MODS_DEPRESSED |
                                                     XKB_STATE_MODS_LATCHED);
   if (xkb_state_mod_index_is_active(xkb_state_.get(), xkb_mod_indexes_.control,
                                     component))
-    modifiers |= EF_CONTROL_DOWN;
+    event_modifiers_->UpdateModifier(MODIFIER_CONTROL, true);
+
   if (xkb_state_mod_index_is_active(xkb_state_.get(), xkb_mod_indexes_.alt,
                                     component))
-    modifiers |= EF_ALT_DOWN;
+    event_modifiers_->UpdateModifier(MODIFIER_ALT, true);
+
   if (xkb_state_mod_index_is_active(xkb_state_.get(), xkb_mod_indexes_.shift,
                                     component))
-    modifiers |= EF_SHIFT_DOWN;
-
-  return modifiers;
+    event_modifiers_->UpdateModifier(MODIFIER_SHIFT, true);
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_xkb_keyboard_layout_engine.h b/ui/ozone/platform/wayland/wayland_xkb_keyboard_layout_engine.h
index 11020be..63c3dd5 100644
--- a/ui/ozone/platform/wayland/wayland_xkb_keyboard_layout_engine.h
+++ b/ui/ozone/platform/wayland/wayland_xkb_keyboard_layout_engine.h
@@ -11,16 +11,22 @@
 
 namespace ui {
 
+class EventModifiers;
+
 class WaylandXkbKeyboardLayoutEngine : public XkbKeyboardLayoutEngine {
  public:
   WaylandXkbKeyboardLayoutEngine(const XkbKeyCodeConverter& converter);
 
   // Used to sync up client side 'xkb_state' instance with modifiers status
   // update from the compositor.
-  int UpdateModifiers(uint32_t depressed_mods,
-                      uint32_t latched_mods,
-                      uint32_t locked_mods,
-                      uint32_t group);
+  void UpdateModifiers(uint32_t depressed_mods,
+                       uint32_t latched_mods,
+                       uint32_t locked_mods,
+                       uint32_t group);
+
+  void set_event_modifiers(EventModifiers* event_modifiers) {
+    event_modifiers_ = event_modifiers;
+  }
 
  private:
   void SetKeymap(xkb_keymap* keymap) override;
@@ -31,6 +37,8 @@
     xkb_mod_index_t alt = 0;
     xkb_mod_index_t shift = 0;
   } xkb_mod_indexes_;
+
+  EventModifiers* event_modifiers_ = nullptr;  // Owned by WaylandKeyboard.
 };
 
 }  // namespace ui
diff --git a/ui/platform_window/android/BUILD.gn b/ui/platform_window/android/BUILD.gn
index 75d0dd77..59a3ed27 100644
--- a/ui/platform_window/android/BUILD.gn
+++ b/ui/platform_window/android/BUILD.gn
@@ -3,11 +3,12 @@
 # found in the LICENSE file.
 
 import("//build/config/android/rules.gni")
+import("//build/config/jumbo.gni")
 import("//testing/test.gni")
 
 assert(is_android)
 
-component("android") {
+jumbo_component("android") {
   output_name = "android_window"
   sources = [
     "android_window_export.h",
diff --git a/ui/platform_window/mojo/BUILD.gn b/ui/platform_window/mojo/BUILD.gn
index 307b6c6..803e2e34 100644
--- a/ui/platform_window/mojo/BUILD.gn
+++ b/ui/platform_window/mojo/BUILD.gn
@@ -2,11 +2,12 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 
 # This target does NOT depend on skia. One can depend on this target to avoid
 # picking up a dependency on skia.
-component("mojo") {
+jumbo_component("mojo") {
   output_name = "mojo_ime_lib"
 
   public_deps = [
diff --git a/ui/platform_window/stub/BUILD.gn b/ui/platform_window/stub/BUILD.gn
index fd53cfe..55cff46 100644
--- a/ui/platform_window/stub/BUILD.gn
+++ b/ui/platform_window/stub/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("stub") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("stub") {
   output_name = "stub_window"
 
   deps = [
diff --git a/ui/platform_window/win/BUILD.gn b/ui/platform_window/win/BUILD.gn
index e7226e1..e5663a6 100644
--- a/ui/platform_window/win/BUILD.gn
+++ b/ui/platform_window/win/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("win") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("win") {
   output_name = "win_window"
 
   deps = [
diff --git a/ui/platform_window/x11/BUILD.gn b/ui/platform_window/x11/BUILD.gn
index cd94e3a..09e5de5 100644
--- a/ui/platform_window/x11/BUILD.gn
+++ b/ui/platform_window/x11/BUILD.gn
@@ -2,12 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//ui/ozone/ozone.gni")
 
 assert(use_x11 || ozone_platform_x11)
 
-component("x11") {
+jumbo_component("x11") {
   output_name = "x11_window"
 
   deps = [
diff --git a/ui/platform_window/x11/x11_window_base.cc b/ui/platform_window/x11/x11_window_base.cc
index d309fc8..d069fb0 100644
--- a/ui/platform_window/x11/x11_window_base.cc
+++ b/ui/platform_window/x11/x11_window_base.cc
@@ -144,18 +144,13 @@
     return;
 
   XMapWindow(xdisplay_, xwindow_);
-
-  // We now block until our window is mapped. Some X11 APIs will crash and
-  // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
-  // asynchronous.
-  if (X11EventSource::GetInstance())
-    X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
   window_mapped_ = true;
 }
 
 void X11WindowBase::Hide() {
   if (!window_mapped_)
     return;
+
   XWithdrawWindow(xdisplay_, xwindow_, 0);
   window_mapped_ = false;
 }
diff --git a/ui/resources/BUILD.gn b/ui/resources/BUILD.gn
index 3e583b0..ac466919a 100644
--- a/ui/resources/BUILD.gn
+++ b/ui/resources/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//tools/grit/grit_rule.gni")
 import("//tools/grit/repack.gni")
 
@@ -212,7 +213,9 @@
 
   if (use_aura && toolkit_views) {
     deps += [ "//ui/app_list/resources" ]
-    sources += [ "$root_gen_dir/ui/app_list/resources/app_list_resources_100_percent.pak" ]
+    sources += [
+      "$root_gen_dir/ui/app_list/resources/app_list_resources_100_percent.pak",
+    ]
   }
 }
 
diff --git a/ui/shell_dialogs/BUILD.gn b/ui/shell_dialogs/BUILD.gn
index bc8caf6..762859b 100644
--- a/ui/shell_dialogs/BUILD.gn
+++ b/ui/shell_dialogs/BUILD.gn
@@ -2,13 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 if (is_android) {
   import("//build/config/android/config.gni")
 }
 
-component("shell_dialogs") {
+jumbo_component("shell_dialogs") {
   sources = [
     "base_shell_dialog.cc",
     "base_shell_dialog.h",
diff --git a/ui/snapshot/BUILD.gn b/ui/snapshot/BUILD.gn
index a3f31979..d48f92aa 100644
--- a/ui/snapshot/BUILD.gn
+++ b/ui/snapshot/BUILD.gn
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 
-component("snapshot") {
+jumbo_component("snapshot") {
   sources = [
     "screenshot_grabber.cc",
     "screenshot_grabber.h",
@@ -72,7 +73,7 @@
   }
 }
 
-source_set("snapshot_win") {
+jumbo_source_set("snapshot_win") {
   sources = [
     "snapshot_win.h",
   ]
@@ -82,7 +83,7 @@
   visibility = [ ":*" ]
 }
 
-source_set("snapshot_export") {
+jumbo_source_set("snapshot_export") {
   sources = [
     "snapshot_export.h",
   ]
@@ -104,9 +105,9 @@
     "//skia",
     "//testing/gtest",
     "//ui/base",
+    "//ui/base:test_support",
     "//ui/compositor:test_support",
     "//ui/gfx",
-    "//ui/gfx:test_support",
     "//ui/gfx/geometry",
     "//ui/gl",
   ]
diff --git a/ui/snapshot/snapshot_mac_unittest.mm b/ui/snapshot/snapshot_mac_unittest.mm
index 860b692f..5365fb1 100644
--- a/ui/snapshot/snapshot_mac_unittest.mm
+++ b/ui/snapshot/snapshot_mac_unittest.mm
@@ -12,9 +12,9 @@
 #include "base/mac/scoped_nsobject.h"
 #include "base/mac/sdk_forward_declarations.h"
 #include "testing/platform_test.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/image/image.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 
 namespace ui {
 namespace {
diff --git a/ui/surface/BUILD.gn b/ui/surface/BUILD.gn
index b583c8b..6f171275 100644
--- a/ui/surface/BUILD.gn
+++ b/ui/surface/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 
-component("surface") {
+jumbo_component("surface") {
   sources = [
     "surface_export.h",
     "transport_dib.cc",
diff --git a/ui/touch_selection/BUILD.gn b/ui/touch_selection/BUILD.gn
index 233dffa..3fb63af 100644
--- a/ui/touch_selection/BUILD.gn
+++ b/ui/touch_selection/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 
@@ -9,7 +10,7 @@
   import("//build/config/android/rules.gni")
 }
 
-component("touch_selection") {
+jumbo_component("touch_selection") {
   output_name = "ui_touch_selection"
 
   sources = [
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm
index d7c93e6..4a7157d0 100644
--- a/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -20,10 +20,10 @@
 #import "ui/base/cocoa/window_size_constants.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/base/material_design/material_design_controller.h"
+#import "ui/base/test/cocoa_helper.h"
 #include "ui/base/test/material_design_controller_test_api.h"
 #include "ui/events/test/cocoa_test_event_utils.h"
 #import "ui/gfx/mac/coordinate_conversion.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 #import "ui/views/cocoa/bridged_content_view.h"
 #import "ui/views/cocoa/native_widget_mac_nswindow.h"
 #import "ui/views/cocoa/views_nswindow_delegate.h"
diff --git a/ui/views/cocoa/cocoa_mouse_capture_unittest.mm b/ui/views/cocoa/cocoa_mouse_capture_unittest.mm
index a3edec3..47235a7f 100644
--- a/ui/views/cocoa/cocoa_mouse_capture_unittest.mm
+++ b/ui/views/cocoa/cocoa_mouse_capture_unittest.mm
@@ -8,8 +8,8 @@
 
 #import "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
+#import "ui/base/test/cocoa_helper.h"
 #import "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/gfx/test/ui_cocoa_test_helper.h"
 #import "ui/views/cocoa/cocoa_mouse_capture_delegate.h"
 
 // Simple test view that counts calls to -[NSView mouseDown:].
diff --git a/ui/views/controls/webview/BUILD.gn b/ui/views/controls/webview/BUILD.gn
index 2836c31..05eb756 100644
--- a/ui/views/controls/webview/BUILD.gn
+++ b/ui/views/controls/webview/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("webview") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("webview") {
   sources = [
     "unhandled_keyboard_event_handler.cc",
     "unhandled_keyboard_event_handler.h",
diff --git a/ui/views/examples/BUILD.gn b/ui/views/examples/BUILD.gn
index f278966..661329c 100644
--- a/ui/views/examples/BUILD.gn
+++ b/ui/views/examples/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 
-component("views_examples_lib") {
+jumbo_component("views_examples_lib") {
   testonly = true
 
   sources = [
@@ -134,7 +135,7 @@
   }
 }
 
-component("views_examples_with_content_lib") {
+jumbo_component("views_examples_with_content_lib") {
   testonly = true
   sources = [
     "examples_window_with_content.cc",
diff --git a/ui/views/examples/label_example.cc b/ui/views/examples/label_example.cc
index be6bbe92..05e30aa 100644
--- a/ui/views/examples/label_example.cc
+++ b/ui/views/examples/label_example.cc
@@ -28,27 +28,32 @@
 
 namespace {
 
-const char* kElideBehaviors[] = { "No Elide", "Truncate", "Elide Head",
-    "Elide Middle", "Elide Tail", "Elide Email", "Fade Tail" };
 const char* kAlignments[] = { "Left", "Center", "Right", "Head" };
 
 // A Label with a clamped preferred width to demonstrate eliding or wrapping.
-class PreferredSizeLabel : public Label {
+class ExamplePreferredSizeLabel : public Label {
  public:
-  PreferredSizeLabel() : Label() {
+  ExamplePreferredSizeLabel() : Label() {
     SetBorder(CreateSolidBorder(1, SK_ColorGRAY));
   }
-  ~PreferredSizeLabel() override {}
+  ~ExamplePreferredSizeLabel() override {}
 
   // Label:
   gfx::Size CalculatePreferredSize() const override {
     return gfx::Size(50, Label::CalculatePreferredSize().height());
   }
 
+  static const char* kElideBehaviors[];
+
  private:
-  DISALLOW_COPY_AND_ASSIGN(PreferredSizeLabel);
+  DISALLOW_COPY_AND_ASSIGN(ExamplePreferredSizeLabel);
 };
 
+// static
+const char* ExamplePreferredSizeLabel::kElideBehaviors[] = {
+    "No Elide",   "Truncate",    "Elide Head", "Elide Middle",
+    "Elide Tail", "Elide Email", "Fade Tail"};
+
 }  // namespace
 
 LabelExample::LabelExample()
@@ -101,12 +106,12 @@
   label->SetShadows(shadows);
   container->AddChildView(label);
 
-  label = new PreferredSizeLabel();
+  label = new ExamplePreferredSizeLabel();
   label->SetText(ASCIIToUTF16("A long label will elide toward its logical end "
       "if the text's width exceeds the label's available width."));
   container->AddChildView(label);
 
-  label = new PreferredSizeLabel();
+  label = new ExamplePreferredSizeLabel();
   label->SetText(ASCIIToUTF16("A multi-line label will wrap onto subsequent "
     "lines if the text's width exceeds the label's available width, which is "
     "helpful for extemely long text used to demonstrate line wrapping."));
@@ -183,8 +188,9 @@
 
   alignment_ = AddCombobox(layout, "Alignment: ", kAlignments,
                            arraysize(kAlignments));
-  elide_behavior_ = AddCombobox(layout, "Elide Behavior: ", kElideBehaviors,
-                                arraysize(kElideBehaviors));
+  elide_behavior_ = AddCombobox(
+      layout, "Elide Behavior: ", ExamplePreferredSizeLabel::kElideBehaviors,
+      arraysize(ExamplePreferredSizeLabel::kElideBehaviors));
 
   column_set = layout->AddColumnSet(1);
   column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
@@ -209,7 +215,7 @@
   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
                         1, GridLayout::USE_PREF, 0, 0);
   layout->StartRow(0, 2);
-  custom_label_ = new PreferredSizeLabel();
+  custom_label_ = new ExamplePreferredSizeLabel();
   custom_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   custom_label_->SetElideBehavior(gfx::NO_ELIDE);
   custom_label_->SetText(textfield_->text());
diff --git a/ui/views/examples/widget_example.cc b/ui/views/examples/widget_example.cc
index 59afbba..960d5f6 100644
--- a/ui/views/examples/widget_example.cc
+++ b/ui/views/examples/widget_example.cc
@@ -23,16 +23,16 @@
 
 namespace {
 
-class DialogExample : public DialogDelegateView {
+class WidgetDialogExample : public DialogDelegateView {
  public:
-  DialogExample();
-  ~DialogExample() override;
+  WidgetDialogExample();
+  ~WidgetDialogExample() override;
   base::string16 GetWindowTitle() const override;
   View* CreateExtraView() override;
   View* CreateFootnoteView() override;
 };
 
-class ModalDialogExample : public DialogExample {
+class ModalDialogExample : public WidgetDialogExample {
  public:
   ModalDialogExample() {}
 
@@ -43,25 +43,25 @@
   DISALLOW_COPY_AND_ASSIGN(ModalDialogExample);
 };
 
-DialogExample::DialogExample() {
+WidgetDialogExample::WidgetDialogExample() {
   SetBackground(CreateSolidBackground(SK_ColorGRAY));
   SetLayoutManager(
       std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10));
   AddChildView(new Label(ASCIIToUTF16("Dialog contents label!")));
 }
 
-DialogExample::~DialogExample() {}
+WidgetDialogExample::~WidgetDialogExample() {}
 
-base::string16 DialogExample::GetWindowTitle() const {
+base::string16 WidgetDialogExample::GetWindowTitle() const {
   return ASCIIToUTF16("Dialog Widget Example");
 }
 
-View* DialogExample::CreateExtraView() {
+View* WidgetDialogExample::CreateExtraView() {
   return MdTextButton::CreateSecondaryUiButton(nullptr,
                                                ASCIIToUTF16("Extra button!"));
 }
 
-View* DialogExample::CreateFootnoteView() {
+View* WidgetDialogExample::CreateFootnoteView() {
   return new Label(ASCIIToUTF16("Footnote label!"));
 }
 
@@ -123,8 +123,9 @@
       ShowWidget(sender, Widget::InitParams(Widget::InitParams::TYPE_POPUP));
       break;
     case DIALOG: {
-      DialogDelegate::CreateDialogWidget(new DialogExample(), NULL,
-          sender->GetWidget()->GetNativeView())->Show();
+      DialogDelegate::CreateDialogWidget(new WidgetDialogExample(), NULL,
+                                         sender->GetWidget()->GetNativeView())
+          ->Show();
       break;
     }
     case MODAL_DIALOG: {
diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
index cb78410..d6b086c1 100644
--- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
+++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
@@ -275,7 +275,6 @@
       new ui::XScopedEventSelector(grab_input_window_, event_mask));
 
   XMapRaised(display, grab_input_window_);
-  ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(grab_input_window_);
 }
 
 }  // namespace views
diff --git a/ui/views_content_client/BUILD.gn b/ui/views_content_client/BUILD.gn
index c9df61e4..a20ef91d 100644
--- a/ui/views_content_client/BUILD.gn
+++ b/ui/views_content_client/BUILD.gn
@@ -2,9 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 
-component("views_content_client") {
+jumbo_component("views_content_client") {
   testonly = true
   sources = [
     "views_content_browser_client.cc",
diff --git a/ui/web_dialogs/BUILD.gn b/ui/web_dialogs/BUILD.gn
index 9c56ea0..63923b1 100644
--- a/ui/web_dialogs/BUILD.gn
+++ b/ui/web_dialogs/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("web_dialogs") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("web_dialogs") {
   sources = [
     "web_dialog_delegate.cc",
     "web_dialog_delegate.h",
diff --git a/ui/webui/resources/html/load_time_data.html b/ui/webui/resources/html/load_time_data.html
index 627fdf9..6f87d6da 100644
--- a/ui/webui/resources/html/load_time_data.html
+++ b/ui/webui/resources/html/load_time_data.html
@@ -1,2 +1,3 @@
+<link rel="import" href="chrome://resources/html/parse_html_subset.html">
 <script src="chrome://resources/js/assert.js"></script>
 <script src="chrome://resources/js/load_time_data.js"></script>
diff --git a/ui/webui/resources/js/compiled_resources2.gyp b/ui/webui/resources/js/compiled_resources2.gyp
index b3fb3e0..25f388b 100644
--- a/ui/webui/resources/js/compiled_resources2.gyp
+++ b/ui/webui/resources/js/compiled_resources2.gyp
@@ -57,7 +57,6 @@
       'target_name': 'i18n_behavior',
       'dependencies': [
         'load_time_data',
-        'parse_html_subset',
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
@@ -65,7 +64,8 @@
       'target_name': 'load_time_data',
       'dependencies': [
         '<(DEPTH)/third_party/jstemplate/compiled_resources2.gyp:jstemplate',
-        'assert'
+        'assert',
+        'parse_html_subset',
       ],
       'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
diff --git a/ui/webui/resources/js/i18n_behavior.js b/ui/webui/resources/js/i18n_behavior.js
index 94704db..5e1bf38 100644
--- a/ui/webui/resources/js/i18n_behavior.js
+++ b/ui/webui/resources/js/i18n_behavior.js
@@ -56,15 +56,14 @@
    * as well as optional additional allowed tags and attributes. Use with
    * Polymer bindings that are inner-h-t-m-l, for example.
    * @param {string} id The ID of the string to translate.
-   * @param {I18nAdvancedOpts=} opts
+   * @param {SanitizeInnerHtmlOpts=} opts
    * @return {string}
    */
   i18nAdvanced: function(id, opts) {
     opts = opts || {};
     var args = [id].concat(opts.substitutions || []);
     var rawString = this.i18nRaw_.apply(this, args);
-    return parseHtmlSubset('<b>' + rawString + '</b>', opts.tags, opts.attrs)
-        .firstChild.innerHTML;
+    return loadTimeData.sanitizeInnerHtml(rawString, opts);
   },
 
   /**
@@ -99,19 +98,10 @@
 };
 
 /**
- * @typedef {{
- *   substitutions: (Array<string>|undefined),
- *   attrs: (Object<function(Node, string):boolean>|undefined),
- *   tags: (Array<string>|undefined),
- * }}
- */
-var I18nAdvancedOpts;
-
-/**
  * TODO(stevenjb): Replace with an interface. b/24294625
  * @typedef {{
  *   i18n: function(string, ...string): string,
- *   i18nAdvanced: function(string, I18nAdvancedOpts=): string,
+ *   i18nAdvanced: function(string, SanitizeInnerHtmlOpts=): string,
  *   i18nDynamic: function(string, string, ...string): string,
  *   i18nExists: function(string),
  *   i18nUpdateLocale: function()
diff --git a/ui/webui/resources/js/load_time_data.js b/ui/webui/resources/js/load_time_data.js
index 3439a24a..bcb89d2 100644
--- a/ui/webui/resources/js/load_time_data.js
+++ b/ui/webui/resources/js/load_time_data.js
@@ -14,6 +14,15 @@
  * change if the page is re-opened later.
  */
 
+/**
+ * @typedef {{
+ *   substitutions: (Array<string>|undefined),
+ *   attrs: (Object<function(Node, string):boolean>|undefined),
+ *   tags: (Array<string>|undefined),
+ * }}
+ */
+var SanitizeInnerHtmlOpts;
+
 /** @type {!LoadTimeData} */ var loadTimeData;
 
 // Expose this type globally as a temporary work around until
@@ -97,6 +106,19 @@
     },
 
     /**
+     * Make a string safe for use with with Polymer bindings that are
+     * inner-h-t-m-l (or other innerHTML use).
+     * @param {string} rawString The unsanitized string.
+     * @param {SanitizeInnerHtmlOpts=} opts Optional additional allowed tags and
+     *     attributes.
+     * @return {string}
+     */
+    sanitizeInnerHtml: function(rawString, opts) {
+      return parseHtmlSubset('<b>' + rawString + '</b>', opts.tags, opts.attrs)
+          .firstChild.innerHTML;
+    },
+
+    /**
      * Returns a formatted localized string where $1 to $9 are replaced by the
      * second to the tenth argument. Any standalone $ signs must be escaped as
      * $$.
diff --git a/ui/webui/resources/polymer_resources.grdp b/ui/webui/resources/polymer_resources.grdp
index 5718dc1..6e5f88e 100644
--- a/ui/webui/resources/polymer_resources.grdp
+++ b/ui/webui/resources/polymer_resources.grdp
@@ -772,10 +772,6 @@
              file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-behavior.html"
              type="chrome_html"
              compress="gzip" />
-  <structure name="IDR_POLYMER_1_0_PAPER_SPINNER_PAPER_SPINNER_EXTRACTED_JS"
-             file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-extracted.js"
-             type="chrome_html"
-             compress="gzip" />
   <structure name="IDR_POLYMER_1_0_PAPER_SPINNER_PAPER_SPINNER_LITE_EXTRACTED_JS"
              file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-lite-extracted.js"
              type="chrome_html"
@@ -788,10 +784,6 @@
              file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner-styles.html"
              type="chrome_html"
              compress="gzip" />
-  <structure name="IDR_POLYMER_1_0_PAPER_SPINNER_PAPER_SPINNER_HTML"
-             file="../../../third_party/polymer/v1_0/components-chromium/paper-spinner/paper-spinner.html"
-             type="chrome_html"
-             compress="gzip" />
   <structure name="IDR_POLYMER_1_0_PAPER_STYLES_CLASSES_SHADOW_LAYOUT_HTML"
              file="../../../third_party/polymer/v1_0/components-chromium/paper-styles/classes/shadow-layout.html"
              type="chrome_html"
diff --git a/ui/wm/BUILD.gn b/ui/wm/BUILD.gn
index 4872ecd..7b832f6 100644
--- a/ui/wm/BUILD.gn
+++ b/ui/wm/BUILD.gn
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//testing/test.gni")
 
-component("wm") {
+jumbo_component("wm") {
   sources = [
     "core/accelerator_delegate.h",
     "core/accelerator_filter.cc",
diff --git a/ui/wm/public/BUILD.gn b/ui/wm/public/BUILD.gn
index 2356a10..a60f7da 100644
--- a/ui/wm/public/BUILD.gn
+++ b/ui/wm/public/BUILD.gn
@@ -2,7 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-component("public") {
+import("//build/config/jumbo.gni")
+
+jumbo_component("public") {
   output_name = "wm_public"
 
   public = [